diff -Nru mathpiper-0.0.svn2556/applet.policy mathpiper-0.81f+dfsg1/applet.policy --- mathpiper-0.0.svn2556/applet.policy 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/applet.policy 2010-01-22 08:53:44.000000000 +0000 @@ -1,3 +1,3 @@ grant { permission java.security.AllPermission; -}; \ No newline at end of file +}; diff -Nru mathpiper-0.0.svn2556/build.xml mathpiper-0.81f+dfsg1/build.xml --- mathpiper-0.0.svn2556/build.xml 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/build.xml 2011-01-16 12:20:23.000000000 +0000 @@ -6,25 +6,36 @@ Build file for MathPiper. - + + + + - + + + + + + + + + + + @@ -50,38 +61,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + - - + + - + - - - - + + + + + + - - - + + + @@ -100,6 +130,8 @@ + + @@ -200,7 +243,10 @@ - + + - - - + + + @@ -275,6 +326,10 @@ + + + + diff -Nru mathpiper-0.0.svn2556/debian/changelog mathpiper-0.81f+dfsg1/debian/changelog --- mathpiper-0.0.svn2556/debian/changelog 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/changelog 2011-11-26 23:18:43.000000000 +0000 @@ -1,3 +1,14 @@ +mathpiper (0.81f+dfsg1-1) unstable; urgency=low + + * New upstream version, from SVN revision 4053. + * Remove watch file, which is not reliable. + * Use javahelper to build the library instead of relying on its + build.xml script. + * Switch from CDBS to debhelper 7. + * Switch to source package format 3.0 (quilt). + + -- Giovanni Mascellani Wed, 23 Nov 2011 08:54:20 +0100 + mathpiper (0.0.svn2556-3) unstable; urgency=low * Add real watch file. diff -Nru mathpiper-0.0.svn2556/debian/control mathpiper-0.81f+dfsg1/debian/control --- mathpiper-0.0.svn2556/debian/control 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/control 2011-11-26 23:18:43.000000000 +0000 @@ -3,8 +3,8 @@ Priority: extra Maintainer: Debian Java Maintainers Uploaders: Giovanni Mascellani -Build-Depends: ant, ant-optional, cdbs, debhelper (>= 7), default-jdk, - libjfreechart-java, libjcommon-java +Build-Depends: debhelper (>= 7.0.50~), javahelper, default-jdk, libjfreechart-java, + libjdom1-java, libjas-java, libjlatexmath-java Standards-Version: 3.9.2 Homepage: http://mathrider.org/ Vcs-Git: git://git.debian.org/git/pkg-java/mathpiper.git @@ -12,8 +12,7 @@ Package: mathpiper Architecture: all -Depends: ${shlibs:Depends}, ${misc:Depends}, libjfreechart-java, - libjcommon-java +Depends: ${shlibs:Depends}, ${misc:Depends}, ${java:Depends} Description: Java Computer Algebra System Mathpiper is a CAS (Computer Algebra System), written in Java. It is part of the mathrider suite, a mathematics computing environment for diff -Nru mathpiper-0.0.svn2556/debian/copyright mathpiper-0.81f+dfsg1/debian/copyright --- mathpiper-0.0.svn2556/debian/copyright 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/copyright 2011-11-26 23:18:43.000000000 +0000 @@ -1,26 +1,102 @@ -Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=59 -Name: mathpiper -Source: https://mathrider.dev.java.net/source/browse/mathrider/trunk/src/library_apps/mathpiper/ +Format: http://dep.debian.net/deps/dep5/ +Upstream-Name: Mathpiper +Source: http://code.google.com/p/mathpiper/ Files: * Copyright: © 2008-2009 Ted Kosan - © 2008-2009, Sherm Ostrowsky - © 1998-2009, Ayal Pinkus + © 2008-2009, Sherm Ostrowsky + © 1998-2009, Ayal Pinkus +License: GPL-2+ + +Files: src/org/mathpiper/ui/gui/controlpanel/HaltButton.java + src/org/mathpiper/ui/gui/MultiSplitLayout.java + src/org/mathpiper/ui/gui/MultiSplitPane.java +Copyright: © 2004, Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A. +License: LGPL-2.1+ + On Debian systems, the LGPL-2.1 license text can be found in: + /usr/share/common-licenses/LGPL-2.1 + +Files: src/org/mathpiper/ui/gui/hoteqn/* +Copyright: © 2006, Stefan Müller + © 2006, Christian Schmid +License: GPL + HotEqn 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; + HotEqn is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Files: src/org/mathpiper/builtin/javareflection/JavaField.java + src/org/mathpiper/builtin/javareflection/JavaMethod.java + src/org/mathpiper/builtin/javareflection/JavaConstructor.java + src/org/mathpiper/builtin/javareflection/StaticReflector.java + src/org/mathpiper/builtin/javareflection/Invoke.java + src/org/mathpiper/builtin/javareflection/Import.java +Copyright: © 1998, Peter Norvig + © 2000, Ken R. Anderson +License: JScheme + This system is licensed under the following + zlib/libpng open-source license. + . + This software is provided 'as-is', without any express or + implied warranty. + . + In no event will the authors be held liable for any damages + arising from the use of this software. + . + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + . + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you + use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not + required. + . + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + . + 3. This notice may not be removed or altered from any source + distribution. +Comment: These files come from the JScheme project. Their license is + not specified in Mathpiper, but I consider safe to assume the JScheme + license is valid here. + +Files: src/org/mathpiper/builtin/library/cern/* +Copyright: © 1999, CERN - European Organization for Nuclear Research +License: CERN + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear in + supporting documentation. CERN makes no representations about the + suitability of this software for any purpose. It is provided "as is" + without expressed or implied warranty. + +Files: src/org/mathpiper/builtin/library/jscistats/SpecialMath.java +Copyright: © 1993, Sun Microsystems, Inc. +License: SUN + Permission to use, copy, modify, and distribute this software is + freely granted, provided that this notice is preserved. + +Files: src/org/mathpiper/builtin/library/statdistlib/* +Copyright: © 1995 - 1998, Ross Ihaka + © 1995 - 1996, Robert Gentleman + © 1998, R Core Team + © Mark Hale + © Jaco van Kooten License: GPL-2+ - On Debian systems, the GPL-2 license text can be found in: - /usr/share/common-licenses/GPL-2 Files: debian/* -Copyright: © 2009, Giovanni Mascellani +Copyright: © 2009-2011, Giovanni Mascellani +License: GPL-2+ + License: GPL-2+ On Debian systems, the GPL-2 license text can be found in: /usr/share/common-licenses/GPL-2 - -Files: src/org/mathpiper/ui/gui/controlpanel/HaltButton.java, - src/org/mathpiper/ui/gui/MultiSplitLayout.java, - src/org/mathpiper/ui/gui/MultiSplitPane.java -Copyright: © 2004, Sun Microsystems, Inc., 4150 Network Circle, - Santa Clara, California 95054, U.S.A. -License: LGPL-2.1+ - On Debian systems, the LGPL-2.1 license text can be found in: - /usr/share/common-licenses/LGPL-2.1 diff -Nru mathpiper-0.0.svn2556/debian/docs mathpiper-0.81f+dfsg1/debian/docs --- mathpiper-0.0.svn2556/debian/docs 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/docs 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -docs/* diff -Nru mathpiper-0.0.svn2556/debian/get_orig_source.sh mathpiper-0.81f+dfsg1/debian/get_orig_source.sh --- mathpiper-0.0.svn2556/debian/get_orig_source.sh 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/get_orig_source.sh 2011-11-26 23:18:43.000000000 +0000 @@ -0,0 +1,45 @@ +#!/bin/bash + +# Input: +# $VERSION - the upstream version of the generated tarball +# $REVISION (optional) - export a specific revision of the SVN repository +# $ONLYFILTER - if not null, don't download the tarball from the SVN; just re-filter its content + +DESTDIR="../tarballs/mathpiper-$VERSION" +DESTTGZ="../tarballs/mathpiper_$VERSION.orig.tar.gz" + +if [ "x$ONLYFILTER" == "x" ] ; then + # Downloads code from SVN repository + test -d ../tarballs/. || mkdir -p ../tarballs + if [ "x$REVISION" == "x" ] ; then + svn export "http://mathpiper.googlecode.com/svn/trunk/src/library_apps/mathpiper" "$DESTDIR" + else + svn export -r "$REVISION" "http://mathpiper.googlecode.com/svn/trunk/src/library_apps/mathpiper" "$DESTDIR" + fi +else + # Uncompress the previous tarball + tar xzfv "$DESTTGZ" -C `dirname "$DESTDIR"` +fi + +# Removes embedded copies of other software +rm -vfr "$DESTDIR/src/org/mathpiper/ui/gui/jmathtex" +rm -vfr "$DESTDIR/src/org/apache" +rm -vfr "$DESTDIR/src/org/matheclipse" +rm -vfr "$DESTDIR/src/org/scilab" +rm -vfr "$DESTDIR/src/edu" + +# Remove other unecessary files +rm -vfr "$DESTDIR/misc" +rm -vf "$DESTDIR/src/org/mathpiper/test/matheclipse/ParseRubiFiles.java" +rm -vf "$DESTDIR/src/org/mathpiper/builtin/functions/optional/ViewGeoGebra.java" + +# Removes all upstream JARs, DLLs, SOs and JNILIBs +for ext in jar dll so jnilib ; do + find "$DESTDIR" -iname '*'."$ext" -print0 | xargs -0 rm -vf +done + +# Builds tarball +tar czfv "$DESTTGZ" -C `dirname "$DESTDIR"` `basename "$DESTDIR"` + +# Deletes snapshot and temporary dir +rm -fr "$DESTDIR" diff -Nru mathpiper-0.0.svn2556/debian/install mathpiper-0.81f+dfsg1/debian/install --- mathpiper-0.0.svn2556/debian/install 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -build/dist/mathpiper.jar usr/share/java diff -Nru mathpiper-0.0.svn2556/debian/javabuild mathpiper-0.81f+dfsg1/debian/javabuild --- mathpiper-0.0.svn2556/debian/javabuild 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/javabuild 2011-11-26 23:18:43.000000000 +0000 @@ -0,0 +1 @@ +mathpiper.jar src/ diff -Nru mathpiper-0.0.svn2556/debian/jlibs mathpiper-0.81f+dfsg1/debian/jlibs --- mathpiper-0.0.svn2556/debian/jlibs 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/jlibs 2011-11-26 23:18:43.000000000 +0000 @@ -0,0 +1 @@ +mathpiper.jar diff -Nru mathpiper-0.0.svn2556/debian/patches/series mathpiper-0.81f+dfsg1/debian/patches/series --- mathpiper-0.0.svn2556/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/patches/series 2011-11-26 23:18:43.000000000 +0000 @@ -0,0 +1 @@ +variableList diff -Nru mathpiper-0.0.svn2556/debian/patches/variableList mathpiper-0.81f+dfsg1/debian/patches/variableList --- mathpiper-0.0.svn2556/debian/patches/variableList 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/patches/variableList 2011-11-26 23:18:43.000000000 +0000 @@ -0,0 +1,77 @@ +From: Giovanni Mascellani +Subject: Fix an out-of-date API from JAS +Last-Update: 2011-11-23 +Forwarded: no + +The variableList static method in the JAS library was moved from +StringUtil to the GenPolynomialTokenizer class. Here we acknowledge +this change. + +Index: mathpiper/src/org/mathpiper/builtin/library/jas/JFactorsPolyInt.java +=================================================================== +--- mathpiper.orig/src/org/mathpiper/builtin/library/jas/JFactorsPolyInt.java 2011-11-23 08:53:56.000000000 +0100 ++++ mathpiper/src/org/mathpiper/builtin/library/jas/JFactorsPolyInt.java 2011-11-23 08:57:29.000000000 +0100 +@@ -19,7 +19,6 @@ + import edu.jas.poly.GenPolynomial; + import edu.jas.poly.GenPolynomialRing; + import edu.jas.poly.TermOrder; +-import edu.jas.util.StringUtil; + + //------------------------------------------------------------------------ + +Index: mathpiper/src/org/mathpiper/builtin/library/jas/JasAccess.java +=================================================================== +--- mathpiper.orig/src/org/mathpiper/builtin/library/jas/JasAccess.java 2011-11-23 08:53:56.000000000 +0100 ++++ mathpiper/src/org/mathpiper/builtin/library/jas/JasAccess.java 2011-11-23 08:57:05.000000000 +0100 +@@ -20,7 +20,7 @@ + import edu.jas.poly.GenPolynomial; + import edu.jas.poly.GenPolynomialRing; + import edu.jas.poly.TermOrder; +-import edu.jas.util.StringUtil; ++import edu.jas.poly.GenPolynomialTokenizer; + + //----------------------------------------------- + public class JasAccess { +@@ -49,7 +49,7 @@ + } + + // convert string of variable names to array of strings as required +- String[] jvars = StringUtil.variableList(vars); ++ String[] jvars = GenPolynomialTokenizer.variableList(vars); + int nvars = jvars.length; + if (debug) { + System.out.print("\n number of variables: "); +Index: mathpiper/src/org/mathpiper/builtin/library/jas/JasAccess2.java +=================================================================== +--- mathpiper.orig/src/org/mathpiper/builtin/library/jas/JasAccess2.java 2011-11-23 08:53:56.000000000 +0100 ++++ mathpiper/src/org/mathpiper/builtin/library/jas/JasAccess2.java 2011-11-23 08:57:05.000000000 +0100 +@@ -21,7 +21,7 @@ + import edu.jas.poly.GenPolynomial; + import edu.jas.poly.GenPolynomialRing; + import edu.jas.poly.TermOrder; +-import edu.jas.util.StringUtil; ++import edu.jas.poly.GenPolynomialTokenizer; + + //----------------------------------------------- + public class JasAccess2 { +@@ -52,7 +52,7 @@ + } + + // convert string of variable names to array of strings as required +- String[] jvars = StringUtil.variableList(vars); ++ String[] jvars = GenPolynomialTokenizer.variableList(vars); + int nvars = jvars.length; + if (debug) { + System.out.print("\n number of variables: "); +Index: mathpiper/src/org/mathpiper/builtin/library/jas/JasPolynomial.java +=================================================================== +--- mathpiper.orig/src/org/mathpiper/builtin/library/jas/JasPolynomial.java 2011-11-23 08:53:56.000000000 +0100 ++++ mathpiper/src/org/mathpiper/builtin/library/jas/JasPolynomial.java 2011-11-23 08:57:22.000000000 +0100 +@@ -23,7 +23,6 @@ + import edu.jas.poly.GenPolynomial; + import edu.jas.poly.GenPolynomialRing; + import edu.jas.poly.TermOrder; +-import edu.jas.util.StringUtil; + + //------------------------------------------------------------------------ + diff -Nru mathpiper-0.0.svn2556/debian/README.Debian mathpiper-0.81f+dfsg1/debian/README.Debian --- mathpiper-0.0.svn2556/debian/README.Debian 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/README.Debian 2011-11-26 23:18:43.000000000 +0000 @@ -0,0 +1,15 @@ +README.Debian for package mathpiper +----------------------------------- + +This Debian version of Mathpiper lacks two classes, that are disabled +for technical reason: + + * ParseRubiFiles.java: it requires the Matheclipse library, which is + not in Debian. This class will be re-enabled as soon as someone will + package Matheclipse in Debian; + + * ViewGeoGebra.java: it requires the GeoGebra classes, but in Debian + Mathpiper is used to build GeoGebra. Since I don't want circular + dependencies, the GeoGebra support in Mathpiper is disabled. + +-- Giovanni Mascellani diff -Nru mathpiper-0.0.svn2556/debian/README.source mathpiper-0.81f+dfsg1/debian/README.source --- mathpiper-0.0.svn2556/debian/README.source 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/README.source 2011-11-26 23:18:43.000000000 +0000 @@ -0,0 +1,43 @@ +mathpiper for Debian +-------------------- + +The upstream source tarball is obtained by the script +get_orig_source.sh by exporing a copy of the SVN tag corresponding to +the desired version and then: + + * Deleting the misc/ directory, which are not necessary for the + Debian package; + + * Deleteing a few embedded copies of other pieces of software, + documented below. + + +QUILT + +This package uses quilt to manage all modifications to the upstream +source. Changes are stored in the source package as diffs in +debian/patches and applied during the build. Please see: + + /usr/share/doc/quilt/README.source + +for more information on how to apply the patches, modify patches, or +remove a patch. + + +EMBEDDED SOFTWARE + +The following pieces of software are present in the upstream +distribution of Mathpiper, but are not included in the Debian package: + + * The JAS (Java Algebra System) library, that is already included in + Debian; + + * The Apache Log4J library, that is already included in Debian; + + * The Matheclipse library, whose use is disabled in the Debian build + of Mathpiper; + + * The JLaTeXMath library, that is already included in Debian; + + * The JMathTeX library, that is already included in Debian (and is + not used anyway). diff -Nru mathpiper-0.0.svn2556/debian/rules mathpiper-0.81f+dfsg1/debian/rules --- mathpiper-0.0.svn2556/debian/rules 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/rules 2011-11-26 23:18:43.000000000 +0000 @@ -1,10 +1,18 @@ #!/usr/bin/make -f +# -*- makefile -*- -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/ant.mk +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 -JAVA_HOME := /usr/lib/jvm/default-java +export JAVA_HOME=/usr/lib/jvm/default-java +export CLASSPATH=/usr/share/java/jdom1.jar:/usr/share/java/jas.jar:/usr/share/java/jfreechart.jar:/usr/share/java/jlatexmath.jar -DEB_JARS := /usr/share/java/jfreechart.jar -DEB_JARS += /usr/share/java/jcommon.jar +%: + dh $@ --with javahelper +# Avoid the default build.xml and its ant dependency +override_dh_auto_build: + true + +override_dh_auto_clean: + true diff -Nru mathpiper-0.0.svn2556/debian/source/format mathpiper-0.81f+dfsg1/debian/source/format --- mathpiper-0.0.svn2556/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/source/format 2011-12-12 14:25:35.000000000 +0000 @@ -0,0 +1 @@ +3.0 (quilt) diff -Nru mathpiper-0.0.svn2556/debian/watch mathpiper-0.81f+dfsg1/debian/watch --- mathpiper-0.0.svn2556/debian/watch 2011-12-12 14:25:35.000000000 +0000 +++ mathpiper-0.81f+dfsg1/debian/watch 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -version=3 -opts="uversionmangle=s|_|~|g" \ - http://code.google.com/p/mathpiper/downloads/list \ - //mathpiper.googlecode.com/files/mathpiperide_unix_mac_dist_v.([-0-9a-z._]*).tar.bz2 diff -Nru mathpiper-0.0.svn2556/docs/functions_that_need_documentation.txt mathpiper-0.81f+dfsg1/docs/functions_that_need_documentation.txt --- mathpiper-0.0.svn2556/docs/functions_that_need_documentation.txt 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/docs/functions_that_need_documentation.txt 2011-02-05 04:36:21.000000000 +0000 @@ -0,0 +1,378 @@ +The following functions and .mpw files need to be documented +(functions that start with * and are indented have already had documentation +added to them): + + + + +AddTerm.mpw +AddTerms.mpw +DivTermList.mpw +MultiDivTerm.mpw +MultiplySingleTerm.mpw +MultiplyTerms.mpw +SubtractTerms.mpw + + +AntiDeriv.mpw + + +//Tensor functions. +ApplyDelta.mpw +MoveDeltas.mpw +Delta.mpw +TD.mpw +TExplicitSum.mpw +TList.mpw +TRun.mpw +TSimplify.mpw +TSum.mpw +TSumRest.mpw +TSumSimplify.mpw +X.mpw + + +ApproxInfSum.mpw +ArcCosh.mpw +ArcCot.mpw +ArcCoth.mpw +ArcCsc.mpw +ArcCsch.mpw +ArcSec.mpw +ArcSech.mpw +ArcSinNum.mpw +ArcSinh.mpw +ArcTanN'Taylor.mpw +ArcTanNum.mpw +ArcTanh.mpw +Average.mpw +BSearch.mpw +BellNumber.mpw +BenchCall.mpw +BenchShow.mpw +Bernoulli1.mpw +BernoulliFracPart.mpw +BesselI.mpw +BesselJ.mpw +BesselJN.mpw +BesselJN0.mpw +BesselNsmall.mpw +BesselY.mpw +Beta.mpw +BinaryFactors.mpw +BisectSqrt.mpw +BitCount.java +BitsToDigits.java +BitsToDigits.mpw +BoundRealRoots.mpw +BrentLn.mpw +BuiltinAssoc.java +CNF.mpw +CanBeUni.mpw +CanonicalAdd.mpw +CatalanConstNum.mpw +ChartUtility.java +CheckIntPower.mpw +ChineseRemainderInteger.mpw +ChineseRemainderPoly.mpw +CommonLispTokenizer.java +CompilePatterns.mpw +Contradict.mpw +ControlChart.mpw +CosN'Doubling.mpw +CosN'Taylor.mpw +CosNum.mpw +Cosh.mpw +Cot.mpw +Coth.mpw +Csc.mpw +Csch.mpw +CustomEval.java +CustomEvalExpression.java +CustomEvalLocals.java +CustomEvalResult.java +CustomEvalStop.java +DawsonIntegral.mpw +DebugFile.java +DebugLine.java +DefLoadFunction.java +DefaultPrint.mpw + +Deriv.mpw +DestructiveAppendList.mpw +Digamma.mpw +DigitalRoot.mpw +DigitsToBits.java +DigitsToBits.mpw +DirichletBeta.mpw +DirichletEta.mpw +DirichletLambda.mpw +DivPoly.mpw +DoUnitSubsumptionAndResolution.mpw +DropEndZeroes.mpw +EqualAsSets.mpw +Erf.mpw +Erfc.mpw +Erfi.mpw +EulerArray.mpw +Example.mpw +Exit.java +ExitRequested.java +ExpN'Doubling.mpw +ExpN'Taylor.mpw +ExpNum.mpw +ExpandFrac.mpw +ExpandSparseUniVar.mpw +ExpandUniVariate.mpw +ExpressionDepth.mpw +ExtendedEuclidean.mpw +ExtendedEuclideanMonic.mpw +FW.mpw +FWatom.mpw +FactorGaussianInteger.mpw +FactorQS.mpw +FactorUniVar.mpw +Factorial.java +FactorizeInt.mpw +FactorsBinomials.mpw +FastArcCos.java +FastArcSin.java +FastArcTan.java +FastCos.java +FastIsPrime.java +FastLog.java +FastPower.java +FastSin.java +FastTan.java +FileSize.java +FindIsq.mpw +FindPredicate.mpw +FindPrimeFactor.mpw +FindPrimeFactorSimple.mpw +FloatIsInt.mpw +ForEachExperimental.mpw +ForEachInArray.mpw +FresnelCos.mpw +FresnelSin.mpw +GammaConstNum.mpw +GarbageCollect.java +GaussianFactorPrime.mpw +GaussianMod.mpw +GcdN.mpw +GcdReduce.mpw +GeoGebra.mpw +GeoGebraHistogram.mpw +GeoGebraPlot.mpw +GeoGebraPoint.mpw +GetNumerDenom.mpw +GetPrimePower.mpw +Groebner.mpw +HighschoolForm.mpw +II.mpw +ImII.mpw +Import.java +InDebugMode.java +IncompleteGamma.mpw +Internal'BernoulliArray.mpw +Internal'BernoulliArray1.mpw +Internal'GammaNum.mpw +Internal'LnGammaNum.mpw +Internal'LnNum.mpw +IsBoolType.mpw +IsComplex.mpw +IsComplexII.mpw +IsNonNegativeInteger.mpw +IsNonNegativeNumber.mpw +IsNotComplex.mpw +IsOne.mpw +IsPerfect.mpw +IsRationalOrNumber.mpw +IsSubset.mpw +IsUniVar.mpw +IsVariable.mpw +JFreeChartHistogram.mpw +JavaAccess.mpw +LexCompare2.java +LexGreaterThan.java +LexLessThan.java +ListHasFuncSome.mpw +LnGamma.mpw +LogicCombine.mpw +LogicFindWith.mpw +LogicRemoveTautologies.mpw +LogicSimplify.mpw +MM.mpw +MacroMapArgs.mpw +MacroMapSingle.mpw +MacroSubstitute.mpw +Magnitude.mpw +MakeMultiNomial.mpw +MakeSparseUniVar.mpw +MakeUni.mpw +ManipEquations.mpw +Manipulate.mpw +MathBitCount.mpw +MathExpDoubling.mpw +MathExpTaylor.mpw +MathFloatPower.mpw +MathIntPower.mpw +MathIsSmall.java +MathLn'Doubling.mpw +MathLn'Taylor.mpw +MathMul2Exp.mpw +MathNegate.java +MathPi.mpw +MathSign.java +MathSqrtFloat.mpw +MatrixRowAndColumnOps.mpw +Maxima.java +MultiDivide.mpw +MultiGcd.mpw +MultiNomial.mpw +MultiSimp.mpw +NN.mpw +NewtonLn.mpw +NextPseudoPrime.mpw +NextTest.mpw +NormalForm.mpw +Nth.java +NumericEqual.mpw +OldCyclotomic.mpw +OptionsListToHash.mpw +PAdicExpandInternal.mpw +PSolve.mpw +PanAxiom.java +PartFracExpand.mpw +PartitionsP.mpw +PatternCreate.java +PatternMatches.java +PollardCombineLists.mpw +PollardMerge.mpw +PollardRhoFactorize.mpw +PolyLog.mpw +PositiveIntPower.mpw +Print.mpw +ProductPrimesTo257.mpw +RabinMiller.mpw +RationalForm.mpw +RationalizeNumber.mpw +ReII.mpw +Regress.mpw +Rem.mpw +RemoveRepeated.mpw +RepeatedSquaresMultiply.mpw +Repunit.mpw +Return.java +Ring.java +Roots.mpw +RootsWithMultiples.mpw +Sec.mpw +Sech.mpw +Series.mpw +Set.java +SetOrder.mpw +SetPlotColor.java +SetPlotWidth.java +ShowLine.mpw +ShuffledDeckNoSuits.mpw +SimpAdd.mpw +SimpDiv.mpw +SimpExpand.mpw +SimpFlatten.mpw +SimpImplode.mpw +SimpMul.mpw +SimulatorPlot.java +SinN'Taylor.mpw +SinN'Tripling.mpw +SinNum.mpw +Sinc.mpw +Sinh.mpw +SmallSort.mpw +SolveSetEqns.mpw +SolveSystem.mpw +SortFactorList.mpw +SparseUniVar.mpw +StackSize.java +StemAndLeaf.mpw +SturmSequence.mpw +SturmVariations.mpw +Substitute.mpw +Subsumes.mpw +SumFunc.mpw +TanNum.mpw +Tanh.mpw +Taylor2.mpw +Taylor3.mpw +TestEquivalent.mpw +Testing.mpw +Totient.mpw +TraceToStdio.java +TrialFactorize.mpw +Trigonometry.mpw +UniDivide.mpw +UniGCD.mpw +UniTaylor.mpw +UniVarList.mpw +UniVariate.mpw +UniVariateCyclotomic.mpw +VarListAll.mpw +ViewGeoGebra.java +ViewSimulator.java +WilkinsonMatrix.mpw +WriteDataItem.mpw +WriteN.mpw + +backends.mpw +equals_greaterthan_operator.mpw +expthreshold.mpw +ggbLine.mpw +html.mpw +jFactorsPoly.mpw +jasFactorsInt.mpw +jas_test.mpw +lessthan_minus_operator.mpw +mathpiperinit.mpw +om.mpw +period_operator.mpw +pound_operator.mpw +randomtest.mpw +scopestack.mpw +sign'change.mpw +sparsenomial.mpw +sparsetree.mpw +stdopers.mpw +xFactor.mpw +xFactors.mpw +xFactorsBinomial.mpw +xFactorsResiduals.mpw +xSolvePoly.mpw +xSolveRational.mpw +xSolveReduce.mpw +xSolveSqrts.mpw +xSolveSystem.mpw +xTerms.mpw +zeta.mpw + + + + + +The following functions have been categorized and have had documentation added to them. + + *IntLog.mpw + *IntNthRoot.mpw + *IntPowerNum.mpw + *IsSumOfTerms.mpw + *MultiplyNum.mpw + *NetwonNum.mpw + *nthroot.mpw NthRoot + *numeric.mpw InNumericMode, NonN + *Remove.mpw + *SumTaylorNum.mpw + *ArithmeticGeometricMean.mpw + *ApplyFast.java + + + + + diff -Nru mathpiper-0.0.svn2556/examples/dungeon2.mpw mathpiper-0.81f+dfsg1/examples/dungeon2.mpw --- mathpiper-0.0.svn2556/examples/dungeon2.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/examples/dungeon2.mpw 2009-12-30 01:00:45.000000000 +0000 @@ -0,0 +1,111 @@ +%mathpiper,title="" + +roomsList := {}; + + + +//Kitchen. +kitchen := {}; +kitchen["name"] := "kitchen"; +kitchen["description"] := +" +You are in a bright white room which has a sink on its +east wall which has cupboards above and below it. A table +with 4 chairs is in the center of the room and a refridgerator is +in its north west corner. Sitting on the table is +a piece of paper with writing on it. + +There is an exit to the north. + +"; + +roomsList["kitchen"] := kitchen; + + +//Dining room. +diningRoom := {}; +diningRoom["name"] := "dining room"; +diningRoom["description"] := +" +You are in a large rectangular room with a high ceiling. +There is an oak table in the center of the room with 12 +chairs around it. There is a crystal chandelier above +the table. + +There is an exit to the south. + +"; + +roomsList["dining room"] := diningRoom; + + + + +//Connect the rooms together. +kitchen["n"] := "dining room"; +diningRoom["s"] := "kitchen"; + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + +%mathpiper + + +currentRoom := diningRoom; + +While( True ) +[ + + userInput := AskUser(currentRoom["description"] : Nl(): "Which direction (n,s,e,w,ne,se,sw,nw,q to quit)?"); + + + If(userInput = "q", Break()); + + + If(currentRoom[userInput] != Empty, currentRoom := roomsList[currentRoom[userInput]], TellUser("There is no exit in that direction.")); + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper,title="" + +ForEach(direction, {"n","s","e","w","ne","se","sw","nw"}) +[ + + Echo(kitchen[direction]); +]; + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + dining room + Empty + Empty + Empty + Empty + Empty + Empty + Empty +. %/output + + diff -Nru mathpiper-0.0.svn2556/examples/dungeon.mpw mathpiper-0.81f+dfsg1/examples/dungeon.mpw --- mathpiper-0.0.svn2556/examples/dungeon.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/examples/dungeon.mpw 2009-12-30 01:00:45.000000000 +0000 @@ -0,0 +1,77 @@ +%mathpiper,title="" + + + + + +//Kitchen. +kitchen := {}; +kitchen["name"] := "kitchen"; +kitchen["description"] := +" +You are in a bright white room which has a sink on its +east wall which has cupboards above and below it. A table +with 4 chairs is in the center of the room and a refridgerator is +in its north west corner. Sitting on the table is +a piece of paper with writing on it. + +There is an exit to the north. + +"; + + +//Dining room. +diningRoom := {}; +diningRoom["name"] := "dining room"; +diningRoom["description"] := +" +You are in a large rectangular room with a high ceiling. +There is an oak table in the center of the room with 12 +chairs around it. There is a crystal chandelier above +the table. + +There is an exit to the south. + +"; + + + + +//Connect the rooms together. +kitchen["n"] := diningRoom; +diningRoom["s"] := kitchen; + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + +%mathpiper + + +currentRoom := diningRoom; + +While( True ) +[ + + userInput := AskUser(currentRoom["description"] : Nl(): "Which direction (n,s,e,w,ne,se,sw,nw,q to quit)?"); + + + If(userInput = "q", Break()); + + + If(currentRoom[userInput] != Empty, currentRoom := currentRoom[userInput], TellUser("There is no exit in that direction.")); + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/examples/dungeon.mrw mathpiper-0.81f+dfsg1/examples/dungeon.mrw --- mathpiper-0.0.svn2556/examples/dungeon.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/examples/dungeon.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -%mathpiper,title="" - - - - - -//Kitchen. -kitchen := {}; -kitchen["name"] := "kitchen"; -kitchen["description"] := -" -You are in a bright white room which has a sink on its -east wall which has cupboards above and below it. A table -with 4 chairs is in the center of the room and a refridgerator is -in its north west corner. Sitting on the table is -a piece of paper with writing on it. - -There is an exit to the north. - -"; - - -//Dining room. -diningRoom := {}; -diningRoom["name"] := "dining room"; -diningRoom["description"] := -" -You are in a large rectangular room with a high ceiling. -There is an oak table in the center of the room with 12 -chairs around it. There is a crystal chandelier above -the table. - -There is an exit to the south. - -"; - - - - -//Connect the rooms together. -kitchen["n"] := diningRoom; -diningRoom["s"] := kitchen; - - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - -%mathpiper - - -currentRoom := diningRoom; - -While( True ) -[ - - userInput := AskUser(currentRoom["description"] : Nl(): "Which direction (n,s,e,w,ne,se,sw,nw,q to quit)?"); - - - If(userInput = "q", Break()); - - - If(currentRoom[userInput] != Empty, currentRoom := currentRoom[userInput], TellUser("There is no exit in that direction.")); - -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/mathpiper_tests.log mathpiper-0.81f+dfsg1/mathpiper_tests.log --- mathpiper-0.0.svn2556/mathpiper_tests.log 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/mathpiper_tests.log 1970-01-01 00:00:00.000000000 +0000 @@ -1,957 +0,0 @@ - -***** Fri Jul 24 19:27:47 EDT 2009 ***** -***** Using a new interpreter instance for each test file. ***** -***** MathPiper version: .76 ***** - -=========================== -arithmetic.mpt: - -Result: True - -Side Effects: -Test suite for Test arithmetic : - -Test suite for Basic calculations : - -Test suite for Testing math stuff : ---IntegerOperations ---PowerN ---Rounding ---Bases ---Factorization -Exception: -=========================== -binaryfactors.mpt: - -Result: True - -Side Effects: - -Exception: -=========================== -calculus.mpt: - -Result: True - -Side Effects: ---UnaryFunctionInverses ---Derivatives ---Limits -Known failure: Limit(k,Infinity)((k-phi)/k)^(k+1/2)=Exp(-phi) ---Pslq -Exception: -=========================== -canprove.mpt: - -Result: True - -Side Effects: -Test suite for Propositional logic theorem prover : -Exception: -=========================== -comments.mpt: - -Result: True - -Side Effects: -Test suite for Checking comment syntax supported : -Exception: -=========================== -complex.mpt: - -Result: True - -Side Effects: -Known failure: (Limit(n,Infinity)(n^2*I^n)/(n^3+1))=0 -Exception: -=========================== -c_tex_form.mpt: - -Result: True - -Side Effects: -Test suite for TeXForm()... : ---IsCFormable -Exception: -=========================== -cyclotomic.mpt: - -Result: True - -Side Effects: -Test suite for Cyclotomic Polynomials : -Exception: -=========================== -deriv.mpt: - -Result: True - -Side Effects: - -Exception: -=========================== -dimensions.mpt: - -Result: True - -Side Effects: ----- Dimensions (Tensor Rank) -Exception: -=========================== -dot.mpt: - -Result: True - -Side Effects: ----- Dot -Exception: -=========================== -GaussianIntegers.mpt: - -Result: True - -Side Effects: -Test suite for Gaussian Integers : -Exception: -=========================== -includetestfiles: is not a MathPiper test file. - -=========================== -integrate.mpt: - -Result: True - -Side Effects: -****************** -tests/scripts/integrate.mpt: 28 - -Integrate(x)Sin(x)/(2*y+4) - evaluates to -(-Cos(x))/(2*y+4) - which differs from -(-Cos(x))/(2*(y+2)) -****************** -Exception: -=========================== -io.mpt: - -Result: True - -Side Effects: ---Error reporting -Exception: -=========================== -journal.mpt: - -Result: True - -Side Effects: - -Exception: -=========================== -linalg.mpt: - -Result: True - -Side Effects: ---LeviCivita ---VectorProducts - -Test suite for Inproduct : - -Test suite for Identity matrices : - -Test suite for Check linear algebra : ---Normalize ---DiagonalMatrix ---ZeroMatrix ---Transpose ---Determinant ---CoFactor ---Minor ---Inverse ---SolveMatrix ---Trace -Exception: -=========================== -lists.mpt: - -Result: True - -Side Effects: -Test suite for VarList : ---BubbleSort ---HeapSort ---ListOperations ---Length ---Nth ---Concat ---Binary searching ---AssocDelete ----- Arithmetic Operations -Exception: -=========================== -logic_simplify_test.mpt: - -Result: True - -Side Effects: -Test suite for CNF : -Exception: -=========================== -macro.mpt: - -Result: True - -Side Effects: - -Exception: -=========================== -mathpiper_tests.log: is not a MathPiper test file. - -=========================== -matrixpower.mpt: - -Result: True - -Side Effects: ----- MatrixPower -Exception: -=========================== -multivar.mpt: - -Result: True - -Side Effects: -Test suite for Test arithmetic : -Exception: -=========================== -nthroot.mpt: - -Result: True - -Side Effects: ----- NthRoot -Exception: -=========================== -numbers.mpt: - -Result: True - -Side Effects: ---Integer logarithms and roots ---Factorial ---Random numbers -Exception: -=========================== -numerics.mpt: - -Result: True - -Side Effects: -****************** -tests/scripts/numerics.mpt: 9 - -RoundTo(N(Sqrt(2),5)-1.41421,5) - evaluates to --0.00001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 16 - -RoundTo(N(Pi,70)-3.1415926535897932384626433832795028841971693993751058209749445923078164062862,70) - evaluates to --4.102067615E-10 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 18 - -RoundTo(N(Sec(2),9)-(-2.402997962),9) - evaluates to -2E-9 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 20 - -RoundTo(N(Cot(2),9)-(-0.457657554),9) - evaluates to --1E-9 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 21 - -RoundTo(N(Sinh(2),10)-3.6268604078,10) - evaluates to --6E-9 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 23 - -RoundTo(N(ArcSin(2),9)-Complex(1.570796327,1.316957897),9) - evaluates to -Complex(3E-9,-7E-9) - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 24 - -RoundTo(N(ArcCos(2),9)-Complex(0,-1.316957897),9) - evaluates to -Complex(0,7E-9) - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 25 - -RoundTo(N(ArcTan(2*I),12)-N(Complex(1.57079632679,0.54930614433),12),11) - evaluates to --2.1E-10 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 26 - -RoundTo(N(ArcSinh(2),9)-1.443635475,9) - evaluates to --5E-9 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 27 - -RoundTo(N(ArcCosh(2),9)-1.316957897,9) - evaluates to --7E-9 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 29 - -RoundTo(N(ArcTanh(2),9)-Complex(0.549306144,1.570796327),9) - evaluates to -Complex(1E-9,3E-9) - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 42 - -RoundTo(RoundTo(N(Sin(2.0)),49)-0.9092974268256816953960198659117448427022549714479,49) - evaluates to -1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 47 - -RoundTo(RoundTo(N(Sin(2.0)),50)-0.90929742682568169539601986591174484270225497144789,50) - evaluates to -3E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 52 - -RoundTo(RoundTo(N(Sin(2.0)),51)-0.90929742682568169539601986591174484270225497144789,51) - evaluates to -2.1E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 62 - -RoundTo(RoundTo(N(Tan(20.0)),49)-2.2371609442247422652871732477303491783724839749188,49) - evaluates to -2E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 67 - -RoundTo(RoundTo(N(Exp(10.32),54),54)-30333.2575962246035600343483350109621778376486335450125,48) - evaluates to -1.3E-47 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 72 - -RoundTo(RoundTo(N(Ln(10.32/4.07)),49)-0.93044076059891305468974486564632598071134270468,49) - evaluates to -1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 77 - -RoundTo(RoundTo(N(1.3^10.32),48)-14.99323664825717956473936947123246987802978985306,48) - evaluates to -4E-47 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 82 - -RoundTo(RoundTo(N(Sqrt(5.3),51),51)-2.302172886644267644194841586420201850185830282633675,51) - evaluates to --2E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 106 - -RoundTo(RoundTo(N(ArcSin(0.32)),49)-0.3257294872946301593103199105324500784354180998123,49) - evaluates to -1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 111 - -RoundTo(RoundTo(N(Sin(N(ArcSin(0.1234567)))),49)-0.1234567,49) - evaluates to -1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 118 - -RoundTo(RoundTo(N((1-Sin(N(ArcSin(1-10^(-25)))))*10^25),25)-1.,25) - evaluates to --2E-25 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 123 - -RoundTo(N(ArcSin(N(Sin(1.234567),50)),50)-N(1.234567,50),49) - evaluates to -1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 128 - -RoundTo(RoundTo(N(ArcCos(0.32)),49)-1.2450668395002664599210017811073013636631665998753,49) - evaluates to --3E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 133 - -RoundTo(RoundTo(N(ArcTan(0.32)),49)-0.3097029445424561999173808103924156700884366304804,49) - evaluates to -1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 138 - -RoundTo(RoundTo(N(Cos(N(ArcCos(0.1234567)))),49)-0.1234567,49) - evaluates to -1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 187 - -RoundTo(RoundTo(N(Internal'GammaNum(10.5)),13)-1133278.3889487855673,13) - evaluates to -2.144327E-7 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 192 - -RoundTo(RoundTo(N(Gamma(10.5)),13)-1133278.3889487855673,13) - evaluates to -2.144327E-7 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 219 - -RoundTo(RoundTo(N(Zeta(40)),19)-1.0000000000009094948,19) - evaluates to -2E-19 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 224 - -RoundTo(RoundTo(N(Zeta(1.5)),19)-2.6123753486854883433,19) - evaluates to --3E-19 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 283 - -RoundTo(N(BesselJ(0,.5))-RoundTo(.93846980724081290422840467359971262556892679709682,50),50) - evaluates to --1E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 284 - -RoundTo(N(BesselJ(0,.9))-RoundTo(.80752379812254477730240904228745534863542363027564,50),50) - evaluates to --1E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 285 - -RoundTo(N(BesselJ(0,.99999))-RoundTo(.76520208704756659155313775543958045290339472808482,50),50) - evaluates to --1E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 291 - -RoundTo(N(BesselJ(11,11))-RoundTo(.20101400990926940339478738551009382430831534125484,50),50) - evaluates to --1E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 293 - -RoundTo(RoundTo(N(BesselJ(1,10)),50)-RoundTo(.04347274616886143666974876802585928830627286711859,50),50) - evaluates to -1.1E-49 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 294 - -RoundTo(N(BesselJ(10,10))-RoundTo(.20748610663335885769727872351875342803274461128682,50),50) - evaluates to --1E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 295 - -RoundTo(RoundTo(N(BesselJ(1,3.6)),50)-RoundTo(.09546554717787640384570674422606098601943275490885,50),50) - evaluates to -1E-50 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 300 - -RoundTo(N(Erf(Sqrt(0.8)),20),19) - evaluates to -0.7940967892679316913 - which differs from -0.7940967892679316912 -****************** -****************** -tests/scripts/numerics.mpt: 303 - -RoundTo(N(Erf(50*I+20)/10^910,22),19) - evaluates to -Complex(1.093171190029095858,0.0047546330693181896) - which differs from -Complex(1.093171190029095854,0.0047546330693181896) -****************** ---Gamma constant -****************** -tests/scripts/numerics.mpt: 308 - -RoundTo(Internal'gamma()+0-0.5772156649015328606065120900824024310422,BuiltinPrecisionGet()) - evaluates to -1E-40 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 311 - -RoundTo(RoundTo(Internal'gamma()+0,19)-0.5772156649015328606,19) - evaluates to -1E-19 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 312 - -RoundTo(RoundTo(N(1/2+gamma+Pi),19)-4.2188083184913260991,19) - evaluates to --1E-19 - which differs from -0 -****************** -Exception: -=========================== -nummethods.mpt: - -Result: True - -Side Effects: - -Exception: -=========================== -ode.mpt: - -Result: True - -Side Effects: - -Exception: -=========================== -openmath.mpt: - -Result: True - -Side Effects: -Test suite for Converting to and from OpenMath expressions : -Exception: -=========================== -orthopoly.mpt: - -Result: True - -Side Effects: -Test suite for Testing orthogonal polynomials : -Exception: -=========================== -outer.mpt: - -Result: True - -Side Effects: ----- Outer -Exception: -=========================== -piper_test.bat: is not a MathPiper test file. - -=========================== -plots.mpt: - -Result: False - -Side Effects: -****************** -tests/scripts/plots.mpt: 6 - -ToString()Write(Plot2D(a,-1:1,output=data,points=4,depth=0)) - evaluates to -"{{{-1,-1},{-0.5,-0.5},{0.0,0.0},{0.5,0.5},{1,1}}}" - which differs from -"{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}" -****************** -****************** -tests/scripts/plots.mpt: 7 - -ToString()Write(Plot2D(b,b=-1:1,output=data,points=4)) - evaluates to -"{{{-1,-1},{-0.5,-0.5},{0.0,0.0},{0.5,0.5},{1,1}}}" - which differs from -"{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}" -****************** -****************** -tests/scripts/plots.mpt: 14 - -ToString()Write(Plot3DS(a,-1:1,-1:1,output=data,points=2)) - evaluates to -"{{{-1,-1,-1},{-1,0,-1},{-1,1,-1},{0,-1,0},{0,0,0},{0,1,0},{1,-1,1},{1,0,1},{1,1,1}}}" - which differs from -"{{{-1,-1,-1},{-1,0,-1},{-1,1.,-1},{0,-1,0},{0,0,0},{0,1.,0},{1.,-1,1.},{1.,0,1.},{1.,1.,1.}}}" -****************** -****************** -tests/scripts/plots.mpt: 14 - -ToString()Write(Plot3DS(x1,x1=-1:1,x2=-1:1,output=data,points=2)) - evaluates to -"{{{-1,-1,0.1011417762},{-1,0,0.1011417762},{-1,1,0.1011417762},{0,-1,0.1011417762},{0,0,0.1011417762},{0,1,0.1011417762},{1,-1,0.1011417762},{1,0,0.1011417762},{1,1,0.1011417762}}}" - which differs from -"{{{-1,-1,-1},{-1,0,-1},{-1,1.,-1},{0,-1,0},{0,0,0},{0,1.,0},{1.,-1,1.},{1.,0,1.},{1.,1.,1.}}}" -****************** -****************** -tests/scripts/plots.mpt: 23 - -RoundTo(RoundTo(f(3),BuiltinPrecisionGet())-0.6666666667,BuiltinPrecisionGet()) - evaluates to -1E-10 - which differs from -0 -****************** -****************** -tests/scripts/plots.mpt: 26 - -RoundTo(RoundTo(f1(3),BuiltinPrecisionGet())-0.6666666667,BuiltinPrecisionGet()) - evaluates to -1E-10 - which differs from -0 -****************** -Exception: -=========================== -poly.mpt: - -Result: True - -Side Effects: -Test suite for Polynomials : -Exception: -=========================== -predicates.mpt: - -Result: True - -Side Effects: ---Predicates ---Boolean Operations ---NumberCompares ---comparisons in exponential notation -****************** -tests/scripts/predicates.mpt: 79 - -1.0000000000000000000000000000111>1 - evaluates to -False - which differs from -True -****************** -****************** -tests/scripts/predicates.mpt: 80 - -0.999999999999999999999999999992<1 - evaluates to -False - which differs from -True -****************** ---Matrix predicates -****************** -tests/scripts/predicates.mpt: 121 - -HasFuncArith(a*b+f({b,c}),List) - evaluates to -True - which differs from -False -****************** ---IsConstant ----- IsScalar ----- IsVector ----- IsVector(IsNumber) ----- Matrix Predicates ------- IsMatrix ------- IsMatrix(IsInteger) ------- IsSquareMatrix -Exception: -=========================== -programming.mpt: - -Result: True - -Side Effects: ---Apply ---ThreadingListables ---MapSingle ---Function definitions ---LocalVariables -Exception: -=========================== -radsimp.mpt: - -Result: True - -Side Effects: -Test suite for Testing simplifying nested radicals : -Exception: -=========================== -regress.mpt: - -Result: True - -Side Effects: -Test suite for Regression on bug reports : -****************** -tests/scripts/regress.mpt: 192 - -RoundTo(RoundTo(N(ArcSin(0.0000000321232123),50),50)-0.00000003212321230000000552466124302049336784679316,50) - evaluates to -5.524661243E-24 - which differs from -0 -****************** -****************** -tests/scripts/regress.mpt: 304 - -RoundTo(N(Cos(Pi*.5))-0,BuiltinPrecisionGet()) - evaluates to --2E-10 - which differs from -0 -****************** -****************** -tests/scripts/regress.mpt: 326 - -(Integrate(x,a,b)Cos(x)^2)-((b-Sin((-2)*b)/2)/2-(a-Sin((-2)*a)/2)/2) - evaluates to -(Sin(2*b)/2+b)/2-(Sin(2*a)/2+a)/2-((b-(-Sin(2*b))/2)/2-(a-(-Sin(2*a))/2)/2) - which differs from -0 -****************** -Known failure: (Limit(x,Infinity)x^n/Ln(x))=Infinity -Known failure: (Limit(x,0,Right)x^(Ln(a)/(1+Ln(x))))=a -Known failure: Gcd(10,3.3)!=3.3AndGcd(10,3.3)!=1 -Known failure: (D(z)Conjugate(z))=Undefined -Known failure: ArcCos(Cos(beta))!=beta -Known failure: (Limit(n,Infinity)n^5/2^n)=0 -Known failure: RoundTo(RoundTo(N(Cot(2),9),9),N(Cot(2),9),9)=0 -Exception: -=========================== -scopestack.mpt: - -Result: True - -Side Effects: - -Exception: -=========================== -simplify.mpt: - -Result: True - -Side Effects: -Test suite for Simplify : -****************** -tests/scripts/simplify.mpt: 10 -Simplify((xx+II)^4) evaluates to -xx^4+4*xx^3*II+6*xx^2*II^2+4*xx*II^3+II^4 - which differs from -xx^4+4*xx^3*II-6*xx^2-4*xx*II+1 - by -6*xx^2*II^2+6*xx^2+4*xx*II^3+4*xx*II+II^4-1 -****************** -Exception: -=========================== -solve.mpt: - -Result: True - -Side Effects: ---Solve ---PSolve -Exception:In function "If" : -bad argument number 1(counting from 1) : - -The offending argument NotApply(compare,{left,right}) evaluated to NotComplex(2.00000000000000000000000000001,1.2E-29) - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff -Nru mathpiper-0.0.svn2556/nbproject/build-impl.xml mathpiper-0.81f+dfsg1/nbproject/build-impl.xml --- mathpiper-0.0.svn2556/nbproject/build-impl.xml 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/nbproject/build-impl.xml 2010-12-20 19:47:24.000000000 +0000 @@ -55,19 +55,68 @@ - + + - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -75,8 +124,8 @@ - + @@ -103,6 +152,7 @@ + @@ -118,20 +168,21 @@ - - - - - - + + + + + + + - Must set src.tests.dir Must set src.src.dir + Must set src.tests.dir Must set build.dir Must set dist.dir Must set build.classes.dir @@ -150,11 +201,53 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + @@ -164,7 +257,7 @@ - + @@ -173,13 +266,16 @@ - + + + + - + @@ -194,15 +290,18 @@ Must set javac.includes - + + + - + + @@ -212,7 +311,7 @@ - + @@ -223,6 +322,7 @@ + @@ -279,10 +379,11 @@ + - - + + @@ -303,8 +404,9 @@ - - + + + @@ -318,20 +420,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + @@ -352,13 +520,19 @@ - + - + - + + + + + + + @@ -373,7 +547,7 @@ Must select some files in the IDE or set javac.includes - + @@ -393,13 +567,13 @@ - + - + - + @@ -414,54 +588,35 @@ java -cp "${run.classpath.with.dist.jar}" ${main.class} - - - - - - - - - - - - - - - - - + + + + + + - - - + + + To run this application from the command line without Ant, try: java -jar "${dist.jar.resolved}" - - - - - - - - - - - - - - - - - + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" - + - + - + - + + + + + + + + + + + + @@ -568,7 +734,7 @@ - + @@ -583,7 +749,7 @@ Must select some files in the IDE or set javac.includes - + @@ -618,7 +784,7 @@ Some tests failed; see details above. - + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + diff -Nru mathpiper-0.0.svn2556/nbproject/genfiles.properties mathpiper-0.81f+dfsg1/nbproject/genfiles.properties --- mathpiper-0.0.svn2556/nbproject/genfiles.properties 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/nbproject/genfiles.properties 2010-12-20 19:47:24.000000000 +0000 @@ -1,8 +1,8 @@ -nbbuild.xml.data.CRC32=f549e609 +nbbuild.xml.data.CRC32=3ff7be42 nbbuild.xml.script.CRC32=b1b8aa36 -nbbuild.xml.stylesheet.CRC32=958a1d3e@1.26.1.45 +nbbuild.xml.stylesheet.CRC32=958a1d3e@1.26.2.45 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=e01480a8 -nbproject/build-impl.xml.script.CRC32=7566b675 -nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.1.45 +nbproject/build-impl.xml.data.CRC32=3ff7be42 +nbproject/build-impl.xml.script.CRC32=bf50b382 +nbproject/build-impl.xml.stylesheet.CRC32=229523de@1.38.3.45 diff -Nru mathpiper-0.0.svn2556/nbproject/project.properties mathpiper-0.81f+dfsg1/nbproject/project.properties --- mathpiper-0.0.svn2556/nbproject/project.properties 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/nbproject/project.properties 2011-02-05 04:04:44.000000000 +0000 @@ -1,3 +1,6 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.run.all.processors=true application.title=mathpiper application.vendor=tkosan build.classes.dir=${build.dir}/classes @@ -21,19 +24,39 @@ dist.dir=dist dist.jar=${dist.dir}/mathpiper.jar dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= excludes= +file.reference.geogebra.jar=/home/tkosan/NetBeansProjects/lib/geogebra.jar +file.reference.geogebra_cas.jar=/home/tkosan/NetBeansProjects/lib/geogebra_cas.jar +file.reference.geogebra_export.jar=/home/tkosan/NetBeansProjects/lib/geogebra_export.jar +file.reference.geogebra_gui.jar=/home/tkosan/NetBeansProjects/lib/geogebra_gui.jar +file.reference.geogebra_javascript.jar=/home/tkosan/NetBeansProjects/lib/geogebra_javascript.jar +file.reference.geogebra_main.jar=/home/tkosan/NetBeansProjects/lib/geogebra_main.jar +file.reference.geogebra_properties.jar=/home/tkosan/NetBeansProjects/lib/geogebra_properties.jar +file.reference.jas.jar=/home/tkosan/NetBeansProjects/lib/jas.jar file.reference.jcommon-1.0.16.jar=/home/tkosan/NetBeansProjects/lib/jcommon-1.0.16.jar +file.reference.jdom.jar=/home/tkosan/NetBeansProjects/lib/jdom.jar file.reference.jfreechart-1.0.13.jar=/home/tkosan/NetBeansProjects/lib/jfreechart-1.0.13.jar file.reference.NetBeansProjects-mathpiper=. includes=** jar.compress=false javac.classpath=\ ${file.reference.jcommon-1.0.16.jar}:\ + ${file.reference.jdom.jar}:\ ${file.reference.jfreechart-1.0.13.jar}:\ - ${file.reference.NetBeansProjects-mathpiper} + ${file.reference.geogebra.jar}:\ + ${file.reference.geogebra_cas.jar}:\ + ${file.reference.geogebra_export.jar}:\ + ${file.reference.geogebra_gui.jar}:\ + ${file.reference.geogebra_javascript.jar}:\ + ${file.reference.geogebra_main.jar}:\ + ${file.reference.geogebra_properties.jar}:\ + ${file.reference.jas.jar} # Space-separated list of extra javac options -javac.compilerargs= +javac.compilerargs=-g javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} javac.source=1.5 javac.target=1.5 javac.test.classpath=\ @@ -58,7 +81,11 @@ platform.active=default_platform run.classpath=\ ${javac.classpath}:\ - ${build.classes.dir} + ${build.classes.dir}:\ + ${file.reference.jcommon-1.0.16.jar}:\ + ${file.reference.jdom.jar}:\ + ${file.reference.jfreechart-1.0.13.jar}:\ + ${file.reference.NetBeansProjects-mathpiper} # Space-separated list of JVM arguments used when running the project # (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value # or test-sys-prop.name=value to set system properties for unit tests): diff -Nru mathpiper-0.0.svn2556/nbproject/project.xml mathpiper-0.81f+dfsg1/nbproject/project.xml --- mathpiper-0.0.svn2556/nbproject/project.xml 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/nbproject/project.xml 2010-03-21 02:46:47.000000000 +0000 @@ -5,8 +5,8 @@ mathpiper - + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/Array.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/Array.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/Array.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/Array.java 2010-07-13 19:57:09.000000000 +0000 @@ -18,6 +18,7 @@ package org.mathpiper.builtin; +import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.cons.Cons; import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.cons.ConsPointerArray; @@ -27,18 +28,9 @@ { ConsPointerArray iArray; - public Array(int aSize,Cons aInitialItem) + public Array(Environment aEnvironment, int aSize,Cons aInitialItem) { - iArray = new ConsPointerArray(aSize,aInitialItem); - } - public String send(ArgumentList aArgList) - { - return null; - } - - public JavaObject execute(String methodName, Object[] arguemnts) throws Exception - { - return null; + iArray = new ConsPointerArray(aEnvironment, aSize,aInitialItem); } public String typeName() @@ -50,20 +42,20 @@ { return iArray.size(); } - public Cons getElement(int aItem) throws Exception + public Cons getElement(int aItem, int aStackTop, Environment aEnvironment) throws Exception { - LispError.lispAssert(aItem>0 && aItem<=iArray.size()); + LispError.lispAssert(aItem>0 && aItem<=iArray.size(), aEnvironment, aStackTop); return iArray.getElement(aItem-1).getCons(); } - public void setElement(int aItem,Cons aObject) throws Exception + public void setElement(int aItem,Cons aObject, int aStackTop, Environment aEnvironment) throws Exception { - LispError.lispAssert(aItem>0 && aItem<=iArray.size()); + LispError.lispAssert(aItem>0 && aItem<=iArray.size(), aEnvironment, aStackTop); iArray.setElement(aItem-1,aObject); } public Object getObject() { - return null; + return this; } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BigNumber.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BigNumber.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BigNumber.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BigNumber.java 2010-03-12 04:56:36.000000000 +0000 @@ -20,6 +20,12 @@ import org.mathpiper.io.MathPiperOutputStream; import org.mathpiper.lisp.LispError; import java.math.*; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.NumberCons; +import org.mathpiper.lisp.cons.SublistCons; /** * @@ -36,6 +42,7 @@ private static BigDecimal two = new BigDecimal("2"); private static BigDecimal ten = new BigDecimal("10"); + public static boolean numericSupportForMantissa() { return true; } @@ -49,7 +56,9 @@ * @param aBasePrecision * @param aBase */ - public BigNumber(String aString, int aBasePrecision, int aBase/*=10*/) { + public BigNumber( String aString, int aBasePrecision, int aBase/*=10*/) { + + setTo(aString, aBasePrecision, aBase); } @@ -261,6 +270,21 @@ } } + + /** + * Return a representation of this BigNumber as a Java int. + * @return + */ + public int toInt() { + if (javaBigInteger != null) { + return javaBigInteger.intValue(); + } else { + return javaBigDecimal.intValue(); + } + } + + + /** * Determines if the specified BigNumber is equal in value to this one. * @@ -491,9 +515,9 @@ * @param aZ * @throws java.lang.Exception */ - public void mod(BigNumber aY, BigNumber aZ) throws Exception { - LispError.check(aY.javaBigInteger != null, LispError.NOT_AN_INTEGER); - LispError.check(aZ.javaBigInteger != null, LispError.NOT_AN_INTEGER); + public void mod(Environment aEnvironment,int aStackTop, BigNumber aY, BigNumber aZ) throws Exception { + LispError.check(aEnvironment, aStackTop, aY.javaBigInteger != null, LispError.NOT_AN_INTEGER, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, aZ.javaBigInteger != null, LispError.NOT_AN_INTEGER, "INTERNAL"); //TODO fixme LispError.check(!IsZero(aZ),LispError.INVALID_ARGUMENT); javaBigInteger = aY.javaBigInteger.mod(aZ.javaBigInteger); javaBigDecimal = null; @@ -505,13 +529,155 @@ * @param aOutput * @throws java.lang.Exception */ - public void dumpNumber(MathPiperOutputStream aOutput) throws Exception { + public void dumpNumber(Environment aEnvironment, int aStackTop, MathPiperOutputStream aOutput) throws Exception { if (javaBigInteger != null) { aOutput.write("BigInteger: " + javaBigInteger.toString() + "\n"); } else { aOutput.write("BigDecimal: " + javaBigDecimal.toPlainString() + " Precision: " + javaBigDecimal.precision() + " Unscaled Value: " + javaBigDecimal.unscaledValue() + " Scale: " + javaBigDecimal.scale() + ".\n"); } - } + + }//end method. + + + public Cons dumpNumber(Environment aEnvironment, int aStackTop) throws Exception + { + Cons resultSublistCons = null; + + + if(javaBigInteger != null) + { + //Create type association list. + Cons typeListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons typeAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"type\""); + + Cons typeValueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"BigInteger\""); + + typeListAtomCons.cdr().setCons(typeAtomCons); + + typeAtomCons.cdr().setCons(typeValueAtomCons); + + Cons typeSublistCons = SublistCons.getInstance(aEnvironment, typeListAtomCons); + + + //Create value association list. + Cons valueListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons valueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"value\""); + + Cons valueValueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, javaBigInteger.toString()); + + valueListAtomCons.cdr().setCons(valueAtomCons); + + valueAtomCons.cdr().setCons(valueValueAtomCons); + + Cons valueSublistCons = SublistCons.getInstance(aEnvironment, valueListAtomCons); + + + //Create result list. + typeSublistCons.cdr().setCons(valueSublistCons); + + Cons resultListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + resultListAtomCons.cdr().setCons(typeSublistCons); + + resultSublistCons = SublistCons.getInstance(aEnvironment, resultListAtomCons); + } + else + { + //Create type association list. + Cons typeListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons typeAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"type\""); + + Cons typeValueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"BigDecimal\""); + + typeListAtomCons.cdr().setCons(typeAtomCons); + + typeAtomCons.cdr().setCons(typeValueAtomCons); + + Cons typeSublistCons = SublistCons.getInstance(aEnvironment, typeListAtomCons); + + + //Create value association list. + Cons valueListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons valueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"value\""); + + Cons valueValueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, javaBigDecimal.toPlainString()); + + valueListAtomCons.cdr().setCons(valueAtomCons); + + valueAtomCons.cdr().setCons(valueValueAtomCons); + + Cons valueSublistCons = SublistCons.getInstance(aEnvironment, valueListAtomCons); + + + //Create precision association list. + Cons precisionListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons precisionAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"precision\""); + + Cons precisionValueAtomCons = new NumberCons(new BigNumber("" + javaBigDecimal.precision(), this.iPrecision, 10)); + + precisionListAtomCons.cdr().setCons(precisionAtomCons); + + precisionAtomCons.cdr().setCons(precisionValueAtomCons); + + Cons precisionSublistCons = SublistCons.getInstance(aEnvironment, precisionListAtomCons); + + + //Create unscaled value association list. + Cons unscaledValueListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons unscaledValueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"unscaledValue\""); + + Cons unscaledValueValueAtomCons = new NumberCons(new BigNumber("" + javaBigDecimal.unscaledValue(), this.iPrecision, 10)); + + unscaledValueListAtomCons.cdr().setCons(unscaledValueAtomCons); + + unscaledValueAtomCons.cdr().setCons(unscaledValueValueAtomCons); + + Cons unscaledValueSublistCons = SublistCons.getInstance(aEnvironment, unscaledValueListAtomCons); + + + //Create scale association list. + Cons scaleListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons scaleAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"scale\""); + + Cons scaleValueAtomCons = new NumberCons(new BigNumber("" + javaBigDecimal.scale(), this.iPrecision, 10)); + + scaleListAtomCons.cdr().setCons(scaleAtomCons); + + scaleAtomCons.cdr().setCons(scaleValueAtomCons); + + Cons scaleSublistCons = SublistCons.getInstance(aEnvironment, scaleListAtomCons); + + + //Create result list. + typeSublistCons.cdr().setCons(valueSublistCons); + + valueSublistCons.cdr().setCons(precisionSublistCons); + + precisionSublistCons.cdr().setCons(unscaledValueSublistCons); + + unscaledValueSublistCons.cdr().setCons(scaleSublistCons); + + Cons resultListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + resultListAtomCons.cdr().setCons(typeSublistCons); + + resultSublistCons = SublistCons.getInstance(aEnvironment, resultListAtomCons); + + }//end else. + + + + + return resultSublistCons; + + }//end method. @@ -596,8 +762,8 @@ * @param aNrToShift * @throws java.lang.Exception */ - public void shiftLeft(BigNumber aX, int aNrToShift) throws Exception { - LispError.lispAssert(aX.javaBigInteger != null); + public void shiftLeft(BigNumber aX, int aNrToShift, Environment aEnvironment, int aStackTop) throws Exception { + LispError.lispAssert(aX.javaBigInteger != null, aEnvironment, aStackTop); javaBigDecimal = null; javaBigInteger = aX.javaBigInteger.shiftLeft(aNrToShift); } @@ -608,8 +774,8 @@ * @param aNrToShift * @throws java.lang.Exception */ - public void shiftRight(BigNumber aX, int aNrToShift) throws Exception { - LispError.lispAssert(aX.javaBigInteger != null); + public void shiftRight(BigNumber aX, int aNrToShift, Environment aEnvironment, int aStackTop) throws Exception { + LispError.lispAssert(aX.javaBigInteger != null, aEnvironment, aStackTop); javaBigDecimal = null; javaBigInteger = aX.javaBigInteger.shiftRight(aNrToShift); } @@ -621,9 +787,9 @@ * @param aY * @throws java.lang.Exception */ - public void gcd(BigNumber aX, BigNumber aY) throws Exception { - LispError.lispAssert(aX.javaBigInteger != null); - LispError.lispAssert(aY.javaBigInteger != null); + public void gcd(BigNumber aX, BigNumber aY, Environment aEnvironment, int aStackTop) throws Exception { + LispError.lispAssert(aX.javaBigInteger != null, aEnvironment, aStackTop); + LispError.lispAssert(aY.javaBigInteger != null, aEnvironment, aStackTop); javaBigInteger = aX.javaBigInteger.gcd(aY.javaBigInteger); javaBigDecimal = null; } @@ -635,9 +801,9 @@ * @param aY * @throws java.lang.Exception */ - public void bitAnd(BigNumber aX, BigNumber aY) throws Exception { - LispError.lispAssert(aX.javaBigInteger != null); - LispError.lispAssert(aY.javaBigInteger != null); + public void bitAnd(BigNumber aX, BigNumber aY, Environment aEnvironment, int aStackTop) throws Exception { + LispError.lispAssert(aX.javaBigInteger != null, aEnvironment, aStackTop); + LispError.lispAssert(aY.javaBigInteger != null, aEnvironment, aStackTop); javaBigInteger = aX.javaBigInteger.and(aY.javaBigInteger); javaBigDecimal = null; } @@ -648,9 +814,9 @@ * @param aY * @throws java.lang.Exception */ - public void bitOr(BigNumber aX, BigNumber aY) throws Exception { - LispError.lispAssert(aX.javaBigInteger != null); - LispError.lispAssert(aY.javaBigInteger != null); + public void bitOr(BigNumber aX, BigNumber aY, Environment aEnvironment, int aStackTop) throws Exception { + LispError.lispAssert(aX.javaBigInteger != null, aEnvironment, aStackTop); + LispError.lispAssert(aY.javaBigInteger != null, aEnvironment, aStackTop); javaBigInteger = aX.javaBigInteger.or(aY.javaBigInteger); javaBigDecimal = null; } @@ -662,9 +828,9 @@ * @param aY * @throws java.lang.Exception */ - public void bitXor(BigNumber aX, BigNumber aY) throws Exception { - LispError.lispAssert(aX.javaBigInteger != null); - LispError.lispAssert(aY.javaBigInteger != null); + public void bitXor(BigNumber aX, BigNumber aY, Environment aEnvironment, int aStackTop) throws Exception { + LispError.lispAssert(aX.javaBigInteger != null, aEnvironment, aStackTop); + LispError.lispAssert(aY.javaBigInteger != null, aEnvironment, aStackTop); javaBigInteger = aX.javaBigInteger.xor(aY.javaBigInteger); javaBigDecimal = null; } @@ -675,8 +841,8 @@ * @param aX * @throws java.lang.Exception */ - void bitNot(BigNumber aX) throws Exception { - LispError.lispAssert(aX.javaBigInteger != null); + void bitNot(BigNumber aX, Environment aEnvironment, int aStackTop) throws Exception { + LispError.lispAssert(aX.javaBigInteger != null, aEnvironment, aStackTop); javaBigInteger = aX.javaBigInteger.not(); javaBigDecimal = null; } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BuiltinContainer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BuiltinContainer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BuiltinContainer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BuiltinContainer.java 2010-04-09 07:43:02.000000000 +0000 @@ -26,12 +26,10 @@ public BuiltinContainer() { } - public abstract String send(ArgumentList aArgList); - public abstract String typeName(); public abstract Object getObject(); - public abstract JavaObject execute(String methodName, Object[] arguments) throws Exception; + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BuiltinFunctionEvaluator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BuiltinFunctionEvaluator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BuiltinFunctionEvaluator.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BuiltinFunctionEvaluator.java 2010-07-14 19:55:04.000000000 +0000 @@ -13,7 +13,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.builtin; @@ -45,12 +44,12 @@ iFlags = aFlags; } - public void evaluate(Environment aEnvironment, ConsPointer aResultPointer, ConsPointer aArgumentsPointer) throws Exception { + public void evaluate(Environment aEnvironment, int aStackTop, ConsPointer aResultPointer, ConsPointer aArgumentsPointer) throws Exception { ConsPointer[] argumentsResultPointerArray = null; /*Trace code*/ if (isTraced()) { ConsPointer argumentsPointer = new ConsPointer(); - argumentsPointer.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); + argumentsPointer.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); String functionName = ""; if (argumentsPointer.car() instanceof ConsPointer) { @@ -71,7 +70,7 @@ if (iNumberOfArguments == 0) { argumentsResultPointerArray = null; } else { - LispError.lispAssert(iNumberOfArguments > 0); + LispError.lispAssert(iNumberOfArguments > 0, aEnvironment, aStackTop); argumentsResultPointerArray = new ConsPointer[iNumberOfArguments]; }//end if. }//end if. @@ -82,18 +81,30 @@ //1 is being added to the number of arguments to take into account // the function name that is at the beginning of the argument list. - LispError.checkNumberOfArguments(iNumberOfArguments + 1, aArgumentsPointer, aEnvironment); + ConsPointer argumentsPointer = new ConsPointer(); + + argumentsPointer.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + + String functionName = ""; + + if (argumentsPointer.car() instanceof ConsPointer) { + ConsPointer sub = (ConsPointer) argumentsPointer.car(); + if (sub.car() instanceof String) { + functionName = (String) sub.car(); + } + }//end function. + LispError.checkNumberOfArguments(aStackTop, iNumberOfArguments + 1, aArgumentsPointer, aEnvironment, functionName); } int stackTop = aEnvironment.iArgumentStack.getStackTopIndex(); - // Push a place holder for the result: push full expression so it is available for error reporting - aEnvironment.iArgumentStack.pushArgumentOnStack(aArgumentsPointer.getCons()); + // Push a place holder for the result and initialize it to the function name for error reporting purposes. + aEnvironment.iArgumentStack.pushArgumentOnStack(aArgumentsPointer.getCons(), aStackTop, aEnvironment); - ConsPointer argumentsConsTraverser = new ConsPointer(aArgumentsPointer.getCons()); + ConsPointer argumentsConsTraverser = new ConsPointer( aArgumentsPointer.getCons()); //Strip the function name from the head of the list. - argumentsConsTraverser.goNext(); + argumentsConsTraverser.goNext(aStackTop, aEnvironment); int i; int numberOfArguments = iNumberOfArguments; @@ -104,43 +115,44 @@ ConsPointer argumentResultPointer = new ConsPointer(); - // Walk over all arguments, evaluating them as necessary ***************************************************** + // Walk over all arguments, evaluating them only if this is a function. ***************************************************** + if ((iFlags & Macro) != 0) {//This is a macro, not a function. for (i = 0; i < numberOfArguments; i++) { //Push all arguments on the stack. - LispError.check(argumentsConsTraverser.getCons() != null, LispError.WRONG_NUMBER_OF_ARGUMENTS); + LispError.check(aEnvironment, aStackTop, argumentsConsTraverser.getCons() != null, LispError.WRONG_NUMBER_OF_ARGUMENTS, "INTERNAL"); - if (isTraced() && argumentsResultPointerArray != null && showFlag) { + if (isTraced() && argumentsResultPointerArray != null && showFlag) { argumentsResultPointerArray[i] = new ConsPointer(); - argumentsResultPointerArray[i].setCons(argumentsConsTraverser.getCons().copy( aEnvironment, false)); + argumentsResultPointerArray[i].setCons(argumentsConsTraverser.getCons().copy(aEnvironment, false)); } - aEnvironment.iArgumentStack.pushArgumentOnStack(argumentsConsTraverser.getCons().copy( aEnvironment, false)); - argumentsConsTraverser.goNext(); + aEnvironment.iArgumentStack.pushArgumentOnStack(argumentsConsTraverser.getCons().copy(aEnvironment, false), aStackTop, aEnvironment); + argumentsConsTraverser.goNext(aStackTop, aEnvironment); } if ((iFlags & Variable) != 0) {//This macro has a variable number of arguments. ConsPointer head = new ConsPointer(); - head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); + head.setCons(aEnvironment.iListAtom.copy(aEnvironment, false)); head.cdr().setCons(argumentsConsTraverser.getCons()); - aEnvironment.iArgumentStack.pushArgumentOnStack(SublistCons.getInstance(aEnvironment,head.getCons())); + aEnvironment.iArgumentStack.pushArgumentOnStack(SublistCons.getInstance(aEnvironment, head.getCons()), aStackTop, aEnvironment); }//end if. } else {//This is a function, not a macro. for (i = 0; i < numberOfArguments; i++) { - LispError.check(argumentsConsTraverser.getCons() != null, LispError.WRONG_NUMBER_OF_ARGUMENTS); - LispError.check(argumentsConsTraverser != null, LispError.WRONG_NUMBER_OF_ARGUMENTS); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, argumentResultPointer, argumentsConsTraverser); + LispError.check(aEnvironment, aStackTop, argumentsConsTraverser.getCons() != null, LispError.WRONG_NUMBER_OF_ARGUMENTS, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, argumentsConsTraverser != null, LispError.WRONG_NUMBER_OF_ARGUMENTS, "INTERNAL"); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, argumentResultPointer, argumentsConsTraverser); - if (isTraced() && argumentsResultPointerArray != null && showFlag) { + if (isTraced() && argumentsResultPointerArray != null && showFlag) { argumentsResultPointerArray[i] = new ConsPointer(); - argumentsResultPointerArray[i].setCons(argumentResultPointer.getCons().copy( aEnvironment, false)); + argumentsResultPointerArray[i].setCons(argumentResultPointer.getCons().copy(aEnvironment, false)); } - aEnvironment.iArgumentStack.pushArgumentOnStack(argumentResultPointer.getCons()); - argumentsConsTraverser.goNext(); + aEnvironment.iArgumentStack.pushArgumentOnStack(argumentResultPointer.getCons(), aStackTop, aEnvironment); + argumentsConsTraverser.goNext(aStackTop, aEnvironment); }//end for. if ((iFlags & Variable) != 0) {//This function has a variable number of arguments. @@ -150,10 +162,10 @@ //printf("Enter\n"); ConsPointer head = new ConsPointer(); - head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); + head.setCons(aEnvironment.iListAtom.copy(aEnvironment, false)); head.cdr().setCons(argumentsConsTraverser.getCons()); ConsPointer listPointer = new ConsPointer(); - listPointer.setCons(SublistCons.getInstance(aEnvironment,head.getCons())); + listPointer.setCons(SublistCons.getInstance(aEnvironment, head.getCons())); /* @@ -161,15 +173,15 @@ printf("before %s\n",res.String()); */ - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, argumentResultPointer, listPointer); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, argumentResultPointer, listPointer); /* PrintExpression(res, arg,aEnvironment,100); printf("after %s\n",res.String()); */ - aEnvironment.iArgumentStack.pushArgumentOnStack(argumentResultPointer.getCons()); - //printf("Leave\n"); + aEnvironment.iArgumentStack.pushArgumentOnStack(argumentResultPointer.getCons(), aStackTop, aEnvironment); + //printf("Leave\n"); /*Trace code */ }//end if. @@ -179,16 +191,16 @@ /*Trace code */ if (isTraced() && argumentsResultPointerArray != null && showFlag == true) { - ConsPointer traceArgumentPointer = new ConsPointer(aArgumentsPointer.getCons()); + ConsPointer traceArgumentPointer = new ConsPointer( aArgumentsPointer.getCons()); - traceArgumentPointer.goNext(); + traceArgumentPointer.goNext(aStackTop, aEnvironment); int parameterIndex = 1; if ((iFlags & Variable) != 0) {//This function has a variable number of arguments. while (traceArgumentPointer.getCons() != null) { - Evaluator.traceShowArg(aEnvironment, new ConsPointer(AtomCons.getInstance(aEnvironment, "parameter" + parameterIndex++ )), traceArgumentPointer); - traceArgumentPointer.goNext(); + Evaluator.traceShowArg(aEnvironment, new ConsPointer( AtomCons.getInstance(aEnvironment, aStackTop, "parameter" + parameterIndex++)), traceArgumentPointer); + traceArgumentPointer.goNext(aStackTop, aEnvironment); }//end while. } else { @@ -198,9 +210,9 @@ argumentsResultPointerArray[i] = new ConsPointer(AtomCons.getInstance(aEnvironment, "NULL")); }*/ - Evaluator.traceShowArg(aEnvironment, new ConsPointer(AtomCons.getInstance(aEnvironment, "parameter" + parameterIndex++ )), argumentsResultPointerArray[i]); + Evaluator.traceShowArg(aEnvironment, new ConsPointer( AtomCons.getInstance(aEnvironment, aStackTop, "parameter" + parameterIndex++)), argumentsResultPointerArray[i]); - traceArgumentPointer.goNext(); + traceArgumentPointer.goNext(aStackTop, aEnvironment); }//end for. } @@ -208,18 +220,20 @@ }//end if. - iCalledBuiltinFunction.evaluate(aEnvironment, stackTop); - aResultPointer.setCons(aEnvironment.iArgumentStack.getElement(stackTop).getCons()); + iCalledBuiltinFunction.evaluate(aEnvironment, stackTop); //********************** built in function is called here. + + + aResultPointer.setCons(aEnvironment.iArgumentStack.getElement(stackTop, aStackTop, aEnvironment).getCons()); if (isTraced() && showFlag == true) { ConsPointer argumentsPointer = new ConsPointer(); - argumentsPointer.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); - String localVariables = aEnvironment.getLocalVariables(); + argumentsPointer.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + String localVariables = aEnvironment.getLocalVariables(aStackTop); Evaluator.traceShowLeave(aEnvironment, aResultPointer, argumentsPointer, "builtin", localVariables); argumentsPointer.setCons(null); }//end if. - aEnvironment.iArgumentStack.popTo(stackTop); + aEnvironment.iArgumentStack.popTo(stackTop, aStackTop, aEnvironment); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BuiltinFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BuiltinFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/BuiltinFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/BuiltinFunction.java 2011-02-05 04:04:44.000000000 +0000 @@ -16,18 +16,21 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.builtin; -import java.io.File; -import java.io.IOException; +import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; +import java.util.HashSet; import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; + import org.mathpiper.builtin.functions.core.Abs; import org.mathpiper.builtin.functions.core.Add; -import org.mathpiper.builtin.functions.core.ApplyPure; -import org.mathpiper.builtin.functions.core.Atom; +import org.mathpiper.builtin.functions.core.And; +import org.mathpiper.builtin.functions.core.ApplyFast; +import org.mathpiper.builtin.functions.core.ArrayCreate; +import org.mathpiper.builtin.functions.core.ArrayGet; +import org.mathpiper.builtin.functions.core.ArraySet; +import org.mathpiper.builtin.functions.core.ArraySize; +import org.mathpiper.builtin.functions.core.AskUser; +import org.mathpiper.builtin.functions.core.ToAtom; import org.mathpiper.builtin.functions.core.BackQuote; import org.mathpiper.builtin.functions.core.BitAnd; import org.mathpiper.builtin.functions.core.BitCount; @@ -39,9 +42,9 @@ import org.mathpiper.builtin.functions.core.BuiltinPrecisionGet; import org.mathpiper.builtin.functions.core.BuiltinPrecisionSet; import org.mathpiper.builtin.functions.core.Ceil; -import org.mathpiper.builtin.functions.core.CharString; +import org.mathpiper.builtin.functions.core.UnicodeToString; import org.mathpiper.builtin.functions.core.Check; -import org.mathpiper.builtin.functions.core.Clear; +import org.mathpiper.builtin.functions.core.Unbind; import org.mathpiper.builtin.functions.core.CommonLispTokenizer; import org.mathpiper.builtin.functions.core.Concatenate; import org.mathpiper.builtin.functions.core.ConcatenateStrings; @@ -66,14 +69,14 @@ import org.mathpiper.builtin.functions.core.DestructiveReplace; import org.mathpiper.builtin.functions.core.DestructiveReverse; import org.mathpiper.builtin.functions.core.DigitsToBits; -import org.mathpiper.builtin.functions.core.Div; +import org.mathpiper.builtin.functions.core.Quotient; import org.mathpiper.builtin.functions.core.Divide; import org.mathpiper.builtin.functions.core.DumpNumber; -import org.mathpiper.builtin.functions.core.Equals; +import org.mathpiper.builtin.functions.core.IsEqual; import org.mathpiper.builtin.functions.core.Eval; import org.mathpiper.builtin.functions.core.Exit; import org.mathpiper.builtin.functions.core.ExitRequested; -import org.mathpiper.builtin.functions.core.XmlExplodeTag; +import org.mathpiper.builtin.functions.core.ExpressionToString; import org.mathpiper.builtin.functions.core.Factorial; import org.mathpiper.builtin.functions.core.FastArcSin; import org.mathpiper.builtin.functions.core.FastIsPrime; @@ -82,30 +85,22 @@ import org.mathpiper.builtin.functions.core.FileSize; import org.mathpiper.builtin.functions.core.FindFile; import org.mathpiper.builtin.functions.core.FindFunction; +import org.mathpiper.builtin.functions.core.First; import org.mathpiper.builtin.functions.core.FlatCopy; import org.mathpiper.builtin.functions.core.Floor; import org.mathpiper.builtin.functions.core.FromBase; -import org.mathpiper.builtin.functions.core.FromFile; -import org.mathpiper.builtin.functions.core.FromString; -import org.mathpiper.builtin.functions.core.FullForm; +import org.mathpiper.builtin.functions.core.PipeFromFile; +import org.mathpiper.builtin.functions.core.PipeFromString; +import org.mathpiper.builtin.functions.core.LispForm; import org.mathpiper.builtin.functions.core.GarbageCollect; import org.mathpiper.builtin.functions.core.Gcd; -import org.mathpiper.builtin.functions.core.ArrayCreate; -import org.mathpiper.builtin.functions.core.ArrayGet; -import org.mathpiper.builtin.functions.core.ArraySet; -import org.mathpiper.builtin.functions.core.ArraySize; -import org.mathpiper.builtin.functions.core.PatternCreate; -import org.mathpiper.builtin.functions.core.PatternMatches; import org.mathpiper.builtin.functions.core.GenericTypeName; -import org.mathpiper.builtin.functions.core.GetCoreError; +import org.mathpiper.builtin.functions.core.ExceptionGet; import org.mathpiper.builtin.functions.core.GetExactBits; -import org.mathpiper.builtin.functions.core.OpLeftPrecedence; -import org.mathpiper.builtin.functions.core.OpPrecedence; -import org.mathpiper.builtin.functions.core.OpRightPrecedence; -import org.mathpiper.builtin.functions.core.GreaterThan; -import org.mathpiper.builtin.functions.core.First; +import org.mathpiper.builtin.functions.core.IsGreaterThan; import org.mathpiper.builtin.functions.core.HistorySize; -import org.mathpiper.builtin.functions.core.HoldArg; +import org.mathpiper.builtin.functions.core.Hold; +import org.mathpiper.builtin.functions.core.HoldArgument; import org.mathpiper.builtin.functions.core.If; import org.mathpiper.builtin.functions.core.InDebugMode; import org.mathpiper.builtin.functions.core.Infix; @@ -113,6 +108,7 @@ import org.mathpiper.builtin.functions.core.IsAtom; import org.mathpiper.builtin.functions.core.IsBodied; import org.mathpiper.builtin.functions.core.IsBound; +import org.mathpiper.builtin.functions.core.IsDecimal; import org.mathpiper.builtin.functions.core.IsFunction; import org.mathpiper.builtin.functions.core.IsGeneric; import org.mathpiper.builtin.functions.core.IsInfix; @@ -123,33 +119,42 @@ import org.mathpiper.builtin.functions.core.IsPrefix; import org.mathpiper.builtin.functions.core.IsPromptShown; import org.mathpiper.builtin.functions.core.IsString; -import org.mathpiper.builtin.functions.core.And; -import org.mathpiper.builtin.functions.core.ExpressionToString; -import org.mathpiper.builtin.functions.core.Or; -import org.mathpiper.builtin.functions.core.LeftPrecedence; +import org.mathpiper.builtin.functions.core.LeftPrecedenceSet; import org.mathpiper.builtin.functions.core.Length; -import org.mathpiper.builtin.functions.core.LessThan; -import org.mathpiper.builtin.functions.core.Listify; -import org.mathpiper.builtin.functions.core.Load; +import org.mathpiper.builtin.functions.core.IsLessThan; +import org.mathpiper.builtin.functions.core.LispRead; +import org.mathpiper.builtin.functions.core.LispReadListed; +import org.mathpiper.builtin.functions.core.FunctionToList; +import org.mathpiper.builtin.functions.core.LoadScript; +import org.mathpiper.builtin.functions.core.Local; import org.mathpiper.builtin.functions.core.LocalSymbols; +import org.mathpiper.builtin.functions.core.MacroRulePattern; import org.mathpiper.builtin.functions.core.MacroRule; -import org.mathpiper.builtin.functions.core.MacroNewRulePattern; import org.mathpiper.builtin.functions.core.MacroRulebase; import org.mathpiper.builtin.functions.core.MacroRulebaseListed; -import org.mathpiper.builtin.functions.core.MacroSet; +import org.mathpiper.builtin.functions.core.MacroBind; import org.mathpiper.builtin.functions.core.MathIsSmall; import org.mathpiper.builtin.functions.core.MathNegate; import org.mathpiper.builtin.functions.core.MathSign; import org.mathpiper.builtin.functions.core.MaxEvalDepth; -import org.mathpiper.builtin.functions.core.Mod; +import org.mathpiper.builtin.functions.core.MetaEntries; +import org.mathpiper.builtin.functions.core.MetaGet; +import org.mathpiper.builtin.functions.core.MetaKeys; +import org.mathpiper.builtin.functions.core.MetaSet; +import org.mathpiper.builtin.functions.core.MetaValues; +import org.mathpiper.builtin.functions.core.Modulo; import org.mathpiper.builtin.functions.core.Multiply; -import org.mathpiper.builtin.functions.core.Local; -import org.mathpiper.builtin.functions.core.Rule; -import org.mathpiper.builtin.functions.core.NewRulePattern; +import org.mathpiper.builtin.functions.core.RulePattern; import org.mathpiper.builtin.functions.core.Not; import org.mathpiper.builtin.functions.core.Nth; +import org.mathpiper.builtin.functions.core.LeftPrecedenceGet; +import org.mathpiper.builtin.functions.core.PrecedenceGet; +import org.mathpiper.builtin.functions.core.RightPrecedenceGet; +import org.mathpiper.builtin.functions.core.Or; import org.mathpiper.builtin.functions.core.PatchLoad; import org.mathpiper.builtin.functions.core.PatchString; +import org.mathpiper.builtin.functions.core.PatternCreate; +import org.mathpiper.builtin.functions.core.PatternMatches; import org.mathpiper.builtin.functions.core.Postfix; import org.mathpiper.builtin.functions.core.Prefix; import org.mathpiper.builtin.functions.core.PrettyPrinterGet; @@ -157,793 +162,923 @@ import org.mathpiper.builtin.functions.core.PrettyReaderGet; import org.mathpiper.builtin.functions.core.PrettyReaderSet; import org.mathpiper.builtin.functions.core.Prog; -import org.mathpiper.builtin.functions.core.Hold; import org.mathpiper.builtin.functions.core.Read; -import org.mathpiper.builtin.functions.core.AskUser; -import org.mathpiper.builtin.functions.core.IsDecimal; -import org.mathpiper.builtin.functions.core.LispRead; -import org.mathpiper.builtin.functions.core.LispReadListed; -import org.mathpiper.builtin.functions.core.MetaEntries; -import org.mathpiper.builtin.functions.core.MetaGet; -import org.mathpiper.builtin.functions.core.MetaKeys; -import org.mathpiper.builtin.functions.core.MetaSet; -import org.mathpiper.builtin.functions.core.MetaValues; import org.mathpiper.builtin.functions.core.ReadToken; import org.mathpiper.builtin.functions.core.Replace; +import org.mathpiper.builtin.functions.core.Rest; import org.mathpiper.builtin.functions.core.Retract; -import org.mathpiper.builtin.functions.core.RightAssociative; -import org.mathpiper.builtin.functions.core.RightPrecedence; +import org.mathpiper.builtin.functions.core.RightAssociativeSet; +import org.mathpiper.builtin.functions.core.RightPrecedenceSet; +import org.mathpiper.builtin.functions.core.RoundToN; +import org.mathpiper.builtin.functions.core.Rule; import org.mathpiper.builtin.functions.core.Rulebase; -import org.mathpiper.builtin.functions.core.RulebaseArgList; +import org.mathpiper.builtin.functions.core.RulebaseArgumentsList; import org.mathpiper.builtin.functions.core.RulebaseDefined; import org.mathpiper.builtin.functions.core.RulebaseListed; import org.mathpiper.builtin.functions.core.Secure; +import org.mathpiper.builtin.functions.core.Bind; import org.mathpiper.builtin.functions.core.SetExactBits; import org.mathpiper.builtin.functions.core.SetGlobalLazyVariable; -import org.mathpiper.builtin.functions.core.Set; import org.mathpiper.builtin.functions.core.ShiftLeft; import org.mathpiper.builtin.functions.core.ShiftRight; import org.mathpiper.builtin.functions.core.StackSize; import org.mathpiper.builtin.functions.core.StringMidGet; import org.mathpiper.builtin.functions.core.StringMidSet; -import org.mathpiper.builtin.functions.core.Stringify; +import org.mathpiper.builtin.functions.core.ToString; import org.mathpiper.builtin.functions.core.Subst; import org.mathpiper.builtin.functions.core.Subtract; import org.mathpiper.builtin.functions.core.SystemCall; -import org.mathpiper.builtin.functions.core.Rest; import org.mathpiper.builtin.functions.core.TellUser; import org.mathpiper.builtin.functions.core.ToBase; -import org.mathpiper.builtin.functions.core.ToFile; -import org.mathpiper.builtin.functions.core.ToStdout; -import org.mathpiper.builtin.functions.core.ToString; +import org.mathpiper.builtin.functions.core.PipeToFile; +import org.mathpiper.builtin.functions.core.PipeToStdout; +import org.mathpiper.builtin.functions.core.PipeToString; import org.mathpiper.builtin.functions.core.TraceRule; import org.mathpiper.builtin.functions.core.TraceStack; -import org.mathpiper.builtin.functions.core.TrapError; +import org.mathpiper.builtin.functions.core.ExceptionCatch; import org.mathpiper.builtin.functions.core.UnFence; -import org.mathpiper.builtin.functions.core.UnList; -import org.mathpiper.builtin.functions.core.Use; +import org.mathpiper.builtin.functions.core.ListToFunction; +import org.mathpiper.builtin.functions.core.LoadScriptOnce; import org.mathpiper.builtin.functions.core.While; import org.mathpiper.builtin.functions.core.Write; import org.mathpiper.builtin.functions.core.WriteString; +import org.mathpiper.builtin.functions.core.XmlExplodeTag; import org.mathpiper.builtin.functions.core.XmlTokenizer; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.printers.MathPiperPrinter; -public abstract class BuiltinFunction { +import java.io.*; +import org.mathpiper.builtin.functions.core.Delay; +import org.mathpiper.builtin.functions.core.FastArcCos; +import org.mathpiper.builtin.functions.core.FastArcTan; +import org.mathpiper.builtin.functions.core.FastCos; +import org.mathpiper.builtin.functions.core.FastSin; +import org.mathpiper.builtin.functions.core.FastTan; +import org.mathpiper.builtin.functions.core.GlobalVariablesGet; +import org.mathpiper.builtin.functions.core.JavaAccess; +import org.mathpiper.builtin.functions.core.JavaCall; +import org.mathpiper.builtin.functions.core.JavaNew; +import org.mathpiper.builtin.functions.core.JavaToValue; +import org.mathpiper.builtin.functions.core.StringToUnicode; - public static synchronized List addOptionalFunctions(Environment aEnvironment, String functionsPath) { +public abstract class BuiltinFunction { - //System.out.println("MATHPIPER: " + System.getProperty("java.class.path")); - List failList = new ArrayList(); + public static synchronized List addOptionalFunctions(Environment aEnvironment, String functionsPath) { - for (String s : System.getProperty("java.class.path").split(System.getProperty("path.separator"))) { + List failList = new ArrayList(); - //System.out.println("MATHPIPER: " + s); - if (s.endsWith("mathpiper.jar")) { - try { - java.util.zip.ZipFile zip = new java.util.zip.ZipFile(new File(s)); - Enumeration fileEnteries = zip.entries(); - - while (fileEnteries.hasMoreElements()) { - ZipEntry ze = (ZipEntry) fileEnteries.nextElement(); - String fileName = ze.getName(); - if (fileName.contains(functionsPath)) { - fileName = fileName.replace("/", "."); - if (fileName.endsWith(".class")) { - fileName = fileName.substring(0, fileName.length() - 6); - //System.out.println(fileName); - try { - Class functionClass = Class.forName(fileName); - - Object functionObject = functionClass.newInstance(); - if (functionObject instanceof BuiltinFunction) { - BuiltinFunction function = (BuiltinFunction) functionObject; - function.plugIn(aEnvironment); - }//end if. - } catch (ClassNotFoundException cnfe) { - System.out.println("Class not found: " + fileName); - } catch (InstantiationException ie) { - System.out.println("Can not instantiate class: " + fileName); - } catch (IllegalAccessException iae) { - System.out.println("Illegal access of class: " + fileName); - } - } - } - }//end for. - } catch (ZipException ze) { - System.out.println("Error opening " + s); - } catch (IOException ioe) { - System.out.println("Error opening " + s); - } - - - break; - } else if (!s.endsWith(".jar")) { - File packageDirectoryFile = new File(s + "/" + functionsPath.substring(0, functionsPath.length() - 1)); - if (packageDirectoryFile.exists()) { - - //System.out.println("package directory found"); - java.io.File[] packageDirectoryContentsArray = packageDirectoryFile.listFiles(new java.io.FilenameFilter() { - - public boolean accept(java.io.File file, String name) { - if (name.startsWith(".")) { - return (false); - } else { - return (true); - } - } - }); - - Arrays.sort(packageDirectoryContentsArray); - - for (File file : packageDirectoryContentsArray) { - String fileName = file.getPath(); - fileName = fileName.substring(s.length() + 1, fileName.length()); - fileName = fileName.replace("/", "."); - fileName = fileName.substring(0, fileName.length() - 6); - //System.out.println(fileName); - try { - Class functionClass = Class.forName(fileName); - - Object functionObject = functionClass.newInstance(); - if (functionObject instanceof BuiltinFunction) { - BuiltinFunction function = (BuiltinFunction) functionObject; - function.plugIn(aEnvironment); - }//end if. - } catch (ClassNotFoundException cnfe) { - System.out.println("Class not found: " + fileName); - } catch (InstantiationException ie) { - System.out.println("Can not instantiate class: " + fileName); - } catch (IllegalAccessException iae) { - System.out.println("Illegal access of class: " + fileName); - } catch (NoClassDefFoundError ncdfe) { - //System.out.println("Class not found: " + fileName); - failList.add(fileName); - } - - }//end for. - break; - }//end if - - }//end if/else - }//end for. - - return failList; - }//end method. - - public abstract void evaluate(Environment aEnvironment, int aStackTop) throws Exception; - - public static ConsPointer getTopOfStackPointer(Environment aEnvironment, int aStackTop) throws Exception { - return aEnvironment.iArgumentStack.getElement(aStackTop); - } - - public static ConsPointer getArgumentPointer(Environment aEnvironment, int aStackTop, int argumentPosition) throws Exception { - return aEnvironment.iArgumentStack.getElement(aStackTop + argumentPosition); - } - - public static ConsPointer getArgumentPointer(ConsPointer cur, int n) throws Exception { - LispError.lispAssert(n >= 0); - - ConsPointer loop = cur; - while (n != 0) { - n--; - loop = loop.cdr(); - } - return loop; - } - - public void plugIn(Environment aEnvironment) { - }//end method. - - public static void addCoreFunctions(Environment aEnvironment) { - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "While"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "Rule"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "MacroRule"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "RulePattern"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "MacroRulePattern"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "FromFile"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "FromString"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "ToFile"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "ToString"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "ToStdout"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "TraceRule"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "Subst"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "LocalSymbols"); - aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "BackQuote"); - aEnvironment.iPrefixOperators.setOperator(0, "`"); - aEnvironment.iPrefixOperators.setOperator(0, "@"); - aEnvironment.iPrefixOperators.setOperator(0, "_"); - aEnvironment.iInfixOperators.setOperator(0, "_"); - - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Hold(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "Hold"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Eval(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Eval"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Write(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "Write"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new WriteString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "WriteString"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FullForm(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FullForm"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DefaultDirectory(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DefaultDirectory"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FromFile(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "FromFile"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FromString(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "FromString"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Read(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Read"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ReadToken(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ReadToken"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ToFile(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "ToFile"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ToString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "ToString"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ToStdout(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "ToStdout"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Load(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Load"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Set(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "Set"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MacroSet(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "MacroSet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Clear(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "Clear"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Clear(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "MacroClear"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Local(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "Local"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Local(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "MacroLocal"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new First(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "First"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Nth(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MathNth"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Rest(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Rest"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DestructiveReverse(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DestructiveReverse"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Length(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Length"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.List(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "List"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new UnList(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "UnList"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Listify(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Listify"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Concatenate(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "Concat"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ConcatenateStrings(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "ConcatStrings"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Delete(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Delete"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DestructiveDelete(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DestructiveDelete"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Insert(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Insert"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DestructiveInsert(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DestructiveInsert"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Replace(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Replace"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DestructiveReplace(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DestructiveReplace"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Atom(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Atom"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Stringify(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "String"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ExpressionToString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ExpressionToString"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CharString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CharString"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FlatCopy(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FlatCopy"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Prog(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "Prog"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new While(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "While"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new If(), 2, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "If"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Check(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "Check"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new TrapError(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "TrapError"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new GetCoreError(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "GetCoreError"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Prefix(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Prefix"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Infix(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Infix"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Postfix(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Postfix"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Bodied(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Bodied"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Rulebase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "RuleBase"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MacroRulebase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MacroRuleBase"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new RulebaseListed(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "RuleBaseListed"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MacroRulebaseListed(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MacroRuleBaseListed"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DefMacroRulebase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "DefMacroRuleBase"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DefMacroRulebaseListed(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "DefMacroRuleBaseListed"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new HoldArg(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "HoldArg"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Rule(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "Rule"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MacroRule(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MacroRule"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new UnFence(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "UnFence"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Retract(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Retract"); - /* aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Not(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "NotN");*/ - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Not(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Not"); //Alias. - /*aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new And(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "AndN");*/ - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new And(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "And"); //Alias. - /*aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Or(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "OrN");*/ - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Or(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "Or"); //Alias. - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Equals(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Equals"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Equals(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "="); //Alias. - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new LessThan(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "LessThan"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new GreaterThan(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "GreaterThan"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsFunction(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsFunction"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsAtom(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsAtom"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsNumber(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsNumber"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsDecimal(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsDecimal"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsInteger(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsInteger"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsList(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsList"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsString"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsBound(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "IsBound"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Multiply(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MultiplyN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Add(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "AddN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Subtract(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "SubtractN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Divide(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DivideN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BuiltinPrecisionSet(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "BuiltinPrecisionSet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new GetExactBits(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "GetExactBitsN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new SetExactBits(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "SetExactBitsN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BitCount(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MathBitCount"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MathSign(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MathSign"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MathIsSmall(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MathIsSmall"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MathNegate(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MathNegate"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Floor(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FloorN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Ceil(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CeilN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Abs(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "AbsN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Mod(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ModN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Div(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DivN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BitsToDigits(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "BitsToDigits"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DigitsToBits(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DigitsToBits"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Gcd(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "GcdN"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new SystemCall(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "SystemCall"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FastArcSin(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FastArcSin"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FastLog(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FastLog"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FastPower(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FastPower"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ShiftLeft(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ShiftLeft"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ShiftRight(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ShiftRight"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FromBase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FromBase"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ToBase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ToBase"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MaxEvalDepth(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MaxEvalDepth"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DefLoad(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DefLoad"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Use(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Use"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new RightAssociative(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "RightAssociative"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new LeftPrecedence(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "LeftPrecedence"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new RightPrecedence(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "RightPrecedence"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsBodied(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsBodied"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsInfix(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsInfix"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsPrefix(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsPrefix"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsPostfix(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsPostfix"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new OpPrecedence(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "OpPrecedence"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new OpLeftPrecedence(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "OpLeftPrecedence"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new OpRightPrecedence(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "OpRightPrecedence"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BuiltinPrecisionGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "BuiltinPrecisionGet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BitAnd(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "BitAnd"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BitOr(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "BitOr"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BitXor(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "BitXor"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Secure(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "Secure"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FindFile(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FindFile"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FindFunction(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FindFunction"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsGeneric(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsGeneric"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new GenericTypeName(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "GenericTypeName"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ArrayCreate(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ArrayCreate"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ArraySize(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ArraySize"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ArrayGet(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ArrayGet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ArraySet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ArraySet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CustomEval(), 4, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "CustomEval"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CustomEvalExpression(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CustomEval'Expression"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CustomEvalResult(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CustomEval'Result"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CustomEvalLocals(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CustomEval'Locals"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CustomEvalStop(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CustomEval'Stop"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new TraceRule(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "TraceRule"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new TraceStack(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "TraceStack"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new LispRead(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "LispRead"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new LispReadListed(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "LispReadListed"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Type(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Type"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new StringMidGet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "StringMidGet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new StringMidSet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "StringMidSet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PatternCreate(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Pattern'Create"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PatternMatches(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Pattern'Matches"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new RulebaseDefined(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "RuleBaseDefined"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DefLoadFunction(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DefLoadFunction"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new RulebaseArgList(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "RuleBaseArgList"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new NewRulePattern(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "RulePattern"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MacroNewRulePattern(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MacroRulePattern"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Subst(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Subst"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new LocalSymbols(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), - "LocalSymbols"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FastIsPrime(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FastIsPrime"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Factorial(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MathFac"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ApplyPure(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "ApplyPure"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PrettyReaderSet(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "PrettyReader'Set"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PrettyPrinterSet(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "PrettyPrinter'Set"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PrettyPrinterGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "PrettyPrinter'Get"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PrettyReaderGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "PrettyReader'Get"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new GarbageCollect(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "GarbageCollect"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new SetGlobalLazyVariable(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "SetGlobalLazyVariable"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PatchLoad(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "PatchLoad"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new PatchString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "PatchString"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MetaSet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MetaSet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MetaGet(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MetaGet"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MetaKeys(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MetaKeys"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MetaValues(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MetaValues"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new MetaEntries(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "MetaEntries"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DefaultTokenizer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DefaultTokenizer"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CommonLispTokenizer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CommonLispTokenizer"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new XmlTokenizer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "XmlTokenizer"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new XmlExplodeTag(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "XmlExplodeTag"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BuiltinAssoc(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Builtin'Assoc"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CurrentFile(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CurrentFile"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new CurrentLine(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "CurrentLine"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new BackQuote(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "`"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DumpNumber(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DumpNumber"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new InDebugMode(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "InDebugMode"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DebugFile(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DebugFile"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new DebugLine(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "DebugLine"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Version(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Version"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new Exit(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Exit"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new ExitRequested(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsExitRequested"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new HistorySize(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "HistorySize"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new StackSize(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "StaSiz"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new IsPromptShown(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "IsPromptShown"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new AskUser(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "AskUser"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new TellUser(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "TellUser"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Time(aEnvironment), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), - "Time"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new FileSize(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "FileSize"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.SystemTimer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "SystemTimer"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Break(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Break"); - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Continue(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Continue"); + try { + String[] listing = getResourceListing(BuiltinFunction.class, functionsPath); + for (int x = 0; x < listing.length; x++) { + + String fileName = listing[x]; + + if (!fileName.toLowerCase().endsWith(".class")) { + continue; + } + + + fileName = fileName.substring(0, fileName.length() - 6); + fileName = functionsPath + fileName; + fileName = fileName.replace("/", "."); + + //System.out.println(fileName); + + try { + Class functionClass = Class.forName(fileName, true, BuiltinFunction.class.getClassLoader()); + + //System.out.println("CLASS :" + functionClass.toString() + " CLASSLOADER: " + BuiltinFunction.class.getClassLoader().toString()); + + Object functionObject = functionClass.newInstance(); + if (functionObject instanceof BuiltinFunction) { + BuiltinFunction function = (BuiltinFunction) functionObject; + function.plugIn(aEnvironment); + }//end if. + } catch (ClassNotFoundException cnfe) { + System.out.println("Class not found: " + fileName); + } catch (InstantiationException ie) { + System.out.println("Can not instantiate class: " + fileName); + } catch (IllegalAccessException iae) { + System.out.println("Illegal access of class: " + fileName); + } catch (NoClassDefFoundError ncdfe) { + //System.out.println("Class not found: " + fileName); + failList.add(fileName); + } + + }//end for. + + + + } catch (Exception e) { + e.printStackTrace(); + } + + + + + return failList; + }//end method. + + public abstract void evaluate(Environment aEnvironment, int aStackTop) throws Exception; + + public static ConsPointer getTopOfStackPointer(Environment aEnvironment, int aStackTop) throws Exception { + return aEnvironment.iArgumentStack.getElement(aStackTop, aStackTop, aEnvironment); + } + + public static ConsPointer getArgumentPointer(Environment aEnvironment, int aStackTop, int argumentPosition) throws Exception { + return aEnvironment.iArgumentStack.getElement(aStackTop + argumentPosition, aStackTop, aEnvironment); + } + + public static ConsPointer getArgumentPointer(Environment aEnvironment, int aStackTop, ConsPointer cur, int n) throws Exception { + LispError.lispAssert(n >= 0, aEnvironment, aStackTop); + + ConsPointer loop = cur; + while (n != 0) { + n--; + loop = loop.cdr(); + } + return loop; + } + + public void plugIn(Environment aEnvironment) throws Exception{ + }//end method. + + public static void addCoreFunctions(Environment aEnvironment) { + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "While"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "Rule"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "MacroRule"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "RulePattern"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "MacroRulePattern"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "PipeFromFile"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "PipeFromString"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "PipeToFile"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "PipeToString"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "PipeToStdout"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "TraceRule"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "Subst"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "LocalSymbols"); + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "BackQuote"); + aEnvironment.iPrefixOperators.setOperator(0, "`"); + aEnvironment.iPrefixOperators.setOperator(0, "@"); + aEnvironment.iPrefixOperators.setOperator(0, "_"); + aEnvironment.iInfixOperators.setOperator(0, "_"); + + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Hold(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "Hold"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Eval(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Eval"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Write(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "Write"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new WriteString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "WriteString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LispForm(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "LispForm"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DefaultDirectory(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DefaultDirectory"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PipeFromFile(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "PipeFromFile"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PipeFromString(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "PipeFromString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Read(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Read"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ReadToken(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ReadToken"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PipeToFile(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "PipeToFile"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PipeToString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "PipeToString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PipeToStdout(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "PipeToStdout"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LoadScript(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "LoadScript"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Bind(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "Bind"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MacroBind(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "MacroBind"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Unbind(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "Unbind"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Unbind(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "MacroUnbind"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Local(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "Local"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Local(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "MacroLocal"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new First(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "First"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Nth(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MathNth"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Rest(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Rest"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DestructiveReverse(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DestructiveReverse"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Length(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Length"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.List(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "List"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Set(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "Set"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ListToFunction(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ListToFunction"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FunctionToList(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FunctionToList"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Concatenate(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "Concat"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ConcatenateStrings(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "ConcatStrings"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Delete(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Delete"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DestructiveDelete(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DestructiveDelete"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Insert(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Insert"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DestructiveInsert(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DestructiveInsert"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Replace(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Replace"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DestructiveReplace(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DestructiveReplace"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ToAtom(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ToAtom"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ToString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ToString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ExpressionToString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ExpressionToString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new UnicodeToString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "UnicodeToString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new StringToUnicode(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "StringToUnicode"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FlatCopy(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FlatCopy"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Prog(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "Prog"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new While(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "While"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new If(), 2, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "If"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Check(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "Check"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ExceptionCatch(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "ExceptionCatch"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ExceptionGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ExceptionGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Prefix(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Prefix"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Infix(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Infix"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Postfix(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Postfix"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Bodied(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Bodied"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Rulebase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "Rulebase"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MacroRulebase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MacroRulebase"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RulebaseListed(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "RulebaseListed"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MacroRulebaseListed(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MacroRulebaseListed"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DefMacroRulebase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "DefMacroRulebase"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DefMacroRulebaseListed(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "DefMacroRulebaseListed"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new HoldArgument(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "HoldArgument"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Rule(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "Rule"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MacroRule(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MacroRule"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new UnFence(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "UnFence"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Retract(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Retract"); + /* aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Not(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "NotN");*/ + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Not(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Not"); //Alias. + /*aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new And(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "AndN");*/ + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new And(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "And"); //Alias. + /*aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Or(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "OrN");*/ + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Or(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "Or"); //Alias. + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsEqual(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsEqual"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsEqual(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "="); //Alias. + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsLessThan(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsLessThan"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsGreaterThan(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsGreaterThan"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsFunction(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsFunction"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsAtom(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsAtom"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsNumber(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsNumber"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsDecimal(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsDecimal"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsInteger(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsInteger"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsList(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsList"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsBound(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "IsBound"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Multiply(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MultiplyN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Add(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "AddN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Subtract(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "SubtractN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Divide(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DivideN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BuiltinPrecisionSet(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "BuiltinPrecisionSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new GetExactBits(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "GetExactBitsN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new SetExactBits(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "SetExactBitsN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BitCount(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MathBitCount"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MathSign(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MathSign"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MathIsSmall(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MathIsSmall"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MathNegate(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MathNegate"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Floor(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FloorN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Ceil(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CeilN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Abs(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "AbsN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Modulo(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ModuloN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Quotient(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "QuotientN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BitsToDigits(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "BitsToDigits"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DigitsToBits(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DigitsToBits"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Gcd(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "GcdN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new SystemCall(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "SystemCall"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastSin(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastSin"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastArcSin(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastArcSin"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastCos(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastCos"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastArcCos(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastArcCos"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastTan(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastTan"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastArcTan(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastArcTan"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastLog(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastLog"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastPower(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastPower"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ShiftLeft(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ShiftLeft"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ShiftRight(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ShiftRight"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FromBase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FromBase"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ToBase(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ToBase"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MaxEvalDepth(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MaxEvalDepth"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DefLoad(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DefLoad"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LoadScriptOnce(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "LoadScriptOnce"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RightAssociativeSet(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "RightAssociativeSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LeftPrecedenceSet(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "LeftPrecedenceSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RightPrecedenceSet(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "RightPrecedenceSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsBodied(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsBodied"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsInfix(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsInfix"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsPrefix(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsPrefix"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsPostfix(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsPostfix"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PrecedenceGet(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "PrecedenceGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LeftPrecedenceGet(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "LeftPrecedenceGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RightPrecedenceGet(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "RightPrecedenceGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BuiltinPrecisionGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "BuiltinPrecisionGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BitAnd(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "BitAnd"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BitOr(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "BitOr"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BitXor(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "BitXor"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Secure(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "Secure"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FindFile(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FindFile"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FindFunction(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FindFunction"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsGeneric(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsGeneric"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new GenericTypeName(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "GenericTypeName"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ArrayCreate(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ArrayCreate"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ArraySize(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ArraySize"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ArrayGet(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ArrayGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ArraySet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ArraySet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CustomEval(), 4, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "CustomEval"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CustomEvalExpression(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CustomEval'Expression"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CustomEvalResult(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CustomEval'Result"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CustomEvalLocals(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CustomEval'Locals"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CustomEvalStop(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CustomEval'Stop"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new TraceRule(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "TraceRule"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new TraceStack(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "TraceStack"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LispRead(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "LispRead"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LispReadListed(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "LispReadListed"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Type(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Type"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new StringMidGet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "StringMidGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new StringMidSet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "StringMidSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PatternCreate(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "PatternCreate"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PatternMatches(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "PatternMatches"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RulebaseDefined(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "RulebaseDefined"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DefLoadFunction(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DefLoadFunction"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RulebaseArgumentsList(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "RulebaseArgumentsList"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RulePattern(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "RulePattern"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MacroRulePattern(), 5, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MacroRulePattern"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Subst(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Subst"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new LocalSymbols(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Macro), + "LocalSymbols"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FastIsPrime(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FastIsPrime"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Factorial(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MathFac"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ApplyFast(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ApplyFast"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PrettyReaderSet(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "PrettyReaderSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PrettyPrinterSet(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "PrettyPrinterSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PrettyPrinterGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "PrettyPrinterGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PrettyReaderGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "PrettyReaderGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new GarbageCollect(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "GarbageCollect"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new SetGlobalLazyVariable(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "SetGlobalLazyVariable"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PatchLoad(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "PatchLoad"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new PatchString(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "PatchString"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MetaSet(), 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MetaSet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MetaGet(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MetaGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MetaKeys(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MetaKeys"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MetaValues(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MetaValues"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new MetaEntries(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "MetaEntries"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DefaultTokenizer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DefaultTokenizer"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CommonLispTokenizer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CommonLispTokenizer"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new XmlTokenizer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "XmlTokenizer"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new XmlExplodeTag(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "XmlExplodeTag"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BuiltinAssoc(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Builtin'Assoc"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CurrentFile(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CurrentFile"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new CurrentLine(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "CurrentLine"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new BackQuote(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "`"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DumpNumber(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DumpNumber"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new InDebugMode(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "InDebugMode"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DebugFile(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DebugFile"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new DebugLine(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "DebugLine"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Version(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Version"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Exit(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Exit"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new ExitRequested(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsExitRequested"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new HistorySize(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "HistorySize"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new StackSize(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "StaSiz"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new IsPromptShown(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IsPromptShown"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new AskUser(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "AskUser"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new TellUser(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "TellUser"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Time(aEnvironment), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "Time"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new FileSize(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FileSize"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.SystemTimer(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "SystemTimer"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Break(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Break"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Continue(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Continue"); + /*aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.Return(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Return");*/ + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new org.mathpiper.builtin.functions.core.ViewConsole(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ViewConsole"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new RoundToN(), 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "RoundToN"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new GlobalVariablesGet(), 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "GlobalVariablesGet"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new JavaAccess(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "JavaAccess"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new JavaCall(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "JavaCall"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new JavaNew(), 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), + "JavaNew"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new JavaToValue(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "JavaToValue"); + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(new Delay(), 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Delay"); + + }//end method. + + + + + public static String[] getResourceListing(Class loadedClass, String path) throws URISyntaxException, IOException { + + InputStream inputStream = loadedClass.getClassLoader().getResourceAsStream(path + "plugins_list.txt"); + + if(inputStream == null) + { + return null; + } + + BufferedReader pluginListFileReader = new BufferedReader(new InputStreamReader(inputStream)); + + + + java.util.Set result = new HashSet(); + + String name = null; + while ((name = pluginListFileReader.readLine()) != null) { + name = name.trim(); + result.add(name); + } + return result.toArray(new String[result.size()]); + + + + +/* URL dirURL = loadedClass.getClassLoader().getResource(path); + if (dirURL != null && dirURL.getProtocol().equals("file")) { + + return new File(dirURL.toURI()).list(); + } + + if (dirURL == null) { + + String loadedClassName = loadedClass.getName().replace(".", "/") + ".class"; + dirURL = loadedClass.getClassLoader().getResource(loadedClassName); + } + + + if (dirURL.getProtocol().equals("jar")) { + + String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); + + JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); + + Enumeration entries = jar.entries(); + + java.util.Set result = new HashSet(); + + while (entries.hasMoreElements()) { + String name = entries.nextElement().getName(); + if (name.startsWith(path)) { + String entry = name.substring(path.length()); + int checkSubdirectory = entry.indexOf("/"); + if (checkSubdirectory >= 0) { + + entry = entry.substring(0, checkSubdirectory); + } + result.add(entry); + } + } + return result.toArray(new String[result.size()]); + }//end if. + + if (dirURL.getProtocol().equals("jeditresource")) { + + try { + + Class jEditJARClassLoaderClass = BuiltinFunction.class.getClassLoader().getClass(); + + if (jEditJARClassLoaderClass != null) { + + Method method = jEditJARClassLoaderClass.getMethod("getZipFile", new java.lang.Class[0]); + + ZipFile zipFile = (ZipFile) method.invoke(BuiltinFunction.class.getClassLoader(), new Object[0]); + + Enumeration entries = zipFile.entries(); + + java.util.Set result = new HashSet(); + + while (entries.hasMoreElements()) { + ZipEntry zipEntry = (ZipEntry) entries.nextElement(); + String name = zipEntry.getName(); + if (name.startsWith(path)) { + String entry = name.substring(path.length()); + int checkSubdirectory = entry.indexOf("/"); + if (checkSubdirectory >= 0) { + + entry = entry.substring(0, checkSubdirectory); + } + result.add(entry); + } + } + return result.toArray(new String[result.size()]); + + }//end if. + + + } catch (NoSuchMethodException nsme) { + nsme.printStackTrace(); + } catch (IllegalAccessException iae) { + iae.printStackTrace(); + } catch(java.lang.reflect.InvocationTargetException ite){ + ite.printStackTrace(); + }catch (NoClassDefFoundError ncdfe) { + ncdfe.printStackTrace(); + } + + + }//end if. + + + throw new UnsupportedOperationException("Cannot list files for URL " + dirURL); + * */ + }//end method. - }//end method. }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Abs.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Abs.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Abs.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Abs.java 2010-09-25 08:09:19.000000000 +0000 @@ -38,7 +38,7 @@ { z.negate(x); } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. @@ -67,8 +67,8 @@ the functions return a floating-point result which is correct only to the current precision. *E.G. - In> - Result> +In> AbsN(-1) +Result: 1 %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Add.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Add.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Add.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Add.java 2011-02-05 07:50:02.000000000 +0000 @@ -19,7 +19,6 @@ import org.mathpiper.builtin.BigNumber; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.Environment; @@ -40,12 +39,12 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - int length = Utility.listLength(getArgumentPointer(aEnvironment, aStackTop, 0)); + int length = Utility.listLength(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0)); if (length == 2) { BigNumber x; x = Utility.getNumber(aEnvironment, aStackTop, 1); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, x)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(x)); return; } else { @@ -54,7 +53,7 @@ int bin = aEnvironment.getPrecision(); BigNumber z = new BigNumber(bin); z.add(x, y, aEnvironment.getPrecision()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); return; } } @@ -85,8 +84,8 @@ the functions return a floating-point result which is correct only to the current precision. *E.G. - In> - Result> +In> +Result: %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/And.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/And.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/And.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/And.java 2011-02-05 07:50:02.000000000 +0000 @@ -37,16 +37,16 @@ int nrnogos = 0; ConsPointer evaluated = new ConsPointer(); - ConsTraverser consTraverser = new ConsTraverser((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); + consTraverser.goNext(aStackTop); while (consTraverser.getCons() != null) { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, evaluated, consTraverser.getPointer()); - if (Utility.isFalse(aEnvironment, evaluated)) + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, consTraverser.getPointer()); + if (Utility.isFalse(aEnvironment, evaluated, aStackTop)) { Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); return; - } else if (!Utility.isTrue(aEnvironment, evaluated)) + } else if (!Utility.isTrue(aEnvironment, evaluated, aStackTop)) { ConsPointer ptr = new ConsPointer(); nrnogos++; @@ -55,7 +55,7 @@ nogos.setCons(ptr.getCons()); } - consTraverser.goNext(); + consTraverser.goNext(aStackTop); } if (nogos.getCons() != null) @@ -67,7 +67,7 @@ { ConsPointer ptr = new ConsPointer(); - Utility.reverseList(ptr, nogos); + Utility.reverseList(aEnvironment, ptr, nogos); nogos.setCons(ptr.getCons()); ptr.setCons(getArgumentPointer(aEnvironment, aStackTop, 0).getCons().copy( aEnvironment, false)); @@ -93,7 +93,7 @@ *CALL a1 And a2 Precedence: -*EVAL OpPrecedence("And") +*EVAL PrecedenceGet("And") And(a1, a2, a3, ..., aN) @@ -117,16 +117,16 @@ *E.G. - In> True And False - Out> False; - In> And(True,True) - Out> True; - In> False And a - Out> False; - In> True And a - Out> And(a); - In> And(True,a,True,b) - Out> b And a; +In> True And False +Result: False; +In> And(True,True) +Result: True; +In> False And a +Result: False; +In> True And a +Result: And(a); +In> And(True,a,True,b) +Result: b And a; *SEE Or, Not %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ApplyFast.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ApplyFast.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ApplyFast.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ApplyFast.java 2011-02-05 04:36:21.000000000 +0000 @@ -0,0 +1,91 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class ApplyFast extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + ConsPointer oper = new ConsPointer(); + oper.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + ConsPointer args = new ConsPointer(); + args.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + + LispError.checkArgument(aEnvironment, aStackTop, args.car() instanceof ConsPointer, 2, "ApplyFast"); + LispError.check(aEnvironment, aStackTop, ((ConsPointer) args.car()).getCons() != null, 2); + + // Apply a pure string + if (oper.car() instanceof String) + { + Utility.applyString(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), + (String) oper.car(), + ((ConsPointer) args.car()).cdr()); + } else + { // Apply a pure function {args,body}. + + ConsPointer args2 = new ConsPointer(); + args2.setCons(((ConsPointer) args.car()).cdr().getCons()); + LispError.checkArgument(aEnvironment, aStackTop, oper.car() instanceof ConsPointer, 1, "ApplyFast"); + LispError.checkArgument(aEnvironment, aStackTop, ((ConsPointer) oper.car()).getCons() != null, 1, "ApplyFast"); + Utility.applyPure(aStackTop, oper, args2, getTopOfStackPointer(aEnvironment, aStackTop), aEnvironment); + } + } +} + + + +/* +%mathpiper_docs,name="ApplyFast",categories="User Functions;Functional Operators",access="private" +*CMD ApplyFast --- a fast built-in version of the Apply function +*CALL + ApplyFast(fn, arglist) + +*PARMS + +{fn} -- function to apply + +{arglist} -- list of arguments + +*DESC +This function is a fast built-in version of the Apply function. + +*E.G. +In> ApplyFast("+", {5,9}); +Result: 14 + +In> ApplyFast({{x,y}, x-y^2}, {Cos(a), Sin(a)}); +Result: Cos(a)-Sin(a)^2 + +In> ApplyFast(Lambda({x,y}, x-y^2), {Cos(a), Sin(a)}); +Result: Cos(a)-Sin(a)^2 + +*SEE Apply +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ApplyPure.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ApplyPure.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ApplyPure.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ApplyPure.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class ApplyPure extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - ConsPointer oper = new ConsPointer(); - oper.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - ConsPointer args = new ConsPointer(); - args.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - - LispError.checkArgument(aEnvironment, aStackTop, args.car() instanceof ConsPointer, 2); - LispError.check(aEnvironment, aStackTop, ((ConsPointer) args.car()).getCons() != null, 2); - - // Apply a pure string - if (oper.car() instanceof String) - { - Utility.applyString(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), - (String) oper.car(), - ((ConsPointer) args.car()).cdr()); - } else - { // Apply a pure function {args,body}. - - ConsPointer args2 = new ConsPointer(); - args2.setCons(((ConsPointer) args.car()).cdr().getCons()); - LispError.checkArgument(aEnvironment, aStackTop, oper.car() instanceof ConsPointer, 1); - LispError.checkArgument(aEnvironment, aStackTop, ((ConsPointer) oper.car()).getCons() != null, 1); - Utility.applyPure(oper, args2, getTopOfStackPointer(aEnvironment, aStackTop), aEnvironment); - } - } -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArrayCreate.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArrayCreate.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArrayCreate.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArrayCreate.java 2010-02-06 21:01:49.000000000 +0000 @@ -37,16 +37,16 @@ ConsPointer sizearg = new ConsPointer(); sizearg.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 1); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 1, "ArrayCreate"); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 1, "ArrayCreate"); int size = Integer.parseInt( (String) sizearg.car(), 10); ConsPointer initarg = new ConsPointer(); initarg.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - Array array = new Array(size, initarg.getCons()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, array)); + Array array = new Array(aEnvironment, size, initarg.getCons()); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, array)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArrayGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArrayGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArrayGet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArrayGet.java 2010-02-06 21:01:49.000000000 +0000 @@ -39,19 +39,19 @@ evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); BuiltinContainer gen = (BuiltinContainer) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Array\""), 1); + LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1,"ArrayGet"); + LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Array\""), 1, "ArrayGet"); ConsPointer sizearg = new ConsPointer(); sizearg.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2, "ArrayGet"); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2, "ArrayGet"); int size = Integer.parseInt( (String) sizearg.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, size > 0 && size <= ((Array) gen).size(), 2); - Cons object = ((Array) gen).getElement(size); + LispError.checkArgument(aEnvironment, aStackTop, size > 0 && size <= ((Array) gen).size(), 2, "ArrayGet"); + Cons object = ((Array) gen).getElement(size, aStackTop, aEnvironment); getTopOfStackPointer(aEnvironment, aStackTop).setCons(object.copy( aEnvironment, false)); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArraySet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArraySet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArraySet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArraySet.java 2010-02-06 21:01:49.000000000 +0000 @@ -39,21 +39,21 @@ evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); BuiltinContainer gen = (BuiltinContainer) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Array\""), 1); + LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1, "ArraySet"); + LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Array\""), 1, "ArraySet"); ConsPointer sizearg = new ConsPointer(); sizearg.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2, "ArraySet"); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2, "ArraySet"); int size = Integer.parseInt( (String) sizearg.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, size > 0 && size <= ((Array) gen).size(), 2); + LispError.checkArgument(aEnvironment, aStackTop, size > 0 && size <= ((Array) gen).size(), 2, "ArraySet"); ConsPointer obj = new ConsPointer(); obj.setCons(getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); - ((Array) gen).setElement(size, obj.getCons()); + ((Array) gen).setElement(size, obj.getCons(), aStackTop, aEnvironment); Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArraySize.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArraySize.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ArraySize.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ArraySize.java 2010-02-06 21:01:49.000000000 +0000 @@ -39,10 +39,10 @@ evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); BuiltinContainer gen = (BuiltinContainer) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Array\""), 1); + LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1, "ArraySize"); + LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Array\""), 1, "ArraySize"); int size = ((Array) gen).size(); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + size)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + size)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/AskUser.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/AskUser.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/AskUser.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/AskUser.java 2010-12-20 20:11:34.000000000 +0000 @@ -35,12 +35,19 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - String messageString = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, messageString != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "AskUser"); - messageString = Utility.stripEndQuotes(messageString); + Object argument = getArgumentPointer(aEnvironment, aStackTop, 1).car(); + + LispError.check(argument instanceof String, "The argument to AskUser must be a string.", "INTERNAL", aStackTop, aEnvironment); + + String messageString = (String) argument; + + LispError.checkArgument(aEnvironment, aStackTop, messageString != null, 1, "AskUser"); + + + messageString = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, messageString); String userInputString = JOptionPane.showInputDialog(null, messageString, "Message from MathPiper", JOptionPane.INFORMATION_MESSAGE); @@ -49,7 +56,7 @@ throw new BreakException(); }//end method. - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"" + userInputString + "\"")); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "\"" + userInputString + "\"")); }//end method. }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Atom.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Atom.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Atom.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Atom.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; - -/** - * - * - */ -public class Atom extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - ConsPointer evaluated = new ConsPointer(); - evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - - // Get operator - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); - String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpUnStringify(orig))); - } -} - - - - -/* -%mathpiper_docs,name="Atom",categories="User Functions;String Manipulation" -*CMD Atom --- convert string to atom -*CORE -*CALL - Atom("string") - -*PARMS - -{"string"} -- a string - -*DESC - -Returns an atom with the string representation given -as the evaluated argument. Example: {Atom("foo");} returns -{foo}. - - -*E.G. - - In> Atom("a") - Out> a; - -*SEE String, ExpressionToString -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BackQuote.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BackQuote.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BackQuote.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BackQuote.java 2011-02-05 07:50:02.000000000 +0000 @@ -34,8 +34,8 @@ { org.mathpiper.lisp.behaviours.BackQuoteSubstitute behaviour = new org.mathpiper.lisp.behaviours.BackQuoteSubstitute(aEnvironment); ConsPointer result = new ConsPointer(); - Utility.substitute(aEnvironment, result, getArgumentPointer(aEnvironment, aStackTop, 1), behaviour); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), result); + Utility.substitute(aEnvironment, aStackTop, result, getArgumentPointer(aEnvironment, aStackTop, 1), behaviour); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), result); } } @@ -66,7 +66,7 @@ The expression should contain some variables (assigned atoms) with the special prefix operator {@}. Variables prefixed by {@} will be evaluated even if they are inside function arguments that are normally not evaluated (e.g. functions -declared with {HoldArg}). If the {@var} pair is in place of a function name, +declared with {HoldArgument}). If the {@var} pair is in place of a function name, e.g. "{@f(x)}", then at the first stage of evaluation the function name itself is replaced, not the return value of the function (see example); so at the second stage of evaluation, a new function may be called. @@ -74,7 +74,7 @@ One way to view backquoting is to view it as a parametric expression generator. {@var} pairs get substituted with the value of the variable {var} even in contexts where nothing would be evaluated. This effect can be also -achieved using {UnList} and {Hold} but the resulting code is much more +achieved using {ListToFunction} and {Hold} but the resulting code is much more difficult to read and maintain. This operation is relatively slow since a new expression is built @@ -87,28 +87,28 @@ soon as the argument is a number (a lot of functions do this only when inside a {N(...)} section). - In> Decl(f1,f2) := \ - In> `(@f1(x_IsNumber) <-- N(@f2(x))); - Out> True; - In> Decl(nSin,Sin) - Out> True; - In> Sin(1) - Out> Sin(1); - In> nSin(1) - Out> 0.8414709848; +In> Decl(f1,f2) := \ +In> `(@f1(x_IsNumber) <-- N(@f2(x))); +Result: True; +In> Decl(nSin,Sin) +Result: True; +In> Sin(1) +Result: Sin(1); +In> nSin(1) +Result: 0.8414709848; This example assigns the expression {func(value)} to variable {var}. Normally -the first argument of {Set} would be unevaluated. +the first argument of {Bind} would be unevaluated. - In> SetF(var,func,value) := \ - In> `(Set(@var,@func(@value))); - Out> True; - In> SetF(a,Sin,x) - Out> True; - In> a - Out> Sin(x); +In> SetF(var,func,value) := \ +In> `(Bind(@var,@func(@value))); +Result: True; +In> SetF(a,Sin,x) +Result: True; +In> a +Result: Sin(x); -*SEE MacroSet, MacroLocal, MacroRuleBase, Hold, HoldArg, DefMacroRuleBase +*SEE MacroBind, MacroLocal, MacroRulebase, Hold, HoldArgument, DefMacroRulebase, MacroExpand %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Bind.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Bind.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Bind.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Bind.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,70 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class Bind extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Utility.setVar(aEnvironment, aStackTop, false, false); + } +} + + + +/* +%mathpiper_docs,name="Bind",categories="User Functions;Variables;Built In" +*CMD Bind --- assignment +*CORE +*CALL + Bind(var, exp) + +*PARMS + +{var} -- variable which should be assigned + +{exp} -- expression to assign to the variable + +*DESC + +The expression "exp" is evaluated and assigned it to the variable +named "var". The first argument is not evaluated. The value True +is returned. + +The statement {Bind(var, exp)} is equivalent to {var := exp}, but the {:=} operator +has more uses, e.g. changing individual entries in a list. + +*E.G. + +In> Bind(a, Sin(x)+3); +Result: True; +In> a; +Result: Sin(x)+3; + +*SEE Unbind, := +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitAnd.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitAnd.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitAnd.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitAnd.java 2010-03-10 06:32:04.000000000 +0000 @@ -33,8 +33,8 @@ BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.bitAnd(x, y); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + z.bitAnd(x, y, null, aStackTop); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitCount.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitCount.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitCount.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitCount.java 2010-02-06 21:01:49.000000000 +0000 @@ -34,6 +34,6 @@ BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.setTo(x.bitCount()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitOr.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitOr.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitOr.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitOr.java 2010-03-10 06:32:04.000000000 +0000 @@ -34,8 +34,8 @@ BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.bitOr(x, y); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + z.bitOr(x, y, null, aStackTop); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitsToDigits.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitsToDigits.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitsToDigits.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitsToDigits.java 2010-02-06 21:01:49.000000000 +0000 @@ -44,10 +44,10 @@ result = Utility.bitsToDigits((long) (x.toDouble()), base); } else { - throw new EvaluationException("BitsToDigits: error: arguments (" + x.toDouble() + ", " + y.toDouble() + ") must be small integers",-1); + throw new EvaluationException("BitsToDigits: error: arguments (" + x.toDouble() + ", " + y.toDouble() + ") must be small integers",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.setTo((long) result); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitXor.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitXor.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BitXor.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BitXor.java 2010-03-10 06:32:04.000000000 +0000 @@ -34,8 +34,8 @@ BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.bitXor(x, y); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + z.bitXor(x, y, null, aStackTop); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Bodied.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Bodied.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Bodied.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Bodied.java 2011-02-05 07:50:02.000000000 +0000 @@ -68,8 +68,8 @@ Precedence is optional (will be set to 0 by default). *E.G. - In> todo +In> todo -*SEE IsBodied, OpPrecedence, Infix, Postfix, Prefix +*SEE IsBodied, PrecedenceGet, Infix, Postfix, Prefix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BuiltinAssoc.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BuiltinAssoc.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BuiltinAssoc.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BuiltinAssoc.java 2010-02-06 21:01:49.000000000 +0000 @@ -44,18 +44,18 @@ Cons listCons; //check that it is a compound object - LispError.checkArgument(aEnvironment, aStackTop, list.car() instanceof ConsPointer, 2); + LispError.checkArgument(aEnvironment, aStackTop, list.car() instanceof ConsPointer, 2, "BuiltinAssoc"); listCons = ((ConsPointer) list.car()).getCons(); - LispError.checkArgument(aEnvironment, aStackTop, listCons != null, 2); + LispError.checkArgument(aEnvironment, aStackTop, listCons != null, 2, "BuiltinAssoc"); listCons = listCons.cdr().getCons(); - Cons result = Utility.associativeListGet(aEnvironment, key, listCons); + Cons result = Utility.associativeListGet(aEnvironment, aStackTop, key, listCons); if (result != null) { getTopOfStackPointer(aEnvironment, aStackTop).setCons(result); } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "Empty")); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "Empty")); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionGet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionGet.java 2011-02-05 07:50:02.000000000 +0000 @@ -32,7 +32,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { // decimal getPrecision - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + aEnvironment.getPrecision())); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + aEnvironment.getPrecision())); } } @@ -51,12 +51,12 @@ *E.G. - In> BuiltinPrecisionGet(); - Out> 10; - In> BuiltinPrecisionSet(20); - Out> True; - In> BuiltinPrecisionGet(); - Out> 20; +In> BuiltinPrecisionGet(); +Result: 10; +In> BuiltinPrecisionSet(20); +Result: True; +In> BuiltinPrecisionGet(); +Result: 20; *SEE BuiltinPrecisionSet, N diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionSet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/BuiltinPrecisionSet.java 2011-02-05 07:50:02.000000000 +0000 @@ -35,11 +35,11 @@ { ConsPointer index = new ConsPointer(); index.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1, "BuiltinPrecisionSet"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1, "BuiltinPrecisionSet"); int ind = Integer.parseInt( (String) index.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 1); + LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 1, "BuiltinPrecisionSet"); aEnvironment.setPrecision(ind); Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } @@ -78,24 +78,24 @@ *E.G. - In> BuiltinPrecisionSet(10) - Out> True; - In> N(Sin(1)) - Out> 0.8414709848; - In> BuiltinPrecisionSet(20) - Out> True; - In> x:=N(Sin(1)) - Out> 0.84147098480789650665; +In> BuiltinPrecisionSet(10) +Result: True; +In> N(Sin(1)) +Result: 0.8414709848; +In> BuiltinPrecisionSet(20) +Result: True; +In> x:=N(Sin(1)) +Result: 0.84147098480789650665; The value {x} is not changed by a {BuiltinPrecisionSet()} call: - In> [ BuiltinPrecisionSet(10); x; ] - Out> 0.84147098480789650665; +In> [ BuiltinPrecisionSet(10); x; ] +Result: 0.84147098480789650665; The value {x} is rounded off to 10 digits after an arithmetic operation: - In> x+0. - Out> 0.8414709848; +In> x+0. +Result: 0.8414709848; In the above operation, {0.} was interpreted as a number which is precise to 10 digits (the user does not need to type {0.0000000000} for this to happen). So the result of {x+0.} is precise only to 10 digits. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Ceil.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Ceil.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Ceil.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Ceil.java 2011-02-05 07:50:02.000000000 +0000 @@ -36,7 +36,7 @@ z.negate(x); z.floor(z); z.negate(z); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. @@ -65,8 +65,8 @@ the functions return a floating-point result which is correct only to the current precision. *E.G. - In> - Result> +In> +Result: %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CharString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CharString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CharString.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CharString.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class CharString extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - String str; - str = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, str != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, Utility.isNumber(str, false), 2); - char asciiCode = (char) Integer.parseInt(str, 10); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"" + asciiCode + "\"")); - } -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Check.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Check.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Check.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Check.java 2010-12-20 20:11:34.000000000 +0000 @@ -34,13 +34,22 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { ConsPointer pred = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, pred, getArgumentPointer(aEnvironment, aStackTop, 1)); - if (!Utility.isTrue(aEnvironment, pred)) + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, pred, getArgumentPointer(aEnvironment, aStackTop, 1)); + if (!Utility.isTrue(aEnvironment, pred, aStackTop)) { - ConsPointer evaluated = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, evaluated, getArgumentPointer(aEnvironment, aStackTop, 2)); - LispError.checkIsString(aEnvironment, aStackTop, evaluated, 2); - throw new EvaluationException( Utility.stripEndQuotes((String) evaluated.car()), -1); + ConsPointer type = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, type, getArgumentPointer(aEnvironment, aStackTop, 2)); + LispError.checkIsString(aEnvironment, aStackTop, type, 2, "Check"); + + + + ConsPointer message = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, message, getArgumentPointer(aEnvironment, aStackTop, 3)); + LispError.checkIsString(aEnvironment, aStackTop, message, 3, "Check"); + + + + throw new EvaluationException( Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, (String) type.car()), Utility.toNormalString(aEnvironment, aStackTop, (String) message.car()), aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber(), "Check"); } getTopOfStackPointer(aEnvironment, aStackTop).setCons(pred.getCons()); } @@ -50,34 +59,37 @@ /* %mathpiper_docs,name="Check",categories="Programmer Functions;Error Reporting;Built In" -*CMD Check --- report "hard" errors +*CMD Check --- throw an exception if a predicate expression returns False *CORE *CALL - Check(predicate,"error text") + Check(predicate, "exceptionType", "exceptionMessage") *PARMS {predicate} -- expression returning {True} or {False} -{"error text"} -- string to print on error +{"exceptionType"} -- string which indicates the type of the exception + +{"exceptionMessage"} -- string which holds the exception message *DESC If {predicate} does not evaluate to {True}, -the current operation will be stopped, the string {"error text"} will be printed, and control will be returned immediately to the command line. This facility can be used to assure that some condition -is satisfied during evaluation of expressions (guarding -against critical internal errors). +the current operation will be stopped and an exception will be thrown. +This facility can be used to assure that some condition +is satisfied during evaluation of expressions. + +Exceptions that are thrown by this function can be caught by the {ExceptionCatch} function. + -A "soft" error reporting facility that does not stop the execution is provided by the function {Assert}. -**E.G. +*E.G. - In> [Check(1=0,"bad value"); Echo(OK);] - In function "Check" : - CommandLine(1) : "bad value" +In> Check(IsInteger(2.3), "Argument", "The argument must be an integer.") +Result: Exception +Exception: The argument must be an integer. -Note that {OK} is not printed. -*SEE Assert, TrapError, GetCoreError +*SEE ExceptionCatch, ExceptionGet %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Clear.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Clear.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Clear.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Clear.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,111 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.lisp.cons.ConsTraverser; -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class Clear extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - if (getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer) { - - ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - - ConsTraverser consTraverser = new ConsTraverser(subList); - consTraverser.goNext(); - int nr = 1; - while (consTraverser.getCons() != null) - { - String variableName; - variableName = (String) consTraverser.car(); - LispError.checkArgument(aEnvironment, aStackTop, variableName != null, nr); - aEnvironment.unbindVariable(variableName); - consTraverser.goNext(); - nr++; - } - } - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} - - - -/* -%mathpiper_docs,name="Clear",categories="User Functions;Variables;Built In" -*CMD Clear --- undo an assignment -*CORE -*CALL - Clear(var, ...) - -*PARMS - -{var} -- name of variable to be cleared - -*DESC - -All assignments made to the variables listed as arguments are -undone. From now on, all these variables remain unevaluated (until a -subsequent assignment is made). Also clears any metadata that may have -been set in an unbound variable. The result of the expression is -True. - -*E.G. - - In> a := 5; - Out> 5; - In> a^2; - Out> 25; - - In> Clear(a); - Out> True; - In> a^2; - Out> a^2; - -*SEE Set, := -%/mathpiper_docs -*/ - - - -/* -%mathpiper_docs,name="MacroClear",categories="Programmer Functions;Programming;Built In" -*CMD MacroClear --- define rules in functions -*CORE -*DESC - -This function has the same effect as its non-macro counterpart, except -that its arguments are evaluated before the required action is performed. -This is useful in macro-like procedures or in functions that need to define new -rules based on parameters. - -Make sure that the arguments of {Macro}... commands evaluate to expressions that would normally be used in the non-macro version! - -*SEE Set, Clear, Local, RuleBase, Rule, Backquoting, MacroSet, MacroLocal, MacroRuleBase, MacroRuleBaseListed, MacroRule -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CommonLispTokenizer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CommonLispTokenizer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CommonLispTokenizer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CommonLispTokenizer.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,6 +33,6 @@ { aEnvironment.write("Function not yet implemented : LispCommonLispTokenizer");//TODO FIXME - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Concatenate.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Concatenate.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Concatenate.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Concatenate.java 2011-02-05 07:50:02.000000000 +0000 @@ -36,21 +36,21 @@ { ConsPointer all = new ConsPointer(); all.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); - ConsTraverser tail = new ConsTraverser(all); - tail.goNext(); + ConsTraverser tail = new ConsTraverser(aEnvironment, all); + tail.goNext(aStackTop); int arg = 1; - ConsTraverser consTraverser = new ConsTraverser((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); + consTraverser.goNext(aStackTop); while (consTraverser.getCons() != null) { - LispError.checkIsList(aEnvironment, aStackTop, consTraverser.getPointer(), arg); - Utility.flatCopy(aEnvironment,tail.getPointer(), ((ConsPointer) consTraverser.getPointer().car()).cdr()); + LispError.checkIsList(aEnvironment, aStackTop, consTraverser.getPointer(), arg, "Concatenate"); + Utility.flatCopy(aEnvironment, aStackTop, tail.getPointer(), ((ConsPointer) consTraverser.getPointer().car()).cdr()); while (tail.getCons() != null) { - tail.goNext(); + tail.goNext(aStackTop); } - consTraverser.goNext(); + consTraverser.goNext(aStackTop); arg++; } getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,all.getCons())); @@ -77,10 +77,10 @@ *E.G. - In> Concat({a,b}, {c,d}); - Out> {a,b,c,d}; - In> Concat({5}, {a,b,c}, {{f(x)}}); - Out> {5,a,b,c,{f(x)}}; +In> Concat({a,b}, {c,d}); +Result: {a,b,c,d}; +In> Concat({5}, {a,b,c}, {{f(x)}}); +Result: {5,a,b,c,{f(x)}}; *SEE ConcatStrings, :, Insert %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ConcatenateStrings.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ConcatenateStrings.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ConcatenateStrings.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ConcatenateStrings.java 2011-02-05 07:50:02.000000000 +0000 @@ -36,15 +36,15 @@ aStringBuffer.append('\"'); int arg = 1; - ConsTraverser consTraverser = new ConsTraverser( (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car() ); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car() ); + consTraverser.goNext(aStackTop); while (consTraverser.getCons() != null) { - LispError.checkIsString(aEnvironment, aStackTop, consTraverser.getPointer(), arg); + LispError.checkIsString(aEnvironment, aStackTop, consTraverser.getPointer(), arg, "ConcatenateStrings"); String thisString = (String) consTraverser.car(); String toAppend = thisString.substring(1, thisString.length() - 1); aStringBuffer.append(toAppend); - consTraverser.goNext(); + consTraverser.goNext(aStackTop); arg++; } aStringBuffer.append('\"'); @@ -54,7 +54,7 @@ { StringBuffer strBuffer = new StringBuffer(""); ConcatenateStrings(strBuffer, aEnvironment, aStackTop); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, strBuffer.toString())); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, strBuffer.toString())); } } @@ -78,8 +78,8 @@ *E.G. - In> ConcatStrings("a","b","c") - Out> "abc"; +In> ConcatStrings("a","b","c") +Result: "abc"; *SEE : %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Continue.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Continue.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Continue.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Continue.java 2009-09-16 17:04:18.000000000 +0000 @@ -48,7 +48,7 @@ *DESC -If Break is executed inside of a While, Until, For, or ForEach loop, all the code between +If Continue is executed inside of a While, Until, For, or ForEach loop, all the code between the continue command and the end of the loop will be skipped and the next loop iteration will be started. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CurrentFile.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CurrentFile.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CurrentFile.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CurrentFile.java 2010-02-05 10:28:57.000000000 +0000 @@ -31,7 +31,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpStringify(aEnvironment.iInputStatus.fileName()))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.getTokenHash().lookUpStringify(aEnvironment.iInputStatus.fileName()))); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CurrentLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CurrentLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CurrentLine.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CurrentLine.java 2010-02-05 10:28:57.000000000 +0000 @@ -31,7 +31,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + aEnvironment.iInputStatus.lineNumber())); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + aEnvironment.iInputStatus.lineNumber())); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalExpression.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalExpression.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalExpression.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalExpression.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,6 +33,6 @@ { aEnvironment.write("Function not yet implemented : CustomEvalExpression");////TODO fixme - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEval.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEval.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEval.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEval.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,6 +33,6 @@ { aEnvironment.write("Function not yet implemented : CustomEval");////TODO fixme - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalLocals.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalLocals.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalLocals.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalLocals.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,6 +33,6 @@ { aEnvironment.write("Function not yet implemented : LispCustomEvalLocals");////TODO fixme - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalResult.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalResult.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalResult.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalResult.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,6 +33,6 @@ { aEnvironment.write("Function not yet implemented : CustomEvalResult");////TODO fixme - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalStop.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalStop.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/CustomEvalStop.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/CustomEvalStop.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,6 +33,6 @@ { aEnvironment.write("Function not yet implemented : LispCustomEvalStop");////TODO fixme - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefaultDirectory.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefaultDirectory.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefaultDirectory.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefaultDirectory.java 2011-02-05 07:50:02.000000000 +0000 @@ -32,10 +32,10 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { // Get file name - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "DefaultDirectory"); String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "DefaultDirectory"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); aEnvironment.iInputDirectories.add(oper); Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } @@ -76,8 +76,8 @@ *E.G. - In> DefaultDirectory("/home/user/myscripts/"); - Out> True; +In> DefaultDirectory("/home/user/myscripts/"); +Result: True; *SEE Load, Use, DefLoad, FindFile %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefaultTokenizer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefaultTokenizer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefaultTokenizer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefaultTokenizer.java 2011-02-05 07:50:02.000000000 +0000 @@ -47,7 +47,7 @@ *DESC A "tokenizer" is an internal routine in the kernel that parses the input into MathPiper expressions. -This affects all input typed in by a user at the prompt and also the input redirected from files or strings using {FromFile} and {FromString} and read using {Read} or {ReadToken}. +This affects all input typed in by a user at the prompt and also the input redirected from files or strings using {PipeFromFile} and {FromString} and read using {Read} or {ReadToken}. The MathPiper environment currently supports some experimental tokenizers for various syntaxes. {DefaultTokenizer} switches to the tokenizer used for @@ -64,11 +64,11 @@ (everything a user types will be parsed using a non-default tokenizer). -**E.G. notest +*E.G. notest - In> +In> -*SEE OMRead, TrapError, XmlExplodeTag, ReadToken, FromFile, FromString, XmlTokenizer +*SEE OMRead, TrapError, XmlExplodeTag, ReadToken, PipeFromFile, FromString, XmlTokenizer %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefLoadFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefLoadFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefLoadFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefLoadFunction.java 2010-12-16 01:32:55.000000000 +0000 @@ -24,7 +24,7 @@ import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.userfunctions.MultipleArityUserFunction; +import org.mathpiper.lisp.rulebases.MultipleArityRulebase; /** * @@ -38,11 +38,11 @@ ConsPointer namePointer = new ConsPointer(); namePointer.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); String orig = (String) namePointer.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "DefLoadFunction"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); - MultipleArityUserFunction multiUserFunction = - aEnvironment.getMultipleArityUserFunction((String)aEnvironment.getTokenHash().lookUp(oper), true); + MultipleArityRulebase multiUserFunction = + aEnvironment.getMultipleArityRulebase(aStackTop, (String)aEnvironment.getTokenHash().lookUp(oper), true); if (multiUserFunction != null) { if (multiUserFunction.iFileToOpen != null) @@ -51,7 +51,7 @@ if (!def.iIsLoaded) { multiUserFunction.iFileToOpen = null; - Utility.use(aEnvironment, def.iFileName); + Utility.loadScriptOnce(aEnvironment, aStackTop, def.iFileName); }//end if. }//end if. }//end if. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefLoad.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefLoad.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefLoad.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefLoad.java 2010-02-06 21:01:49.000000000 +0000 @@ -39,11 +39,11 @@ evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "DefLoad"); String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "DefLoad"); - Utility.loadDefFile(aEnvironment, orig); + Utility.loadDefFile(aEnvironment, aStackTop, orig); Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefMacroRulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefMacroRulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefMacroRulebase.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefMacroRulebase.java 2011-02-05 07:50:02.000000000 +0000 @@ -29,18 +29,18 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - org.mathpiper.lisp.Utility.defMacroRuleBase(aEnvironment, aStackTop, false); + org.mathpiper.lisp.Utility.defMacroRulebase(aEnvironment, aStackTop, false); } } /* -%mathpiper_docs,name="DefMacroRuleBase",categories="Programmer Functions;Programming;Built In" -*CMD DefMacroRuleBase --- define a function as a macro +%mathpiper_docs,name="DefMacroRulebase",categories="Programmer Functions;Programming;Built In" +*CMD DefMacroRulebase --- define a function as a macro *CORE *CALL - DefMacroRuleBase(name,params) + DefMacroRulebase(name,params) *PARMS @@ -50,7 +50,7 @@ *DESC -{DefMacroRuleBase} is similar to {RuleBase}, with the difference that it declares a macro, +{DefMacroRulebase} is similar to {Rulebase}, with the difference that it declares a macro, instead of a function. After this call, rules can be defined for the function "{name}", but their interpretation will be different. @@ -109,18 +109,18 @@ with two arguments, and a macro {foo(a,b,c)} with three arguments. -**E.G. +*E.G. The following example defines a macro {myfor}, and shows one use, referencing a variable {a} from the calling environment. - In> DefMacroRuleBase("myfor",{init,pred,inc,body}) - Out> True; - In> myfor(_init,_pred,_inc,_body)<--[@init;While(@pred)[@body;@inc;];True;]; - Out> True; - In> a:=10 - Out> 10; - In> myfor(i:=1,i<10,i++,Echo(a*i)) +In> DefMacroRulebase("myfor",{init,pred,inc,body}) +Result: True; +In> myfor(_init,_pred,_inc,_body)<--[@init;While(@pred)[@body;@inc;];True;]; +Result: True; +In> a:=10 +Result: 10; +In> myfor(i:=1,i<10,i++,Echo(a*i)) 10 20 30 @@ -130,10 +130,10 @@ 70 80 90 - Out> True; - In> i - Out> 10; +Result: True; +In> i +Result: 10; -*SEE RuleBase, Backquoting, DefMacroRuleBaseListed +*SEE Rulebase, `, DefMacroRulebaseListed %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefMacroRulebaseListed.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefMacroRulebaseListed.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DefMacroRulebaseListed.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DefMacroRulebaseListed.java 2010-09-20 04:22:24.000000000 +0000 @@ -29,18 +29,18 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - org.mathpiper.lisp.Utility.defMacroRuleBase(aEnvironment, aStackTop, true); + org.mathpiper.lisp.Utility.defMacroRulebase(aEnvironment, aStackTop, true); } } /* -%mathpiper_docs,name="DefMacroRuleBaseListed",categories="Programmer Functions;Programming;Built In" -*CMD DefMacroRuleBaseListed --- define macro with variable number of arguments +%mathpiper_docs,name="DefMacroRulebaseListed",categories="Programmer Functions;Programming;Built In" +*CMD DefMacroRulebaseListed --- define macro with variable number of arguments *CORE *CALL - DefMacroRuleBaseListed("name", params) + DefMacroRulebaseListed("name", params) *PARMS @@ -50,9 +50,9 @@ *DESC -This does the same as {DefMacroRuleBase} (define a macro), but with a variable -number of arguments, similar to {RuleBaseListed}. +This does the same as {DefMacroRulebase} (define a macro), but with a variable +number of arguments, similar to {RulebaseListed}. -*SEE RuleBase, RuleBaseListed, Backquoting, DefMacroRuleBase +*SEE Rulebase, RulebaseListed, `, DefMacroRulebase %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Delay.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Delay.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Delay.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Delay.java 2010-08-01 06:27:20.000000000 +0000 @@ -0,0 +1,65 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class Delay extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber milliseconds = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + Thread.sleep(milliseconds.toLong()); + + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +}//end class. + + + +/* +%mathpiper_docs,name="Delay",categories="User Functions;Built In;Input/Output" +*CMD Delay --- delays execution of a program for a specified number of milliseconds +*CORE +*CALL + Delay(ms) + + *PARAMS + {ms} -- the number of milliseconds to delay + +*DESC + +This function delays execution of a program for the specified number of milliseconds. +The delay can be terminated by pressing the "Halt Calculation" button. + +*E.G. +In> Delay(1000) +Result: True + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Delete.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Delete.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Delete.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Delete.java 2011-02-05 07:50:02.000000000 +0000 @@ -59,8 +59,8 @@ *E.G. - In> Delete({a,b,c,d,e,f}, 4); - Out> {a,b,c,e,f}; +In> Delete({a,b,c,d,e,f}, 4); +Result: {a,b,c,e,f}; *SEE DestructiveDelete, Insert, Replace %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveDelete.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveDelete.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveDelete.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveDelete.java 2011-02-05 07:50:02.000000000 +0000 @@ -62,16 +62,16 @@ *E.G. - In> lst := {a,b,c,d,e,f}; - Out> {a,b,c,d,e,f}; - In> Delete(lst, 4); - Out> {a,b,c,e,f}; - In> lst; - Out> {a,b,c,d,e,f}; - In> DestructiveDelete(lst, 4); - Out> {a,b,c,e,f}; - In> lst; - Out> {a,b,c,e,f}; +In> lst := {a,b,c,d,e,f}; +Result: {a,b,c,d,e,f}; +In> Delete(lst, 4); +Result: {a,b,c,e,f}; +In> lst; +Result: {a,b,c,d,e,f}; +In> DestructiveDelete(lst, 4); +Result: {a,b,c,e,f}; +In> lst; +Result: {a,b,c,e,f}; *SEE Delete, DestructiveInsert, DestructiveReplace %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveInsert.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveInsert.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveInsert.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveInsert.java 2011-02-05 07:50:02.000000000 +0000 @@ -64,16 +64,16 @@ *E.G. - In> lst := {a,b,c,d}; - Out> {a,b,c,d}; - In> Insert(lst, 2, x); - Out> {a,x,b,c,d}; - In> lst; - Out> {a,b,c,d}; - In> DestructiveInsert(lst, 2, x); - Out> {a,x,b,c,d}; - In> lst; - Out> {a,x,b,c,d}; +In> lst := {a,b,c,d}; +Result: {a,b,c,d}; +In> Insert(lst, 2, x); +Result: {a,x,b,c,d}; +In> lst; +Result: {a,b,c,d}; +In> DestructiveInsert(lst, 2, x); +Result: {a,x,b,c,d}; +In> lst; +Result: {a,x,b,c,d}; *SEE Insert, DestructiveDelete, DestructiveReplace %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveReplace.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveReplace.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveReplace.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveReplace.java 2011-02-05 07:50:02.000000000 +0000 @@ -66,16 +66,16 @@ *E.G. - In> lst := {a,b,c,d,e,f}; - Out> {a,b,c,d,e,f}; - In> Replace(lst, 4, x); - Out> {a,b,c,x,e,f}; - In> lst; - Out> {a,b,c,d,e,f}; - In> DestructiveReplace(lst, 4, x); - Out> {a,b,c,x,e,f}; - In> lst; - Out> {a,b,c,x,e,f}; +In> lst := {a,b,c,d,e,f}; +Result: {a,b,c,d,e,f}; +In> Replace(lst, 4, x); +Result: {a,b,c,x,e,f}; +In> lst; +Result: {a,b,c,d,e,f}; +In> DestructiveReplace(lst, 4, x); +Result: {a,b,c,x,e,f}; +In> lst; +Result: {a,b,c,x,e,f}; *SEE Replace, DestructiveDelete, DestructiveInsert %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveReverse.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveReverse.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DestructiveReverse.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DestructiveReverse.java 2011-02-05 07:50:02.000000000 +0000 @@ -34,7 +34,7 @@ { ConsPointer reversed = new ConsPointer(); reversed.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); - Utility.reverseList(reversed.cdr(), ((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()).cdr()); + Utility.reverseList(aEnvironment, reversed.cdr(), ((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()).cdr()); getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,reversed.getCons())); } } @@ -65,12 +65,12 @@ *E.G. - In> lst := {a,b,c,13,19}; - Out> {a,b,c,13,19}; - In> revlst := DestructiveReverse(lst); - Out> {19,13,c,b,a}; - In> lst; - Out> {a}; +In> lst := {a,b,c,13,19}; +Result: {a,b,c,13,19}; +In> revlst := DestructiveReverse(lst); +Result: {19,13,c,b,a}; +In> lst; +Result: {a}; *SEE FlatCopy, Reverse %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DigitsToBits.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DigitsToBits.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DigitsToBits.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DigitsToBits.java 2010-02-06 21:01:49.000000000 +0000 @@ -44,10 +44,10 @@ result = Utility.digitsToBits((long) (x.toDouble()), base); } else { - throw new EvaluationException("BitsToDigits: error: arguments (" + x.toDouble() + ", " + y.toDouble() + ") must be small integers",-1); + throw new EvaluationException("BitsToDigits: error: arguments (" + x.toDouble() + ", " + y.toDouble() + ") must be small integers",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.setTo((long) result); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Divide.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Divide.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Divide.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Divide.java 2011-02-05 07:50:02.000000000 +0000 @@ -51,7 +51,7 @@ { z.divide(x, y, aEnvironment.getPrecision()); } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); return; } }//end class. @@ -81,8 +81,8 @@ the functions return a floating-point result which is correct only to the current precision. *E.G. - In> - Result> +In> +Result: %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Div.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Div.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Div.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Div.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BigNumber; -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class Div extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); - BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); - if (x.isInteger() && y.isInteger()) - { // both integer, perform integer division - - BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.divide(x, y, aEnvironment.getPrecision()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); - return; - } else - { - throw new Exception("LispDiv: error: both arguments must be integer"); - } - } -}//end class. - - - -/* -%mathpiper_docs,name="DivN",categories="User Functions;Numeric;Built In" -*CMD DivN --- integer division result is an integer (arbitrary-precision math function) -*CORE -*CALL - DivN(x,y) () - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs -*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DumpNumber.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DumpNumber.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/DumpNumber.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/DumpNumber.java 2010-12-29 04:07:15.000000000 +0000 @@ -21,7 +21,7 @@ import org.mathpiper.builtin.BigNumber; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.Cons; /** * @@ -34,9 +34,19 @@ { BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); - x.dumpNumber(aEnvironment.iCurrentOutput); + Cons resultCons = x.dumpNumber(aEnvironment, aStackTop); + + /* + ConsPointer isVerbosePointer = Utility.lispEvaluate(aEnvironment, aStackTop, "InVerboseMode();"); + + if(((String)isVerbosePointer.car()).equals("True")) + { + x.dumpNumber(aEnvironment, aStackTop, aEnvironment.iCurrentOutput); + } + */ + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(resultCons); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); }//end method. @@ -62,15 +72,14 @@ This function prints the implementation details of an integer or decimal number. *E.G. -In> DumpNumber(42) -Result> True -Side Effects> -BigInteger: 42 - -In> DumpNumber(42.2343) -Result> True -Side Effects> -BigDecimal: 42.2343 Precision: 6 Unscaled Value: 422343 Scale: 4 +In> DumpNumber(4) +Result> {{"type","BigInteger"},{"value",4}} + +In> DumpNumber(3.2) +Result> {{"type","BigDecimal"},{"value",3.2},{"precision",2},{"unscaledValue",32},{"scale",1}} + +In> DumpNumber(3.2)["precision"] +Result> 2 %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Equals.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Equals.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Equals.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Equals.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class Equals extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - ConsPointer evaluated1 = new ConsPointer(); - evaluated1.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - ConsPointer evaluated2 = new ConsPointer(); - evaluated2.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - - Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), - Utility.equals(aEnvironment, evaluated1, evaluated2)); - } -}//end class. - - - - -/* -%mathpiper_docs,name="Equals",categories="User Functions;Built In" -*CMD Equals --- check equality -*CORE -*CALL - Equals(a,b) - -*DESC -Compares evaluated {a} and {b} recursively -(stepping into expressions). So "Equals(a,b)" returns -"True" if the expressions would be printed exactly -the same, and "False" otherwise. - -*SEE GreaterThan, LessThan - -%/mathpiper_docs -*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Eval.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Eval.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Eval.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Eval.java 2011-02-05 07:50:02.000000000 +0000 @@ -30,7 +30,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); } }//end class @@ -53,14 +53,14 @@ *E.G. - In> a := x; - Out> x; - In> x := 5; - Out> 5; - In> a; - Out> x; - In> Eval(a); - Out> 5; +In> a := x; +Result: x; +In> x := 5; +Result: 5; +In> a; +Result: x; +In> Eval(a); +Result: 5; The variable {a} is bound to {x}, and {x} is bound to 5. Hence evaluating {a} will give {x}. Only when an extra @@ -72,7 +72,7 @@ while {x} had the value 5, the variable {a} would also get the value 5 because the assignment operator {:=} evaluates the right-hand side. -*SEE Hold, HoldArg, := +*SEE Hold, HoldArgument, := %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ExceptionCatch.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ExceptionCatch.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ExceptionCatch.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ExceptionCatch.java 2010-12-16 03:07:53.000000000 +0000 @@ -0,0 +1,158 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class ExceptionCatch extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + try + { + //Return the first argument. + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); + } catch (Throwable exception) + { //Return the second argument. + //e.printStackTrace(); + Boolean interrupted = Thread.currentThread().interrupted(); //Clear interrupted condition. + aEnvironment.iException = exception; + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); + aEnvironment.iException = null; + } + } +} + + + +/* +%mathpiper_docs,name="ExceptionCatch",categories="Programmer Functions;Error Reporting;Built In" +*CMD ExceptionCatch --- catches exceptions +*CORE +*CALL + ExceptionCatch(expression, exceptionHandler) + +*PARMS + +{expression} -- expression to evaluate (causing potential error) + +{exceptionHandler} -- expression which is evaluated to handle the exception + +*DESC +ExceptionCatch evaluates its argument {expression} and returns the +result of evaluating {expression}. If an exception is thrown, +{errorHandler} is evaluated, returning its return value instead. + +{ExceptionGet} can be used to obtain information about the caught exception. + + + +*E.G. + + +In> ExceptionCatch(Check(1 = 2, "Test", "Throwing a test exception."), "This string is returned if an exception is thrown."); +Result: "This string is returned if an exception is thrown." + + + + +/%mathpiper,title="Example of how to use ExceptionCatch and ExceptionGet in test code (long version)." +[ + Local(exception); + + exception := False; + + ExceptionCatch(Check(1 = 2, "Test", "Throwing a test exception."), exception := True); + + Verify(exception, True); + +]; +/%/mathpiper + + /%output,preserve="false" + Result: True +. /%/output + + + + + +/%mathpiper,title="Example of how to use ExceptionCatch and ExceptionGet in test code (short version)." + +//ExceptionGet returns False if there is no exception or an association list if there is. +Verify( ExceptionCatch(Check(1 = 2, "Test", "Throwing a test exception."), ExceptionGet()) = False, False); + +/%/mathpiper + + /%output,preserve="false" + Result: True +. /%/output + + + + + +/%mathpiper,title="Example of how to handle a caught exception." + +TestFunction(x) := +[ + + Check(IsInteger(x), "Argument", "The argument must be an integer."); + +]; + + + + +caughtException := ExceptionCatch(TestFunction(1.2), ExceptionGet()); + +Echo(caughtException); + +NewLine(); + +Echo("Type: ", caughtException["type"]); + +NewLine(); + +Echo("Message: ", caughtException["message"]); + + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + {{"type","Argument"},{"message","The argument must be an integer."},{"exceptionObject",class org.mathpiper.exceptions.EvaluationException}} + + Type: Argument + + Message: The argument must be an integer. + +. /%/output + +*SEE Check, ExceptionGet + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ExceptionGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ExceptionGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ExceptionGet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ExceptionGet.java 2010-12-16 03:07:53.000000000 +0000 @@ -0,0 +1,171 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.exceptions.EvaluationException; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.SublistCons; + +/** + * + * + */ +public class ExceptionGet extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + if(aEnvironment.iException == null) + { + Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } + else + { + Throwable exception = aEnvironment.iException; + + String type = null; + + String message = null; + + if(exception instanceof EvaluationException) + { + EvaluationException evaluationException = (EvaluationException) exception; + + type = evaluationException.getType(); + } + else + { + type = exception.getClass().getName(); + } + + message = exception.getMessage(); + + + JavaObject exceptionObject = new JavaObject(exception); + + + + //Create type association list. + Cons typeListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons typeNameAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"type\""); + + Cons typeValueValueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, Utility.toMathPiperString(aEnvironment, aStackTop, type)); + + typeListAtomCons.cdr().setCons(typeNameAtomCons); + + typeNameAtomCons.cdr().setCons(typeValueValueAtomCons); + + Cons typeSublistCons = SublistCons.getInstance(aEnvironment, typeListAtomCons); + + + + + //Create message association list. + Cons messageListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons messageNameAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"message\""); + + Cons messageValueValueAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, Utility.toMathPiperString(aEnvironment, aStackTop, message)); + + messageListAtomCons.cdr().setCons(messageNameAtomCons); + + messageNameAtomCons.cdr().setCons(messageValueValueAtomCons); + + Cons messageSublistCons = SublistCons.getInstance(aEnvironment, messageListAtomCons); + + + + //Create exception object association list. + Cons exceptionObjectListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons exceptionObjectNameAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "\"exceptionObject\""); + + Cons exceptionObjectValueValueAtomCons = BuiltinObjectCons.getInstance(aEnvironment, aStackTop, exceptionObject); + + exceptionObjectListAtomCons.cdr().setCons(exceptionObjectNameAtomCons); + + exceptionObjectNameAtomCons.cdr().setCons(exceptionObjectValueValueAtomCons); + + Cons exceptionObjectSublistCons = SublistCons.getInstance(aEnvironment, exceptionObjectListAtomCons); + + + + //Create result list. + typeSublistCons.cdr().setCons(messageSublistCons); + + messageSublistCons.cdr().setCons(exceptionObjectSublistCons); + + //exceptionSublistCons.cdr().setCons(xxxSublistCons); + + //xxxSublistCons.cdr().setCons(yyySublistCons); + + Cons resultListAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + resultListAtomCons.cdr().setCons(typeSublistCons); + + Cons resultSublistCons = SublistCons.getInstance(aEnvironment, resultListAtomCons); + + + + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(resultSublistCons); + + } + } +} + + + +/* +%mathpiper_docs,name="ExceptionGet",categories="Programmer Functions;Built In" +*CMD ExceptionGet --- returns the exception object which was thrown. +*CORE +*CALL + ExceptionGet() + +*DESC + +ExceptionGet is designed to be used in the {exceptionHandler} argument of {ExceptionCatch} and it + returns an association list which contains information about the caught exception. If {ExceptionGet} is + evaluated outside of {ExceptionCatch}, it always returns {False}; +{ExceptionCatch} and {ExceptionGet} are used in combination to write +an exception handler. + +*E.G. + +In> ExceptionGet() +Result: False + + + +In> ExceptionCatch(Check(1 = 2, "Test", "Throwing a test exception."), Echo(ExceptionGet())) +Result: True +Side Effects: +{{"type","Test"},{"message","Throwing a test exception."},{"exceptionObject",class org.mathpiper.exceptions.EvaluationException}} + +*SEE Check, ExceptionCatch + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ExpressionToString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ExpressionToString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ExpressionToString.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ExpressionToString.java 2010-12-29 04:07:15.000000000 +0000 @@ -17,7 +17,6 @@ package org.mathpiper.builtin.functions.core; -import org.mathpiper.builtin.BuiltinContainer; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.cons.AtomCons; import org.mathpiper.lisp.Environment; @@ -37,12 +36,12 @@ evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // Get operator - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "ExpressionToString"); - String expressionString = Utility.printExpression(evaluated, aEnvironment, 0); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"" + expressionString + "\"")); + String expressionString = Utility.printMathPiperExpression(aStackTop, evaluated, aEnvironment, 0); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "\"" + expressionString + "\"")); }//end method. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Factorial.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Factorial.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Factorial.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Factorial.java 2010-03-10 06:32:04.000000000 +0000 @@ -33,21 +33,21 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons().getNumber(0) != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons().getNumber(0, aEnvironment) != null, 1, "Factorial"); ConsPointer arg = getArgumentPointer(aEnvironment, aStackTop, 1); //TODO fixme I am sure this can be optimized still // LispError.check(arg.type().equals("Number"), LispError.INVALID_ARGUMENT); - int nr = (int) ((BigNumber) arg.getCons().getNumber(0)).toLong(); - LispError.check(nr >= 0, LispError.INVALID_ARGUMENT); - BigNumber fac = new BigNumber("1", 10, 10); + int nr = (int) ((BigNumber) arg.getCons().getNumber(0, aEnvironment)).toLong(); + LispError.check(aEnvironment, aStackTop, nr >= 0, LispError.INVALID_ARGUMENT, "Factorial"); + BigNumber fac = new BigNumber( "1", 10, 10); int i; for (i = 2; i <= nr; i++) { - BigNumber m = new BigNumber("" + i, 10, 10); + BigNumber m = new BigNumber( "" + i, 10, 10); m.multiply(fac, m, 0); fac = m; } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, fac)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(fac)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastArcCos.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastArcCos.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastArcCos.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastArcCos.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,76 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class FastArcCos extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber x; + + x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + double xDouble = x.toDouble(); + + double result = Math.acos(xDouble); + + if(Double.isNaN(result)) + { + LispError.raiseError("The argument must have a value between -1 and 1.", "FastArcCos", aStackTop, aEnvironment); + } + + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + + z.setTo(result); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + } +}//end class. + + + + +/* +%mathpiper,name="FastArcCos",categories="Programmer Functions;Built In" +*CMD FastArcCos --- double-precision math function +*CORE +*CALL + FastArcCos(x) + +*PARMS +{a} -- a number + +*DESC +This function uses the Java math library. It +should be faster than the arbitrary precision version. + +*SEE FastLog, FastPower + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastArcSin.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastArcSin.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastArcSin.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastArcSin.java 2010-12-29 04:07:15.000000000 +0000 @@ -21,6 +21,7 @@ import org.mathpiper.builtin.BigNumber; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; /** * @@ -32,11 +33,23 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { BigNumber x; + x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); - double result = Math.asin(x.toDouble()); + + double xDouble = x.toDouble(); + + double result = Math.asin(xDouble); + + if(Double.isNaN(result)) + { + LispError.raiseError("The argument must have a value between -1 and 1.", "FastArcSin", aStackTop, aEnvironment); + } + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + z.setTo(result); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. @@ -45,7 +58,7 @@ /* %mathpiper,name="FastArcSin",categories="Programmer Functions;Built In" -*CMD FastArcSin --- double-precision math functions +*CMD FastArcSin --- double-precision math function *CORE *CALL FastArcSin(x) diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastArcTan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastArcTan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastArcTan.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastArcTan.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,76 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class FastArcTan extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber x; + + x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + double xDouble = x.toDouble(); + + double result = Math.atan(xDouble); + + if(Double.isNaN(result)) + { + LispError.raiseError("The argument is NaN.", "FastArcTan", aStackTop, aEnvironment); + } + + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + + z.setTo(result); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + } +}//end class. + + + + +/* +%mathpiper,name="FastArcTan",categories="Programmer Functions;Built In" +*CMD FastArcTan --- double-precision math function +*CORE +*CALL + FastArcTan(x) + +*PARMS +{a} -- a number + +*DESC +This function uses the Java math library. It +should be faster than the arbitrary precision version. + +*SEE FastLog, FastPower + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastCos.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastCos.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastCos.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastCos.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,76 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class FastCos extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber x; + + x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + double xDouble = x.toDouble(); + + double result = Math.cos(xDouble); + + if(Double.isNaN(result)) + { + LispError.raiseError("The result is NaN.", "FastCos", aStackTop, aEnvironment); + } + + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + + z.setTo(result); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + } +}//end class. + + + + +/* +%mathpiper,name="FastCos",categories="Programmer Functions;Built In" +*CMD FastCos --- double-precision math function +*CORE +*CALL + FastCos(x) + +*PARMS +{a} -- a number + +*DESC +This function uses the Java math library. It +should be faster than the arbitrary precision version. + +*SEE FastLog, FastPower + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastIsPrime.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastIsPrime.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastIsPrime.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastIsPrime.java 2010-02-06 21:01:49.000000000 +0000 @@ -56,6 +56,6 @@ BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.setTo(result); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastLog.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastLog.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastLog.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastLog.java 2010-02-06 21:01:49.000000000 +0000 @@ -36,7 +36,7 @@ double result = Math.log(x.toDouble()); BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.setTo(result); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastPower.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastPower.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastPower.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastPower.java 2010-02-06 21:01:49.000000000 +0000 @@ -37,7 +37,7 @@ double result = Math.pow(x.toDouble(), y.toDouble()); BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.setTo(result); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastSin.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastSin.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastSin.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastSin.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,76 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class FastSin extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber x; + + x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + double xDouble = x.toDouble(); + + double result = Math.sin(xDouble); + + if(Double.isNaN(result)) + { + LispError.raiseError("The result is NaN.", "FastSin", aStackTop, aEnvironment); + } + + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + + z.setTo(result); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + } +}//end class. + + + + +/* +%mathpiper,name="FastSin",categories="Programmer Functions;Built In" +*CMD FastSin --- double-precision math function +*CORE +*CALL + FastSin(x) + +*PARMS +{a} -- a number + +*DESC +This function uses the Java math library. It +should be faster than the arbitrary precision version. + +*SEE FastLog, FastPower + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastTan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastTan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FastTan.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FastTan.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,76 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class FastTan extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber x; + + x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + double xDouble = x.toDouble(); + + double result = Math.tan(xDouble); + + if(Double.isNaN(result)) + { + LispError.raiseError("The result is NaN.", "FastTan", aStackTop, aEnvironment); + } + + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + + z.setTo(result); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + } +}//end class. + + + + +/* +%mathpiper,name="FastTan",categories="Programmer Functions;Built In" +*CMD FastTan --- double-precision math function +*CORE +*CALL + FastTan(x) + +*PARMS +{a} -- a number + +*DESC +This function uses the Java math library. It +should be faster than the arbitrary precision version. + +*SEE FastLog, FastPower + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FileSize.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FileSize.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FileSize.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FileSize.java 2010-12-16 01:32:55.000000000 +0000 @@ -39,8 +39,8 @@ { ConsPointer fnameObject = new ConsPointer(); fnameObject.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkIsString(aEnvironment, aStackTop, fnameObject, 1); - String fname = Utility.unstringify( (String) fnameObject.car()); + LispError.checkIsString(aEnvironment, aStackTop, fnameObject, 1, "FileSize"); + String fname = Utility.toNormalString(aEnvironment, aStackTop, (String) fnameObject.car()); String hashedname = (String) aEnvironment.getTokenHash().lookUp(fname); long fileSize = 0; @@ -52,7 +52,7 @@ MathPiperInputStream newInput = // new StdFileInput(hashedname, aEnvironment.iInputStatus); Utility.openInputFile(aEnvironment, aEnvironment.iInputDirectories, hashedname, aEnvironment.iInputStatus); - LispError.check(newInput != null, LispError.FILE_NOT_FOUND); + LispError.check(aEnvironment, aStackTop, newInput != null, LispError.FILE_NOT_FOUND, "FileSize"); fileSize = newInput.startPtr().length(); } catch (Exception e) { @@ -61,6 +61,6 @@ { aEnvironment.iInputStatus.restoreFrom(oldstatus); } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + fileSize)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + fileSize)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FindFile.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FindFile.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FindFile.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FindFile.java 2010-12-16 01:32:55.000000000 +0000 @@ -40,13 +40,13 @@ evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "FindFile"); String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "FindFile"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); String filename = Utility.findFile(oper, aEnvironment.iInputDirectories); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpStringify(filename))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.getTokenHash().lookUpStringify(filename))); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FindFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FindFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FindFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FindFunction.java 2011-02-05 07:50:02.000000000 +0000 @@ -20,12 +20,11 @@ import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.DefFile; import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.userfunctions.MultipleArityUserFunction; +import org.mathpiper.lisp.rulebases.MultipleArityRulebase; /** * @@ -42,14 +41,16 @@ evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "FindFunction"); String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "FindFunction"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); - MultipleArityUserFunction multiUserFunc = - aEnvironment.getMultipleArityUserFunction((String)aEnvironment.getTokenHash().lookUp(oper), false); - if (multiUserFunc != null) + MultipleArityRulebase multiUserFunc = aEnvironment.getMultipleArityRulebase(aStackTop, (String)aEnvironment.getTokenHash().lookUp(oper), false); + + String fileLocation = "\"\"" ; + + if (multiUserFunc != null ) { /*DefFile def = multiUserFunc.iFileToOpen; if (def != null) @@ -57,12 +58,21 @@ getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, def.iFileName)); return; }*/ - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, multiUserFunc.iFileLocation)); - return; - } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"\"")); - } -} + if(multiUserFunc.iFileLocation != null) + { + fileLocation = multiUserFunc.iFileLocation; + } + else + { + fileLocation = "Function is defined, but it has no body."; + } + + }//end if + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, fileLocation)); + }//end method + +}//end class. @@ -86,10 +96,10 @@ *E.G. - In> FindFunction("Sum") - Out> "sums.rep/code.ys"; - In> FindFunction("Integrate") - Out> "integrate.rep/code.ys"; +In> FindFunction("Sum") +Result: "sums.rep/code.ys"; +In> FindFunction("Integrate") +Result: "integrate.rep/code.ys"; *SEE Vi %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/First.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/First.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/First.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/First.java 2011-02-05 07:50:02.000000000 +0000 @@ -30,7 +30,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - Utility.nth(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1), 1); + Utility.nth(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1), 1); } } @@ -55,10 +55,10 @@ *E.G. - In> First({a,b,c}) - Out> a; - In> First(f(a,b,c)); - Out> a; +In> First({a,b,c}) +Result: a; +In> First(f(a,b,c)); +Result: a; *SEE Rest, Length %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FlatCopy.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FlatCopy.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FlatCopy.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FlatCopy.java 2011-02-05 07:50:02.000000000 +0000 @@ -33,7 +33,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { ConsPointer copied = new ConsPointer(); - Utility.flatCopy(aEnvironment, copied, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); + Utility.flatCopy(aEnvironment, aStackTop, copied, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,copied.getCons())); } } @@ -63,14 +63,14 @@ The following shows a possible way to define a command that reverses a list nondestructively. - In> reverse(l_IsList) <-- DestructiveReverse \ +In> reverse(l_IsList) <-- DestructiveReverse \ (FlatCopy(l)); - Out> True; - In> lst := {a,b,c,d,e}; - Out> {a,b,c,d,e}; - In> reverse(lst); - Out> {e,d,c,b,a}; - In> lst; - Out> {a,b,c,d,e}; +Result: True; +In> lst := {a,b,c,d,e}; +Result: {a,b,c,d,e}; +In> reverse(lst); +Result: {e,d,c,b,a}; +In> lst; +Result: {a,b,c,d,e}; %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Floor.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Floor.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Floor.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Floor.java 2010-12-29 04:07:15.000000000 +0000 @@ -2,7 +2,6 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ - package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BigNumber; @@ -13,27 +12,25 @@ * * */ - public class Floor extends BuiltinFunction - { - public void evaluate(Environment aEnvironment,int aStackTop) throws Exception - { - BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); - BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.floor(x); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); - } - }//end class. +public class Floor extends BuiltinFunction { + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + z.floor(x); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + } +}//end class. /* %mathpiper_docs,name="FloorN",categories="User Functions;Numeric;Built In" -*CMD FloorN --- largest integer not larger than x (arbitrary-precision math function) -*CORE -*CALL - FloorN(x) + *CMD FloorN --- largest integer not larger than x (arbitrary-precision math function) + *CORE + *CALL +FloorN(x) -*DESC + *DESC This command performs the calculation of an elementary mathematical function. The arguments must be numbers. The reason for the @@ -48,9 +45,9 @@ {BuiltinPrecisionSet}. However, when the result is mathematically not an integer, the functions return a floating-point result which is correct only to the current precision. -*E.G. - In> - Result> + *E.G. +In> +Result> %/mathpiper_docs -*/ + */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FromBase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FromBase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FromBase.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FromBase.java 2011-02-05 07:50:02.000000000 +0000 @@ -24,7 +24,6 @@ import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.NumberCons; /** * @@ -41,10 +40,10 @@ oper.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // check that getTopOfStackPointer is a number, and that it is in fact an integer // LispError.check(oper.type().equals("Number"), LispError.KLispErrInvalidArg); - BigNumber num = (BigNumber) oper.getCons().getNumber(aEnvironment.getPrecision()); - LispError.checkArgument(aEnvironment, aStackTop, num != null, 1); + BigNumber num = (BigNumber) oper.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + LispError.checkArgument(aEnvironment, aStackTop, num != null, 1, "FromBase"); // check that the base is an integer between 2 and 32 - LispError.checkArgument(aEnvironment, aStackTop, num.isInteger(), 1); + LispError.checkArgument(aEnvironment, aStackTop, num.isInteger(), 1, "FromBase"); // Get a short platform integer from the car argument int base = (int) (num.toDouble()); @@ -54,15 +53,15 @@ fromNum.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); String str2; str2 = (String) fromNum.car(); - LispError.checkArgument(aEnvironment, aStackTop, str2 != null, 2); + LispError.checkArgument(aEnvironment, aStackTop, str2 != null, 2, "FromBase"); // Added, unquote a string - LispError.checkArgument(aEnvironment, aStackTop, Utility.isString(str2), 2); + LispError.checkArgument(aEnvironment, aStackTop, Utility.isString(str2), 2, "FromBase"); str2 = aEnvironment.getTokenHash().lookUpUnStringify(str2); // convert using correct base BigNumber z = new BigNumber(str2, aEnvironment.getPrecision(), base); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } @@ -100,8 +99,8 @@ Write the binary number {111111} as a decimal number: - In> FromBase(2,"111111") - Out> 63; +In> FromBase(2,"111111") +Result: 63; *SEE PAdicExpand,ToBase diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FromFile.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FromFile.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FromFile.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FromFile.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.io.InputStatus; -import org.mathpiper.lisp.Environment; -import org.mathpiper.io.MathPiperInputStream; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class FromFile extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - LispError.check(aEnvironment, aStackTop, aEnvironment.iSecure == false, LispError.SECURITY_BREACH); - ConsPointer evaluated = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, evaluated, getArgumentPointer(aEnvironment, aStackTop, 1)); - - // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); - String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - - String hashedname = aEnvironment.getTokenHash().lookUpUnStringify(orig); - - InputStatus oldstatus = aEnvironment.iInputStatus; - MathPiperInputStream previous = aEnvironment.iCurrentInput; - try - { - aEnvironment.iInputStatus.setTo(hashedname); - MathPiperInputStream input = // new StdFileInput(hashedname, aEnvironment.iInputStatus); - Utility.openInputFile(aEnvironment, aEnvironment.iInputDirectories, hashedname, aEnvironment.iInputStatus); - aEnvironment.iCurrentInput = input; - // Open file - LispError.check(aEnvironment, aStackTop, input != null, LispError.FILE_NOT_FOUND); - - // Evaluate the body - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); - } catch (Exception e) - { - throw e; - } finally - { - aEnvironment.iCurrentInput = previous; - aEnvironment.iInputStatus.restoreFrom(oldstatus); - } - //Return the getTopOfStackPointer - } -} - - - -/* -%mathpiper_docs,name="FromFile",categories="User Functions;Input/Output;Built In" -*CMD FromFile --- connect current input to a file -*CORE -*CALL - FromFile(name) body - -*PARMS - -{name} - string, the name of the file to read - -{body} - expression to be evaluated - -*DESC - -The current input is connected to the file "name". Then the expression -"body" is evaluated. If some functions in "body" try to read -from current input, they will now read from the file "name". Finally, the -file is closed and the result of evaluating "body" is returned. - -*E.G. notest - -Suppose that the file {foo} contains - - 2 + 5; - -Then we can have the following dialogue: - - In> FromFile("foo") res := Read(); - Out> 2+5; - In> FromFile("foo") res := ReadToken(); - Out> 2; - -*SEE ToFile, FromString, Read, ReadToken -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FromString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FromString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FromString.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FromString.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.io.InputStatus; -import org.mathpiper.io.StringInputStream; -import org.mathpiper.lisp.Environment; -import org.mathpiper.io.MathPiperInputStream; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class FromString extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - ConsPointer evaluated = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, evaluated, getArgumentPointer(aEnvironment, aStackTop, 1)); - - // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); - String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); - - InputStatus oldstatus = aEnvironment.iInputStatus; - aEnvironment.iInputStatus.setTo("String"); - StringInputStream newInput = new StringInputStream(new StringBuffer(oper), aEnvironment.iInputStatus); - - MathPiperInputStream previous = aEnvironment.iCurrentInput; - aEnvironment.iCurrentInput = newInput; - try - { - // Evaluate the body - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); - } catch (Exception e) - { - throw e; - } finally - { - aEnvironment.iCurrentInput = previous; - aEnvironment.iInputStatus.restoreFrom(oldstatus); - } - - //Return the getTopOfStackPointer - } -} - - - -/* -%mathpiper_docs,name="FromString",categories="User Functions;Input/Output;Built In" -*CMD FromString --- connect current input to a string -*CORE -*CALL - FromString(str) body; - -*PARMS - -{str} -- a string containing the text to parse - -{body} -- expression to be evaluated - -*DESC - -The commands in "body" are executed, but everything that is read -from the current input is now read from the string "str". The -result of "body" is returned. - -*E.G. - - In> FromString("2+5; this is never read") \ - res := Read(); - Out> 2+5; - In> FromString("2+5; this is never read") \ - res := Eval(Read()); - Out> 7; - -*SEE ToString, FromFile, Read, ReadToken -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FullForm.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FullForm.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FullForm.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FullForm.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.printers.LispPrinter; - -/** - * - * - */ -public class FullForm extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispPrinter printer = new LispPrinter(); - printer.print(getTopOfStackPointer(aEnvironment, aStackTop), aEnvironment.iCurrentOutput, aEnvironment); - aEnvironment.write("\n"); - } -} - - - -/* -%mathpiper_docs,name="FullForm",categories="User Functions;Input/Output;Built In" -*CMD FullForm --- print an expression in LISP-format -*CORE -*CALL - FullForm(expr) - -*PARMS - -{expr} -- expression to be printed in LISP-format - -*DESC - -Evaluates "expr", and prints it in LISP-format on the current -output. It is followed by a newline. The evaluated expression is also -returned. - -This can be useful if you want to study the internal representation of -a certain expression. - -*E.G. notest - - In> FullForm(a+b+c); - (+ (+ a b )c ) - Out> a+b+c; - In> FullForm(2*I*b^2); - (* (Complex 0 2 )(^ b 2 )) - Out> Complex(0,2)*b^2; - -The first example shows how the expression {a+b+c} is -internally represented. In the second example, {2*I} is -first evaluated to {Complex(0,2)} before the expression -is printed. - -*SEE LispRead, Listify, Unlist -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FunctionToList.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FunctionToList.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/FunctionToList.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/FunctionToList.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,73 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.SublistCons; + +/** + * + * + */ +public class FunctionToList extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer, 1, "FunctionToList"); + ConsPointer head = new ConsPointer(); + head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); + head.cdr().setCons(((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()).getCons()); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,head.getCons())); + } +} + + + +/* +%mathpiper_docs,name="FunctionToList",categories="User Functions;Lists (Operations);Built In" +*CMD FunctionToList --- convert a function application to a list +*CORE +*CALL + FunctionToList(expr) + +*PARMS + +{expr} -- expression to be converted + +*DESC + +The parameter "expr" is expected to be a compound object, i.e. not +an atom. It is evaluated and then converted to a list. The car entry +in the list is the top-level operator in the evaluated expression and +the other entries are the arguments to this operator. Finally, the +list is returned. + +*E.G. + +In> FunctionToList(Cos(x)); +Result: {Cos,x}; +In> FunctionToList(3*a); +Result: {*,3,a}; + +*SEE List, ListToFunction, IsAtom +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Gcd.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Gcd.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Gcd.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Gcd.java 2011-02-05 07:50:02.000000000 +0000 @@ -34,8 +34,8 @@ BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.gcd(x, y); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + z.gcd(x, y, null, aStackTop); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. @@ -64,8 +64,8 @@ the functions return a floating-point result which is correct only to the current precision. *E.G. - In> - Result> +In> +Result: %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GenericTypeName.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GenericTypeName.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GenericTypeName.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GenericTypeName.java 2011-02-05 07:50:02.000000000 +0000 @@ -36,8 +36,8 @@ { ConsPointer evaluated = new ConsPointer(); evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, evaluated.car() instanceof BuiltinContainer, 1); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, ((BuiltinContainer) evaluated.car()).typeName())); + LispError.checkArgument(aEnvironment, aStackTop, evaluated.car() instanceof BuiltinContainer, 1, "GenericTypeName"); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, ((BuiltinContainer) evaluated.car()).typeName())); } }//end class. @@ -56,8 +56,8 @@ *E.G. - In> GenericTypeName(ArrayCreate(10,1)) - Out> "Array"; +In> GenericTypeName(ArrayCreate(10,1)) +Result: "Array"; %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GetCoreError.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GetCoreError.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GetCoreError.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GetCoreError.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class GetCoreError extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpStringify(aEnvironment.iError))); - } -} - - - -/* -%mathpiper_docs,name="GetCoreError",categories="Programmer Functions;Built In" -*CMD GetCoreError --- get "hard" error string -*CORE -*CALL - GetCoreError() - -*DESC - -GetCoreError returns a string describing the core error. -TrapError and GetCoreError can be used in combination to write -a custom error handler error reporting facility that does not stop the execution is provided by the function {Assert}. - -**E.G. - - In> - -*SEE Assert, Check, TrapError - -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GetExactBits.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GetExactBits.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GetExactBits.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GetExactBits.java 2011-02-05 07:50:02.000000000 +0000 @@ -39,7 +39,7 @@ ? numberToCheck.bitCount() // for integers, return the bit count : Utility.digitsToBits((long) (numberToCheck.getPrecision()), 10) // for floats, return the getPrecision ); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, numberToReturn)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(numberToReturn)); } } @@ -73,17 +73,17 @@ *E.G. The default precision of 10 decimals corresponds to 33 bits: - In> GetExactBitsN(1000.123) - Out> 33; - In> x:=SetExactBits(10., 20) - Out> 10.; - In> GetExactBitsN(x) - Out> 20; +In> GetExactBitsN(1000.123) +Result: 33; +In> x:=SetExactBits(10., 20) +Result: 10.; +In> GetExactBitsN(x) +Result: 20; Prepare a "floating zero" representing an interval [-4, 4]: - In> x:=SetExactBits(0., -2) - Out> 0.; - In> x=0 - Out> True; +In> x:=SetExactBits(0., -2) +Result: 0.; +In> x=0 +Result: True; *SEE BuiltinPrecisionSet, BuiltinPrecisionGet, SetExactBitsN %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GlobalVariablesGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GlobalVariablesGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GlobalVariablesGet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GlobalVariablesGet.java 2011-04-24 07:45:56.000000000 +0000 @@ -0,0 +1,78 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.SublistCons; + +/** + * + * + */ +public class GlobalVariablesGet extends BuiltinFunction { + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + java.util.Set variablesSet = ((Map) aEnvironment.getGlobalState().getMap()).keySet(); + + java.util.List variablesList = new ArrayList(variablesSet); + + Collections.sort(variablesList, new NameComparator() ); + + Cons head = Utility.iterableToList(aEnvironment, aStackTop, variablesList); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, head)); + + }//end method. + + + + private class NameComparator implements Comparator{ + + public int compare(String s1, String s2) { + return s1.compareToIgnoreCase(s2); + }//end method. + }//end class. + +}//end class. + + + +/* +%mathpiper_docs,name="GlobalVariablesGet",categories="User Functions;Variables" +*CMD GlobalVariablesGet --- return a list which contains the names of all the global variables + +*CALL +GlobalVariablesGet() + + +*DESC +Return a list which contains the names of all the global variables. + +*E.G. +In> GlobalVariablesGet() +Result> {\$CacheOfConstantsN1,%,I,\$numericMode2} + +%/mathpiper_docs + */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GreaterThan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GreaterThan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/GreaterThan.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/GreaterThan.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class GreaterThan extends BuiltinFunction -{ - - LexGreaterThan compare = new LexGreaterThan(); - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - compare.Compare(aEnvironment, aStackTop); - } -}//end class. - - - -/* -%mathpiper_docs,name="GreaterThan" -*CMD GreaterThan --- comparison predicate -*CORE -*CALL - GreaterThan(a,b) - -*PARMS -{a}, {b} -- numbers or strings -*DESC -Comparing numbers or strings (lexicographically). - -**E.G. - In> GreaterThan(1,1) - Out> False; - In> GreaterThan("b","a") - Out> True; - -*SEE LessThan, Equals -%/mathpiper_docs -*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/HistorySize.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/HistorySize.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/HistorySize.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/HistorySize.java 2011-02-05 07:50:02.000000000 +0000 @@ -33,7 +33,7 @@ { aEnvironment.write("Function not yet implemented : LispHistorySize");//TODO FIXME - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } @@ -65,9 +65,9 @@ *E.G. - In> HistorySize(200) - Out> True; - In> quit +In> HistorySize(200) +Result: True; +In> quit *SEE quit %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/HoldArg.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/HoldArg.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/HoldArg.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/HoldArg.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class HoldArg extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - // Get operator - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - - // The arguments - String tohold = (String) getArgumentPointer(aEnvironment, aStackTop, 2).car(); - LispError.checkArgument(aEnvironment, aStackTop, tohold != null, 2); - aEnvironment.holdArgument(Utility.getSymbolName(aEnvironment, orig), tohold); - // Return true - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} - - - -/* -%mathpiper_docs,name="HoldArg",categories="User Functions;Built In" -*CMD HoldArg --- mark argument as not evaluated -*CORE -*CALL - HoldArg("operator",parameter) - -*PARMS - -{"operator"} -- string, name of a function - -{parameter} -- atom, symbolic name of parameter - -*DESC -Specify that parameter should -not be evaluated before used. This will be -declared for all arities of "operator", at the moment -this function is called, so it is best called -after all {RuleBase} calls for this operator. -"operator" can be a string or atom specifying the -function name. - -The {parameter} must be an atom from the list of symbolic -arguments used when calling {RuleBase}. - -*SEE RuleBase, HoldArgNr, RuleBaseArgList -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/HoldArgument.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/HoldArgument.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/HoldArgument.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/HoldArgument.java 2010-07-14 23:26:25.000000000 +0000 @@ -0,0 +1,77 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class HoldArgument extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + // Get operator + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "HoldArgument"); + String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "HoldArgument"); + + // The arguments + String tohold = (String) getArgumentPointer(aEnvironment, aStackTop, 2).car(); + LispError.checkArgument(aEnvironment, aStackTop, tohold != null, 2, "HoldArgument"); + aEnvironment.holdArgument(aStackTop, Utility.getSymbolName(aEnvironment, orig), tohold, aEnvironment); + // Return true + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + + +/* +%mathpiper_docs,name="HoldArgument",categories="Programmer Functions;Programming;Built In" +*CMD HoldArgument --- mark argument as not evaluated +*CORE +*CALL + HoldArgument("operator",parameter) + +*PARMS + +{"operator"} -- string, name of a function + +{parameter} -- atom, symbolic name of parameter + +*DESC +Specify that parameter should +not be evaluated before used. This will be +declared for all arities of "operator", at the moment +this function is called, so it is best called +after all {Rulebase} calls for this operator. +"operator" can be a string or atom specifying the +function name. + +The {parameter} must be an atom from the list of symbolic +arguments used when calling {Rulebase}. + +*SEE Rulebase, HoldArgumentNumber, RulebaseArgumentsList +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Hold.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Hold.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Hold.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Hold.java 2010-07-14 23:26:25.000000000 +0000 @@ -34,7 +34,7 @@ } /* -%mathpiper_docs,name="Hold",categories="User Functions;Control Flow;Built In" +%mathpiper_docs,name="Hold",categories="Programmer Functions;Programming;Built In" *CMD Hold --- keep expression unevaluated *CORE *CALL @@ -50,14 +50,16 @@ prevent the evaluation of a certain expression in a context in which evaluation normally takes place. -The function {UnList()} also leaves its result unevaluated. Both functions stop the process of evaluation (no more rules will be applied). +The function {ListToFunction()} also leaves its result unevaluated. + Both functions stop the process of evaluation (no more rules will be applied). -*E.G. notest +*E.G. - In> Echo({ Hold(1+1), "=", 1+1 }); - 1+1 = 2 - Out> True; +In> Echo({ Hold(1+1), "=", 1+1 }); +Result: True +Side Effects: +{1+1,"=",2} -*SEE Eval, HoldArg, UnList +*SEE Eval, HoldArgument, ListToFunction %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/If.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/If.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/If.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/If.java 2011-02-05 07:50:02.000000000 +0000 @@ -32,21 +32,21 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - int nrArguments = Utility.listLength(getArgumentPointer(aEnvironment, aStackTop, 0)); + int nrArguments = Utility.listLength(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0)); LispError.check(aEnvironment, aStackTop, nrArguments == 3 || nrArguments == 4, LispError.WRONG_NUMBER_OF_ARGUMENTS); ConsPointer predicate = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, predicate, getArgumentPointer(aEnvironment, aStackTop, 1)); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, predicate, getArgumentPointer(aEnvironment, aStackTop, 1)); - if (Utility.isTrue(aEnvironment, predicate)) + if (Utility.isTrue(aEnvironment, predicate, aStackTop)) { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(getArgumentPointer(aEnvironment, aStackTop, 0), 2)); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0), 2)); } else { - LispError.checkArgument(aEnvironment, aStackTop, Utility.isFalse(aEnvironment, predicate), 1); + LispError.checkArgument(aEnvironment, aStackTop, Utility.isFalse(aEnvironment, predicate, aStackTop), 1, "If"); if (nrArguments == 4) { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(getArgumentPointer(aEnvironment, aStackTop, 0), 3)); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0), 3)); } else { Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); @@ -84,19 +84,19 @@ The sign function is defined to be 1 if its argument is positive and -1 if its argument is negative. A possible implementation is - In> mysign(x) := If (IsPositiveReal(x), 1, -1); - Out> True; - In> mysign(Pi); - Out> 1; - In> mysign(-2.5); - Out> -1; +In> mysign(x) := If (IsPositiveReal(x), 1, -1); +Result: True; +In> mysign(Pi); +Result: 1; +In> mysign(-2.5); +Result: -1; Note that this will give incorrect results, if "x" cannot be numerically approximated. - In> mysign(a); - Out> -1; +In> mysign(a); +Result: -1; Hence a better implementation would be - In> mysign(_x)_IsNumber(N(x)) <-- If \ +In> mysign(_x)_IsNumber(N(x)) <-- If \ (IsPositiveReal(x), 1, -1); - Out> True; +Result: True; %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Infix.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Infix.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Infix.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Infix.java 2011-02-05 07:50:02.000000000 +0000 @@ -63,11 +63,11 @@ Precedence is optional (will be set to 0 by default). *E.G. - In> Infix("##", 5) - Out> True; - In> a ## b ## c - Out> a##b##c; +In> Infix("##", 5) +Result: True; +In> a ## b ## c +Result: a##b##c; -*SEE IsBodied, OpPrecedence, Bodied, Postfix, Prefix +*SEE IsBodied, PrecedenceGet, Bodied, Postfix, Prefix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Insert.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Insert.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Insert.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Insert.java 2011-02-05 07:50:02.000000000 +0000 @@ -66,12 +66,12 @@ *E.G. - In> Insert({a,b,c,d}, 4, x); - Out> {a,b,c,x,d}; - In> Insert({a,b,c,d}, 5, x); - Out> {a,b,c,d,x}; - In> Insert({a,b,c,d}, 1, x); - Out> {x,a,b,c,d}; +In> Insert({a,b,c,d}, 4, x); +Result: {a,b,c,x,d}; +In> Insert({a,b,c,d}, 5, x); +Result: {a,b,c,d,x}; +In> Insert({a,b,c,d}, 1, x); +Result: {x,a,b,c,d}; *SEE DestructiveInsert, :, Append, Delete, Remove %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsAtom.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsAtom.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsAtom.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsAtom.java 2011-02-05 07:50:02.000000000 +0000 @@ -58,10 +58,10 @@ *E.G. - In> IsAtom(x+5); - Out> False; - In> IsAtom(5); - Out> True; +In> IsAtom(x+5); +Result: False; +In> IsAtom(5); +Result: True; *SEE IsFunction, IsNumber, IsString %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsBodied.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsBodied.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsBodied.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsBodied.java 2011-02-05 07:50:02.000000000 +0000 @@ -19,9 +19,8 @@ package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.InfixOperator; +import org.mathpiper.lisp.Operator; import org.mathpiper.lisp.Utility; /** @@ -33,7 +32,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - InfixOperator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iBodiedOperators); + Operator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iBodiedOperators); Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), op != null); } } @@ -58,11 +57,11 @@ *E.G. - In> IsBodied("While"); - Out> True; - In> IsBodied("Sin"); - Out> False; +In> IsBodied("While"); +Result: True; +In> IsBodied("Sin"); +Result: False; -*SEE Bodied, OpPrecedence,IsInfix,IsPostfix,IsPrefix +*SEE Bodied, PrecedenceGet,IsInfix,IsPostfix,IsPrefix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsBound.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsBound.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsBound.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsBound.java 2011-02-05 07:50:02.000000000 +0000 @@ -37,7 +37,7 @@ { String str = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); ConsPointer val = new ConsPointer(); - aEnvironment.getGlobalVariable(str, val); + aEnvironment.getGlobalVariable(aStackTop, str, val); if (val.getCons() != null) { Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); @@ -68,12 +68,12 @@ *E.G. - In> IsBound(x); - Out> False; - In> x := 5; - Out> 5; - In> IsBound(x); - Out> True; +In> IsBound(x); +Result: False; +In> x := 5; +Result: 5; +In> IsBound(x); +Result: True; *SEE IsAtom %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsDecimal.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsDecimal.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsDecimal.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsDecimal.java 2010-07-23 05:26:16.000000000 +0000 @@ -36,7 +36,7 @@ ConsPointer result = new ConsPointer(); result.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - Object cons = result.getCons().getNumber(aEnvironment.getPrecision()); + Object cons = result.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); BigNumber bigNumber; if(cons instanceof BigNumber) @@ -74,16 +74,16 @@ *E.G. In> IsDecimal(3.25); -Out> True; +Result: True; In> IsDecimal(6); -Out> False; +Result: False; In> IsDecimal(1/2); -Out> False; +Result: False; In> IsDecimal(3.2/10); -Out> False; +Result: False; *SEE IsString, IsAsom, IsInteger, IsPositiveNumber, IsNegativeNumber, IsNumber %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsEqual.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsEqual.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsEqual.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsEqual.java 2010-02-06 21:01:49.000000000 +0000 @@ -0,0 +1,63 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class IsEqual extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + ConsPointer evaluated1 = new ConsPointer(); + evaluated1.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + ConsPointer evaluated2 = new ConsPointer(); + evaluated2.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + + Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), + Utility.equals(aEnvironment, aStackTop, evaluated1, evaluated2)); + } +}//end class. + + + + +/* +%mathpiper_docs,name="IsEqual",categories="User Functions;Built In" +*CMD IsEqual --- check equality +*CORE +*CALL + IsEqual(a,b) + +*DESC +Compares evaluated {a} and {b} recursively +(stepping into expressions). So "IsEqual(a,b)" returns +"True" if the expressions would be printed exactly +the same, and "False" otherwise. + +*SEE GreaterThan, IsLessThan + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsFunction.java 2011-02-05 07:50:02.000000000 +0000 @@ -58,10 +58,10 @@ *E.G. - In> IsFunction(x+5); - Out> True; - In> IsFunction(x); - Out> False; +In> IsFunction(x+5); +Result: True; +In> IsFunction(x); +Result: False; *SEE IsAtom, IsList, Type %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsGreaterThan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsGreaterThan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsGreaterThan.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsGreaterThan.java 2011-01-20 22:07:09.000000000 +0000 @@ -0,0 +1,61 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class IsGreaterThan extends BuiltinFunction +{ + + LexGreaterThan compare = new LexGreaterThan(); + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + compare.Compare(aEnvironment, aStackTop); + } +}//end class. + + + +/* +%mathpiper_docs,name="IsGreaterThan",categories="User Functions;Predicates;Built In" +*CMD IsGreaterThan --- comparison predicate +*CORE +*CALL + IsGreaterThan(a,b) + +*PARMS +{a}, {b} -- decimal numbers or strings +*DESC +Compare decimal numbers or strings (lexicographically). + +*E.G. +In> IsGreaterThan(1,1) +Result: False; +In> IsGreaterThan("b","a") +Result: True; + +*SEE IsLessThan, IsEqual +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsInfix.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsInfix.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsInfix.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsInfix.java 2011-02-05 07:50:02.000000000 +0000 @@ -19,9 +19,8 @@ package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.InfixOperator; +import org.mathpiper.lisp.Operator; import org.mathpiper.lisp.Utility; /** @@ -33,7 +32,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - InfixOperator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); + Operator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), op != null); } } @@ -58,9 +57,9 @@ *E.G. - In> IsInfix("+"); - Out> True; +In> IsInfix("+"); +Result: True; -*SEE Bodied, OpPrecedence,IsBodied,IsPostfix,IsPrefix +*SEE Bodied, PrecedenceGet,IsBodied,IsPostfix,IsPrefix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsInteger.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsInteger.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsInteger.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsInteger.java 2010-12-29 04:07:15.000000000 +0000 @@ -21,10 +21,8 @@ import org.mathpiper.builtin.BigNumber; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.NumberCons; /** * @@ -39,7 +37,7 @@ result.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // LispError.check(result.type().equals("Number"), LispError.KLispErrInvalidArg); - BigNumber num = (BigNumber) result.getCons().getNumber(aEnvironment.getPrecision()); + BigNumber num = (BigNumber) result.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); if (num == null) { Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); @@ -70,16 +68,16 @@ *E.G. In> IsInteger(6); -Out> True; +Result: True; In> IsInteger(3.25); -Out> False; +Result: False; In> IsInteger(1/2); -Out> False; +Result: False; In> IsInteger(3.2/10); -Out> False; +Result: False; *SEE IsString, IsAtom, IsInteger, IsDecimal, IsPositiveNumber, IsNegativeNumber, IsNumber %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsLessThan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsLessThan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsLessThan.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsLessThan.java 2011-01-20 22:07:09.000000000 +0000 @@ -0,0 +1,62 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class IsLessThan extends BuiltinFunction +{ + + LexLessThan compare = new LexLessThan(); + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + compare.Compare(aEnvironment, aStackTop); + } +}//end class. + + + + +/* +%mathpiper_docs,name="IsLessThan",categories="User Functions;Predicates;Built In" +*CMD IsLessThan --- comparison predicate +*CORE +*CALL + IsLessThan(a,b) + +*PARMS +{a}, {b} -- decimal numbers or strings +*DESC +Compare decimal numbers or strings (lexicographically). + +*E.G. +In> IsLessThan(1,1) +Result: False; +In> IsLessThan("a","b") +Result: True; + +*SEE IsGreaterThan, IsEqual +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsList.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsList.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsList.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsList.java 2011-02-05 07:50:02.000000000 +0000 @@ -58,10 +58,10 @@ *E.G. - In> IsList({2,3,5}); - Out> True; - In> IsList(2+3+5); - Out> False; +In> IsList({2,3,5}); +Result: True; +In> IsList(2+3+5); +Result: False; *SEE IsFunction %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsNumber.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsNumber.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsNumber.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsNumber.java 2010-11-29 09:04:48.000000000 +0000 @@ -34,7 +34,7 @@ { ConsPointer result = new ConsPointer(); result.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), result.getCons().getNumber(aEnvironment.getPrecision()) != null); + Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), result.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment) != null); } } @@ -56,18 +56,42 @@ This function tests whether "expr" is a number. There are two kinds of numbers, integers (e.g. 6) and reals (e.g. -2.75 or 6.0). Note that a complex number is represented by the {Complex} -function, so {IsNumber} will return {False}. +function, so {IsNumber} will return {False}. The value {False} will be returned +for all expressions which are lists, but the user should be especially aware of expression +lists which might appear to be numbers, such as those returned by Hold(-1) (see below). + *E.G. +In> IsNumber(6); +Result: True; - In> IsNumber(6); - Out> True; - In> IsNumber(3.25); - Out> True; - In> IsNumber(I); - Out> False; - In> IsNumber("duh"); - Out> False; +In> IsNumber(3.25); +Result: True; + +In> IsNumber(I); +Result: False; + +In> IsNumber(-1) +Result: True + +In> LispForm(-1) +Result: -1 +Side Effects: +-1 + +In> Hold(-1) +Result: -1 + +In> IsNumber(Hold(-1)) +Result: False + +In> LispForm(Hold(-1)) +Result: -1 +Side Effects: +(- 1 ) + +In> IsNumber("duh"); +Result: False; *SEE IsAtom, IsString, IsInteger, IsDecimal, IsPositiveNumber, IsNegativeNumber, Complex %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsPostfix.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsPostfix.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsPostfix.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsPostfix.java 2011-02-05 07:50:02.000000000 +0000 @@ -19,9 +19,8 @@ package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.InfixOperator; +import org.mathpiper.lisp.Operator; import org.mathpiper.lisp.Utility; /** @@ -33,7 +32,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - InfixOperator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPostfixOperators); + Operator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPostfixOperators); Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), op != null); } } @@ -58,9 +57,9 @@ *E.G. - In> IsPostfix("!"); - Out> True; +In> IsPostfix("!"); +Result: True; -*SEE Bodied, OpPrecedence,IsBodied,IsInfix,IsPrefix +*SEE Bodied, PrecedenceGet,IsBodied,IsInfix,IsPrefix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsPrefix.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsPrefix.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsPrefix.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsPrefix.java 2011-02-05 07:50:02.000000000 +0000 @@ -19,9 +19,8 @@ package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.InfixOperator; +import org.mathpiper.lisp.Operator; import org.mathpiper.lisp.Utility; /** @@ -33,7 +32,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - InfixOperator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPrefixOperators); + Operator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPrefixOperators); Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), op != null); } } @@ -58,9 +57,9 @@ *E.G. - In> IsPrefix("-") - Result> True +In> IsPrefix("-") +Result: True -*SEE Bodied, OpPrecedence,IsBodied,IsInfix,IsPostfix +*SEE Bodied, PrecedenceGet,IsBodied,IsInfix,IsPostfix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsPromptShown.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsPromptShown.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsPromptShown.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsPromptShown.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,7 +33,7 @@ { aEnvironment.write("Function not yet implemented : LispIsPromptShown");//TODO FIXME - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/IsString.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/IsString.java 2011-02-05 07:50:02.000000000 +0000 @@ -69,10 +69,10 @@ *E.G. - In> IsString("duh"); - Out> True; - In> IsString(duh); - Out> False; +In> IsString("duh"); +Result: True; +In> IsString(duh); +Result: False; *SEE IsAtom, IsNumber %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaAccess.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaAccess.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaAccess.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaAccess.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,78 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.ConsPointer; + +/** + * + * + */ +public class JavaAccess extends BuiltinFunction { + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + ConsPointer args = new ConsPointer(); + + args.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + + args.goSub(aStackTop, aEnvironment); + + args.goNext(aStackTop, aEnvironment); + + ConsPointer result = new ConsPointer(); + + Utility.applyString(aEnvironment, aStackTop, result, "\"JavaCall\"", args); + + Utility.applyString(aEnvironment, aStackTop, result, "\"JavaToValue\"", result); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(result.getCons()); + + }//end method. +} + + + +/* +%mathpiper_docs,name="JavaAccess",categories="Programmer Functions;Built In;Native Objects",access="experimental" +*CMD JavaAccess --- calls a method on a Java object and converts the result into a MathPiper data structure +*CALL + JavaAccess(javaObject, methodName, methodParameter1, methodParameter2, ...) + +*PARMS +{javaObject} -- a Java object + +{methodName} -- the name of a method to call on the Java object (it can be either a string or an atom) + +{methodParameters} -- zero or more parameters which will be sent to the method + +*DESC +This is a convenience function which can be used instead of using JavaCall and JavaToValue. + +*E.G. +In> javaString := JavaNew("java.lang.String", "Hello") +Result: java.lang.String + +In> JavaAccess(javaString, "charAt",1) +Result: e + +*SEE JavaNew, JavaCall, JavaToValue +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaCall.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaCall.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaCall.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaCall.java 2011-02-04 02:14:48.000000000 +0000 @@ -0,0 +1,230 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import java.util.ArrayList; +import java.util.List; +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinContainer; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.builtin.javareflection.Invoke; +import org.mathpiper.builtin.javareflection.JavaField; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.ConsTraverser; +import org.mathpiper.lisp.cons.NumberCons; +import org.mathpiper.lisp.cons.SublistCons; + +/** + * + * + */ +public class JavaCall extends BuiltinFunction { + + //private StandardFileOutputStream out = new StandardFileOutputStream(System.out); + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + if (getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer) { + + ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, subList); + + //Skip past List type. + consTraverser.goNext(aStackTop); + + //Obtain the Java object to call. + Cons argumentCons = consTraverser.getPointer().getCons(); + + BuiltinContainer builtinContainer = null; + + if (argumentCons != null) { + + + + + if (argumentCons.car() instanceof String) { + String firstArgumentString = (String) argumentCons.car(); + //Strip leading and trailing quotes. + firstArgumentString = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop,firstArgumentString); + Object clas = Class.forName(firstArgumentString); + builtinContainer = new JavaObject(clas); + } else if (argumentCons.car() instanceof BuiltinContainer) { + builtinContainer = (BuiltinContainer) argumentCons.car(); + }//end else. + + + if (builtinContainer != null) { + + + consTraverser.goNext(aStackTop); + argumentCons = consTraverser.getPointer().getCons(); + String methodName = (String) argumentCons.car(); + //Strip leading and trailing quotes. + methodName = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, methodName); + + consTraverser.goNext(aStackTop); + + ArrayList argumentArrayList = new ArrayList(); + + while (consTraverser.getCons() != null) { + argumentCons = consTraverser.getPointer().getCons(); + + Object argument = null; + + if (argumentCons instanceof NumberCons) { + NumberCons numberCons = (NumberCons) argumentCons; + BigNumber bigNumber = (BigNumber) numberCons.getNumber(aEnvironment.getPrecision(), aEnvironment); + + if (bigNumber.isInteger()) { + argument = bigNumber.toInt(); + } else { + argument = bigNumber.toDouble(); + } + } else if (argumentCons instanceof AtomCons) { + String string = (String) ((AtomCons) argumentCons).car(); + if (string != null) { + + if (Utility.isString(string)) { //MathPiper string. + argument = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, (String) string); + } else { //Atom. + if (string.equals("True")) { + argument = Boolean.TRUE; + }//end if. + + if (string.equals("False")) { + argument = Boolean.FALSE; + }//end if. + }//end if/else. + + }//end if. + } else { + argument = argumentCons.car(); + + + if (argument instanceof JavaObject) { + argument = ((JavaObject) argument).getObject(); + } + + }//end if/else. + + + argumentArrayList.add(argument); + + consTraverser.goNext(aStackTop); + + }//end while. + + + Object[] argumentsArray = (Object[]) argumentArrayList.toArray(new Object[0]); + + Object targetObject = builtinContainer.getObject(); + + Object returnObject = null; + + if(targetObject instanceof Class) + { + try + { + returnObject = Invoke.invokeStatic((Class) targetObject, methodName, argumentsArray); + } + catch(Exception e1) + { + try + { + returnObject = JavaField.getField((Class) targetObject, methodName, true).get(null); + } + catch(Exception e2) + { + LispError.raiseError("Method or field " + methodName + " does not exist.", "", -2, null); + } + } + } + else + { + returnObject = Invoke.invokeInstance(targetObject, methodName, argumentsArray, true); + } + + if (returnObject instanceof List) { + Cons listCons = Utility.iterableToList(aEnvironment, aStackTop, (List) returnObject); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, listCons)); + } else { + JavaObject response = new JavaObject(returnObject); + if (response == null || response.getObject() == null) { + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + return; + } + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + } + + + return; + + }//end if. + + }//end if. + + }//end if. + + Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + + }//end method. +} + + + + +/* +%mathpiper_docs,name="JavaCall",categories="Programmer Functions;Built In;Native Objects",access="experimental" +*CMD JavaCall --- calls a method on a Java object and returns the result as a Java object +*CALL + JavaCall(javaObject, methodName, methodParameter1, methodParameter2, ...) + +*PARMS +{javaObject} -- a Java object + +{methodName} -- the name of a method to call on the Java object (it can be either a string or an atom) + +{methodParameters} -- zero or more parameters which will be sent to the method + +*DESC +This function calls a method on {javaObject} and returns the result as a Java object. The returned Java object +can be converted into a MathPiper data structure by passing it to JavaToValue, or in can be passed +to JavaCall or JavaAccess for further processing. + +*E.G. +In> javaString := JavaNew("java.lang.String", "Hello") +Result: java.lang.String + +In> javaString := JavaCall(javaString, "replace", "e", "o") +Result: java.lang.String + +In> JavaToValue(javaString) +Result: Hollo + +In> JavaAccess(javaString, "charAt", 0) +Result: H + +*SEE JavaNew, JavaAccess, JavaToValue +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaNew.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaNew.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaNew.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaNew.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,155 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import java.util.ArrayList; +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.builtin.javareflection.Invoke; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.ConsTraverser; +import org.mathpiper.lisp.cons.NumberCons; + +/** + * + * + */ +public class JavaNew extends BuiltinFunction { + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + if (getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer) { + + ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, subList); + + //Skip past List type. + consTraverser.goNext(aStackTop); + + Cons argumentCons = consTraverser.getPointer().getCons(); + + if (argumentCons != null) { + + String fullyQualifiedClassName = (String) argumentCons.car(); + //Strip leading and trailing quotes. + fullyQualifiedClassName = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, fullyQualifiedClassName); + + consTraverser.goNext(aStackTop); + + ArrayList argumentArrayList = new ArrayList(); + + while (consTraverser.getCons() != null) { + argumentCons = consTraverser.getPointer().getCons(); + + Object argument = null; + + if(argumentCons instanceof NumberCons) + { + NumberCons numberCons = (NumberCons) argumentCons; + BigNumber bigNumber = (BigNumber) numberCons.getNumber(aEnvironment.getPrecision(), aEnvironment); + + if(bigNumber.isInteger()) + { + argument = bigNumber.toInt(); + } + else + { + argument = bigNumber.toDouble(); + } + } + else + { + argument = argumentCons.car(); + + + if (argument instanceof String) { + argument = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, (String)argument); + } + + if(argument instanceof JavaObject) + { + argument = ((JavaObject)argument).getObject(); + } + }//end if/else. + + argumentArrayList.add(argument); + + consTraverser.goNext(aStackTop); + + }//end while. + + Object[] argumentsArray = (Object[]) argumentArrayList.toArray(new Object[0]); + + Object o = Invoke.invokeConstructor(fullyQualifiedClassName, argumentsArray); + + JavaObject response = new JavaObject(o); + + //JavaObject response = JavaObject.instantiate(fullyQualifiedClassName, argumentsArray); + //System.out.println("XXXXXXXXXXX: " + response); + + if (response == null) { + Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + return; + } else { + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + return; + }//end if/else. + + + + }//end if. + + }//end if. + + Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + + }//end method. +} + + + + +/* +%mathpiper_docs,name="JavaNew",categories="Programmer Functions;Built In;Native Objects",access="experimental" +*CMD JavaNew --- instantiates a Java object +*CALL + JavaNew(fullyQualifiedClassName, constructorParameter1, constructorParameter2, ...) + +*PARMS +{fullyQualifiedClassName} -- (string) the fully qualified name of a Java class + +{constructorParameters} -- zero or more parameters which will be sent to the constructor + +*DESC +This function instantiates a Java object and then returns it as a result. + +*E.G. +In> javaString := JavaNew("java.lang.String", "Hello") +Result: java.lang.String + +In> javaString := JavaAccess(javaString, "toUpperCase") +Result: HELLO + +*SEE JavaCall, JavaAccess, JavaToValue +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaToValue.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaToValue.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/JavaToValue.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/JavaToValue.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,121 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.SublistCons; + +/** + * + * + */ +public class JavaToValue extends BuiltinFunction { + + //private StandardFileOutputStream out = new StandardFileOutputStream(System.out); + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + Object argument = getArgumentPointer(aEnvironment, aStackTop, 1).car(); + + if (argument instanceof JavaObject) { + String atomValue = ""; + + JavaObject javaObject = (JavaObject) argument; + + Object object = javaObject.getObject(); + + if (object != null) { + + if (object instanceof java.lang.Boolean) { + if (((Boolean) object).booleanValue() == true) { + atomValue = "True"; + } else { + atomValue = "False"; + } + } else if (object instanceof String[]) { + + String[] stringArray = (String[]) object; + + Cons listAtomCons = aEnvironment.iListAtom.copy(aEnvironment, false); + + Cons sublistCons = SublistCons.getInstance(aEnvironment, listAtomCons); + + ConsPointer consPointer = new ConsPointer(listAtomCons); + + for(String javaString : stringArray) + { + Cons atomCons = AtomCons.getInstance(aEnvironment, aStackTop, Utility.toMathPiperString(aEnvironment, aStackTop, javaString)); + + consPointer.cdr().setCons(atomCons); + + consPointer.goNext(aStackTop, aEnvironment); + }//end for. + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(sublistCons); + + return; + + } else { + atomValue = (String) javaObject.getObject().toString().trim(); + } + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, atomValue)); + + return; + } + } else { + LispError.raiseError("The argument must be a JavaObject.", "JavaToValue", aStackTop, aEnvironment); + } + + + Utility.putFalseInPointer(aEnvironment, null); + }//end method. +}//end class. + + + + + +/* +%mathpiper_docs,name="JavaToValue",categories="Programmer Functions;Built In;Native Objects",access="experimental" +*CMD JavaToValue --- converts a Java object into a MathPiper data structure +*CALL + JavaToValue(javaObject) + +*PARMS +{javaObject} -- a Java object + +*DESC +This function is used to convert a Java object into a MathPiper data structure. It is typically +used with JavaCall. + +*E.G. +In> javaString := JavaNew("java.lang.String", "Hello") +Result: java.lang.String + +In> JavaToValue(javaString) +Result: Hello + +*SEE JavaCall, JavaAccess, JavaNew +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LeftPrecedenceGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LeftPrecedenceGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LeftPrecedenceGet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LeftPrecedenceGet.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,73 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Operator; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class LeftPrecedenceGet extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Operator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); + if (op == null) + { // infix and postfix operators have left precedence + + op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPostfixOperators); + LispError.check(aEnvironment, aStackTop, op != null, LispError.IS_NOT_INFIX); + } + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + op.iLeftPrecedence)); + } +} + + + +/* +%mathpiper_docs,name="LeftPrecedenceGet",categories="Programmer Functions;Programming;Built In" +*CMD LeftPrecedenceGet --- get operator precedence +*CORE +*CALL + LeftPrecedenceGet("op") + +*PARMS + +{"op"} -- string, the name of a function + +*DESC + +Returns the precedence of the function named "op" which should have been declared as a bodied function or an infix, postfix, or prefix operator. Generates an error message if the string str does not represent a type of function that can have precedence. + +For infix operators, right precedence can differ from left precedence. Bodied functions and prefix operators cannot have left precedence, while postfix operators cannot have right precedence; for these operators, there is only one value of precedence. + +*E.G. +In> LeftPrecedenceGet("!") +Result: 0; + +*SEE PrecedenceGet,RightPrecedenceGet,LeftPrecedence,RightPrecedenceSet,RightAssociativeSet +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LeftPrecedence.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LeftPrecedence.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LeftPrecedence.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LeftPrecedence.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class LeftPrecedence extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - // Get operator - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - - ConsPointer index = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, index, getArgumentPointer(aEnvironment, aStackTop, 2)); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2); - int ind = Integer.parseInt( (String) index.car(), 10); - - aEnvironment.iInfixOperators.setLeftPrecedence(Utility.getSymbolName(aEnvironment, orig), ind); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} - - - -/* -%mathpiper_docs,name="LeftPrecedence",categories="User Functions;Built In" -*CMD LeftPrecedence --- set operator precedence -*CORE -*CALL - LeftPrecedence("op",precedence) - -*PARMS - -{"op"} -- string, the name of a function - -{precedence} -- nonnegative integer - -*DESC - -{"op"} should be an infix operator. This function call tells the -infix expression printer to bracket the left hand side of -the expression if its precedence is larger than precedence. - -This functionality was required in order to display expressions like {a-(b-c)} -correctly. Thus, {a+b+c} is the same as {a+(b+c)}, but {a-(b-c)} is not -the same as {a-b-c}. - -Note that the left precedence of an infix operator does not affect the way MathPiper interprets expressions typed by the user. You cannot make MathPiper parse {a-b-c} as {a-(b-c)} unless you declare the operator "{-}" to be right-associative. - -*SEE OpPrecedence, OpLeftPrecedence, OpRightPrecedence, RightAssociative, RightPrecedence -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LeftPrecedenceSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LeftPrecedenceSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LeftPrecedenceSet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LeftPrecedenceSet.java 2010-02-06 21:01:49.000000000 +0000 @@ -0,0 +1,81 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class LeftPrecedenceSet extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + // Get operator + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "LeftPrecedenceSet"); + String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "LeftPrecedenceSet"); + + ConsPointer index = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, index, getArgumentPointer(aEnvironment, aStackTop, 2)); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2, "LeftPrecedenceSet"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2, "LeftPrecedenceSet"); + int ind = Integer.parseInt( (String) index.car(), 10); + + aEnvironment.iInfixOperators.setLeftPrecedence(aStackTop, Utility.getSymbolName(aEnvironment, orig), ind); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + + +/* +%mathpiper_docs,name="LeftPrecedenceSet",categories="User Functions;Built In" +*CMD LeftPrecedenceSet --- set operator precedence +*CORE +*CALL + LeftPrecedenceSet("op",precedence) + +*PARMS + +{"op"} -- string, the name of a function + +{precedence} -- nonnegative integer + +*DESC + +{"op"} should be an infix operator. This function call tells the +infix expression printer to bracket the left hand side of +the expression if its precedence is larger than precedence. + +This functionality was required in order to display expressions like {a-(b-c)} +correctly. Thus, {a+b+c} is the same as {a+(b+c)}, but {a-(b-c)} is not +the same as {a-b-c}. + +Note that the left precedence of an infix operator does not affect the way MathPiper interprets expressions typed by the user. You cannot make MathPiper parse {a-b-c} as {a-(b-c)} unless you declare the operator "{-}" to be right-associative. + +*SEE PrecedenceGet, LeftPrecedenceGet, RightPrecedenceGet, RightAssociativeSet, RightPrecedenceSet +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Length.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Length.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Length.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Length.java 2011-02-05 07:50:02.000000000 +0000 @@ -40,8 +40,8 @@ if (argument instanceof ConsPointer) { - int num = Utility.listLength(((ConsPointer)argument).cdr()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + num)); + int num = Utility.listLength(aEnvironment, aStackTop, ((ConsPointer)argument).cdr()); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + num)); return; }//end if. @@ -53,7 +53,7 @@ if (gen.typeName().equals("\"Array\"")) { int size = ((Array) gen).size(); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + size)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + size)); return; } // CHK_ISLIST_CORE(aEnvironment,aStackTop,getArgumentPointer(aEnvironment, aStackTop, 1),1); @@ -61,12 +61,12 @@ - LispError.check(argument instanceof String, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, argument instanceof String, LispError.INVALID_ARGUMENT, "Length"); String string = (String) argument; if (Utility.isString(string)) { int num = string.length() - 2; - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + num)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + num)); return; }//end if. @@ -95,10 +95,10 @@ *E.G. - In> Length({a,b,c}) - Out> 3; - In> Length("abcdef"); - Out> 6; +In> Length({a,b,c}) +Result: 3; +In> Length("abcdef"); +Result: 6; *SEE First, Rest, Nth, Count %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LessThan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LessThan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LessThan.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LessThan.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class LessThan extends BuiltinFunction -{ - - LexLessThan compare = new LexLessThan(); - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - compare.Compare(aEnvironment, aStackTop); - } -}//end class. - - - - -/* -%mathpiper_docs,name="LessThan" -*CMD LessThan --- comparison predicate -*CORE -*CALL - LessThan(a,b) - -*PARMS -{a}, {b} -- numbers or strings -*DESC -Comparing numbers or strings (lexicographically). - -**E.G. - In> LessThan(1,1) - Out> False; - In> LessThan("a","b") - Out> True; - -*SEE GreaterThan, Equals -%/mathpiper_docs -*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LexCompare2.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LexCompare2.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LexCompare2.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LexCompare2.java 2010-02-06 21:01:49.000000000 +0000 @@ -24,6 +24,8 @@ import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.NumberCons; /** * @@ -32,34 +34,46 @@ abstract public class LexCompare2 { - abstract boolean lexfunc(String f1, String f2, TokenMap aHashTable, int aPrecision); + abstract boolean lexFunction(String f1, String f2, TokenMap aHashTable, int aPrecision); - abstract boolean numfunc(BigNumber n1, BigNumber n2); + abstract boolean numFunction(BigNumber n1, BigNumber n2); void Compare(Environment aEnvironment, int aStackTop) throws Exception { - ConsPointer result1 = new ConsPointer(); - ConsPointer result2 = new ConsPointer(); - result1.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - result2.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + ConsPointer argument1 = new ConsPointer(); + + ConsPointer argument2 = new ConsPointer(); + + argument1.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + + argument2.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + + + //LispError.check(argument1.getCons() instanceof NumberCons || argument1.getCons() instanceof AtomCons, "The first argument must be a non-complex decimal number or a string.","LexCompare2"); + //LispError.check(argument2.getCons() instanceof NumberCons || argument2.getCons() instanceof AtomCons, "The second argument must be a non-complex decimal number or a string.","LexCompare2"); + + LispError.checkArgumentTypeWithError(aEnvironment, aStackTop, argument1.getCons() instanceof NumberCons || argument1.getCons() instanceof AtomCons, 1, "The first argument must be a non-complex decimal number or a string.","LexCompare2"); + LispError.checkArgumentTypeWithError(aEnvironment, aStackTop, argument2.getCons() instanceof NumberCons || argument2.getCons() instanceof AtomCons, 2, "The second argument must be a non-complex decimal number or a string.","LexCompare2"); + + boolean cmp; -// LispError.check(result1.type().equals("Number"), LispError.KLispErrInvalidArg); -// LispError.check(result2.type().equals("Number"), LispError.KLispErrInvalidArg); - BigNumber n1 = (BigNumber) result1.getCons().getNumber(aEnvironment.getPrecision()); - BigNumber n2 = (BigNumber) result2.getCons().getNumber(aEnvironment.getPrecision()); + BigNumber n1 = (BigNumber) argument1.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + BigNumber n2 = (BigNumber) argument2.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + if (n1 != null && n2 != null) { - cmp = numfunc(n1, n2); + cmp = numFunction(n1, n2); } else { + String str1; String str2; - str1 = (String) result1.car(); - str2 = (String) result2.car(); - LispError.checkArgument(aEnvironment, aStackTop, str1 != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, str2 != null, 2); + str1 = (String) argument1.car(); + str2 = (String) argument2.car(); + LispError.checkArgument(aEnvironment, aStackTop, str1 != null, 1, "LexCompare2"); + LispError.checkArgument(aEnvironment, aStackTop, str2 != null, 2, "LexCompare2"); // the getPrecision argument is ignored in "lex" functions - cmp = lexfunc(str1, str2, + cmp = lexFunction(str1, str2, aEnvironment.getTokenHash(), aEnvironment.getPrecision()); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LexGreaterThan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LexGreaterThan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LexGreaterThan.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LexGreaterThan.java 2010-02-04 07:25:40.000000000 +0000 @@ -28,12 +28,12 @@ public class LexGreaterThan extends LexCompare2 { - boolean lexfunc(String f1, String f2, TokenMap aHashTable, int aPrecision) + boolean lexFunction(String f1, String f2, TokenMap aHashTable, int aPrecision) { return f1.compareTo(f2) > 0; } - boolean numfunc(BigNumber n1, BigNumber n2) + boolean numFunction(BigNumber n1, BigNumber n2) { return !(n1.lessThan(n2) || n1.equals(n2)); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LexLessThan.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LexLessThan.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LexLessThan.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LexLessThan.java 2010-02-04 07:25:40.000000000 +0000 @@ -28,12 +28,12 @@ public class LexLessThan extends LexCompare2 { - boolean lexfunc(String f1, String f2, TokenMap aHashTable, int aPrecision) + boolean lexFunction(String f1, String f2, TokenMap aHashTable, int aPrecision) { return f1.compareTo(f2) < 0; } - boolean numfunc(BigNumber n1, BigNumber n2) + boolean numFunction(BigNumber n1, BigNumber n2) { return n1.lessThan(n2) && !n1.equals(n2); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LispForm.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LispForm.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LispForm.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LispForm.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,78 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.printers.LispPrinter; + +/** + * + * + */ +public class LispForm extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + getTopOfStackPointer(aEnvironment, aStackTop).setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + LispPrinter printer = new LispPrinter(); + printer.print(aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), aEnvironment.iCurrentOutput, aEnvironment); + aEnvironment.write("\n"); + } +} + + + +/* +%mathpiper_docs,name="LispForm",categories="User Functions;Input/Output;Built In" +*CMD LispForm --- print an expression in LISP-format +*CORE +*CALL + LispForm(expr) + +*PARMS + +{expr} -- expression to be printed in LISP-format + +*DESC + +Evaluates "expr", and prints it in LISP-format on the current +output. It is followed by a newline. The evaluated expression is also +returned. + +This can be useful if you want to study the internal representation of +a certain expression. + +*E.G. notest + +In> LispForm(a+b+c); + (+ (+ a b )c ) +Result: a+b+c; +In> LispForm(2*I*b^2); + (* (Complex 0 2 )(^ b 2 )) +Result: Complex(0,2)*b^2; + +The first example shows how the expression {a+b+c} is +internally represented. In the second example, {2*I} is +first evaluated to {Complex(0,2)} before the expression +is printed. + +*SEE LispRead, ViewList +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LispRead.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LispRead.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LispRead.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LispRead.java 2011-02-05 07:50:02.000000000 +0000 @@ -35,7 +35,7 @@ aEnvironment.iCurrentInput, aEnvironment); // Read expression - parser.parse(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop)); + parser.parse(aStackTop, getTopOfStackPointer(aEnvironment, aStackTop)); } } @@ -60,14 +60,14 @@ *E.G. notest - In> FromString("(+ a b)") LispRead(); - Out> a+b; - In> FromString("(List (Sin x) (- (Cos x)))") \ +In> PipeFromString("(+ a b)") LispRead(); +Result: a+b; +In> PipeFromString("(List (Sin x) (- (Cos x)))") \ LispRead(); - Out> {Sin(x),-Cos(x)}; - In> FromString("(+ a b)")LispRead() - Out> a+b; +Result: {Sin(x),-Cos(x)}; +In> PipeFromString("(+ a b)")LispRead() +Result: a+b; -*SEE FromFile, FromString, Read, ReadToken, FullForm, LispReadListed +*SEE PipeFromFile, PipeFromString, Read, ReadToken, LispForm, LispReadListed %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LispReadListed.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LispReadListed.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LispReadListed.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LispReadListed.java 2011-02-05 07:50:02.000000000 +0000 @@ -36,7 +36,7 @@ aEnvironment); parser.iListed = true; // Read expression - parser.parse(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop)); + parser.parse(aStackTop, getTopOfStackPointer(aEnvironment, aStackTop)); } } @@ -53,15 +53,15 @@ The function {LispReadListed} reads a LISP expression and returns it in a list, instead of the form usual to MathPiper (expressions). -The result can be thought of as applying {Listify} to {LispRead}. +The result can be thought of as applying {FunctionToList} to {LispRead}. The function {LispReadListed} is more useful for reading arbitrary LISP expressions, because the first object in a list can be itself a list (this is never the case for MathPiper expressions where the first object in a list is always a function atom). *E.G. notest - In> FromString("(+ a b)")LispReadListed() - Out> {+,a,b}; +In> PipeFromString("(+ a b)")LispReadListed() +Result: {+,a,b}; -*SEE FromFile, FromString, Read, ReadToken, FullForm, LispRead +*SEE PipeFromFile, PipeFromString, Read, ReadToken, LispForm, LispRead %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Listify.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Listify.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Listify.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Listify.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.SublistCons; - -/** - * - * - */ -public class Listify extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer, 1); - ConsPointer head = new ConsPointer(); - head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); - head.cdr().setCons(((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()).getCons()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,head.getCons())); - } -} - - - -/* -%mathpiper_docs,name="Listify",categories="User Functions;Lists (Operations);Built In" -*CMD Listify --- convert a function application to a list -*CORE -*CALL - Listify(expr) - -*PARMS - -{expr} -- expression to be converted - -*DESC - -The parameter "expr" is expected to be a compound object, i.e. not -an atom. It is evaluated and then converted to a list. The car entry -in the list is the top-level operator in the evaluated expression and -the other entries are the arguments to this operator. Finally, the -list is returned. - -*E.G. - - In> Listify(Cos(x)); - Out> {Cos,x}; - In> Listify(3*a); - Out> {*,3,a}; - -*SEE List, UnList, IsAtom -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/List.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/List.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/List.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/List.java 2011-02-05 07:50:02.000000000 +0000 @@ -13,9 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; @@ -28,27 +26,26 @@ * * */ - public class List extends BuiltinFunction - { - public void evaluate(Environment aEnvironment,int aStackTop) throws Exception - { - ConsPointer allPointer = new ConsPointer(); - allPointer.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); - ConsTraverser tail = new ConsTraverser(allPointer); - tail.goNext(); - ConsTraverser consTraverser = new ConsTraverser((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); - consTraverser.goNext(); - while (consTraverser.getCons() != null) - { - ConsPointer evaluated = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment,evaluated,consTraverser.getPointer()); - tail.getPointer().setCons(evaluated.getCons()); - tail.goNext(); - consTraverser.goNext(); - } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,allPointer.getCons())); - } - } +public class List extends BuiltinFunction { + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + ConsPointer allPointer = new ConsPointer(); + allPointer.setCons(aEnvironment.iListAtom.copy(aEnvironment, false)); + ConsTraverser tail = new ConsTraverser(aEnvironment, allPointer); + tail.goNext(aStackTop); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); + consTraverser.goNext(aStackTop); + while (consTraverser.getCons() != null) { + ConsPointer evaluated = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, consTraverser.getPointer()); + tail.getPointer().setCons(evaluated.getCons()); + tail.goNext(aStackTop); + consTraverser.goNext(aStackTop); + } + getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, allPointer.getCons())); + } + +} @@ -71,13 +68,13 @@ *E.G. - In> List(); - Out> {}; - In> List(a,b); - Out> {a,b}; - In> List(a,{1,2},d); - Out> {a,{1,2},d}; +In> List(); +Result: {}; +In> List(a,b); +Result: {a,b}; +In> List(a,{1,2},d); +Result: {a,{1,2},d}; -*SEE UnList, Listify +*SEE ListToFunction, FunctionToList %/mathpiper_docs -*/ \ No newline at end of file +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ListToFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ListToFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ListToFunction.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ListToFunction.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,81 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.ConsPointer; + +/** + * + * + */ +public class ListToFunction extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "ListToFunction"); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer, 1, "ListToFunction"); + Cons atom = ((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()).getCons(); + LispError.checkArgument(aEnvironment, aStackTop, atom != null, 1, "ListToFunction"); + LispError.checkArgument(aEnvironment, aStackTop, atom.car() == aEnvironment.iListAtom.car(), 1, "ListToFunction"); + Utility.tail(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); + } +} + + + +/* +%mathpiper_docs,name="ListToFunction",categories="User Functions;Lists (Operations);Built In" +*CMD ListToFunction --- convert a list to a function application +*CORE +*CALL + ListToFunction(list) + +*PARMS + +{list} -- list to be converted + +*DESC + +This command converts a list to a function application. The car +entry of "list" is treated as a function atom, and the following entries +are the arguments to this function. So the function referred to in the +car element of "list" is applied to the other elements. + +Note that "list" is evaluated before the function application is +formed, but the resulting expression is left unevaluated. The functions {ListToFunction()} and {Hold()} both stop the process of evaluation. + +*E.G. + +In> ListToFunction({Cos, x}); +Result: Cos(x); +In> ListToFunction({f}); +Result: f(); +In> ListToFunction({Taylor,x,0,5,Cos(x)}); +Result: Taylor(x,0,5)Cos(x); +In> Eval(%); +Result: 1-x^2/2+x^4/24; + +*SEE List, FunctionToList, Hold +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Load.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Load.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Load.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Load.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class Load extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - LispError.check(aEnvironment, aStackTop, aEnvironment.iSecure == false, LispError.SECURITY_BREACH); - - ConsPointer evaluated = new ConsPointer(); - evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - - // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); - String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - - Utility.load(aEnvironment, orig); - - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - - } -} - - - -/* -%mathpiper_docs,name="Load",categories="User Functions;Input/Output;Built In" -*CMD Load --- evaluate all expressions in a file -*CORE -*CALL - Load(name) - -*PARMS - -{name} -- string, name of the file to load - -*DESC - -The file "name" is opened. All expressions in the file are read and -evaluated. {Load} always returns {true}. - -*SEE Use, DefLoad, DefaultDirectory, FindFile -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LoadScript.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LoadScript.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LoadScript.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LoadScript.java 2010-02-20 21:59:44.000000000 +0000 @@ -0,0 +1,72 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class LoadScript extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + LispError.check(aEnvironment, aStackTop, aEnvironment.iSecure == false, LispError.SECURITY_BREACH); + + ConsPointer evaluated = new ConsPointer(); + evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + + // Get file name + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "LoadScript"); + String orig = (String) evaluated.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "LoadScript"); + + Utility.loadScript(aEnvironment, aStackTop, orig); + + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + + } +} + + + +/* +%mathpiper_docs,name="LoadScript",categories="User Functions;Input/Output;Built In" +*CMD LoadScript --- evaluate all expressions in a script file +*CORE +*CALL + LoadScript(name) + +*PARMS + +{name} -- string, name of the script file to load + +*DESC + +The file "name" is opened. All expressions in the file are read and +evaluated. {LoadScript} always returns {true}. + +*SEE LoadScriptOnce, DefLoad, DefaultDirectory, FindFile +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LoadScriptOnce.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LoadScriptOnce.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LoadScriptOnce.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LoadScriptOnce.java 2010-02-20 21:59:44.000000000 +0000 @@ -0,0 +1,73 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class LoadScriptOnce extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + ConsPointer evaluated = new ConsPointer(); + evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + + // Get file name + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "LoadScriptOnce"); + String orig = (String) evaluated.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "LoadScriptOnce"); + + Utility.loadScriptOnce(aEnvironment, aStackTop, orig); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + +/* +%mathpiper_docs,name="LoadScriptOnce",categories="User Functions;Control Flow;Input/Output;Built In" +*CMD LoadScriptOnce --- load a script file (but not twice) +*CORE +*CALL + LoadScriptOnce(name) + +*PARMS + +{name} -- name of the script file to load + +*DESC + +If the file "name" has been loaded before, either by an earlier call +to {LoadScriptOnce} or via the {DefLoad} +mechanism, nothing happens. Otherwise all expressions in the file are +read and evaluated. {LoadScriptOnce} always returns {True}. + +The purpose of this function is to make sure that the file will at +least have been loaded, but is not loaded twice. + +*SEE LoadScript, DefLoad, DefaultDirectory +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Local.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Local.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Local.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Local.java 2011-02-05 07:50:02.000000000 +0000 @@ -37,17 +37,17 @@ ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - ConsTraverser consTraverser = new ConsTraverser(subList); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, subList); + consTraverser.goNext(aStackTop); int nr = 1; while (consTraverser.getCons() != null) { String variable = (String) consTraverser.car(); - LispError.checkArgument(aEnvironment, aStackTop, variable != null, nr); + LispError.checkArgument(aEnvironment, aStackTop, variable != null, nr, "Local"); // printf("Variable %s\n",variable.String()); - aEnvironment.newLocalVariable(variable, null); - consTraverser.goNext(); + aEnvironment.newLocalVariable(variable, null, aStackTop); + consTraverser.goNext(aStackTop); nr++; } } @@ -86,18 +86,18 @@ *E.G. - In> a := 3; - Out> 3; +In> a := 3; +Result: 3; - In> [ a := 4; a; ]; - Out> 4; - In> a; - Out> 4; - - In> [ Local(a); a := 5; a; ]; - Out> 5; - In> a; - Out> 4; +In> [ a := 4; a; ]; +Result: 4; +In> a; +Result: 4; + +In> [ Local(a); a := 5; a; ]; +Result: 5; +In> a; +Result: 4; In the car block, {a} is not declared local and hence defaults to be a global variable. Indeed, changing the variable @@ -125,6 +125,6 @@ Make sure that the arguments of {Macro}... commands evaluate to expressions that would normally be used in the non-macro version! -*SEE Set, Clear, Local, RuleBase, Rule, Backquoting, MacroSet, MacroClear, MacroRuleBase, MacroRuleBaseListed, MacroRule +*SEE Bind, Unbind, Local, Rulebase, Rule, `, MacroBind, MacroUnbind, MacroRulebase, MacroRulebaseListed, MacroRule %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LocalSymbols.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LocalSymbols.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/LocalSymbols.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/LocalSymbols.java 2011-02-05 07:50:02.000000000 +0000 @@ -34,7 +34,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - int numberOfArguments = Utility.listLength(getArgumentPointer(aEnvironment, aStackTop, 0)); + int numberOfArguments = Utility.listLength(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0)); int numberOfSymbols = numberOfArguments - 2; String atomNames[] = new String[numberOfSymbols]; @@ -44,8 +44,8 @@ int i; for (i = 0; i < numberOfSymbols; i++) { - String atomName = (String) getArgumentPointer(getArgumentPointer(aEnvironment, aStackTop, 0), i + 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, atomName != null, i + 1); + String atomName = (String) getArgumentPointer(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0), i + 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, atomName != null, i + 1, "LocalSymbols"); atomNames[i] = atomName; String newAtomName = "$" + atomName + uniqueNumber; String variable = (String) aEnvironment.getTokenHash().lookUp(newAtomName); @@ -53,8 +53,8 @@ } LocalSymbolSubstitute substituteBehaviour = new LocalSymbolSubstitute(aEnvironment, atomNames, localAtomNames, numberOfSymbols); ConsPointer result = new ConsPointer(); - Utility.substitute(aEnvironment, result, getArgumentPointer(getArgumentPointer(aEnvironment, aStackTop, 0), numberOfArguments - 1), substituteBehaviour); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), result); + Utility.substitute(aEnvironment, aStackTop, result, getArgumentPointer(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0), numberOfArguments - 1), substituteBehaviour); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), result); } }//end class. @@ -78,7 +78,7 @@ Given the symbols passed as the first arguments to LocalSymbols a set of local symbols will be created, and creates unique ones for them, typically of the -form {$}, where {symbol} was the symbol entered by the user, +form {\$}, where {symbol} was the symbol entered by the user, and {number} is a unique number. This scheme was used to ensure that a generated symbol can not accidentally be entered by a user. @@ -87,8 +87,8 @@ *E.G. notest - In> LocalSymbols(a,b)a+b - Out> $a6+ $b6; +In> LocalSymbols(a,b)a+b +Result: \$a6+ \$b6; *SEE UniqueConstant %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroBind.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroBind.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroBind.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroBind.java 2010-09-20 04:22:24.000000000 +0000 @@ -0,0 +1,54 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class MacroBind extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Utility.setVar(aEnvironment, aStackTop, true, false); + } +} + + + +/* +%mathpiper_docs,name="MacroBind",categories="Programmer Functions;Programming;Built In" +*CMD MacroBind --- define rules in functions +*CORE +*DESC + +This function has the same effect as its non-macro counterpart, except +that its arguments are evaluated before the required action is performed. +This is useful in macro-like procedures or in functions that need to define new +rules based on parameters. + +Make sure that the arguments of {Macro}... commands evaluate to expressions that would normally be used in the non-macro version! + +*SEE Bind, Unbind, Local, Rulebase, Rule, `, MacroUnbind, MacroLocal, MacroRulebase, MacroRulebaseListed, MacroRule +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroNewRulePattern.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroNewRulePattern.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroNewRulePattern.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroNewRulePattern.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class MacroNewRulePattern extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - org.mathpiper.lisp.Utility.newRulePattern(aEnvironment, aStackTop, true); - } -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRulebase.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRulebase.java 2010-09-20 04:22:24.000000000 +0000 @@ -29,15 +29,15 @@ { public void evaluate(Environment aEnvironment,int aStackTop) throws Exception { - org.mathpiper.lisp.Utility.ruleDatabase(aEnvironment, aStackTop, false); + org.mathpiper.lisp.Utility.rulebase(aEnvironment, aStackTop, false); } } /* -%mathpiper_docs,name="MacroRuleBase",categories="Programmer Functions;Programming;Built In" -*CMD MacroRuleBase --- define rules in functions +%mathpiper_docs,name="MacroRulebase",categories="Programmer Functions;Programming;Built In" +*CMD MacroRulebase --- define rules in functions *CORE *DESC @@ -48,6 +48,6 @@ Make sure that the arguments of {Macro}... commands evaluate to expressions that would normally be used in the non-macro version! -*SEE Set, Clear, Local, RuleBase, Rule, Backquoting, MacroSet, MacroClear, MacroLocal, MacroRuleBaseListed, MacroRule +*SEE Bind, Unbind, Local, Rulebase, Rule, `, MacroBind, MacroUnbind, MacroLocal, MacroRulebaseListed, MacroRule %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRulebaseListed.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRulebaseListed.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRulebaseListed.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRulebaseListed.java 2010-12-29 04:07:15.000000000 +0000 @@ -2,7 +2,6 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ - package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; @@ -12,19 +11,19 @@ * * */ - public class MacroRulebaseListed extends BuiltinFunction - { - public void evaluate(Environment aEnvironment,int aStackTop) throws Exception - { - org.mathpiper.lisp.Utility.ruleDatabase(aEnvironment, aStackTop, true); - } - } +public class MacroRulebaseListed extends BuiltinFunction { + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + org.mathpiper.lisp.Utility.rulebase(aEnvironment, aStackTop, true); + } + +} /* -%mathpiper_docs,name="MacroRuleBaseListed",categories="Programmer Functions;Programming;Built In" -*CMD MacroRuleBaseListed --- define rules in functions +%mathpiper_docs,name="MacroRulebaseListed",categories="Programmer Functions;Programming;Built In" +*CMD MacroRulebaseListed --- define rules in functions *CORE *DESC @@ -35,6 +34,6 @@ Make sure that the arguments of {Macro}... commands evaluate to expressions that would normally be used in the non-macro version! -*SEE Set, Clear, Local, RuleBase, Rule, Backquoting, MacroSet, MacroClear, MacroLocal, MacroRuleBase, MacroRule +*SEE Bind, Unbind, Local, Rulebase, Rule, `, MacroBind, MacroUnbind, MacroLocal, MacroRulebase, MacroRule %/mathpiper_docs -*/ \ No newline at end of file +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRule.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRule.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRule.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRule.java 2010-12-10 04:56:58.000000000 +0000 @@ -29,7 +29,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - org.mathpiper.lisp.Utility.newRule(aEnvironment, aStackTop); + org.mathpiper.lisp.Utility.newRule(aEnvironment, aStackTop, false); } } @@ -48,6 +48,6 @@ Make sure that the arguments of {Macro}... commands evaluate to expressions that would normally be used in the non-macro version! -*SEE Set, Clear, Local, RuleBase, Rule, Backquoting, MacroSet, MacroClear, MacroLocal, MacroRuleBase, MacroRuleBaseListed +*SEE Bind, Unbind, Local, Rulebase, Rule, `, MacroBind, MacroUnbind, MacroLocal, MacroRulebase, MacroRulebaseListed %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRulePattern.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRulePattern.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroRulePattern.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroRulePattern.java 2010-12-10 04:56:58.000000000 +0000 @@ -0,0 +1,61 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class MacroRulePattern extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + org.mathpiper.lisp.Utility.newRule(aEnvironment, aStackTop, true); + } +} + + + + +/* +%mathpiper_docs,name="MacroRulePattern",categories="Programmer Functions;Programming;Built In" +*CMD MacroRulePattern --- defines a rule which uses a pattern as its predicate + +*CALL + MacroRulePattern("operator", arity, precedence, pattern) body +*PARMS + +{"operator"} -- string, name of function + +{arity}, {precedence} -- integers + +{pattern} -- a pattern object + +{body} -- expression, body of rule + +*DESC +This function defines a rule which uses a pattern as its predicate. + +*SEE RulePattern +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MacroSet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MacroSet.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class MacroSet extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - Utility.setVar(aEnvironment, aStackTop, true, false); - } -} - - - -/* -%mathpiper_docs,name="MacroSet",categories="Programmer Functions;Programming;Built In" -*CMD MacroSet --- define rules in functions -*CORE -*DESC - -This function has the same effect as its non-macro counterpart, except -that its arguments are evaluated before the required action is performed. -This is useful in macro-like procedures or in functions that need to define new -rules based on parameters. - -Make sure that the arguments of {Macro}... commands evaluate to expressions that would normally be used in the non-macro version! - -*SEE Set, Clear, Local, RuleBase, Rule, Backquoting, MacroClear, MacroLocal, MacroRuleBase, MacroRuleBaseListed, MacroRule -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MathNegate.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MathNegate.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MathNegate.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MathNegate.java 2010-02-06 21:01:49.000000000 +0000 @@ -34,6 +34,6 @@ BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.negate(x); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MathSign.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MathSign.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MathSign.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MathSign.java 2010-02-06 21:01:49.000000000 +0000 @@ -34,6 +34,6 @@ BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.setTo(x.sign()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MaxEvalDepth.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MaxEvalDepth.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MaxEvalDepth.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MaxEvalDepth.java 2011-02-05 07:50:02.000000000 +0000 @@ -35,8 +35,8 @@ { ConsPointer index = new ConsPointer(); index.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1, "MaxEvalDepth"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1, "MaxEvalDepth"); int ind = Integer.parseInt( (String) index.car(), 10); aEnvironment.iMaxEvalDepth = ind; @@ -71,9 +71,9 @@ An example of an infinite recursion, caught because the maximum evaluation depth is reached. - In> f(x) := f(x) - Out> True; - In> f(x) +In> f(x) := f(x) +Result: True; +In> f(x) Error on line 1 in file [CommandLine] Max evaluation stack depth reached. Please use MaxEvalDepth to increase the stack @@ -82,21 +82,21 @@ However, a long calculation may cause the maximum evaluation depth to be reached without the presence of infinite recursion. The function {MaxEvalDepth} is meant for these cases. - In> 10 # g(0) <-- 1; - Out> True; - In> 20 # g(n_IsPositiveInteger) <-- \ +In> 10 # g(0) <-- 1; +Result: True; +In> 20 # g(n_IsPositiveInteger) <-- \ 2 * g(n-1); - Out> True; - In> g(1001); +Result: True; +In> g(1001); Error on line 1 in file [CommandLine] Max evaluation stack depth reached. Please use MaxEvalDepth to increase the stack size as needed. - In> MaxEvalDepth(10000); - Out> True; - In> g(1001); - Out> 21430172143725346418968500981200036211228096234 +In> MaxEvalDepth(10000); +Result: True; +In> g(1001); +Result: 21430172143725346418968500981200036211228096234 1106721488750077674070210224987224498639675763139171 6255189345835106293650374290571384628087196915514939 7149607869135549648461970842149210124742283755908364 diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaEntries.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaEntries.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaEntries.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaEntries.java 2010-04-09 00:30:19.000000000 +0000 @@ -62,14 +62,14 @@ //Add -> operator cons. - Cons operatorCons = AtomCons.getInstance(aEnvironment, "->"); + Cons operatorCons = AtomCons.getInstance(aEnvironment, aStackTop, "->"); //Add key cons. String key = (String) keyIterator.next(); - Cons keyCons = AtomCons.getInstance(aEnvironment, key); + Cons keyCons = AtomCons.getInstance(aEnvironment, aStackTop, key); operatorCons.cdr().setCons(keyCons); @@ -84,7 +84,7 @@ //Place entry in list. consPointer.getCons().cdr().setCons(SublistCons.getInstance(aEnvironment, operatorCons)); - consPointer.goNext(); + consPointer.goNext(aStackTop, aEnvironment); @@ -106,7 +106,7 @@ /* -%mathpiper_docs,name="MetaValues",categories="User Functions;Built In" +%mathpiper_docs,name="MetaEntries",categories="User Functions;Built In" *CMD MetaValues --- returns the metadata values for a value or an unbound variable *CORE *CALL @@ -120,11 +120,13 @@ *DESC -Returns the metadata values for a value or an unbound variables. The metadata is +todo:tk: not functional yet. + +Returns the metadata values for a value or an unbound variable. The metadata is held in an associative list. -*SEE MetaGet, MetaSet, MetaKeys, Clear +*SEE MetaGet, MetaSet, MetaKeys, Unbind %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaGet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaGet.java 2010-04-09 00:23:39.000000000 +0000 @@ -24,13 +24,13 @@ ConsPointer keyPointer = new ConsPointer(); keyPointer.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkIsString(aEnvironment, aStackTop, keyPointer, 2); + LispError.checkIsString(aEnvironment, aStackTop, keyPointer, 2, "MetaGet"); Map metadataMap = objectPointer.getCons().getMetadataMap(); if (metadataMap == null) { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "Empty")); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "Empty")); return; }//end if. @@ -40,7 +40,7 @@ if (valueCons == null) { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "Empty")); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "Empty")); } else { getTopOfStackPointer(aEnvironment, aStackTop).setCons(valueCons); } @@ -55,7 +55,7 @@ /* -%mathpiper_docs,name="MetaSet",categories="User Functions;Built In" +%mathpiper_docs,name="MetaGet",categories="User Functions;Built In" *CMD MetaGet --- returns the metadata for a value or an unbound variable *CORE *CALL @@ -75,6 +75,6 @@ -*SEE MetaSet, MetaKeys, MetaValues, Clear +*SEE MetaSet, MetaKeys, MetaValues, Unbind %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaKeys.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaKeys.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaKeys.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaKeys.java 2010-04-09 00:23:39.000000000 +0000 @@ -18,11 +18,10 @@ package org.mathpiper.builtin.functions.core; -import java.util.Iterator; import java.util.Map; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.cons.Cons; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.cons.SublistCons; @@ -45,30 +44,10 @@ }//end if. - ConsPointer consPointer = new ConsPointer(); - - Cons head = aEnvironment.iListAtom.copy( aEnvironment, false); - - consPointer.setCons(head); - java.util.Set keySet = (java.util.Set) metadataMap.keySet(); - Iterator keyIterator = keySet.iterator(); - - while(keyIterator.hasNext()) - { - String key = (String) keyIterator.next(); - - Cons stringCons = AtomCons.getInstance(aEnvironment, key); - - consPointer.getCons().cdr().setCons(stringCons); - - consPointer.goNext(); - - }//end while. + Cons head = Utility.iterableToList(aEnvironment, aStackTop, keySet); - - getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,head)); @@ -90,17 +69,12 @@ *PARMS - {value_or_unbound_variable} -- a value or an unbound variable - *DESC - Returns the metadata keys for a value or an unbound variables. The metadata is held in an associative list. - - -*SEE MetaGet, MetaSet, MetaValues, Clear +*SEE MetaGet, MetaSet, MetaValues, Unbind %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaSet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaSet.java 2010-04-09 00:23:39.000000000 +0000 @@ -37,7 +37,7 @@ ConsPointer keyPointer = new ConsPointer(); keyPointer.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkIsString(aEnvironment, aStackTop, keyPointer, 2); + LispError.checkIsString(aEnvironment, aStackTop, keyPointer, 2, "MetaSet"); ConsPointer value = new ConsPointer(); @@ -105,7 +105,7 @@ //Check for global variable. - variablePointer = new ConsPointer(); + variablePointer = new ConsPointer(aEnvironment); aEnvironment.getGlobalVariable((String) object.car(), variablePointer); if (variablePointer.getCons() != null) { @@ -190,8 +190,55 @@ held in an associative list. MetaSet returns the given value or unbound variable as a result after it has had metadata added to it. +*E.G. +In> a := MetaSet(b,"TAG",DATA) +Result: b +In> a +Result: b - *SEE MetaGet, MetaKeys, MetaValues, Clear +In> MetaKeys(a) +Result: {"TAG"} + +In> MetaValues(a) +Result: {DATA} + +In> MetaGet(a,"TAG") +Result: DATA + + +In> a := MetaSet(3,"TAG",DATA) +Result: 3 + +In> a +Result: 3 + +In> MetaKeys(a) +Result: {"TAG"} + +In> MetaValues(a) +Result: {DATA} + +In> MetaGet(a,"TAG") +Result: DATA + + +In> f(x) := MetaSet(x^2,"TAG",DATA) +Result: True + +In> f(x) +Result: x^2 + +In> MetaKeys(f(x)) +Result: {"TAG"} + +In> MetaValues(f(x)) +Result: {DATA} + +In> MetaGet(f(x),"TAG") +Result: DATA + + +*SEE MetaGet, MetaKeys, MetaValues, Unbind %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaValues.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaValues.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/MetaValues.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/MetaValues.java 2010-12-29 04:07:15.000000000 +0000 @@ -22,7 +22,6 @@ import java.util.Map; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.cons.AtomCons; import org.mathpiper.lisp.cons.Cons; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.cons.SublistCons; @@ -61,7 +60,7 @@ consPointer.getCons().cdr().setCons(cons); - consPointer.goNext(); + consPointer.goNext(aStackTop, aEnvironment); }//end while. @@ -94,11 +93,11 @@ *DESC -Returns the metadata values for a value or an unbound variables. The metadata is +Returns the metadata values for a value or an unbound variable. The metadata is held in an associative list. -*SEE MetaGet, MetaSet, MetaKeys, Clear +*SEE MetaGet, MetaSet, MetaKeys, Unbind %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Mod.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Mod.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Mod.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Mod.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BigNumber; -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class Mod extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); - BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); - BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.mod(x, y); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); - } -}//end class. - - - -/* -%mathpiper_docs,name="ModN",categories="User Functions;Numeric;Built In" -*CMD ModN --- remainder of division or x mod y (arbitrary-precision math function) -*CORE -*CALL - ModN(x,y) () - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs -*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Modulo.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Modulo.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Modulo.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Modulo.java 2010-03-10 06:32:04.000000000 +0000 @@ -0,0 +1,71 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class Modulo extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + z.mod(null,aStackTop, x, y); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + } +}//end class. + + + +/* +%mathpiper_docs,name="ModuloN",categories="User Functions;Numeric;Built In" +*CMD ModuloN --- remainder of division or x modulo y (arbitrary-precision math function) +*CORE +*CALL + ModuloN(x,y) () + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> Modulo(2,3) +Result: 2 + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Multiply.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Multiply.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Multiply.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Multiply.java 2011-02-05 07:50:02.000000000 +0000 @@ -35,7 +35,7 @@ BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.multiply(x, y, aEnvironment.getPrecision()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. @@ -64,8 +64,8 @@ the functions return a floating-point result which is correct only to the current precision. *E.G. - In> - Result> +In> +Result: %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/NewRulePattern.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/NewRulePattern.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/NewRulePattern.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/NewRulePattern.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class NewRulePattern extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - org.mathpiper.lisp.Utility.newRulePattern(aEnvironment, aStackTop, false); - } -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Not.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Not.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Not.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Not.java 2011-02-05 07:50:02.000000000 +0000 @@ -34,9 +34,9 @@ { ConsPointer evaluated = new ConsPointer(); evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - if (Utility.isTrue(aEnvironment, evaluated) || Utility.isFalse(aEnvironment, evaluated)) + if (Utility.isTrue(aEnvironment, evaluated, aStackTop) || Utility.isFalse(aEnvironment, evaluated, aStackTop)) { - Utility.not(getTopOfStackPointer(aEnvironment, aStackTop), aEnvironment, evaluated); + Utility.not(aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), aEnvironment, evaluated); } else { ConsPointer ptr = new ConsPointer(); @@ -69,12 +69,12 @@ *E.G. - In> Not True - Out> False; - In> Not False - Out> True; - In> Not(a) - Out> Not a; +In> Not True +Result: False; +In> Not False +Result: True; +In> Not(a) +Result: Not a; *SEE And, Or %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Nth.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Nth.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Nth.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Nth.java 2010-02-05 10:28:57.000000000 +0000 @@ -33,9 +33,9 @@ { String str; str = (String) getArgumentPointer(aEnvironment, aStackTop, 2).car(); - LispError.checkArgument(aEnvironment, aStackTop, str != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, Utility.isNumber(str, false), 2); + LispError.checkArgument(aEnvironment, aStackTop, str != null, 2, "Nth"); + LispError.checkArgument(aEnvironment, aStackTop, Utility.isNumber(str, false), 2, "Nth"); int index = Integer.parseInt(str); - Utility.nth(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1), index); + Utility.nth(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1), index); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/OpLeftPrecedence.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/OpLeftPrecedence.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/OpLeftPrecedence.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/OpLeftPrecedence.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.InfixOperator; -import org.mathpiper.lisp.LispError; - -/** - * - * - */ -public class OpLeftPrecedence extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - InfixOperator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); - if (op == null) - { // infix and postfix operators have left precedence - - op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPostfixOperators); - LispError.check(aEnvironment, aStackTop, op != null, LispError.IS_NOT_INFIX); - } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + op.iLeftPrecedence)); - } -} - - - -/* -%mathpiper_docs,name="OpLeftPrecedence",categories="Programmer Functions;Programming;Built In" -*CMD OpLeftPrecedence --- get operator precedence -*CORE -*CALL - OpLeftPrecedence("op") - -*PARMS - -{"op"} -- string, the name of a function - -*DESC - -Returns the precedence of the function named "op" which should have been declared as a bodied function or an infix, postfix, or prefix operator. Generates an error message if the string str does not represent a type of function that can have precedence. - -For infix operators, right precedence can differ from left precedence. Bodied functions and prefix operators cannot have left precedence, while postfix operators cannot have right precedence; for these operators, there is only one value of precedence. - -*E.G. - In> OpLeftPrecedence("!") - Out> 0; - -*SEE OpPrecedence,OpRightPrecedence -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/OpPrecedence.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/OpPrecedence.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/OpPrecedence.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/OpPrecedence.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.InfixOperator; -import org.mathpiper.lisp.LispError; - -/** - * - * - */ -public class OpPrecedence extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - InfixOperator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); - if (op == null) - { // also need to check for a postfix or prefix operator - - op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPrefixOperators); - if (op == null) - { - op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPostfixOperators); - if (op == null) - { // or maybe it's a bodied function - - op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iBodiedOperators); - LispError.check(aEnvironment, aStackTop, op != null, LispError.IS_NOT_INFIX); - } - } - } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + op.iPrecedence)); - } -} - - - -/* -%mathpiper_docs,name="OpPrecedence",categories="Programmer Functions;Programming;Built In" -*CMD OpPrecedence --- get operator precedence -*CORE -*CALL - OpPrecedence("op") - -*PARMS - -{"op"} -- string, the name of a function - -*DESC - -Returns the precedence of the function named "op" which should have been declared as a bodied function or an infix, postfix, or prefix operator. Generates an error message if the string str does not represent a type of function that can have precedence. - -For infix operators, right precedence can differ from left precedence. Bodied functions and prefix operators cannot have left precedence, while postfix operators cannot have right precedence; for these operators, there is only one value of precedence. - -*E.G. - In> OpPrecedence("+") - Out> 6; - -*SEE OpLeftPrecedence,OpRightPrecedence -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/OpRightPrecedence.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/OpRightPrecedence.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/OpRightPrecedence.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/OpRightPrecedence.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.InfixOperator; -import org.mathpiper.lisp.LispError; - -/** - * - * - */ -public class OpRightPrecedence extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - InfixOperator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); - if (op == null) - { // bodied, infix and prefix operators have right precedence - - op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPrefixOperators); - if (op == null) - { // or maybe it's a bodied function - - op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iBodiedOperators); - LispError.check(aEnvironment, aStackTop, op != null, LispError.IS_NOT_INFIX); - } - } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + op.iRightPrecedence)); - } -} - - - -/* -%mathpiper_docs,name="OpRightPrecedence",categories="Programmer Functions;Programming;Built In" -*CMD OpRightPrecedence --- get operator precedence -*CORE -*CALL - OpRightPrecedence("op") - -*PARMS - -{"op"} -- string, the name of a function - -*DESC - -Returns the precedence of the function named "op" which should have been declared as a bodied function or an infix, postfix, or prefix operator. Generates an error message if the string str does not represent a type of function that can have precedence. - -For infix operators, right precedence can differ from left precedence. Bodied functions and prefix operators cannot have left precedence, while postfix operators cannot have right precedence; for these operators, there is only one value of precedence. - -*E.G. - In> OpRightPrecedence("+") - Result> 70 - -*SEE OpPrecedence,OpLeftPrecedence -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Or.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Or.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Or.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Or.java 2011-02-05 07:50:02.000000000 +0000 @@ -38,16 +38,16 @@ ConsPointer evaluated = new ConsPointer(); - ConsTraverser consTraverser = new ConsTraverser((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); + consTraverser.goNext(aStackTop); while (consTraverser.getCons() != null) { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, evaluated, consTraverser.getPointer()); - if (Utility.isTrue(aEnvironment, evaluated)) + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, consTraverser.getPointer()); + if (Utility.isTrue(aEnvironment, evaluated, aStackTop)) { Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); return; - } else if (!Utility.isFalse(aEnvironment, evaluated)) + } else if (!Utility.isFalse(aEnvironment, evaluated, aStackTop)) { ConsPointer ptr = new ConsPointer(); nrnogos++; @@ -56,7 +56,7 @@ ptr.cdr().setCons(nogos.getCons()); nogos.setCons(ptr.getCons()); } - consTraverser.goNext(); + consTraverser.goNext(aStackTop); } if (nogos.getCons() != null) @@ -68,7 +68,7 @@ { ConsPointer ptr = new ConsPointer(); - Utility.reverseList(ptr, nogos); + Utility.reverseList(aEnvironment, ptr, nogos); nogos.setCons(ptr.getCons()); ptr.setCons(getArgumentPointer(aEnvironment, aStackTop, 0).getCons().copy( aEnvironment, false)); @@ -93,7 +93,7 @@ *CALL a1 Or a2 Precedence: -*EVAL OpPrecedence("Or") +*EVAL PrecedenceGet("Or") Or(a1, a2, a3, ..., aN) *PARMS @@ -115,12 +115,12 @@ *E.G. - In> True Or False - Out> True; - In> False Or a - Out> Or(a); - In> Or(False,a,b,True) - Out> True; +In> True Or False +Result: True; +In> False Or a +Result: Or(a); +In> Or(False,a,b,True) +Result: True; *SEE And, Not %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatchLoad.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatchLoad.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatchLoad.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatchLoad.java 2010-12-29 04:07:15.000000000 +0000 @@ -19,8 +19,12 @@ package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.exceptions.EvaluationException; import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; +import org.mathpiper.io.InputStatus; +import org.mathpiper.io.StandardFileInputStream; /** * @@ -31,9 +35,30 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - aEnvironment.write("Function not yet implemented : PatchLoad");//TODO FIXME + ConsPointer evaluated = new ConsPointer(); + evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - throw new EvaluationException("Function not yet supported",-1); + // Get file name + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "PatchLoad"); + String string = (String) evaluated.car(); + LispError.checkArgument(aEnvironment, aStackTop, string != null, 1, "PatchLoad"); + + String oper = Utility.toNormalString(aEnvironment, aStackTop, string); + String hashedName = (String) aEnvironment.getTokenHash().lookUp(oper); + + InputStatus oldStatus = new InputStatus(aEnvironment.iInputStatus); + aEnvironment.iInputStatus.setTo(hashedName); + + StandardFileInputStream newInput = + new StandardFileInputStream(oper, aEnvironment.iInputStatus); + + String inputString = new String(newInput.startPtr()); + + Utility.doPatchString(inputString, aEnvironment.iCurrentOutput, aEnvironment, aStackTop); + + aEnvironment.iInputStatus.restoreFrom(oldStatus); + + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } } @@ -62,6 +87,6 @@ This is similar to the way PHP works. You can have a static text file with dynamic content generated by MathPiper. -*SEE PatchString, Load +*SEE PatchString, LoadScript %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatchString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatchString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatchString.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatchString.java 2010-12-29 04:07:15.000000000 +0000 @@ -19,17 +19,11 @@ import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.io.InputStatus; -import org.mathpiper.io.MathPiperOutputStream; -import org.mathpiper.io.StringInputStream; import org.mathpiper.io.StringOutputStream; import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.parsers.MathPiperParser; -import org.mathpiper.lisp.parsers.Parser; -import org.mathpiper.lisp.tokenizers.MathPiperTokenizer; /** * @@ -38,64 +32,24 @@ public class PatchString extends BuiltinFunction { public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - String unpatchedString; - unpatchedString = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, unpatchedString != null, 2); - - String resultString; - StringBuilder resultStringBuilder = new StringBuilder(); - String[] tags = unpatchedString.split("\\?\\>"); - if (tags.length > 1) { - for (int x = 0; x < tags.length; x++) { - String[] tag = tags[x].split("\\<\\?"); - if (tag.length > 1) { - resultStringBuilder.append(tag[0]); - String scriptCode = tag[1]; - if (scriptCode.endsWith(";")) { - scriptCode = scriptCode.substring(0, scriptCode.length() - 1); - } - resultString = lispEvaluate(aEnvironment, "Eval(" + scriptCode + ");"); - resultStringBuilder.append(resultString); - } - }//end for. - resultStringBuilder.append(tags[tags.length - 1]); - } else { - resultStringBuilder.append(unpatchedString); - } - - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, resultStringBuilder.toString())); + String unpatchedString = + (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, unpatchedString != null, 2, "PatchString"); + + InputStatus oldStatus = new InputStatus(aEnvironment.iInputStatus); + aEnvironment.iInputStatus.setTo("STRING"); + + StringBuffer resultBuffer = new StringBuffer(); + StringOutputStream resultStream = new StringOutputStream(resultBuffer); + + Utility.doPatchString(unpatchedString, resultStream, aEnvironment, aStackTop); + + aEnvironment.iInputStatus.restoreFrom(oldStatus); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, resultBuffer.toString())); } - private String lispEvaluate(Environment aEnvironment, String inputExpression) throws Exception { - ConsPointer result = new ConsPointer(); - StringBuffer oper = new StringBuffer(); - StringOutputStream newOutput = new StringOutputStream(oper); - MathPiperOutputStream previous = aEnvironment.iCurrentOutput; - aEnvironment.iCurrentOutput = newOutput; - - MathPiperTokenizer tokenizer = new MathPiperTokenizer(); - InputStatus someStatus = new InputStatus(); - ConsPointer inputExpressionPointer = new ConsPointer(); - try { - StringBuffer inp = new StringBuffer(); - inp.append(inputExpression); - inp.append(";"); - StringInputStream inputExpressionBuffer = new StringInputStream(inp, someStatus); - - Parser infixParser = new MathPiperParser(tokenizer, inputExpressionBuffer, aEnvironment, aEnvironment.iPrefixOperators, aEnvironment.iInfixOperators, aEnvironment.iPostfixOperators, aEnvironment.iBodiedOperators); - infixParser.parse(aEnvironment, inputExpressionPointer); - - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result, inputExpressionPointer); - - String resultString = Utility.printExpression(result, aEnvironment, 0); - - } catch (Exception e) { - throw e; - } finally { - aEnvironment.iCurrentOutput = previous; - } - return oper.toString(); - } + }//end class. @@ -118,10 +72,8 @@ details. *E.G. - - In> PatchString("Two plus three \ - is "); - Out> "Two plus three is 5 "; +In> PatchString("Two plus three is "); +Result: "Two plus three is 5 "; *SEE PatchLoad %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatternCreate.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatternCreate.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatternCreate.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatternCreate.java 2010-07-18 20:33:50.000000000 +0000 @@ -40,18 +40,18 @@ ConsPointer postPredicatePointer = new ConsPointer(); postPredicatePointer.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - ConsTraverser patternPointerTraverser = new ConsTraverser(patternPointer); - LispError.checkArgument(aEnvironment, aStackTop, patternPointerTraverser.getCons() != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, patternPointerTraverser.car() instanceof ConsPointer, 1); - patternPointerTraverser.goSub(); - LispError.checkArgument(aEnvironment, aStackTop, patternPointerTraverser.getCons() != null, 1); - patternPointerTraverser.goNext(); + ConsTraverser patternPointerTraverser = new ConsTraverser(aEnvironment, patternPointer); + LispError.checkArgument(aEnvironment, aStackTop, patternPointerTraverser.getCons() != null, 1, "PatternCreate"); + LispError.checkArgument(aEnvironment, aStackTop, patternPointerTraverser.car() instanceof ConsPointer, 1, "PatternCreate"); + patternPointerTraverser.goSub(aStackTop); + LispError.checkArgument(aEnvironment, aStackTop, patternPointerTraverser.getCons() != null, 1, "PatternCreate"); + patternPointerTraverser.goNext(aStackTop); patternPointer = patternPointerTraverser.getPointer(); - org.mathpiper.lisp.parametermatchers.Pattern matcher = new org.mathpiper.lisp.parametermatchers.Pattern(aEnvironment, patternPointer, postPredicatePointer); + org.mathpiper.lisp.parametermatchers.ParametersPatternMatcher matcher = new org.mathpiper.lisp.parametermatchers.ParametersPatternMatcher(aEnvironment, aStackTop, patternPointer, postPredicatePointer); PatternContainer patternContainer = new PatternContainer(matcher); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, patternContainer)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, patternContainer)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatternMatches.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatternMatches.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PatternMatches.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PatternMatches.java 2010-02-06 21:01:49.000000000 +0000 @@ -39,24 +39,24 @@ ConsPointer pattern = new ConsPointer(); pattern.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); BuiltinContainer gen = (BuiltinContainer) pattern.car(); - LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Pattern\""), 1); + LispError.checkArgument(aEnvironment, aStackTop, gen != null, 1, "PatternMatches"); + LispError.checkArgument(aEnvironment, aStackTop, gen.typeName().equals("\"Pattern\""), 1, "PatternMatches"); ConsPointer list = new ConsPointer(); list.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); PatternContainer patclass = (PatternContainer) gen; - ConsTraverser consTraverser = new ConsTraverser(list); - LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, consTraverser.car() instanceof ConsPointer, 2); - consTraverser.goSub(); - LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getCons() != null, 2); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, list); + LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getCons() != null, 2, "PatternMatches"); + LispError.checkArgument(aEnvironment, aStackTop, consTraverser.car() instanceof ConsPointer, 2, "PatternMatches"); + consTraverser.goSub(aStackTop); + LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getCons() != null, 2, "PatternMatches"); + consTraverser.goNext(aStackTop); ConsPointer ptr = consTraverser.getPointer(); - LispError.checkArgument(aEnvironment, aStackTop, ptr != null, 2); - boolean matches = patclass.matches(aEnvironment, ptr); + LispError.checkArgument(aEnvironment, aStackTop, ptr != null, 2, "PatternMatches"); + boolean matches = patclass.matches(aEnvironment, aStackTop, ptr); Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), matches); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeFromFile.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeFromFile.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeFromFile.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeFromFile.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,110 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.io.InputStatus; +import org.mathpiper.lisp.Environment; +import org.mathpiper.io.MathPiperInputStream; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class PipeFromFile extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + LispError.check(aEnvironment, aStackTop, aEnvironment.iSecure == false, LispError.SECURITY_BREACH); + ConsPointer evaluated = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, getArgumentPointer(aEnvironment, aStackTop, 1)); + + // Get file name + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "PipeFromFile"); + String orig = (String) evaluated.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "PipeFromFile"); + + String hashedname = aEnvironment.getTokenHash().lookUpUnStringify(orig); + + InputStatus oldstatus = aEnvironment.iInputStatus; + MathPiperInputStream previous = aEnvironment.iCurrentInput; + try + { + aEnvironment.iInputStatus.setTo(hashedname); + MathPiperInputStream input = // new StdFileInput(hashedname, aEnvironment.iInputStatus); + Utility.openInputFile(aEnvironment, aEnvironment.iInputDirectories, hashedname, aEnvironment.iInputStatus); + aEnvironment.iCurrentInput = input; + // Open file + LispError.check(aEnvironment, aStackTop, input != null, LispError.FILE_NOT_FOUND); + + // Evaluate the body + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); + } catch (Exception e) + { + throw e; + } finally + { + aEnvironment.iCurrentInput = previous; + aEnvironment.iInputStatus.restoreFrom(oldstatus); + } + //Return the getTopOfStackPointer + } +} + + + +/* +%mathpiper_docs,name="PipeFromFile",categories="User Functions;Input/Output;Built In" +*CMD PipeFromFile --- connect current input to a file +*CORE +*CALL + PipeFromFile(name) body + +*PARMS + +{name} - string, the name of the file to read + +{body} - expression to be evaluated + +*DESC + +The current input is connected to the file "name". Then the expression +"body" is evaluated. If some functions in "body" try to read +from current input, they will now read from the file "name". Finally, the +file is closed and the result of evaluating "body" is returned. + +*E.G. notest + +Suppose that the file {foo} contains + + 2 + 5; + +Then we can have the following dialogue: + +In> PipeFromFile("foo") res := Read(); +Result: 2+5; +In> PipeFromFile("foo") res := ReadToken(); +Result: 2; + +*SEE PipeToFile, FromString, Read, ReadToken +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeFromString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeFromString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeFromString.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeFromString.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,102 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.io.InputStatus; +import org.mathpiper.io.StringInputStream; +import org.mathpiper.lisp.Environment; +import org.mathpiper.io.MathPiperInputStream; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class PipeFromString extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + ConsPointer evaluated = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, getArgumentPointer(aEnvironment, aStackTop, 1)); + + // Get file name + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "PipeFromString"); + String orig = (String) evaluated.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "PipeFromString"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); + + InputStatus oldstatus = aEnvironment.iInputStatus; + aEnvironment.iInputStatus.setTo("String"); + StringInputStream newInput = new StringInputStream(new StringBuffer(oper), aEnvironment.iInputStatus); + + MathPiperInputStream previous = aEnvironment.iCurrentInput; + aEnvironment.iCurrentInput = newInput; + try + { + // Evaluate the body + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); + } catch (Exception e) + { + throw e; + } finally + { + aEnvironment.iCurrentInput = previous; + aEnvironment.iInputStatus.restoreFrom(oldstatus); + } + + //Return the getTopOfStackPointer + } +} + + + +/* +%mathpiper_docs,name="PipeFromString",categories="User Functions;Input/Output;Built In" +*CMD PipeFromString --- connect current input to a string +*CORE +*CALL + PipeFromString(str) body; + +*PARMS + +{str} -- a string containing the text to parse + +{body} -- expression to be evaluated + +*DESC + +The commands in "body" are executed, but everything that is read +from the current input is now read from the string "str". The +result of "body" is returned. + +*E.G. + +In> PipeFromString("2+5; this is never read") \ + res := Read(); +Result: 2+5; +In> PipeFromString("2+5; this is never read") \ + res := Eval(Read()); +Result: 7; + +*SEE PipeToString, PipeFromFile, Read, ReadToken +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeToFile.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeToFile.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeToFile.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeToFile.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,142 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import java.io.FileOutputStream; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.io.StandardFileOutputStream; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.io.MathPiperOutputStream; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class PipeToFile extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + LispError.check(aEnvironment, aStackTop, aEnvironment.iSecure == false, LispError.SECURITY_BREACH); + + ConsPointer evaluated = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, getArgumentPointer(aEnvironment, aStackTop, 1)); + + // Get file name + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "PipeToFile"); + String orig = (String) evaluated.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "PipeToFile"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); + + // Open file for writing + FileOutputStream localFP = new FileOutputStream(oper, true); + + LispError.check(aEnvironment, aStackTop, localFP != null, LispError.FILE_NOT_FOUND); + + StandardFileOutputStream newStream = new StandardFileOutputStream(localFP); + + MathPiperOutputStream originalStream = aEnvironment.iCurrentOutput; + + aEnvironment.iCurrentOutput = newStream; + + try + { + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); + } catch (Exception e) + { + throw e; + } finally + { + localFP.flush(); + localFP.close(); + aEnvironment.iCurrentOutput = originalStream; + } + } +} + + + +/* +%mathpiper_docs,name="PipeToFile",categories="User Functions;Input/Output;Built In" +*CMD PipeToFile --- connect current output to a file +*CORE +*CALL + PipeToFile(name) body + +*PARMS + +{name} -- string, the name of the file to write the result to + +{body} -- expression to be evaluated + +*DESC + +The current output is connected to the file "name". Then the expression +"body" is evaluated. Everything that the commands in "body" print +to the current output, ends up in the file "name". Finally, the +file is closed and the result of evaluating "body" is returned. + +If the file is opened again, the new information will be appended to the +existing information in the file. + +*E.G. notest + +Here is how one can create a file with C code to evaluate an expression: + +In> PipeToFile("expr1.c") WriteString(CForm(Sqrt(x-y)*Sin(x)) ); +Result> True; + +The file {expr1.c} was created in the current working directory and it +contains the line sqrt(x-y)*sin(x) + + +As another example, take a look at the following command: + +In> [ Echo("Result:"); PrettyForm(Taylor(x,0,9) Sin(x)); ]; +Result: + + 3 5 7 9 + x x x x + x - -- + --- - ---- + ------ + 6 120 5040 362880 + +Result> True; + +Now suppose one wants to send the output of this command to a +file. This can be achieved as follows: + +In> PipeToFile("out") [ Echo("Result:"); PrettyForm(Taylor(x,0,9) Sin(x)); ]; +Result> True; + +After this command the file {out} contains: + + +Result: + + 3 5 7 9 + x x x x + x - -- + --- - ---- + ------ + 6 120 5040 362880 + + +*SEE PipeFromFile, PipeToString, Echo, Write, WriteString, PrettyForm, Taylor +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeToStdout.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeToStdout.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeToStdout.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeToStdout.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,75 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.io.MathPiperOutputStream; + +/** + * + * + */ +public class PipeToStdout extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + MathPiperOutputStream previous = aEnvironment.iCurrentOutput; + aEnvironment.iCurrentOutput = aEnvironment.iInitialOutput; + try + { + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); + } catch (Exception e) + { + throw e; + } finally + { + aEnvironment.iCurrentOutput = previous; + } + } +} + + + +/* +%mathpiper_docs,name="PipeToStdout",categories="User Functions;Input/Output;Built In" +*CMD PipeToStdout --- select initial output stream for output +*CORE +*CALL + PipeToStdout() body + +*PARMS + +{body} -- expression to be evaluated + +*DESC + +When using {PipeToString} or {PipeToFile}, it might happen that something needs to be +written to the standard default initial output (typically the screen). {PipeToStdout} can be used to select this stream. + +*E.G. + +In> PipeToString()[Echo("aaaa");PipeToStdout()Echo("bbbb");]; + bbbb +Result: "aaaa + " + +*SEE PipeToString, PipeToFile +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeToString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeToString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PipeToString.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PipeToString.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,83 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.io.StringOutputStream; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.io.MathPiperOutputStream; + +/** + * + * + */ +public class PipeToString extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + StringBuffer oper = new StringBuffer(); + StringOutputStream newOutput = new StringOutputStream(oper); + MathPiperOutputStream previous = aEnvironment.iCurrentOutput; + aEnvironment.iCurrentOutput = newOutput; + try + { + // Evaluate the body + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); + + //Return the getTopOfStackPointer + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.getTokenHash().lookUpStringify(oper.toString()))); + } catch (Exception e) + { + throw e; + } finally + { + aEnvironment.iCurrentOutput = previous; + } + } +} + + + +/* +%mathpiper_docs,name="PipeToString",categories="User Functions;Input/Output;Built In" +*CMD PipeToString --- connect current output to a string +*CORE +*CALL + PipeToString() body + +*PARMS + +{body} -- expression to be evaluated + +*DESC + +The commands in "body" are executed. Everything that is printed on +the current output, by {Echo} for instance, is +collected in a string and this string is returned. + +*E.G. + +In> str := PipeToString() [ WriteString( \ + "The square of 8 is "); Write(8^2); ]; +Result: "The square of 8 is 64"; + +*SEE PipeFromFile, PipeToString, Echo, Write, WriteString +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Postfix.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Postfix.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Postfix.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Postfix.java 2011-02-05 07:50:02.000000000 +0000 @@ -18,7 +18,6 @@ package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.Utility; @@ -31,7 +30,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - int nrArguments = Utility.listLength(getArgumentPointer(aEnvironment, aStackTop, 0)); + int nrArguments = Utility.listLength(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0)); if (nrArguments == 2) { Utility.singleFix(0, aEnvironment, aStackTop, aEnvironment.iPostfixOperators); @@ -71,8 +70,8 @@ Precedence is optional (will be set to 0 by default). *E.G. - In> todo +In> todo -*SEE IsBodied, OpPrecedence, Bodied, Infix, Prefix +*SEE IsBodied, PrecedenceGet, Bodied, Infix, Prefix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrecedenceGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrecedenceGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrecedenceGet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrecedenceGet.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,82 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Operator; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class PrecedenceGet extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Operator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); + if (op == null) + { // also need to check for a postfix or prefix operator + + op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPrefixOperators); + if (op == null) + { + op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPostfixOperators); + if (op == null) + { // or maybe it's a bodied function + + op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iBodiedOperators); + LispError.check(aEnvironment, aStackTop, op != null, LispError.IS_NOT_INFIX); + } + } + } + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + op.iPrecedence)); + } +} + + + +/* +%mathpiper_docs,name="PrecedenceGet",categories="Programmer Functions;Programming;Built In" +*CMD PrecedenceGet --- get operator precedence +*CORE +*CALL + PrecedenceGet("op") + +*PARMS + +{"op"} -- string, the name of a function + +*DESC + +Returns the precedence of the function named "op" which should have been declared as a bodied function or an infix, postfix, or prefix operator. Generates an error message if the string str does not represent a type of function that can have precedence. + +For infix operators, right precedence can differ from left precedence. Bodied functions and prefix operators cannot have left precedence, while postfix operators cannot have right precedence; for these operators, there is only one value of precedence. + +*E.G. +In> PrecedenceGet("+") +Result: 6; + +*SEE LeftPrecedenceGet,RightPrecedenceGet,LeftPrecedenceSet,RightPrecedenceSet,RightAssociativeSet +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Prefix.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Prefix.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Prefix.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Prefix.java 2011-02-05 07:50:02.000000000 +0000 @@ -60,21 +60,21 @@ Precedence is optional (will be set to 0 by default). *E.G. - In> YY x := x+1; +In> YY x := x+1; CommandLine(1) : Error parsing expression - In> Prefix("YY", 2) - Out> True; - In> YY x := x+1; - Out> True; - In> YY YY 2*3 - Out> 12; +In> Prefix("YY", 2) +Result: True; +In> YY x := x+1; +Result: True; +In> YY YY 2*3 +Result: 12; Note that, due to a current parser limitation, a function atom that is declared prefix cannot be used by itself as an argument. - In> YY +In> YY CommandLine(1) : Error parsing expression -*SEE IsBodied, OpPrecedence, Bodied, Infix, Postfix +*SEE IsBodied, PrecedenceGet, Bodied, Infix, Postfix %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyPrinterGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyPrinterGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyPrinterGet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyPrinterGet.java 2011-02-05 07:50:02.000000000 +0000 @@ -31,12 +31,12 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - if (aEnvironment.iPrettyPrinter == null) + if (aEnvironment.iPrettyPrinterName == null) { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"\"")); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "\"\"")); } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.iPrettyPrinter)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.iPrettyPrinterName)); } } } @@ -61,8 +61,8 @@ *E.G. - In> PrettyPrinter'Get() - Result> "" +In> PrettyPrinterGet() +Result: "" *SEE PrettyForm, Write, TeXForm, CForm, OMForm, PrettyReaderSet, PrettyReaderGet, PrettyPrinterSet %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyPrinterSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyPrinterSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyPrinterSet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyPrinterSet.java 2011-02-05 07:50:02.000000000 +0000 @@ -33,18 +33,18 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - int nrArguments = Utility.listLength(getArgumentPointer(aEnvironment, aStackTop, 0)); + int nrArguments = Utility.listLength(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0)); if (nrArguments == 1) { - aEnvironment.iPrettyPrinter = null; + aEnvironment.iPrettyPrinterName = null; } else { LispError.check(aEnvironment, aStackTop, nrArguments == 2, LispError.WRONG_NUMBER_OF_ARGUMENTS); ConsPointer oper = new ConsPointer(); oper.setCons(getArgumentPointer(aEnvironment, aStackTop, 0).getCons()); - oper.goNext(); - LispError.checkIsString(aEnvironment, aStackTop, oper, 1); - aEnvironment.iPrettyPrinter = (String) oper.car(); + oper.goNext(aStackTop, aEnvironment); + LispError.checkIsString(aEnvironment, aStackTop, oper, 1, "PrettyPrinterSet"); + aEnvironment.iPrettyPrinterName = (String) oper.car(); } Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } @@ -81,23 +81,23 @@ *E.G. - In> Taylor(x,0,5)Sin(x) - Out> x-x^3/6+x^5/120; - In> PrettyPrinterSet("PrettyForm"); +In> Taylor(x,0,5)Sin(x) +Result: x-x^3/6+x^5/120; +In> PrettyPrinterSet("PrettyForm"); True - In> Taylor(x,0,5)Sin(x) +In> Taylor(x,0,5)Sin(x) 3 5 x x x - -- + --- 6 120 - In> PrettyPrinterSet(); - Out> True; - In> Taylor(x,0,5)Sin(x) - Out> x-x^3/6+x^5/120; +In> PrettyPrinterSet(); +Result: True; +In> Taylor(x,0,5)Sin(x) +Result: x-x^3/6+x^5/120; *SEE PrettyForm, Write, TeXForm, CForm, OMForm, PrettyReaderSet, PrettyReaderGet, PrettyPrinterGet %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyReaderGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyReaderGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyReaderGet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyReaderGet.java 2011-02-05 07:50:02.000000000 +0000 @@ -31,12 +31,12 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - if (aEnvironment.iPrettyReader == null) + if (aEnvironment.iPrettyReaderName == null) { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"\"")); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "\"\"")); } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.iPrettyReader)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.iPrettyReaderName)); } } } @@ -61,8 +61,8 @@ *E.G. - In> PrettyReader'Get() - Result> "" +In> PrettyReaderGet() +Result: "" *SEE Read, LispRead, OMRead, PrettyPrinterSet, PrettyPrinterGet, PrettyReaderSet %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyReaderSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyReaderSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/PrettyReaderSet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/PrettyReaderSet.java 2011-02-05 07:50:02.000000000 +0000 @@ -33,18 +33,18 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - int nrArguments = Utility.listLength(getArgumentPointer(aEnvironment, aStackTop, 0)); + int nrArguments = Utility.listLength(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0)); if (nrArguments == 1) { - aEnvironment.iPrettyReader = null; + aEnvironment.iPrettyReaderName = null; } else { LispError.check(aEnvironment, aStackTop, nrArguments == 2, LispError.WRONG_NUMBER_OF_ARGUMENTS); ConsPointer oper = new ConsPointer(); oper.setCons(getArgumentPointer(aEnvironment, aStackTop, 0).getCons()); - oper.goNext(); - LispError.checkIsString(aEnvironment, aStackTop, oper, 1); - aEnvironment.iPrettyReader = (String) oper.car(); + oper.goNext(aStackTop, aEnvironment); + LispError.checkIsString(aEnvironment, aStackTop, oper, 1, "PrettyReaderSet"); + aEnvironment.iPrettyReaderName = (String) oper.car(); } Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } @@ -81,12 +81,12 @@ *E.G. - In> Taylor(x,0,5)Sin(x) - Out> x-x^3/6+x^5/120 - In> PrettyReaderSet("LispRead") - Out> True - In> (Taylor x 0 5 (Sin x)) - Out> x-x^3/6+x^5/120 +In> Taylor(x,0,5)Sin(x) +Result: x-x^3/6+x^5/120 +In> PrettyReaderSet("LispRead") +Result: True +In> (Taylor x 0 5 (Sin x)) +Result: x-x^3/6+x^5/120 *SEE Read, LispRead, OMRead, PrettyPrinterSet, PrettyPrinterGet, PrettyReaderGet %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Prog.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Prog.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Prog.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Prog.java 2010-02-07 03:43:56.000000000 +0000 @@ -13,48 +13,52 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.builtin.functions.core; + import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.exceptions.ReturnException; import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.cons.ConsTraverser; import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.cons.ConsPointer; + /** * * */ -public class Prog extends BuiltinFunction -{ +public class Prog extends BuiltinFunction { - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { // Allow accessing previous locals. aEnvironment.pushLocalFrame(false, "Prog"); - try - { - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - // Evaluate args one by one. + try { + + ConsPointer resultPointer = new ConsPointer(); + + Utility.putTrueInPointer(aEnvironment, resultPointer); - ConsTraverser consTraverser = new ConsTraverser((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); - consTraverser.goNext(); - while (consTraverser.getCons() != null) - { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), consTraverser.getPointer()); - consTraverser.goNext(); + // Evaluate args one by one. + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); + consTraverser.goNext(aStackTop); + while (consTraverser.getCons() != null) { + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, resultPointer, consTraverser.getPointer()); + consTraverser.goNext(aStackTop); } - } catch (Exception e) - { + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(resultPointer.getCons()); + + } catch (Exception e) { throw e; - } finally - { - aEnvironment.popLocalFrame(); + } finally { + aEnvironment.popLocalFrame(aStackTop); } } + + } @@ -79,6 +83,6 @@ function bodies. The {[ ... ]} construct is a syntactically nicer version of the {Prog} call; it is converted into {Prog(...)} during the parsing stage. -*SEE [, ] +*SEE [, ], ReturnFromBlock %/mathpiper_docs -*/ \ No newline at end of file +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Quotient.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Quotient.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Quotient.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Quotient.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,79 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class Quotient extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + BigNumber y = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + if (x.isInteger() && y.isInteger()) + { // both integer, perform integer division + + BigNumber z = new BigNumber(aEnvironment.getPrecision()); + z.divide(x, y, aEnvironment.getPrecision()); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); + return; + } else + { + throw new Exception("LispDiv: error: both arguments must be integer"); + } + } +}//end class. + + + +/* +%mathpiper_docs,name="QuotientN",categories="User Functions;Numeric;Built In" +*CMD QuotientN --- integer division result is an integer (arbitrary-precision math function) +*CORE +*CALL + QuotientN(x,y) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Read.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Read.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Read.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Read.java 2011-02-05 07:50:02.000000000 +0000 @@ -38,7 +38,7 @@ aEnvironment.iPostfixOperators, aEnvironment.iBodiedOperators); // Read expression - parser.parse(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop)); + parser.parse(aStackTop, getTopOfStackPointer(aEnvironment, aStackTop)); } } @@ -58,11 +58,11 @@ *E.G. - In> FromString("2+5;") Read(); - Out> 2+5; - In> FromString("") Read(); - Out> EndOfFile; +In> PipeFromString("2+5;") Read(); +Result: 2+5; +In> PipeFromString("") Read(); +Result: EndOfFile; -*SEE FromFile, FromString, LispRead, ReadToken, Write +*SEE PipeFromFile, PipeFromString, LispRead, ReadToken, Write %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ReadToken.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ReadToken.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ReadToken.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ReadToken.java 2011-02-05 07:50:02.000000000 +0000 @@ -33,14 +33,14 @@ { MathPiperTokenizer tok = aEnvironment.iCurrentTokenizer; String result; - result = tok.nextToken(aEnvironment.iCurrentInput, aEnvironment.getTokenHash()); + result = tok.nextToken(aEnvironment, aStackTop, aEnvironment.iCurrentInput, aEnvironment.getTokenHash()); if (result.length() == 0) { getTopOfStackPointer(aEnvironment, aStackTop).setCons(aEnvironment.iEndOfFileAtom.copy( aEnvironment, false)); return; } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, result)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, result)); } } @@ -72,7 +72,7 @@ *E.G. notest - In> FromString("a := Sin(x)") While \ +In> PipeFromString("a := Sin(x)") While \ ((tok := ReadToken()) != EndOfFile) \ Echo(tok); a @@ -81,17 +81,17 @@ ( x ) - Out> True; +Result: True; We can read some junk too: - In> FromString("-$3")ReadToken(); - Out> -$; +In> PipeFromString("-$3")ReadToken(); +Result: -$; The result is an atom with the string representation {-$}. MathPiper assumes that {-$} is an operator symbol yet to be defined. The "{3}" will be in the next token. (The results will be different if a non-default tokenizer is selected.) -*SEE FromFile, FromString, Read, LispRead, DefaultTokenizer +*SEE PipeFromFile, PipeFromString, Read, LispRead, DefaultTokenizer %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Replace.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Replace.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Replace.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Replace.java 2011-02-05 07:50:02.000000000 +0000 @@ -63,8 +63,8 @@ *E.G. - In> Replace({a,b,c,d,e,f}, 4, x); - Out> {a,b,c,x,e,f}; +In> Replace({a,b,c,d,e,f}, 4, x); +Result: {a,b,c,x,e,f}; *SEE Delete, Insert, DestructiveReplace %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Rest.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Rest.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Rest.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Rest.java 2011-02-05 07:50:02.000000000 +0000 @@ -32,8 +32,8 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { ConsPointer first = new ConsPointer(); - Utility.tail(aEnvironment, first, getArgumentPointer(aEnvironment, aStackTop, 1)); - Utility.tail(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop), first); + Utility.tail(aEnvironment, aStackTop, first, getArgumentPointer(aEnvironment, aStackTop, 1)); + Utility.tail(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), first); ConsPointer head = new ConsPointer(); head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); head.cdr().setCons(((ConsPointer) getTopOfStackPointer(aEnvironment, aStackTop).car()).getCons()); @@ -60,8 +60,8 @@ *E.G. - In> Rest({a,b,c}) - Out> {b,c}; +In> Rest({a,b,c}) +Result: {b,c}; *SEE First, Length %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Retract.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Retract.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Retract.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Retract.java 2010-07-14 01:07:17.000000000 +0000 @@ -36,23 +36,23 @@ ConsPointer evaluated = new ConsPointer(); evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "Retract"); String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "Retract"); String oper = Utility.getSymbolName(aEnvironment, orig); ConsPointer arityPointer = new ConsPointer(); arityPointer.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, arityPointer.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, arityPointer.car() instanceof String, 2, "Retract"); String arityString = (String) arityPointer.car(); if(arityString.equalsIgnoreCase("*")) { - aEnvironment.retractFunction(oper, -1); + aEnvironment.retractRule(oper, -1, aStackTop, aEnvironment); } else { int arity = Integer.parseInt(arityString, 10); - aEnvironment.retractFunction(oper, arity); + aEnvironment.retractRule(oper, arity, aStackTop, aEnvironment); } Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); @@ -71,16 +71,17 @@ *PARMS {"function"} -- string, name of function -{arity} -- positive integer +{arity} -- positive integer or * *DESC Remove a rulebase for the function named {"function"} with the specific {arity}, if it exists at all. This will make -MathPiper forget all rules defined for a given function. Rules for functions with -the same name but different arities are not affected. +MathPiper forget all rules defined for a given function with the given arity. Rules for functions with +the same name but different arities are not affected unless the * wildcard character is used. If * is used for the +arity, then all arities of the rulebase are removed. -Assignment {:=} of a function does this to the function being (re)defined. +Assignment {:=} of a function automatically does a single arity retract to the function being (re)defined. -*SEE RuleBaseArgList, RuleBase, := +*SEE RulebaseArgumentsList, Rulebase, := %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Return.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Return.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Return.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Return.java 2010-01-19 05:25:49.000000000 +0000 @@ -0,0 +1,40 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.exceptions.ReturnException; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class Return extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + throw new ReturnException(); + } + +}//end class. + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightAssociative.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightAssociative.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightAssociative.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightAssociative.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class RightAssociative extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - // Get operator - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - aEnvironment.iInfixOperators.setRightAssociative(Utility.getSymbolName(aEnvironment, orig)); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} - - - -/* -%mathpiper_docs,name="RightAssociative",categories="Programmer Functions;Programming;Built In" -*CMD RightAssociative --- declare associativity -*CORE -*CALL - RightAssociative("op") - -*PARMS - -{"op"} -- string, the name of a function - -*DESC -This makes the operator right-associative. For example: - RightAssociative("*") -would make multiplication right-associative. Take care not to abuse this -function, because the reverse, making an infix operator left-associative, is -not implemented. (All infix operators are by default left-associative until -they are declared to be right-associative.) - -*SEE OpPrecedence -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightAssociativeSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightAssociativeSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightAssociativeSet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightAssociativeSet.java 2010-02-05 10:28:57.000000000 +0000 @@ -0,0 +1,67 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class RightAssociativeSet extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + // Get operator + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "RightAssociativeSet"); + String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "RightAssociativeSet"); + aEnvironment.iInfixOperators.setRightAssociative(aStackTop, Utility.getSymbolName(aEnvironment, orig)); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + + +/* +%mathpiper_docs,name="RightAssociativeSet",categories="Programmer Functions;Programming;Built In" +*CMD RightAssociativeSet --- declare associativity +*CORE +*CALL + RightAssociativeSet("op") + +*PARMS + +{"op"} -- string, the name of a function + +*DESC +This makes the operator right-associative. For example: + RightAssociativeSet("*") +would make multiplication right-associative. Take care not to abuse this +function, because the reverse, making an infix operator left-associative, is +not implemented. (All infix operators are by default left-associative until +they are declared to be right-associative.) + +*SEE PrecedenceGet, LeftPrecedenceGet, RightPrecedenceGet, LeftPrecedenceSet, RightPrecedenceSet +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightPrecedenceGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightPrecedenceGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightPrecedenceGet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightPrecedenceGet.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,78 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Operator; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class RightPrecedenceGet extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Operator op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iInfixOperators); + if (op == null) + { // bodied, infix and prefix operators have right precedence + + op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iPrefixOperators); + if (op == null) + { // or maybe it's a bodied function + + op = Utility.operatorInfo(aEnvironment, aStackTop, aEnvironment.iBodiedOperators); + LispError.check(aEnvironment, aStackTop, op != null, LispError.IS_NOT_INFIX); + } + } + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + op.iRightPrecedence)); + } +} + + + +/* +%mathpiper_docs,name="RightPrecedenceGet",categories="Programmer Functions;Programming;Built In" +*CMD RightPrecedenceGet --- get operator precedence +*CORE +*CALL + RightPrecedenceGet("op") + +*PARMS + +{"op"} -- string, the name of a function + +*DESC + +Returns the precedence of the function named "op" which should have been declared as a bodied function or an infix, postfix, or prefix operator. Generates an error message if the string str does not represent a type of function that can have precedence. + +For infix operators, right precedence can differ from left precedence. Bodied functions and prefix operators cannot have left precedence, while postfix operators cannot have right precedence; for these operators, there is only one value of precedence. + +*E.G. +In> RightPrecedenceGet("+") +Result: 70 + +*SEE PrecedenceGet,LeftPrecedenceGet,LeftPrecedenceSet,RightPrecedenceSet,RightAssociativeSet +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightPrecedence.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightPrecedence.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightPrecedence.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightPrecedence.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class RightPrecedence extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - // Get operator - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - - ConsPointer index = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, index, getArgumentPointer(aEnvironment, aStackTop, 2)); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2); - int ind = Integer.parseInt ( (String) index.car(), 10); - - aEnvironment.iInfixOperators.setRightPrecedence(Utility.getSymbolName(aEnvironment, orig), ind); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} - - - -/* -%mathpiper_docs,name="RightPrecedence",categories="User Functions;Built In" -*CMD RightPrecedence --- set operator precedence -*CORE -*CALL - RightPrecedence("op",precedence) - -*PARMS - -{"op"} -- string, the name of a function - -{precedence} -- nonnegative integer - -*DESC - -{"op"} should be an infix operator. This function call tells the -infix expression printer to bracket the right hand side of -the expression if its precedence is larger than precedence. - -This functionality was required in order to display expressions like {a-(b-c)} -correctly. Thus, {a+b+c} is the same as {a+(b+c)}, but {a-(b-c)} is not -the same as {a-b-c}. - -Note that the right precedence of an infix operator does not affect the way MathPiper interprets expressions typed by the user. You cannot make MathPiper parse {a-b-c} as {a-(b-c)} unless you declare the operator "{-}" to be right-associative. - -*SEE OpPrecedence, OpLeftPrecedence, OpRightPrecedence, RightAssociative, LeftPrecedence -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightPrecedenceSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightPrecedenceSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RightPrecedenceSet.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RightPrecedenceSet.java 2010-02-06 21:01:49.000000000 +0000 @@ -0,0 +1,81 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class RightPrecedenceSet extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + // Get operator + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "RightPrecedenceSet"); + String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "RightPrecedenceSet"); + + ConsPointer index = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, index, getArgumentPointer(aEnvironment, aStackTop, 2)); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2, "RightPrecedenceSet"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2, "RightPrecedenceSet"); + int ind = Integer.parseInt ( (String) index.car(), 10); + + aEnvironment.iInfixOperators.setRightPrecedence(aStackTop, Utility.getSymbolName(aEnvironment, orig), ind); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + + +/* +%mathpiper_docs,name="RightPrecedenceSet",categories="User Functions;Built In" +*CMD RightPrecedenceSet --- set operator precedence +*CORE +*CALL + RightPrecedenceSet("op",precedence) + +*PARMS + +{"op"} -- string, the name of a function + +{precedence} -- nonnegative integer + +*DESC + +{"op"} should be an infix operator. This function call tells the +infix expression printer to bracket the right hand side of +the expression if its precedence is larger than precedence. + +This functionality was required in order to display expressions like {a-(b-c)} +correctly. Thus, {a+b+c} is the same as {a+(b+c)}, but {a-(b-c)} is not +the same as {a-b-c}. + +Note that the right precedence of an infix operator does not affect the way MathPiper interprets expressions typed by the user. You cannot make MathPiper parse {a-b-c} as {a-(b-c)} unless you declare the operator "{-}" to be right-associative. + +*SEE PrecedenceGet, LeftPrecedenceGet, RightPrecedenceGet, LeftPrecedenceSet, RightAssociativeSet +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RoundToN.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RoundToN.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RoundToN.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RoundToN.java 2010-03-13 06:38:19.000000000 +0000 @@ -0,0 +1,127 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.NumberCons; +import org.mathpiper.lisp.cons.SublistCons; + +/** + * + * + */ +public class RoundToN extends BuiltinFunction { + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + BigNumber requestedPrecision = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + + + + Cons argument1 = getArgumentPointer(aEnvironment, aStackTop, 1).getCons(); + + if(argument1 instanceof NumberCons) + { + + BigNumber decimalToBeRounded = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + if(decimalToBeRounded.getPrecision() != requestedPrecision.toInt()) + { + decimalToBeRounded.setPrecision(requestedPrecision.toInt()); + } + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(decimalToBeRounded)); + + return; + + } + else if (argument1 instanceof SublistCons) + { + ConsPointer consPointer = new ConsPointer(argument1); + + consPointer.goSub(aStackTop, aEnvironment); + + String functionName = ((String) consPointer.car()); + + if(functionName.equals("Complex")) + { + consPointer.goNext(aStackTop, aEnvironment); + + BigNumber realPart = (BigNumber) ((NumberCons) (consPointer.getCons())).getNumber(aEnvironment.getPrecision(), aEnvironment); + + if(realPart.getPrecision() != requestedPrecision.toInt()) + { + realPart.setPrecision(requestedPrecision.toInt()); + }//end if. + + consPointer.goNext(aStackTop, aEnvironment); + + BigNumber imaginaryPart = (BigNumber) ((NumberCons) (consPointer.getCons())).getNumber(aEnvironment.getPrecision(), aEnvironment); + + if(imaginaryPart.getPrecision() != requestedPrecision.toInt()) + { + imaginaryPart.setPrecision(requestedPrecision.toInt()); + }//end if. + + + + Cons complexAtomCons = AtomCons.getInstance(aEnvironment, aStackTop, "Complex"); + + Cons realNumberCons = new NumberCons(realPart); + + complexAtomCons.cdr().setCons(realNumberCons); + + Cons imaginaryNumberCons = new NumberCons(imaginaryPart); + + realNumberCons.cdr().setCons(imaginaryNumberCons); + + Cons complexSublistCons = SublistCons.getInstance(aEnvironment, complexAtomCons); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(complexSublistCons); + + return; + + }//end if. + + + }//end else. + + LispError.raiseError("The first argument must be a number.", "RoundToN", aStackTop, aEnvironment); + + }//end method. + + +}//end class. + + + +/* +%mathpiper_docs,name="RoundToN",categories="User Functions;Numeric;Built In" +*CMD RoundToN --- rounds a decimal number to a given precision +*CORE +*CALL + RoundToN(decimalNumber, precision) + +*PARMS +{decimalNumber} -- a decimal number to be rounded +{precision} -- precision to round the number to + +*DESC + +This command rounds a decimal number to a given precision. + +*E.G. +In> RoundToN(7.57809824,2) +Result> 7.6 + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseArgList.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseArgList.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseArgList.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseArgList.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.SublistCons; -import org.mathpiper.lisp.userfunctions.SingleArityBranchingUserFunction; - -/** - * - * - */ -public class RulebaseArgList extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - ConsPointer name = new ConsPointer(); - name.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - String orig = (String) name.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); - - ConsPointer sizearg = new ConsPointer(); - sizearg.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2); - - int arity = Integer.parseInt( (String) sizearg.car(), 10); - - SingleArityBranchingUserFunction userFunc = aEnvironment.getUserFunction((String)aEnvironment.getTokenHash().lookUp(oper), arity); - LispError.check(aEnvironment, aStackTop, userFunc != null, LispError.INVALID_ARGUMENT); - - ConsPointer list = userFunc.argList(); - ConsPointer head = new ConsPointer(); - head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); - head.cdr().setCons(list.getCons()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,head.getCons())); - } -} - - - -/* -%mathpiper_docs,name="RuleBaseArgList",categories="User Functions;Built In;Built In" -*CMD RuleBaseArgList --- obtain list of arguments -*CORE -*CALL - RuleBaseArgList("operator", arity) - -*PARMS -{"operator"} -- string, name of function - -{arity} -- integer - -*DESC - -Returns a list of atoms, symbolic parameters specified in the {RuleBase} call -for the function named {"operator"} with the specific {arity}. - -*SEE RuleBase, HoldArgNr, HoldArg -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseArgumentsList.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseArgumentsList.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseArgumentsList.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseArgumentsList.java 2011-01-29 01:58:56.000000000 +0000 @@ -0,0 +1,84 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.SublistCons; +import org.mathpiper.lisp.rulebases.SingleArityRulebase; + +/** + * + * + */ +public class RulebaseArgumentsList extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + ConsPointer name = new ConsPointer(); + name.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + String orig = (String) name.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "RulebaseArgumentsList"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); + + ConsPointer sizearg = new ConsPointer(); + sizearg.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2, "RulebaseArgumentsList"); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2, "RulebaseArgumentsList"); + + int arity = Integer.parseInt( (String) sizearg.car(), 10); + + SingleArityRulebase userFunc = aEnvironment.getRulebase((String)aEnvironment.getTokenHash().lookUp(oper), arity, aStackTop); + + LispError.check(userFunc != null, "User function for this arity is not defined.", "RulebaseArgumentsList", aStackTop, aEnvironment); + + ConsPointer list = userFunc.argList(); + ConsPointer head = new ConsPointer(); + head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); + head.cdr().setCons(list.getCons()); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,head.getCons())); + } +} + + + +/* +%mathpiper_docs,name="RulebaseArgumentsList",categories="Programmer Functions;Programming;Built In" +*CMD RulebaseArgumentsList --- obtain list of arguments +*CORE +*CALL + RulebaseArgumentsList("operator", arity) + +*PARMS +{"operator"} -- string, name of function + +{arity} -- integer + +*DESC + +Returns a list of atoms, symbolic parameters specified in the {Rulebase} call +for the function named {"operator"} with the specific {arity}. + +*SEE Rulebase, HoldArgumentNumber, HoldArgument +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseDefined.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseDefined.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseDefined.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseDefined.java 2011-01-29 01:58:56.000000000 +0000 @@ -23,7 +23,7 @@ import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.userfunctions.SingleArityBranchingUserFunction; +import org.mathpiper.lisp.rulebases.SingleArityRulebase; /** * @@ -37,17 +37,38 @@ ConsPointer name = new ConsPointer(); name.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); String orig = (String) name.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "RulebaseDefined"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); ConsPointer sizearg = new ConsPointer(); sizearg.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.getCons() != null, 2, "RulebaseDefined"); + LispError.checkArgument(aEnvironment, aStackTop, sizearg.car() instanceof String, 2, "RulebaseDefined"); int arity = Integer.parseInt( (String) sizearg.car(), 10); - SingleArityBranchingUserFunction userFunc = aEnvironment.getUserFunction((String)aEnvironment.getTokenHash().lookUp(oper), arity); + SingleArityRulebase userFunc = aEnvironment.getRulebase((String)aEnvironment.getTokenHash().lookUp(oper), arity, aStackTop); Utility.putBooleanInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), userFunc != null); } } + + + + + +/* +%mathpiper_docs,name="RulebaseDefined",categories="Programmer Functions;Programming;Built In" +*CMD RulebaseDefined --- predicate function which indicates whether or not a rulebase is defined. +*CORE +*CALL + RulebaseDefined(name) + +*PARMS + +{name} -- string, name of rulebase + +*DESC +This is a predicate function which indicates whether or not a rulebase is defined. + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Rulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Rulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Rulebase.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Rulebase.java 2010-07-14 23:26:25.000000000 +0000 @@ -28,18 +28,18 @@ { public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - org.mathpiper.lisp.Utility.ruleDatabase(aEnvironment, aStackTop, false); + org.mathpiper.lisp.Utility.rulebase(aEnvironment, aStackTop, false); } } /* -%mathpiper_docs,name="RuleBase",categories="User Functions;Built In" -*CMD RuleBase --- define function with a fixed number of arguments +%mathpiper_docs,name="Rulebase",categories="Programmer Functions;Programming;Built In" +*CMD Rulebase --- define function with a fixed number of arguments *CORE *CALL - RuleBase(name,params) + Rulebase(name,params) *PARMS @@ -54,12 +54,12 @@ In the context of the transformation rule declaration facilities this is a useful function in that it allows the stating of argument -names that can he used with HoldArg. +names that can he used with HoldArgument. Functions can be overloaded: the same function can be defined with different number of arguments. -*SEE MacroRuleBase, RuleBaseListed, MacroRuleBaseListed, HoldArg, Retract +*SEE MacroRulebase, RulebaseListed, MacroRulebaseListed, HoldArgument, Retract %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseListed.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseListed.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulebaseListed.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulebaseListed.java 2011-02-05 07:50:02.000000000 +0000 @@ -29,18 +29,18 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - org.mathpiper.lisp.Utility.ruleDatabase(aEnvironment, aStackTop, true); + org.mathpiper.lisp.Utility.rulebase(aEnvironment, aStackTop, true); } } /* -%mathpiper_docs,name="RuleBaseListed",categories="User Functions;Built In" -*CMD RuleBaseListed --- define function with variable number of arguments +%mathpiper_docs,name="RulebaseListed",categories="Programmer Functions;Programming;Built In" +*CMD RulebaseListed --- define function with variable number of arguments *CORE *CALL - RuleBaseListed("name", params) + RulebaseListed("name", params) *PARMS @@ -50,21 +50,21 @@ *DESC -The command {RuleBaseListed} defines a new function. It essentially works the -same way as {RuleBase}, except that it declares a new function with a variable +The command {RulebaseListed} defines a new function. It essentially works the +same way as {Rulebase}, except that it declares a new function with a variable number of arguments. The list of parameters {params} determines the smallest number of arguments that the new function will accept. If the number of arguments passed to the new function is larger than the number of parameters in {params}, then the last argument actually passed to the new function will be a list containing all the remaining arguments. -A function defined using {RuleBaseListed} will appear to have the arity equal +A function defined using {RulebaseListed} will appear to have the arity equal to the number of parameters in the {param} list, and it can accept any number of arguments greater or equal than that. As a consequence, it will be impossible to define a new function with the same name and with a greater arity. The function body will know that the function is passed more arguments than the length of the {param} list, because the last argument will then be a list. The -rest then works like a {RuleBase}-defined function with a fixed number of +rest then works like a {Rulebase}-defined function with a fixed number of arguments. Transformation rules can be defined for the new function as usual. @@ -72,7 +72,7 @@ The definitions - RuleBaseListed("f",{a,b,c}) + RulebaseListed("f",{a,b,c}) 10 # f(_a,_b,{_c,_d}) <-- Echo({"four args",a,b,c,d}); 20 # f(_a,_b,c_IsList) <-- @@ -80,30 +80,30 @@ 30 # f(_a,_b,_c) <-- Echo({"three args",a,b,c}); give the following interaction: - In> f(A) - Out> f(A); - In> f(A,B) - Out> f(A,B); - In> f(A,B,C) +In> f(A) +Result: f(A); +In> f(A,B) +Result: f(A,B); +In> f(A,B,C) three args A B C - Out> True; - In> f(A,B,C,D) +Result: True; +In> f(A,B,C,D) four args A B C D - Out> True; - In> f(A,B,C,D,E) +Result: True; +In> f(A,B,C,D,E) more than four args A B {C,D,E} - Out> True; - In> f(A,B,C,D,E,E) +Result: True; +In> f(A,B,C,D,E,E) more than four args A B {C,D,E,E} - Out> True; +Result: True; The function {f} now appears to occupy all arities greater than 3: - In> RuleBase("f", {x,y,z,t}); +In> Rulebase("f", {x,y,z,t}); CommandLine(1) : Rule base with this arity already defined -*SEE RuleBase, Retract, Echo +*SEE Rulebase, Retract, Echo %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Rule.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Rule.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Rule.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Rule.java 2011-02-03 08:38:42.000000000 +0000 @@ -29,19 +29,18 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - org.mathpiper.lisp.Utility.newRule(aEnvironment, aStackTop); + org.mathpiper.lisp.Utility.newRule(aEnvironment, aStackTop, false); } } /* -%mathpiper_docs,name="Rule",categories="User Functions;Built In" +%mathpiper_docs,name="Rule",categories="Programmer Functions;Programming;Built In" *CMD Rule --- define a rewrite rule *CORE *CALL - Rule("operator", arity, - precedence, predicate) body + Rule("operator", arity, precedence, predicate) body *PARMS {"operator"} -- string, name of function @@ -59,7 +58,7 @@ "body". The "precedence" goes from low to high: rules with low precedence will be applied first. The arity for a rules database equals the number of arguments. Different -rules data bases can be built for functions with the same name but with +rules databases can be built for functions with the same name but with a different number of arguments. Rules with a low precedence value will be tried before rules with a high value, so diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulePattern.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulePattern.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/RulePattern.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/RulePattern.java 2010-12-10 04:56:58.000000000 +0000 @@ -0,0 +1,61 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; + +/** + * + * + */ +public class RulePattern extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + org.mathpiper.lisp.Utility.newRule(aEnvironment, aStackTop, true); + } +} + + + + +/* +%mathpiper_docs,name="RulePattern",categories="Programmer Functions;Programming;Built In" +*CMD RulePattern --- defines a rule which uses a pattern as its predicate + +*CALL + RulePattern("operator", arity, precedence, pattern) body +*PARMS + +{"operator"} -- string, name of function + +{arity}, {precedence} -- integers + +{pattern} -- a pattern object + +{body} -- expression, body of rule + +*DESC +This function defines a rule which uses a pattern as its predicate. + +*SEE MacroRulePattern +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Secure.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Secure.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Secure.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Secure.java 2010-02-05 10:28:57.000000000 +0000 @@ -34,7 +34,7 @@ aEnvironment.iSecure = true; try { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); } catch (Exception e) { throw e; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SetExactBits.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SetExactBits.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SetExactBits.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SetExactBits.java 2011-02-05 07:50:02.000000000 +0000 @@ -42,7 +42,7 @@ { z.setPrecision((int) (Utility.bitsToDigits((long) (y.toDouble()), 10))); } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } } @@ -73,17 +73,17 @@ *E.G. The default precision of 10 decimals corresponds to 33 bits: - In> GetExactBitsN(1000.123) - Out> 33; - In> x:=SetExactBitsN(10., 20) - Out> 10.; - In> GetExactBitsN(x) - Out> 20; +In> GetExactBitsN(1000.123) +Result: 33; +In> x:=SetExactBitsN(10., 20) +Result: 10.; +In> GetExactBitsN(x) +Result: 20; Prepare a "floating zero" representing an interval [-4, 4]: - In> x:=SetExactBitsN(0., -2) - Out> 0.; - In> x=0 - Out> True; +In> x:=SetExactBitsN(0., -2) +Result: 0.; +In> x=0 +Result: True; *SEE BuiltinPrecisionSet, BuiltinPrecisionGet, GetExactBitsN %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SetGlobalLazyVariable.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SetGlobalLazyVariable.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SetGlobalLazyVariable.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SetGlobalLazyVariable.java 2011-02-05 07:50:02.000000000 +0000 @@ -53,7 +53,7 @@ *DESC {SetGlobalLazyVariable} enforces that a global variable will re-evaluate -when used. This functionality doesn't survive if {Clear(var)} +when used. This functionality doesn't survive if {Unbind(var)} is called afterwards. Places where this is used include the global variables {%} and {I}. @@ -63,8 +63,8 @@ called. The {SetGlobalLazyVariable} property only holds once: after that, the result of evaluation is stored in the global variable, and it won't be reevaluated again: - In> SetGlobalLazyVariable(a,Hold(Taylor(x,0,30)Sin(x))) - Out> True +In> SetGlobalLazyVariable(a,Hold(Taylor(x,0,30)Sin(x))) +Result: True Then the first time you call {a} it evaluates {Taylor(...)} and assigns the result to {a}. The next time you call {a} it immediately returns the result. @@ -72,27 +72,27 @@ The following example demonstrates the sequence of execution: - In> SetGlobalLazyVariable(test,Hold(Write("hello"))) - Out> True +In> SetGlobalLazyVariable(test,Hold(Write("hello"))) +Result: True The text "hello" is not written out to screen yet. However, evaluating the variable {test} forces the expression to be evaluated: - In> test - "hello"Out> True +In> test + "hello"Result: True *E.G. - In> Set(a,Hold(2+3)) - Out> True - In> a - Out> 2+3 - In> SetGlobalLazyVariable(a,Hold(2+3)) - Out> True - In> a - Out> 5 +In> Set(a,Hold(2+3)) +Result: True +In> a +Result: 2+3 +In> SetGlobalLazyVariable(a,Hold(2+3)) +Result: True +In> a +Result: 5 -*SEE Set, Clear, Local, %, I +*SEE Bind, Unbind, Local, %, I %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Set.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Set.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Set.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Set.java 2010-07-15 05:35:03.000000000 +0000 @@ -13,58 +13,55 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.builtin.functions.core; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsTraverser; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.SublistCons; /** + * Used to create sets like List() is used to create lists. * - * */ -public class Set extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - Utility.setVar(aEnvironment, aStackTop, false, false); - } -} +public class Set extends BuiltinFunction { + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + ConsPointer allPointer = new ConsPointer(); + allPointer.setCons(aEnvironment.iListAtom.copy(aEnvironment, false)); + ConsTraverser tail = new ConsTraverser(aEnvironment, allPointer); + tail.goNext(aStackTop); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()); + consTraverser.goNext(aStackTop); + while (consTraverser.getCons() != null) { + ConsPointer evaluated = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, consTraverser.getPointer()); + tail.getPointer().setCons(evaluated.getCons()); + tail.goNext(aStackTop); + consTraverser.goNext(aStackTop); + } -/* -%mathpiper_docs,name="Set",categories="User Functions;Variables;Built In" -*CMD Set --- assignment -*CORE -*CALL - Set(var, exp) + Cons head = SublistCons.getInstance(aEnvironment, AtomCons.getInstance(aEnvironment, aStackTop, "RemoveDuplicates")); -*PARMS + ((ConsPointer) head.car()).cdr().setCons(SublistCons.getInstance(aEnvironment, allPointer.getCons())); -{var} -- variable which should be assigned + ConsPointer removeDuplicatesResultPointer = new ConsPointer(); -{exp} -- expression to assign to the variable + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, removeDuplicatesResultPointer, new ConsPointer(head)); + + ConsPointer resultPointer = new ConsPointer(); -*DESC + resultPointer.setCons(aEnvironment.iSetAtom.copy(aEnvironment, false)); -The expression "exp" is evaluated and assigned it to the variable -named "var". The first argument is not evaluated. The value True -is returned. + removeDuplicatesResultPointer.goSub(aStackTop, aEnvironment); -The statement {Set(var, exp)} is equivalent to {var := exp}, but the {:=} operator -has more uses, e.g. changing individual entries in a list. + resultPointer.getCons().cdr().setCons(removeDuplicatesResultPointer.cdr().getCons()); -*E.G. - - In> Set(a, Sin(x)+3); - Out> True; - In> a; - Out> Sin(x)+3; - -*SEE Clear, := -%/mathpiper_docs -*/ \ No newline at end of file + getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment,resultPointer.getCons())); + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ShiftLeft.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ShiftLeft.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ShiftLeft.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ShiftLeft.java 2010-03-10 06:32:04.000000000 +0000 @@ -35,8 +35,8 @@ BigNumber n = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); long nrToShift = n.toLong(); BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.shiftLeft(x, (int) nrToShift); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + z.shiftLeft(x, (int) nrToShift, null, aStackTop); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ShiftRight.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ShiftRight.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ShiftRight.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ShiftRight.java 2010-03-10 06:32:04.000000000 +0000 @@ -35,8 +35,8 @@ BigNumber n = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); long nrToShift = n.toLong(); BigNumber z = new BigNumber(aEnvironment.getPrecision()); - z.shiftRight(x, (int) nrToShift); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + z.shiftRight(x, (int) nrToShift, null, aStackTop); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StackSize.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StackSize.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StackSize.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StackSize.java 2009-10-04 06:10:14.000000000 +0000 @@ -33,6 +33,6 @@ { aEnvironment.write("Function not yet implemented : LispStackSize");//TODO FIXME - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Stringify.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Stringify.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Stringify.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Stringify.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinContainer; -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; - -/** - * - * - */ -public class Stringify extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - ConsPointer evaluated = new ConsPointer(); - evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - - // Get operator - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); - - String orig = null; - if(evaluated.car() instanceof String) - { - orig = (String) evaluated.car(); - } - else if(evaluated.car() instanceof BuiltinContainer) - { - BuiltinContainer container = (BuiltinContainer) evaluated.car(); - orig = container.getObject().toString(); - } - - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpStringify(orig))); - } -} - - - -/* -%mathpiper_docs,name="String",categories="User Functions;String Manipulation;Built In" -*CMD String --- convert atom to string -*CORE -*CALL - String(atom) - -*PARMS - -{atom} -- an atom - -*DESC - -{String} is the inverse of {Atom}: turns {atom} into {"atom"}. - -*E.G. - - In> String(a) - Out> "a"; - -*SEE Atom, ExpressionToString -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StringMidGet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StringMidGet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StringMidGet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StringMidGet.java 2011-02-05 07:50:02.000000000 +0000 @@ -35,24 +35,24 @@ { ConsPointer evaluated = new ConsPointer(); evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); - LispError.checkIsString(aEnvironment, aStackTop, evaluated, 3); + LispError.checkIsString(aEnvironment, aStackTop, evaluated, 3, "StringMidGet"); String orig = (String) evaluated.car(); ConsPointer index = new ConsPointer(); index.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1, "StringMidGet"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1, "StringMidGet"); int from = Integer.parseInt( (String) index.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, from > 0, 1); + LispError.checkArgument(aEnvironment, aStackTop, from > 0, 1, "StringMidGet"); index.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2, "StringMidGet"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2, "StringMidGet"); int count = Integer.parseInt( (String) index.car(), 10); String str = "\"" + orig.substring(from, from + count) + "\""; - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, str)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, str)); } } @@ -80,10 +80,10 @@ *E.G. - In> StringMidGet(3,2,"abcdef") - Out> "cd"; - In> "abcdefg"[2 .. 4] - Out> "bcd"; +In> StringMidGet(3,2,"abcdef") +Result: "cd"; +In> "abcdefg"[2 .. 4] +Result: "bcd"; *SEE StringMidSet, Length %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StringMidSet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StringMidSet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StringMidSet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StringMidSet.java 2011-02-05 07:50:02.000000000 +0000 @@ -35,19 +35,19 @@ { ConsPointer evaluated = new ConsPointer(); evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); - LispError.checkIsString(aEnvironment, aStackTop, evaluated, 3); + LispError.checkIsString(aEnvironment, aStackTop, evaluated, 3, "StringMidSet"); String orig = (String) evaluated.car(); ConsPointer index = new ConsPointer(); index.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 1, "StringMidSet"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 1, "StringMidSet"); int from = Integer.parseInt( (String) index.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, from > 0, 1); + LispError.checkArgument(aEnvironment, aStackTop, from > 0, 1, "StringMidSet"); ConsPointer ev2 = new ConsPointer(); ev2.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkIsString(aEnvironment, aStackTop, ev2, 2); + LispError.checkIsString(aEnvironment, aStackTop, ev2, 2, "StringMidSet"); String replace =(String) ev2.car(); LispError.check(aEnvironment, aStackTop, from + replace.length() - 2 < orig.length(), LispError.INVALID_ARGUMENT); @@ -56,7 +56,7 @@ str = str + replace.substring(1, replace.length() - 1); //System.out.println("from="+from+replace.length()-2); str = str + orig.substring(from + replace.length() - 2, orig.length()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, str)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, str)); } } @@ -84,8 +84,8 @@ *E.G. - In> StringMidSet(3,"XY","abcdef") - Out> "abXYef"; +In> StringMidSet(3,"XY","abcdef") +Result: "abXYef"; *SEE StringMidGet, Length %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StringToUnicode.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StringToUnicode.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/StringToUnicode.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/StringToUnicode.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,71 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + +/** + * + * + */ +public class StringToUnicode extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "StringToUnicode"); + String str = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, str != null, 1, "StringToUnicode"); + LispError.check(str.length() == 3, "The string must be one character long.", "StringToUnicode", aStackTop, aEnvironment); + LispError.checkArgument(aEnvironment, aStackTop, str.charAt(0) == '\"', 1, "StringToUnicode"); + LispError.checkArgument(aEnvironment, aStackTop, str.charAt(str.length() - 1) == '\"', 1, "StringToUnicode"); + + int unicodeValue = (int) str.charAt(1); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + unicodeValue)); + } +} + + + +/* +%mathpiper_docs,name="StringToUnicode",categories="User Functions;String Manipulation;Built In",access="experimental" +*CMD StringToUnicode --- returns the unicode value of the character in a single character string +*CORE +*CALL + StringToUnicode(s) + +*PARMS + {s} - a single character string + +*DESC +This function returns the unicode value of the character in a single character string. + +*E.G. +In> StringToUnicode("A") +Result> 65 + +%/mathpiper_docs +*/ + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Subst.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Subst.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Subst.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Subst.java 2011-02-05 07:50:02.000000000 +0000 @@ -37,7 +37,7 @@ to.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); body.setCons(getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); org.mathpiper.lisp.behaviours.ExpressionSubstitute behaviour = new org.mathpiper.lisp.behaviours.ExpressionSubstitute(aEnvironment, from, to); - Utility.substitute(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop), body, behaviour); + Utility.substitute(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), body, behaviour); } } @@ -65,12 +65,12 @@ *E.G. - In> Subst(x, Sin(y)) x^2+x+1; - Out> Sin(y)^2+Sin(y)+1; - In> Subst(a+b, x) a+b+c; - Out> x+c; - In> Subst(b+c, x) a+b+c; - Out> a+b+c; +In> Subst(x, Sin(y)) x^2+x+1; +Result: Sin(y)^2+Sin(y)+1; +In> Subst(a+b, x) a+b+c; +Result: x+c; +In> Subst(b+c, x) a+b+c; +Result: a+b+c; The explanation for the last result is that the expression {a+b+c} is internally stored as {(a+b)+c}. Hence {a+b} is a subexpression, but {b+c} is not. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Subtract.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Subtract.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Subtract.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Subtract.java 2011-02-05 07:50:02.000000000 +0000 @@ -32,13 +32,13 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - int length = Utility.listLength(getArgumentPointer(aEnvironment, aStackTop, 0)); + int length = Utility.listLength(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 0)); if (length == 2) { BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); BigNumber z = new BigNumber(x); z.negate(x); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); return; } else { @@ -48,7 +48,7 @@ yneg.negate(y); BigNumber z = new BigNumber(aEnvironment.getPrecision()); z.add(x, yneg, aEnvironment.getPrecision()); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(aEnvironment, z)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(z)); return; } } @@ -80,8 +80,8 @@ the functions return a floating-point result which is correct only to the current precision. *E.G. - In> - Result> +In> +Result: %/mathpiper_docs */ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SystemCall.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SystemCall.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SystemCall.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SystemCall.java 2011-02-05 07:50:02.000000000 +0000 @@ -34,10 +34,10 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "SystemCall"); String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "SystemCall"); + String oper = Utility.toNormalString(aEnvironment, aStackTop, orig); String ls_str; Process ls_proc = Runtime.getRuntime().exec(oper); // getCons its output (your input) stream @@ -75,24 +75,24 @@ In a UNIX environment, the command {SystemCall("ls")} would print the contents of the current directory. - In> SystemCall("ls") +In> SystemCall("ls") AUTHORS COPYING ChangeLog ... (truncated to save space) - Out> True; +Result: True; The standard UNIX command {test} returns success or failure depending on conditions. For example, the following command will check if a directory exists: - In> SystemCall("test -d scripts/") - Out> True; +In> SystemCall("test -d scripts/") +Result: True; Check that a file exists: - In> SystemCall("test -f COPYING") - Out> True; - In> SystemCall("test -f nosuchfile.txt") - Out> False; +In> SystemCall("test -f COPYING") +Result: True; +In> SystemCall("test -f nosuchfile.txt") +Result: False; *SEE Secure %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SystemTimer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SystemTimer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/SystemTimer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/SystemTimer.java 2010-02-05 10:28:57.000000000 +0000 @@ -33,7 +33,7 @@ { long currentTime = System.nanoTime(); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + currentTime)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + currentTime)); }//end method. }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TellUser.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TellUser.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TellUser.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TellUser.java 2010-12-29 04:07:15.000000000 +0000 @@ -23,7 +23,6 @@ import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.AtomCons; /** * @@ -34,12 +33,17 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - String messageString = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, messageString != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "TellUser"); + Object argument = getArgumentPointer(aEnvironment, aStackTop, 1).car(); - messageString = Utility.stripEndQuotes(messageString); + LispError.check(argument instanceof String, "The argument to TellUser must be a string.", "INTERNAL", aStackTop, aEnvironment); + + String messageString = (String) argument; + + LispError.checkArgument(aEnvironment, aStackTop, messageString != null, 1, "TellUser"); + + messageString = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, messageString); JOptionPane.showMessageDialog(null, messageString, "Message from MathPiper", JOptionPane.INFORMATION_MESSAGE); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Time.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Time.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Time.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Time.java 2011-02-05 07:50:02.000000000 +0000 @@ -47,7 +47,7 @@ ConsPointer res = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, res, getArgumentPointer(aEnvironment, aStackTop, 1)); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, res, getArgumentPointer(aEnvironment, aStackTop, 1)); BigDecimal endTime = new BigDecimal(System.nanoTime()); @@ -57,7 +57,7 @@ timeDiff = timeDiff.movePointLeft(9); - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "" + timeDiff)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "" + timeDiff)); } } @@ -80,8 +80,8 @@ Therefore, any CPU-intensive processes running alongside MathPiper will not significantly affect the result of {Time}. *E.G. - In> Time() Simplify((a*b)/(b*a)) - Out> 0.09; +In> Time() Simplify((a*b)/(b*a)) +Result: 0.09; *SEE EchoTime, SystemTimer diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToAtom.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToAtom.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToAtom.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToAtom.java 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,74 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; + +/** + * + * + */ +public class ToAtom extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + ConsPointer evaluated = new ConsPointer(); + evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + + // Get operator + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "ToAtom"); + String orig = (String) evaluated.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "ToAtom"); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.getTokenHash().lookUpUnStringify(orig))); + } +} + + + + +/* +%mathpiper_docs,name="ToAtom",categories="User Functions;String Manipulation" +*CMD ToAtom --- convert string to atom +*CORE +*CALL + ToAtom("string") + +*PARMS + +{"string"} -- a string + +*DESC + +Returns an atom with the string representation given +as the evaluated argument. Example: {ToAtom("foo");} returns +{foo}. + + +*E.G. + +In> ToAtom("a") +Result: a; + +*SEE ToString, ExpressionToString +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToBase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToBase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToBase.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToBase.java 2011-02-05 07:50:02.000000000 +0000 @@ -40,10 +40,10 @@ oper.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // check that getTopOfStackPointer is a number, and that it is in fact an integer // LispError.check(oper.type().equals("Number"), LispError.KLispErrInvalidArg); - BigNumber num =(BigNumber) oper.getCons().getNumber(aEnvironment.getPrecision()); - LispError.checkArgument(aEnvironment, aStackTop, num != null, 1); + BigNumber num =(BigNumber) oper.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + LispError.checkArgument(aEnvironment, aStackTop, num != null, 1, "ToBase"); // check that the base is an integer between 2 and 32 - LispError.checkArgument(aEnvironment, aStackTop, num.isInteger(), 1); + LispError.checkArgument(aEnvironment, aStackTop, num.isInteger(), 1, "ToBase"); // Get a short platform integer from the car argument int base = (int) (num.toLong()); @@ -56,7 +56,7 @@ str = x.numToString(aEnvironment.getPrecision(), base); // Get unique string from hash table, and create an atom from it. - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpStringify(str))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.getTokenHash().lookUpStringify(str))); } } @@ -94,8 +94,8 @@ Write the (decimal) number {255} in hexadecimal notation: - In> ToBase(16,255) - Out> "ff"; +In> ToBase(16,255) +Result: "ff"; *SEE PAdicExpand,FromBase %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToFile.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToFile.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToFile.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToFile.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import java.io.FileOutputStream; -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.io.StandardFileOutputStream; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.io.MathPiperOutputStream; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class ToFile extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - LispError.check(aEnvironment, aStackTop, aEnvironment.iSecure == false, LispError.SECURITY_BREACH); - - ConsPointer evaluated = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, evaluated, getArgumentPointer(aEnvironment, aStackTop, 1)); - - // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); - String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - String oper = Utility.unstringify(orig); - - // Open file for writing - FileOutputStream localFP = new FileOutputStream(oper); - LispError.check(aEnvironment, aStackTop, localFP != null, LispError.FILE_NOT_FOUND); - StandardFileOutputStream newOutput = new StandardFileOutputStream(localFP); - - MathPiperOutputStream previous = aEnvironment.iCurrentOutput; - aEnvironment.iCurrentOutput = newOutput; - - try - { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); - } catch (Exception e) - { - throw e; - } finally - { - aEnvironment.iCurrentOutput = previous; - } - } -} - - - -/* -%mathpiper_docs,name="ToFile",categories="User Functions;Input/Output;Built In" -*CMD ToFile --- connect current output to a file -*CORE -*CALL - ToFile(name) body - -*PARMS - -{name} -- string, the name of the file to write the result to - -{body} -- expression to be evaluated - -*DESC - -The current output is connected to the file "name". Then the expression -"body" is evaluated. Everything that the commands in "body" print -to the current output, ends up in the file "name". Finally, the -file is closed and the result of evaluating "body" is returned. - -If the file is opened again, the old contents will be overwritten. -This is a limitation of {ToFile}: one cannot append to a file that has already been created. - -*E.G. notest - -Here is how one can create a file with C code to evaluate an expression: - - In> ToFile("expr1.c") WriteString( - CForm(Sqrt(x-y)*Sin(x)) ); - Out> True; -The file {expr1.c} was created in the current working directory and it -contains the line - sqrt(x-y)*sin(x) - -As another example, take a look at the following command: - - In> [ Echo("Result:"); \ - PrettyForm(Taylor(x,0,9) Sin(x)); ]; - Result: - - 3 5 7 9 - x x x x - x - -- + --- - ---- + ------ - 6 120 5040 362880 - - Out> True; - -Now suppose one wants to send the output of this command to a -file. This can be achieved as follows: - - In> ToFile("out") [ Echo("Result:"); \ - PrettyForm(Taylor(x,0,9) Sin(x)); ]; - Out> True; - -After this command the file {out} contains: - - - Result: - - 3 5 7 9 - x x x x - x - -- + --- - ---- + ------ - 6 120 5040 362880 - - -*SEE FromFile, ToString, Echo, Write, WriteString, PrettyForm, Taylor -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToStdout.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToStdout.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToStdout.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToStdout.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.io.MathPiperOutputStream; - -/** - * - * - */ -public class ToStdout extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - MathPiperOutputStream previous = aEnvironment.iCurrentOutput; - aEnvironment.iCurrentOutput = aEnvironment.iInitialOutput; - try - { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); - } catch (Exception e) - { - throw e; - } finally - { - aEnvironment.iCurrentOutput = previous; - } - } -} - - - -/* -%mathpiper_docs,name="ToStdout",categories="User Functions;Input/Output;Built In" -*CMD ToStdout --- select initial output stream for output -*CORE -*CALL - ToStdout() body - -*PARMS - -{body} -- expression to be evaluated - -*DESC - -When using {ToString} or {ToFile}, it might happen that something needs to be -written to the standard default initial output (typically the screen). {ToStdout} can be used to select this stream. - -**E.G. - - In> ToString()[Echo("aaaa");ToStdout()Echo("bbbb");]; - bbbb - Out> "aaaa - " - -*SEE ToString, ToFile -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ToString.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ToString.java 2010-07-23 05:26:16.000000000 +0000 @@ -17,67 +17,66 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.builtin.functions.core; +import org.mathpiper.builtin.BuiltinContainer; import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.io.StringOutputStream; import org.mathpiper.lisp.cons.AtomCons; import org.mathpiper.lisp.Environment; -import org.mathpiper.io.MathPiperOutputStream; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; /** * - * + * */ public class ToString extends BuiltinFunction { public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - StringBuffer oper = new StringBuffer(); - StringOutputStream newOutput = new StringOutputStream(oper); - MathPiperOutputStream previous = aEnvironment.iCurrentOutput; - aEnvironment.iCurrentOutput = newOutput; - try - { - // Evaluate the body - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); + ConsPointer evaluated = new ConsPointer(); + evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - //Return the getTopOfStackPointer - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpStringify(oper.toString()))); - } catch (Exception e) + // Get operator + LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1, "ToString"); + + String orig = null; + if(evaluated.car() instanceof String) { - throw e; - } finally + orig = (String) evaluated.car(); + } + else if(evaluated.car() instanceof BuiltinContainer) { - aEnvironment.iCurrentOutput = previous; + BuiltinContainer container = (BuiltinContainer) evaluated.car(); + orig = container.getObject().toString(); } + + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "ToString"); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.getTokenHash().lookUpStringify(orig))); } } /* -%mathpiper_docs,name="ToString",categories="User Functions;Input/Output;Built In" -*CMD ToString --- connect current output to a string +%mathpiper_docs,name="ToString",categories="User Functions;String Manipulation;Built In" +*CMD ToString --- convert atom to string *CORE *CALL - ToString() body + ToString(atom) *PARMS -{body} -- expression to be evaluated +{atom} -- an atom *DESC -The commands in "body" are executed. Everything that is printed on -the current output, by {Echo} for instance, is -collected in a string and this string is returned. +{ToString} is the inverse of {ToAtom}: turns {atom} into {"atom"}. *E.G. +In> ToString(a) +Result: "a"; - In> str := ToString() [ WriteString( \ - "The square of 8 is "); Write(8^2); ]; - Out> "The square of 8 is 64"; - -*SEE FromFile, ToString, Echo, Write, WriteString +*SEE ToAtom, ExpressionToString %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TraceRule.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TraceRule.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TraceRule.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TraceRule.java 2011-02-05 07:50:02.000000000 +0000 @@ -33,14 +33,14 @@ { aEnvironment.write("Function not yet implemented : LispTraceRule");////TODO fixme - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } /* -%mathpiper_docs,name="TraceRule",categories="User Functions;Control Flow;Built In" +%mathpiper_docs,name="TraceRule",categories="User Functions;Control Flow;Built In",access="private" *CMD TraceRule --- turn on tracing for a particular function *CORE *CALL @@ -69,7 +69,7 @@ *E.G. notest - In> TraceRule(x+y) 2+3*5+4; +In> TraceRule(x+y) 2+3*5+4; TrEnter(2+3*5+4); TrEnter(2+3*5); TrArg(2, 2); @@ -78,7 +78,7 @@ TrArg(2+3*5, 17); TrArg(4, 4); TrLeave(2+3*5+4, 21); - Out> 21; +Result: 21; *SEE TraceStack, TraceExp %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TraceStack.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TraceStack.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TraceStack.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TraceStack.java 2011-02-05 07:50:02.000000000 +0000 @@ -33,14 +33,14 @@ { aEnvironment.write("Function not yet implemented : TraceStack");////TODO fixme - throw new EvaluationException("Function not yet supported",-1); + throw new EvaluationException("Function not yet supported",aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } } /* -%mathpiper_docs,name="TraceStack",categories="User Functions;Control Flow;Built In" +%mathpiper_docs,name="TraceStack",categories="User Functions;Control Flow;Built In",access="private" *CMD TraceStack --- show calling stack after an error occurs *CORE *CALL @@ -72,9 +72,9 @@ Here is an example of a function calling itself recursively, causing MathPiper to flood its stack: - In> f(x):=f(Sin(x)) - Out> True; - In> TraceStack(f(2)) +In> f(x):=f(Sin(x)) +Result: True; +In> TraceStack(f(2)) Debug> 982 : f (Rule # 0 in body) Debug> 983 : f (Rule # 0 in body) Debug> 984 : f (Rule # 0 in body) diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TrapError.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TrapError.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/TrapError.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/TrapError.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; - -/** - * - * - */ -public class TrapError extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - try - { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); - } catch (Exception e) - { - //e.printStackTrace(); - aEnvironment.iError ="Caught in TrapError function: " + e.toString(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 2)); - aEnvironment.iError = null; - } - } -} - - - -/* -%mathpiper_docs,name="TrapError",categories="Programmer Functions;Error Reporting;Built In" -*CMD TrapError --- trap "hard" errors -*CORE -*CALL - TrapError(expression,errorHandler) - -*PARMS - -{expression} -- expression to evaluate (causing potential error) - -{errorHandler} -- expression to be called to handle error - -*DESC -TrapError evaluates its argument {expression}, returning the -result of evaluating {expression}. If an error occurs, -{errorHandler} is evaluated, returning its return value in stead. - -**E.G. - - In> - - -*SEE Assert, Check, GetCoreError - -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Type.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Type.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Type.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Type.java 2011-02-05 07:50:02.000000000 +0000 @@ -13,46 +13,40 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.builtin.functions.core; + import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.cons.AtomCons; -import org.mathpiper.lisp.cons.Cons; import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.cons.ConsPointer; + /** * * */ -public class Type extends BuiltinFunction -{ +public class Type extends BuiltinFunction { + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { ConsPointer evaluated = new ConsPointer(); + evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - - if (!( evaluated.car() instanceof ConsPointer)) - { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"\"")); - return; - } - ConsPointer subList = (ConsPointer) evaluated.car(); - Cons head = null; - head = subList.getCons(); - if (!( head.car() instanceof String)) - { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"\"")); - return; + + String functionType = Utility.functionType(evaluated); + + if (functionType.equals("")) { + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "\"\"")); + } else { + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, aEnvironment.getTokenHash().lookUpStringify(functionType))); } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aEnvironment.getTokenHash().lookUpStringify((String) head.car()))); - return; - } -} + }//end method. + + +}//end class. @@ -76,13 +70,13 @@ *E.G. - In> Type({a,b,c}); - Out> "List"; - In> Type(a*(b+c)); - Out> "*"; - In> Type(123); - Out> ""; +In> Type({a,b,c}); +Result: "List"; +In> Type(a*(b+c)); +Result: "*"; +In> Type(123); +Result: ""; -*SEE IsAtom, NrArgs +*SEE IsAtom, ArgumentsCount %/mathpiper_docs -*/ \ No newline at end of file +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Unbind.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Unbind.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Unbind.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Unbind.java 2010-04-09 00:23:39.000000000 +0000 @@ -0,0 +1,98 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.lisp.cons.ConsTraverser; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class Unbind extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + if (getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer) { + + ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, subList); + consTraverser.goNext(aStackTop); + int nr = 1; + while (consTraverser.getCons() != null) + { + String variableName; + variableName = (String) consTraverser.car(); + LispError.checkArgument(aEnvironment, aStackTop, variableName != null, nr, "Unbind"); + aEnvironment.unbindVariable(aStackTop, variableName); + consTraverser.goNext(aStackTop); + nr++; + } + } + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + + +/* +%mathpiper_docs,name="Unbind",categories="User Functions;Variables;Built In" +*CMD Unbind --- undo an assignment +*CORE +*CALL + Unbind(var, ...) + +*PARMS + +{var} -- name of variable to be unbound + +*DESC + +All assignments made to the variables listed as arguments are +undone. From now on, all these variables remain unevaluated (until a +subsequent assignment is made). Also unbinds any metadata that may have +been set in an unbound variable. If a * wildcard character is passed in + as the variable name, all local and global variables are unbound. + +*E.G. +In> a := 5; +Result> 5; + +In> a^2; +Result> 25; + +In> Unbind(a); +Result> True; + +In> a^2; +Result> a^2; + +In> Unbind(*) +Result> True + +*SEE Bind, := +%/mathpiper_docs +*/ + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/UnFence.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/UnFence.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/UnFence.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/UnFence.java 2010-07-14 01:07:17.000000000 +0000 @@ -32,16 +32,16 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { // Get operator - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "UnFence"); String orig = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "UnFence"); // The arity - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 2).getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 2).car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 2).getCons() != null, 2, "UnFence"); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 2).car() instanceof String, 2, "UnFence"); int arity = Integer.parseInt( (String) getArgumentPointer(aEnvironment, aStackTop, 2).car(), 10); - aEnvironment.unFenceRule(Utility.getSymbolName(aEnvironment, orig), arity); + aEnvironment.unfenceRule(aStackTop, Utility.getSymbolName(aEnvironment, orig), arity); // Return true Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/UnicodeToString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/UnicodeToString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/UnicodeToString.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/UnicodeToString.java 2010-09-25 08:53:26.000000000 +0000 @@ -0,0 +1,64 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.core; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class UnicodeToString extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + String str; + str = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); + LispError.checkArgument(aEnvironment, aStackTop, str != null, 2, "UnicodeToString"); + LispError.checkArgument(aEnvironment, aStackTop, Utility.isNumber(str, false), 2, "UnicodeToString"); + char asciiCode = (char) Integer.parseInt(str, 10); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "\"" + asciiCode + "\"")); + } +} + + + +/* +%mathpiper_docs,name="UnicodeToString",categories="User Functions;String Manipulation;Built In",access="experimental" +*CMD UnicodeToString --- creates a single character string from the character's unicode value +*CORE +*CALL + UnicodeToString(n) + +*PARMS + {n} - a unicode value + +*DESC +This function creates a single character string from the character's unicode value. + +*E.G. +In> UnicodeToString(65) +Result> "A" + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/UnList.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/UnList.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/UnList.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/UnList.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.cons.Cons; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.ConsPointer; - -/** - * - * - */ -public class UnList extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer, 1); - Cons atom = ((ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car()).getCons(); - LispError.checkArgument(aEnvironment, aStackTop, atom != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, atom.car() == aEnvironment.iListAtom.car(), 1); - Utility.tail(aEnvironment,getTopOfStackPointer(aEnvironment, aStackTop), getArgumentPointer(aEnvironment, aStackTop, 1)); - } -} - - - -/* -%mathpiper_docs,name="UnList",categories="User Functions;Lists (Operations);Built In" -*CMD UnList --- convert a list to a function application -*CORE -*CALL - UnList(list) - -*PARMS - -{list} -- list to be converted - -*DESC - -This command converts a list to a function application. The car -entry of "list" is treated as a function atom, and the following entries -are the arguments to this function. So the function referred to in the -car element of "list" is applied to the other elements. - -Note that "list" is evaluated before the function application is -formed, but the resulting expression is left unevaluated. The functions {UnList()} and {Hold()} both stop the process of evaluation. - -*E.G. - - In> UnList({Cos, x}); - Out> Cos(x); - In> UnList({f}); - Out> f(); - In> UnList({Taylor,x,0,5,Cos(x)}); - Out> Taylor(x,0,5)Cos(x); - In> Eval(%); - Out> 1-x^2/2+x^4/24; - -*SEE List, Listify, Hold -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Use.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Use.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Use.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Use.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.core; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Utility; - -/** - * - * - */ -public class Use extends BuiltinFunction -{ - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - ConsPointer evaluated = new ConsPointer(); - evaluated.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - - // Get file name - LispError.checkArgument(aEnvironment, aStackTop, evaluated.getCons() != null, 1); - String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - - Utility.use(aEnvironment, orig); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} - - -/* -%mathpiper_docs,name="Use",categories="User Functions;Control Flow;Input/Output;Built In" -*CMD Use --- load a file (but not twice) -*CORE -*CALL - Use(name) - -*PARMS - -{name} -- name of the file to load - -*DESC - -If the file "name" has been loaded before, either by an earlier call -to {Use} or via the {DefLoad} -mechanism, nothing happens. Otherwise all expressions in the file are -read and evaluated. {Use} always returns {True}. - -The purpose of this function is to make sure that the file will at -least have been loaded, but is not loaded twice. - -*SEE Load, DefLoad, DefaultDirectory -%/mathpiper_docs -*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Version.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Version.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Version.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Version.java 2011-02-05 07:50:02.000000000 +0000 @@ -31,7 +31,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, "\"" + org.mathpiper.Version.version + "\"")); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, "\"" + org.mathpiper.Version.version + "\"")); } } @@ -50,14 +50,14 @@ *E.G. notest - In> Version() - Out> "1.0.48rev3"; - In> LessThan(Version(), "1.0.47") - Out> False; - In> GreaterThan(Version(), "1.0.47") - Out> True; +In> Version() +Result: "1.0.48rev3"; +In> IsLessThan(Version(), "1.0.47") +Result: False; +In> GreaterThan(Version(), "1.0.47") +Result: True; -The last two calls show that the {LessThan} and {GreaterThan} +The last two calls show that the {IsLessThan} and {GreaterThan} functions can be used for comparing version numbers. This method is only guaranteed, however, if the version is always expressed in the form {d.d.dd} as above. @@ -65,8 +65,8 @@ *REM Note that on the Windows platforms the output may be different: In> Version() -Out> "Windows-latest"; +Result: "Windows-latest"; -*SEE LessThan, GreaterThan +*SEE IsLessThan, GreaterThan %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ViewConsole.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ViewConsole.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/ViewConsole.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/ViewConsole.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,93 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.core; + +import java.awt.Dimension; +import java.awt.BorderLayout; +import java.awt.Container; +import javax.swing.JFrame; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.ui.gui.consoles.Console; + +/** + * + * + */ +public class ViewConsole extends BuiltinFunction +{ + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Console console = new Console(); + + JFrame frame = new javax.swing.JFrame(); + Container contentPane = frame.getContentPane(); + contentPane.add(console, BorderLayout.CENTER); + //frame.setAlwaysOnTop(true); + frame.setSize(new Dimension(800, 600)); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + //frame.setResizable(false); + frame.setPreferredSize(new Dimension(800, 600)); + frame.setLocationRelativeTo(null); // added + frame.pack(); + frame.setVisible(true); + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="ViewConsole",categories="User Functions;Built In" +*CMD ViewConsole --- show the console window +*CORE +*CALL + ViewConsole() + +*DESC + +Shows the console window. + +*E.G. +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewConsole() +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/While.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/While.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/While.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/While.java 2010-07-23 05:26:16.000000000 +0000 @@ -37,7 +37,7 @@ ConsPointer arg2 = getArgumentPointer(aEnvironment, aStackTop, 2); ConsPointer predicate = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, predicate, arg1); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, predicate, arg1); ConsPointer evaluated = new ConsPointer(); @@ -45,29 +45,29 @@ int beforeEvaluationDepth = -1; try { - while (Utility.isTrue(aEnvironment, predicate)) { + while (Utility.isTrue(aEnvironment, predicate, aStackTop)) { beforeStackTop = aEnvironment.iArgumentStack.getStackTopIndex(); beforeEvaluationDepth = aEnvironment.iEvalDepth; try { - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, evaluated, arg2); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, evaluated, arg2); } catch (ContinueException ce) { - aEnvironment.iArgumentStack.popTo(beforeStackTop); + aEnvironment.iArgumentStack.popTo(beforeStackTop, aStackTop, aEnvironment); aEnvironment.iEvalDepth = beforeEvaluationDepth; Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); }//end continue catch. - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, predicate, arg1); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, predicate, arg1); }//end while. - LispError.checkArgument(aEnvironment, aStackTop, Utility.isFalse(aEnvironment, predicate), 1); + LispError.checkArgument(aEnvironment, aStackTop, Utility.isFalse(aEnvironment, predicate, aStackTop), 1, "While"); } catch (BreakException be) { - aEnvironment.iArgumentStack.popTo(beforeStackTop); + aEnvironment.iArgumentStack.popTo(beforeStackTop, aStackTop, aEnvironment); aEnvironment.iEvalDepth = beforeEvaluationDepth; } @@ -79,18 +79,17 @@ /* %mathpiper_docs,name="While",categories="User Functions;Control Flow;Built In" - *CMD While --- loop while a condition is met - *CORE - *CALL +*CMD While --- loop while a condition is met +*CORE +*CALL While(pred) body - *PARMS - +*PARMS {pred} -- predicate deciding whether to keep on looping {body} -- expression to loop over - *DESC +*DESC Keep on evaluating "body" while "pred" evaluates to {True}. More precisely, {While} evaluates the predicate "pred", which should evaluate to either {True} or {False}. If the result is {True}, the expression "body" is evaluated and then @@ -101,10 +100,10 @@ In particular, if "pred" immediately evaluates to {False}, the body is never executed. {While} is the fundamental looping construct on which all other loop commands are based. It is equivalent to the {while} command in the programming language C. - *E.G. notest +*E.G. notest In> x := 0; -Out> 0; +Result: 0; In> While (x! < 10^6) \ [ Echo({x, x!}); x++; ]; 0 1 @@ -117,7 +116,7 @@ 7 5040 8 40320 9 362880 -Out> True; +Result: True; *SEE Until, For, ForEach, Break, Continue %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Write.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Write.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/Write.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/Write.java 2011-02-05 07:50:02.000000000 +0000 @@ -17,7 +17,6 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.builtin.functions.core; -import org.mathpiper.lisp.cons.ConsTraverser; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.cons.ConsPointer; @@ -38,12 +37,12 @@ ConsPointer subList = (ConsPointer) arguments.car(); - ConsPointer consTraverser = new ConsPointer(subList.getCons()); - consTraverser.goNext(); + ConsPointer consTraverser = new ConsPointer( subList.getCons()); + consTraverser.goNext(aStackTop, aEnvironment); while (consTraverser.getCons() != null) { - aEnvironment.iCurrentPrinter.print(consTraverser, aEnvironment.iCurrentOutput, aEnvironment); - consTraverser.goNext(); + aEnvironment.iCurrentPrinter.print(aStackTop, consTraverser, aEnvironment.iCurrentOutput, aEnvironment); + consTraverser.goNext(aStackTop, aEnvironment); } } Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); @@ -72,12 +71,12 @@ *E.G. notest - In> Write(1); - 1Out> True; - In> Write(1,2); - 1 2Out> True; +In> Write(1); + 1Result: True; +In> Write(1,2); + 1 2Result: True; -Write does not write a newline, so the {Out>} prompt +Write does not write a newline, so the {Result:} prompt immediately follows the output of {Write}. *SEE Echo, WriteString diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/WriteString.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/WriteString.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/WriteString.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/WriteString.java 2011-02-05 07:50:02.000000000 +0000 @@ -31,11 +31,11 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "WriteString"); String str = (String) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, str != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, str.charAt(0) == '\"', 1); - LispError.checkArgument(aEnvironment, aStackTop, str.charAt(str.length() - 1) == '\"', 1); + LispError.checkArgument(aEnvironment, aStackTop, str != null, 1, "WriteString"); + LispError.checkArgument(aEnvironment, aStackTop, str.charAt(0) == '\"', 1, "WriteString"); + LispError.checkArgument(aEnvironment, aStackTop, str.charAt(str.length() - 1) == '\"', 1, "WriteString"); int i = 1; int nr = str.length() - 1; @@ -72,14 +72,14 @@ *E.G. notest - In> Write("Hello, world!"); - "Hello, world!"Out> True; - In> WriteString("Hello, world!"); - Hello, world!Out> True; +In> Write("Hello, world!"); + "Hello, world!"Result: True; +In> WriteString("Hello, world!"); + Hello, world!Result: True; This example clearly shows the difference between Write and WriteString. Note that Write and WriteString do not write a newline, -so the {Out>} prompt immediately follows the output. +so the {Result:} prompt immediately follows the output. *SEE Echo, Write %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/XmlExplodeTag.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/XmlExplodeTag.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/XmlExplodeTag.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/XmlExplodeTag.java 2011-02-05 07:50:02.000000000 +0000 @@ -38,7 +38,7 @@ { ConsPointer out = new ConsPointer(); out.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkIsString(aEnvironment, aStackTop, out, 1); + LispError.checkIsString(aEnvironment, aStackTop, out, 1, "XmlExplodeTag"); String str = (String) out.car(); int strInd = 0; @@ -48,7 +48,7 @@ getTopOfStackPointer(aEnvironment, aStackTop).setCons(out.getCons()); return; } - LispError.checkArgument(aEnvironment, aStackTop, str.charAt(strInd) == '<', 1); + LispError.checkArgument(aEnvironment, aStackTop, str.charAt(strInd) == '<', 1, "XmlExplodeTag"); strInd++; String type = "\"Open\""; @@ -94,9 +94,9 @@ name = name + c; } name = name + "\""; - LispError.checkArgument(aEnvironment, aStackTop, str.charAt(strInd) == '=', 1); + LispError.checkArgument(aEnvironment, aStackTop, str.charAt(strInd) == '=', 1, "XmlExplodeTag"); strInd++; - LispError.checkArgument(aEnvironment, aStackTop, str.charAt(strInd) == '\"', 1); + LispError.checkArgument(aEnvironment, aStackTop, str.charAt(strInd) == '\"', 1, "XmlExplodeTag"); String value = new String(); value = value + (str.charAt(strInd)); @@ -111,9 +111,9 @@ //printf("[%s], [%s]\n",name.String(),value.String()); { - Cons ls = AtomCons.getInstance(aEnvironment, "List"); - Cons nm = AtomCons.getInstance(aEnvironment, name); - Cons vl = AtomCons.getInstance(aEnvironment, value); + Cons ls = AtomCons.getInstance(aEnvironment, aStackTop, "List"); + Cons nm = AtomCons.getInstance(aEnvironment, aStackTop, name); + Cons vl = AtomCons.getInstance(aEnvironment, aStackTop, value); nm.cdr().setCons(vl); ls.cdr().setCons(nm); Cons newinfo = SublistCons.getInstance(aEnvironment, ls); @@ -137,14 +137,14 @@ } } { - Cons ls = AtomCons.getInstance(aEnvironment, "List"); + Cons ls = AtomCons.getInstance(aEnvironment, aStackTop, "List"); ls.cdr().setCons(info); info = SublistCons.getInstance(aEnvironment, ls); } - Cons xm = AtomCons.getInstance(aEnvironment, "XmlTag"); - Cons tg = AtomCons.getInstance(aEnvironment, tag); - Cons tp = AtomCons.getInstance(aEnvironment, type); + Cons xm = AtomCons.getInstance(aEnvironment, aStackTop, "XmlTag"); + Cons tg = AtomCons.getInstance(aEnvironment, aStackTop, tag); + Cons tp = AtomCons.getInstance(aEnvironment, aStackTop, type); info.cdr().setCons(tp); tg.cdr().setCons(info); xm.cdr().setCons(tg); @@ -188,16 +188,16 @@ *E.G. - In> XmlExplodeTag("some plain text") - Out> "some plain text"; - In> XmlExplodeTag(" XmlExplodeTag("some plain text") +Result: "some plain text"; +In> XmlExplodeTag("") - Out> XmlTag("A",{{"ALIGN","left"}, +Result: XmlTag("A",{{"ALIGN","left"}, {"NAME","blah blah"}},"Open"); - In> XmlExplodeTag("

") - Out> XmlTag("P",{},"Close"); - In> XmlExplodeTag("
") - Out> XmlTag("BR",{},"OpenClose"); +In> XmlExplodeTag("

") +Result: XmlTag("P",{},"Close"); +In> XmlExplodeTag("
") +Result: XmlTag("BR",{},"OpenClose"); *SEE XmlTokenizer %/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/XmlTokenizer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/XmlTokenizer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/core/XmlTokenizer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/core/XmlTokenizer.java 2011-02-05 07:50:02.000000000 +0000 @@ -47,7 +47,7 @@ *DESC A "tokenizer" is an internal routine in the kernel that parses the input into MathPiper expressions. -This affects all input typed in by a user at the prompt and also the input redirected from files or strings using {FromFile} and {FromString} and read using {Read} or {ReadToken}. +This affects all input typed in by a user at the prompt and also the input redirected from files or strings using {PipeFromFile} and {FromString} and read using {Read} or {ReadToken}. The MathPiper environment currently supports some experimental tokenizers for various syntaxes. {XmlTokenizer} switches to an XML syntax. @@ -70,17 +70,17 @@ Any malformed XML will be treated as plain text. -**E.G. notest +*E.G. notest - In> [XmlTokenizer(); q:=ReadToken(); \ +In> [XmlTokenizer(); q:=ReadToken(); \ DefaultTokenizer();q;] -
Out> ; + Result: ; Note that: -* 1. after switching to {XmlTokenizer} the {In>} prompt disappeared; the user typed {} and the {Out>} prompt with the resulting expression appeared. +* 1. after switching to {XmlTokenizer} the {In>} prompt disappeared; the user typed {} and the {Result:} prompt with the resulting expression appeared. * 2. The resulting expression is an atom with the string representation {}; it is not a string. -*SEE OMRead, TrapError, XmlExplodeTag, ReadToken, FromFile, FromString, DefaultTokenizer +*SEE OMRead, TrapError, XmlExplodeTag, ReadToken, PipeFromFile, FromString, DefaultTokenizer %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/FScoreToProbability.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/FScoreToProbability.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/FScoreToProbability.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/FScoreToProbability.java 2010-02-09 09:09:05.000000000 +0000 @@ -0,0 +1,79 @@ + + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.library.jscistats.FDistribution; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + + + +public class FScoreToProbability extends BuiltinFunction{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "FScoreToProbability"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber degreesOfFreedom1 = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + LispError.check(degreesOfFreedom1.isInteger() && degreesOfFreedom1.toInt() >= 0, "The first argument must be an integer which is greater than 0.", "FScoreToProbability", aStackTop, aEnvironment); + + BigNumber degreesOfFreedom2 = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + + LispError.check(degreesOfFreedom2.isInteger() && degreesOfFreedom2.toInt() >= 0, "The second argument must be an integer which is greater than 0.", "FScoreToProbability", aStackTop, aEnvironment); + + BigNumber fScore = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 3); + + LispError.check(fScore.toDouble() >= 0, "The third argument must be greater than 0.", "FScoreToProbability", aStackTop, aEnvironment); + + + FDistribution fDistribution = new FDistribution(degreesOfFreedom1.toDouble(),degreesOfFreedom2.toDouble()); + + double probability = fDistribution.cumulative(fScore.toDouble()); + + BigNumber cumulativeProbability = new BigNumber(aEnvironment.getPrecision()); + + cumulativeProbability.setTo(probability); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(cumulativeProbability)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="FScoreToProbability",categories="User Functions;Statistics & Probability" +*CMD FScoreToProbability --- calculates the cumulative probability for a given f-score + +*CALL + + FScoreToProbability(degreesOfFreedom1, degreesOfFreedom2, fScore) + +*PARMS +{degreesOfFreedom1} -- integer, the first degree of freedom + +{degreesOfFreedom2} -- integer, the second degree of freedom + +{fScore} -- the fScore + +*DESC +Calculates the cumulative probability for a given f-score. + +*E.G. +In> FScoreToProbability(1,1,161.448) +Result> 0.9500000557 + + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Help.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Help.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Help.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Help.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.builtin.functions.optional; - -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.builtin.BuiltinFunctionEvaluator; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.Utility; -import org.mathpiper.ui.gui.help.FunctionTreePanel; - -/** - * - * - */ -public class Help extends BuiltinFunction -{ - - public void plugIn(Environment aEnvironment) - { - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), - "Help"); - }//end method. - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - FunctionTreePanel.main(null); - - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - - }//end method. - -}//end class. - - - - -/* -%mathpiper_docs,name="Help",categories="User Functions;Built In" -*CMD Help --- show the function help window -*CORE -*CALL - - Break() - -*DESC - -Shows the function help window. - - -%/mathpiper_docs -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Import.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Import.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Import.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Import.java 2010-12-20 20:11:34.000000000 +0000 @@ -33,7 +33,7 @@ public class Import extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), @@ -46,9 +46,13 @@ ConsPointer pathPointer = getArgumentPointer(aEnvironment, aStackTop, 1); - LispError.checkIsString(aEnvironment, aStackTop, pathPointer, 1); + LispError.checkIsString(aEnvironment, aStackTop, pathPointer, 1, "Import"); + + String path = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, (String) pathPointer.car()); + + /*org.mathpiper.builtin.javareflection.Import.addImport(path); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop));*/ - String path = Utility.stripEndQuotes((String) pathPointer.car()); List failList = BuiltinFunction.addOptionalFunctions(aEnvironment, path); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/IncompleteBeta.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/IncompleteBeta.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/IncompleteBeta.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/IncompleteBeta.java 2010-02-09 09:09:05.000000000 +0000 @@ -0,0 +1,68 @@ + + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.library.cern.Gamma; +import org.mathpiper.lisp.Environment; + + + +public class IncompleteBeta extends BuiltinFunction{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IncompleteBeta"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber a = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + BigNumber b = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + + BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 3); + + double resultValue = Gamma.incompleteBeta(a.toDouble(), b.toDouble(), x.toDouble()); + + BigNumber result = new BigNumber(aEnvironment.getPrecision()); + + result.setTo(resultValue); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(result)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="IncompleteBeta",categories="User Functions;Statistics & Probability" +*CMD IncompleteBeta --- the incomplete beta function +*CALL + IncompleteBeta(a, b, x) + +*PARMS +{a} -- the alpha parameter of the beta distribution + +{b} -- the beta parameter of the beta distribution + +{x} -- the integration end point + +*DESC + +The incomplete gamma function. + +*E.G. +In> IncompleteGamma(2.5,3.6) +Result> 0.3188972206 + + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/IncompleteGamma.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/IncompleteGamma.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/IncompleteGamma.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/IncompleteGamma.java 2010-02-09 09:09:05.000000000 +0000 @@ -0,0 +1,65 @@ + + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.library.cern.Gamma; +import org.mathpiper.lisp.Environment; + + + +public class IncompleteGamma extends BuiltinFunction{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "IncompleteGamma"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber a = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + BigNumber x = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + + double resultValue = Gamma.incompleteGammaComplement(x.toDouble(), a.toDouble()); + + BigNumber result = new BigNumber(aEnvironment.getPrecision()); + + result.setTo(resultValue); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(result)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="IncompleteGamma",categories="User Functions;Statistics & Probability" +*CMD IncompleteGamma --- the incomplete gamma function +*CORE +*CALL + IncompleteGamma(a, x) + +*PARMS +{a} -- the parameter of the gamma distribution + +{x} -- the integration end point + +*DESC + +The incomplete gamma function. + +*E.G. +In> IncompleteBeta(.2,.2,.2) +Result> 0.3927221644 + + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/JavaCall.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/JavaCall.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/JavaCall.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/JavaCall.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.optional; - -import java.util.ArrayList; -import org.mathpiper.builtin.BuiltinContainer; -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.builtin.BuiltinFunctionEvaluator; -import org.mathpiper.builtin.JavaObject; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.BuiltinObjectCons; -import org.mathpiper.lisp.cons.Cons; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.ConsTraverser; - -/** - * - * - */ -public class JavaCall extends BuiltinFunction { - - public void plugIn(Environment aEnvironment) - { - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "JavaCall"); - }//end method. - - //private StandardFileOutputStream out = new StandardFileOutputStream(System.out); - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - - if (getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer) { - - ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - ConsTraverser consTraverser = new ConsTraverser(subList); - - //Skip past List type. - consTraverser.goNext(); - - //Obtain the Java object to call. - Cons argumentCons = consTraverser.getPointer().getCons(); - - BuiltinContainer builtinContainer = null; - - if (argumentCons != null) { - - - - - if (argumentCons.car() instanceof String) { - String firstArgumentString = (String) argumentCons.car(); - //Strip leading and trailing quotes. - firstArgumentString = firstArgumentString.substring(1, firstArgumentString.length()); - firstArgumentString = firstArgumentString.substring(0, firstArgumentString.length() - 1); - Object clas = Class.forName(firstArgumentString); - builtinContainer = new JavaObject(clas); - } else if (argumentCons.car() instanceof BuiltinContainer) { - builtinContainer = (BuiltinContainer) argumentCons.car(); - }//end else. - - - if (builtinContainer != null) { - - - consTraverser.goNext(); - argumentCons = consTraverser.getPointer().getCons(); - String methodName = (String) argumentCons.car(); - //Strip leading and trailing quotes. - methodName = methodName.substring(1, methodName.length()); - methodName = methodName.substring(0, methodName.length() - 1); - - consTraverser.goNext(); - - ArrayList argumentArrayList = new ArrayList(); - - while (consTraverser.getCons() != null) { - argumentCons = consTraverser.getPointer().getCons(); - - Object argument = argumentCons.car(); - - if (argument instanceof String) { - if (argument instanceof String) { - argument = ((String) argument).substring(1, ((String) argument).length()); - argument = ((String) argument).substring(0, ((String) argument).length() - 1); - } - } - - argumentArrayList.add(argument); - - consTraverser.goNext(); - - }//end while. - - - // JavaObject response = builtinContainer.execute(methodName, (String[]) argumentArrayList.toArray(new String[0])); - JavaObject response = builtinContainer.execute(methodName, (Object[]) argumentArrayList.toArray(new Object[0])); - //System.out.println("XXXXXXXXXXX: " + response); - - if (response == null) { - Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - return; - } /*else if (response.equalsIgnoreCase("")) { - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - return; - }*/ - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, response)); - - return; - - }//end if. - - }//end if. - - }//end if. - - Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - - }//end method. -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/JavaNew.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/JavaNew.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/JavaNew.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/JavaNew.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.builtin.functions.optional; - -import java.util.ArrayList; -import org.mathpiper.builtin.BuiltinFunction; -import org.mathpiper.builtin.BuiltinFunctionEvaluator; -import org.mathpiper.builtin.JavaObject; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.BuiltinObjectCons; -import org.mathpiper.lisp.cons.Cons; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.ConsTraverser; - -/** - * - * - */ -public class JavaNew extends BuiltinFunction { - - public void plugIn(Environment aEnvironment) { - aEnvironment.getBuiltinFunctions().setAssociation( - new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), - "JavaNew"); - }//end method. - - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { - - if (getArgumentPointer(aEnvironment, aStackTop, 1).car() instanceof ConsPointer) { - - ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - ConsTraverser consTraverser = new ConsTraverser(subList); - - //Skip past List type. - consTraverser.goNext(); - - Cons argumentCons = consTraverser.getPointer().getCons(); - - if (argumentCons != null) { - - String fullyQualifiedClassName = (String) argumentCons.car(); - //Strip leading and trailing quotes. - fullyQualifiedClassName = fullyQualifiedClassName.substring(1, fullyQualifiedClassName.length()); - fullyQualifiedClassName = fullyQualifiedClassName.substring(0, fullyQualifiedClassName.length() - 1); - - consTraverser.goNext(); - - ArrayList argumentArrayList = new ArrayList(); - - while (consTraverser.getCons() != null) { - argumentCons = consTraverser.getPointer().getCons(); - Object argument = argumentCons.car(); - - if (argument instanceof String) { - argument = ((String) argument).substring(1, ((String) argument).length()); - argument = ((String) argument).substring(0, ((String) argument).length() - 1); - } - - argumentArrayList.add(argument); - - consTraverser.goNext(); - - }//end while. - - - JavaObject response = JavaObject.instantiate(fullyQualifiedClassName, (Object[]) argumentArrayList.toArray(new Object[0])); - //System.out.println("XXXXXXXXXXX: " + response); - - if (response == null) { - Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - return; - } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, response)); - return; - }//end if/else. - - - - }//end if. - - }//end if. - - Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - - }//end method. -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/MacroExpand.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/MacroExpand.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/MacroExpand.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/MacroExpand.java 2010-09-27 05:18:22.000000000 +0000 @@ -24,6 +24,7 @@ import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.printers.MathPiperPrinter; /** * @@ -31,23 +32,77 @@ */ public class MacroExpand extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), "MacroExpand"); + + aEnvironment.iBodiedOperators.setOperator(MathPiperPrinter.KMaxPrecedence, "MacroExpand"); }//end method. + + //todo:tk:this function is not complete yet. It currently only expands backquoted expressions. public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { org.mathpiper.lisp.behaviours.BackQuoteSubstitute behaviour = new org.mathpiper.lisp.behaviours.BackQuoteSubstitute(aEnvironment); + ConsPointer result = new ConsPointer(); + ConsPointer argument = getArgumentPointer(aEnvironment, aStackTop, 1); + Cons argumentCons = argument.getCons(); + argument = ((ConsPointer) argumentCons.car()).cdr(); - Utility.substitute(aEnvironment, result, argument, behaviour); - String substitutedResult = Utility.printExpression(result, aEnvironment, 0); + + Utility.substitute(aEnvironment, aStackTop, result, argument, behaviour); + + String substitutedResult = Utility.printMathPiperExpression(aStackTop, result, aEnvironment, 0); + aEnvironment.write(substitutedResult); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} + + aEnvironment.write("\n"); + + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), result); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="MacroExpand",categories="Programmer Functions;Built In;Programming",access="experimental" +*CMD MacroExpand --- shows the expanded form of a macro +*CALL + MacroExpand() macro + +*PARMS +{macro} -- a macro to expand + +*DESC +This function shows the expanded form of the Lisp-like macros that MathPiper supports. +Note: only back quoted macros are supported at this time. + +*E.G. +//Bind the variable var to the atom Echo. +In> var := Echo; +Result: Echo + +//Show the macro in expanded form. +In> MacroExpand()`(@var(2,"Hello")) +Result: True +Side Effects: +Echo(2,"Hello") +2 Hello + +//Execute the macro. +In> `(@var(2,"Hello")) +Result: True +Side Effects: +2 Hello + +*SEE ` +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Maxima.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Maxima.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Maxima.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Maxima.java 2010-06-29 02:06:05.000000000 +0000 @@ -51,7 +51,7 @@ /** Creates a new instance of MaximaWrapper */ public Maxima() { - +/* ArrayList command = new ArrayList(); //command.add("C:\\Program Files\\Maxima-5.15.0\\bin\\maxima.bat"); @@ -73,22 +73,25 @@ send("display2d:false;\n"); getResponse(); + maximaInstalled = true; } catch (Throwable t) { t.printStackTrace(); } - maximaInstalled = true; - System.out.println("M+"); + + + + //System.out.println("M+"); } else { - System.out.println("M-"); + //System.out.println("M-"); } + - - +*/ /*//Add temporary files directory to maxima search path. - File tempFile = File.createTempFile("mathrider", ".tmp"); + File tempFile = File.createTempFile("mathpiperide", ".tmp"); tempFile.deleteOnExit(); String searchDirectory = tempFile.getParent() + File.separator + "###.{mac,mc}"; searchDirectory = searchDirectory.replace("\\","/"); @@ -166,11 +169,12 @@ }//end method - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), "Maxima"); + }//end method. public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { @@ -178,9 +182,9 @@ expressionPointerr.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // Get operator - LispError.checkArgument(aEnvironment, aStackTop, expressionPointerr.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, expressionPointerr.getCons() != null, 1, "Maxima"); String orig = (String) expressionPointerr.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "Maxima"); if(maximaInstalled) { @@ -195,7 +199,7 @@ response = response.substring(1); } - getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, response)); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, response)); } catch (Throwable t) { t.printStackTrace(); Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/NormalDistributionValue.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/NormalDistributionValue.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/NormalDistributionValue.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/NormalDistributionValue.java 2010-05-24 06:12:27.000000000 +0000 @@ -0,0 +1,66 @@ + + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.library.cern.Probability; +import org.mathpiper.builtin.library.statdistlib.Normal; +import org.mathpiper.builtin.library.statdistlib.Uniform; +import org.mathpiper.lisp.Environment; + + + +public class NormalDistributionValue extends BuiltinFunction{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "NormalDistributionValue"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber mean = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + //LispError.check(mean.isInteger() && mean.toInt() >= 0, "The first argument must be an integer which is greater than 0.", "NormalDistributionValue", aStackTop, aEnvironment); + + BigNumber sigma = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + + //LispError.check(sigma.toDouble() >= 0, "The second argument must be greater than 0.", "NormalDistributionValue", aStackTop, aEnvironment); + + double randomVariableDouble = Normal.random(mean.toDouble(), sigma.toDouble(), new Uniform()); + + BigNumber randomVariable = new BigNumber(aEnvironment.getPrecision()); + + randomVariable.setTo(randomVariableDouble); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(randomVariable)); + + }//end method. + +}//end class. + + + +/* +%mathpiper_docs,name="NormalDistributionValue",categories="User Functions;Built In;Statistics & Probability",access="experimental +*CMD NormalDistributionValue --- returns a value from the normal distribution +*CALL + NormalDistributionValue(mean, standardDeviation) + +*PARMS +{mean} -- the mean of the distribution +{standardDeviation} -- the standard deviation of the distribution + +*DESC +This function returns a value from the given normal distribution. + +*E.G. +In> NormalDistributionValue(3,2) +Result> 5.440398494 + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/OneTailAlphaToTScore.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/OneTailAlphaToTScore.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/OneTailAlphaToTScore.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/OneTailAlphaToTScore.java 2010-11-29 19:11:34.000000000 +0000 @@ -0,0 +1,72 @@ + + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.library.cern.Probability; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + + + +public class OneTailAlphaToTScore extends BuiltinFunction{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "OneTailAlphaToTScore"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber degreesOfFreedom = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + LispError.check(degreesOfFreedom.isInteger() && degreesOfFreedom.toInt() >= 0, "The first argument must be an integer which is greater than 0.", "OneTailAlphaToTScore", aStackTop, aEnvironment); + + BigNumber alpha = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + + LispError.check(alpha.toDouble() >= 0 && alpha.toDouble() <= .5, "The second argument must be greater than 0 and less than or equal to .5.", "OneTailAlphaToTScore", aStackTop, aEnvironment); + + double cdf = Probability.studentTInverse(alpha.toDouble()*2, (int) degreesOfFreedom.toLong()); + + BigNumber tScore = new BigNumber(aEnvironment.getPrecision()); + + tScore.setTo(cdf); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(tScore)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="OneTailAlphaToTScore",categories="User Functions;Statistics & Probability" +*CMD OneTailAlphaToTScore --- convert a one-tail alpha to a t-score + +*CALL + + OneTailAlphaToTScore(degreesOfFreedom, alpha) + +*PARMS + +{degreesOfFreedom} -- integer, the degrees of freedom + +{alpha} -- the one tailed alpha value + +*DESC + +Calculates the t value for the given one tail alpha value and degrees of freedom. + +*E.G. +In> OneTailAlphaToTScore(9,.025) +Result> 2.262157163 + + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/PanAxiom.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/PanAxiom.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/PanAxiom.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/PanAxiom.java 2010-06-29 02:04:29.000000000 +0000 @@ -0,0 +1,214 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.ConsPointer; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.io.*; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class PanAxiom extends BuiltinFunction { + + private static PanAxiom FriCASInstance = null; + private StringBuffer responseBuffer; + private Pattern inputPromptPattern; + private InputStream inputStream; + private OutputStream outputStream; + private String response; + private String startMessage; + private String fileSearchMaximaAppendResponse; + private String fileSearchLispAppendResponse; + private boolean keepRunning; + private String prompt; + private boolean fricasInstalled = false; + + /** Creates a new instance of MaximaWrapper */ + public PanAxiom() { + + + /* + ArrayList command = new ArrayList(); + //command.add("C:\\Program Files\\Maxima-5.15.0\\bin\\maxima.bat"); + + String fricasPath = "/home/tkosan/checkouts/usr/local/bin/fricas"; + File fricasCommandFile = new File(fricasPath); + if(fricasCommandFile.exists()) + { + command.add(fricasPath); + command.add("-nox"); + command.add("-noclef"); + + + try { + ProcessBuilder processBuilder = new ProcessBuilder(command); + Process fricasProcess = processBuilder.start(); + inputStream = fricasProcess.getInputStream(); + outputStream = fricasProcess.getOutputStream(); + responseBuffer = new StringBuffer(); + inputPromptPattern = Pattern.compile("\\n\\([0-9]+\\) \\->"); + startMessage = getResponse(); + + send("2+2\n"); + getResponse(); + + fricasInstalled = true; + } catch (Throwable t) { + t.printStackTrace(); + + } + + + + //System.out.println("M+"); + } + else + { + //System.out.println("M-"); + } + + + + + */ + + }//end constructor. + + public String getStartMessage() { + return startMessage; + }//end method. + + public String getPrompt() { + return prompt; + }//end method. + + public static PanAxiom getInstance() throws Throwable { + if (FriCASInstance == null) { + FriCASInstance = new PanAxiom(); + } + return FriCASInstance; + }//end method. + + public synchronized void send(String send) throws Throwable { + outputStream.write(send.getBytes()); + outputStream.flush(); + }//end send. + + protected String getResponse() throws Throwable { + boolean keepChecking = true; + + mainLoop: + while (keepChecking) { + int serialAvailable = inputStream.available(); + if (serialAvailable == 0) { + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + System.out.println("FriCAS session interrupted."); + } + continue mainLoop; + }//end while + + byte[] bytes = new byte[serialAvailable]; + + inputStream.read(bytes, 0, serialAvailable); + responseBuffer.append(new String(bytes)); + response = responseBuffer.toString(); + //System.out.println("SSSSS " + response); + Matcher matcher = inputPromptPattern.matcher(response); + if (matcher.find()) { + //System.out.println("PPPPPP found end"); + + responseBuffer.delete(0, responseBuffer.length()); + + /* + int promptIndex = response.lastIndexOf("(%"); + if (promptIndex == -1) { + promptIndex = response.lastIndexOf("MAX"); + } + prompt = response.substring(promptIndex, response.length()); + response = response.substring(0, promptIndex); + */ + + keepChecking = false; + + }//end if. + + }//end while. + + return response; + + }//end method + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Maxima"); + + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + ConsPointer expressionPointerr = new ConsPointer(); + expressionPointerr.setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + + // Get operator + LispError.checkArgument(aEnvironment, aStackTop, expressionPointerr.getCons() != null, 1, "Maxima"); + String orig = (String) expressionPointerr.car(); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "Maxima"); + + if(fricasInstalled) + { + orig = orig.substring(1,orig.length()-1); //Strip quotes. + + try { + send(orig + ";\n"); + String response = getResponse(); + + if(response.startsWith("\n")) + { + response = response.substring(1); + } + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(AtomCons.getInstance(aEnvironment, aStackTop, response)); + } catch (Throwable t) { + t.printStackTrace(); + Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } + } + else + { + aEnvironment.write("FriCAS is not installed."); + Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } + + + } +}//end class. + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ProbabilityToFScore.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ProbabilityToFScore.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ProbabilityToFScore.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ProbabilityToFScore.java 2010-02-09 09:09:05.000000000 +0000 @@ -0,0 +1,80 @@ + + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.library.jscistats.FDistribution; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; + + + +public class ProbabilityToFScore extends BuiltinFunction{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ProbabilityToFScore"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + BigNumber degreesOfFreedom1 = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 1); + + LispError.check(degreesOfFreedom1.isInteger() && degreesOfFreedom1.toInt() >= 0, "The first argument must be an integer which is greater than 0.", "ProbabilityToFScore", aStackTop, aEnvironment); + + BigNumber degreesOfFreedom2 = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 2); + + LispError.check(degreesOfFreedom2.isInteger() && degreesOfFreedom2.toInt() >= 0, "The second argument must be an integer which is greater than 0.", "ProbabilityToFScore", aStackTop, aEnvironment); + + BigNumber probability = org.mathpiper.lisp.Utility.getNumber(aEnvironment, aStackTop, 3); + + LispError.check(probability.toDouble() >= 0, "The third argument must be greater than 0.", "ProbabilityToFScore", aStackTop, aEnvironment); + + + FDistribution fDistribution = new FDistribution(degreesOfFreedom1.toDouble(),degreesOfFreedom2.toDouble()); + + double fScoreValue = fDistribution.inverse(probability.toDouble()); + + BigNumber fScore = new BigNumber(aEnvironment.getPrecision()); + + probability.setTo(fScoreValue); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(new org.mathpiper.lisp.cons.NumberCons(probability)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="ProbabilityToFScore",categories="User Functions;Statistics & Probability" +*CMD ProbabilityToFScore --- calculates the f-score for a given cumulative probability + +*CALL + + ProbabilityToFScore(degreesOfFreedom1, degreesOfFreedom2, probability) + +*PARMS + +{degreesOfFreedom1} -- integer, the first degree of freedom + +{degreesOfFreedom2} -- integer, the second degree of freedom + +{probability} -- the cumulative probability + +*DESC +Calculates the calculates the f-score for a given cumulative probability. + +*E.G. +In> ProbabilityToFScore(1,1,.95) +Result> 161.4476388 + + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Ring.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Ring.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/Ring.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/Ring.java 2010-12-20 20:11:34.000000000 +0000 @@ -0,0 +1,65 @@ + +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.lisp.cons.ConsPointer; + +/** + * + * + */ +public class Ring extends BuiltinFunction +{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "Ring"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + + ConsPointer pathPointer = getArgumentPointer(aEnvironment, aStackTop, 1); + + + LispError.checkIsString(aEnvironment, aStackTop, pathPointer, 1, "Ring"); + + String configurationString = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, (String) pathPointer.car()); + + org.mathpiper.builtin.library.jas.Ring ring = new org.mathpiper.builtin.library.jas.Ring(aEnvironment, configurationString); + + JavaObject response = new JavaObject(ring); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + return; + + + }//end method. + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SetPlotColor.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SetPlotColor.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SetPlotColor.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SetPlotColor.java 2010-02-09 09:09:05.000000000 +0000 @@ -33,7 +33,7 @@ public class SetPlotColor extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 3, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), @@ -43,7 +43,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { ConsPointer consPointer = new ConsPointer(); - aEnvironment.getGlobalVariable("Simulator", consPointer); + aEnvironment.getGlobalVariable(aStackTop, "Simulator", consPointer); org.mathpiper.ui.gui.simulator.SimulatorFrame simulator = (org.mathpiper.ui.gui.simulator.SimulatorFrame) ((BuiltinContainer)consPointer.car()).getObject(); Cons redCons = getArgumentPointer(aEnvironment, aStackTop, 1).getCons(); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SetPlotWidth.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SetPlotWidth.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SetPlotWidth.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SetPlotWidth.java 2010-02-09 09:09:05.000000000 +0000 @@ -33,7 +33,7 @@ public class SetPlotWidth extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), @@ -43,7 +43,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { ConsPointer consPointer = new ConsPointer(); - aEnvironment.getGlobalVariable("Simulator", consPointer); + aEnvironment.getGlobalVariable(aStackTop, "Simulator", consPointer); org.mathpiper.ui.gui.simulator.SimulatorFrame simulator = (org.mathpiper.ui.gui.simulator.SimulatorFrame) ((BuiltinContainer)consPointer.car()).getObject(); Cons redCons = getArgumentPointer(aEnvironment, aStackTop, 1).getCons(); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SimulatorPlot.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SimulatorPlot.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SimulatorPlot.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SimulatorPlot.java 2010-02-09 09:09:05.000000000 +0000 @@ -33,7 +33,7 @@ public class SimulatorPlot extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), @@ -42,7 +42,7 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { ConsPointer consPointer = new ConsPointer(); - aEnvironment.getGlobalVariable("Simulator", consPointer); + aEnvironment.getGlobalVariable(aStackTop, "Simulator", consPointer); org.mathpiper.ui.gui.simulator.SimulatorFrame simulator = (org.mathpiper.ui.gui.simulator.SimulatorFrame) ((BuiltinContainer)consPointer.car()).getObject(); Cons xCons = getArgumentPointer(aEnvironment, aStackTop, 1).getCons(); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/StackTrace.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/StackTrace.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/StackTrace.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/StackTrace.java 2010-05-30 06:06:06.000000000 +0000 @@ -0,0 +1,142 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class StackTrace extends BuiltinFunction +{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "StackTrace"); + }//end method. + + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + String dump = aEnvironment.iArgumentStack.dump(aStackTop, aEnvironment); + + aEnvironment.write(dump); + + dump = aEnvironment.dumpLocalVariablesFrame(aStackTop); + + aEnvironment.write(dump); + + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="StackTrace",categories="Programmer Functions;Built In;Debugging",access="experimental" +*CMD StackTrace --- shows the current state of the user function stack and the built in function stack +*CALL + StackTrace() + +*DESC +This function shows the current state of the user function stack and the built in function stack. + +It is currently somewhat difficult to follow the stack traces at points where user functions call built in +functions and vice versa because there are no clear markers which indicate where control leave one stack +and enters the other. However, even with this difficulty, the StackTrace function has still been proven +to be a useful debugging tool. + +*E.G. +/%mathpiper +TestFunction() := +[ + index := 1; + While(index < 10) + [ + If(index = 5, StackTrace()); + + index++; + ]; + +]; +/%/mathpiper + + +In> TestFunction() +Result: True +Side Effects: + + +========================================= Start Of Built In Function Stack Trace +0: Prog + 1: -> TestFunction() +----------------------------------------- +2: Prog + 3: -> index:=1 + 4: -> While(index<10)[ + If(index=5,StackTrace()); + index++; +] + +----------------------------------------- +5: index<10 +----------------------------------------- +6: [ + If(index=5,StackTrace()); + index++; +] + +----------------------------------------- +7: Prog + 8: -> If(index=5,StackTrace()) + 9: -> index++ +----------------------------------------- +10: index=5 +----------------------------------------- +11: {StackTrace()} +----------------------------------------- +12: StackTrace +========================================= End Of Built In Function Stack Trace + + + +========================================= Start Of User Function Stack Trace +0: Prog +----------------------------------------- +1: Prog +----------------------------------------- +2: TestFunction +----------------------------------------- +3: Prog +----------------------------------------- +4: +========================================= End Of User Function Stack Trace + +*SEE StackTraceOn, StackTraceOff, TraceSome, TraceExcept, TraceOn, TraceOff +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/StackTraceOff.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/StackTraceOff.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/StackTraceOff.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/StackTraceOff.java 2010-05-30 06:06:06.000000000 +0000 @@ -0,0 +1,66 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Evaluator; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class StackTraceOff extends BuiltinFunction +{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "StackTraceOff"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Evaluator.stackTraceOff(); + aEnvironment.write("Stack tracing is off.\n"); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + + + +/* +%mathpiper_docs,name="StackTraceOff",categories="Programmer Functions;Built In;Debugging",access="experimental" +*CMD StackTraceOff --- clears the flag which will show a stack trace when an exception is thrown +*CALL + StackTraceOff() + +*DESC +This function clears the flag which will show the current state of the user function stack and the built in function stack +when an exception is thrown. + +See the StackTraceOn function for more information. + +*SEE StackTrace, StackTraceOn, TraceSome, TraceExcept, TraceOn, TraceOff +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/StackTraceOn.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/StackTraceOn.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/StackTraceOn.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/StackTraceOn.java 2010-05-30 06:06:06.000000000 +0000 @@ -0,0 +1,118 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Evaluator; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class StackTraceOn extends BuiltinFunction { + + public void plugIn(Environment aEnvironment) throws Exception { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "StackTraceOn"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + Evaluator.stackTraceOn(); + aEnvironment.write("Stack tracing is on.\n"); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="StackTraceOn",categories="Programmer Functions;Built In;Debugging",access="experimental" +*CMD StackTraceOn --- sets the flag which will show a stack trace when an exception is thrown +*CALL + StackTraceOn() + +*DESC +This function sets the flag which will show the current state of the user function stack and the built in function stack +when an exception is thrown. + +It is currently somewhat difficult to follow the stack traces at points where user functions call built in +functions and vice versa because there are no clear markers which indicate where control leave one stack +and enters the other. However, even with this difficulty, the StackTrace function has still been proven +to be a useful debugging tool. + +*E.G. +/%mathpiper + +TestFunction() := +[ + IsLessThan(Complex(1,1),3); +]; + + +StackTraceOn(); + +TestFunction(); + +StackTraceOff(); + +/%/mathpiper + + /%error,preserve="false" + Result: In function "IsLessThan" : + bad argument number 1(counting from 1) : + The first argument must be a non-complex decimal number or a string. + The offending argument Complex(1,1) evaluated to Complex(1,1) + + + ========================================= Start Of Built In Function Stack Trace + 0: LoadScript + 1: -> "/tmp/mathpiperide917565545585604790.mpw_tmp" + ----------------------------------------- + 2: Prog + 3: -> IsLessThan(Complex(1,1),3) + ----------------------------------------- + 4: IsLessThan + 5: -> Complex(1,1) + 6: -> 3 + ========================================= End Of Built In Function Stack Trace + + + + ========================================= Start Of User Function Stack Trace + 0: Prog + ----------------------------------------- + 1: TestFunction + ----------------------------------------- + 2: + ========================================= End Of User Function Stack Trace + + In function: TestFunction, Error near line 14 + + Side Effects: + Stack tracing is on. + +. /%/error + +*SEE StackTrace, StackTraceOff, TraceSome, TraceExcept, TraceOn, TraceOff +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SysOut.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SysOut.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/SysOut.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/SysOut.java 2010-05-30 06:06:06.000000000 +0000 @@ -31,7 +31,7 @@ */ public class SysOut extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), @@ -46,12 +46,12 @@ ConsPointer subList = (ConsPointer) getArgumentPointer(aEnvironment, aStackTop, 1).car(); - ConsTraverser consTraverser = new ConsTraverser(subList); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, subList); + consTraverser.goNext(aStackTop); while (consTraverser.getCons() != null) { - aEnvironment.iCurrentPrinter.print(consTraverser.getPointer(), out, aEnvironment); - consTraverser.goNext(); + aEnvironment.iCurrentPrinter.print(aStackTop, consTraverser.getPointer(), out, aEnvironment); + consTraverser.goNext(aStackTop); } } String output = out.toString(); @@ -64,4 +64,24 @@ }//end method. -} +}//end class. + + + + +/* +%mathpiper_docs,name="SysOut",categories="User Functions;Built In;Input/Output",access="experimental" +*CMD SysOut --- similar to the Write function, except a copy of the output is also sent to Java's System.out stream +*CALL + SysOut() + +*DESC +If a function prints side effect output, the output is not displayed until the function returns. If a function +throws an exception, the output may not be displayed at all. Therefore, sometimes it is desireable to see +the output as it is printed instead of waiting until the function returns. SysOut +is similar to the Write function, except it also sends a copy of its side effect output to Java's System.out +stream so that it can be viewed immediately. + +*SEE Write +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceExcept.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceExcept.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceExcept.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceExcept.java 2010-12-21 23:06:59.000000000 +0000 @@ -34,7 +34,7 @@ public class TraceExcept extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), @@ -49,13 +49,13 @@ ConsPointer bodyPointer = getArgumentPointer(aEnvironment, aStackTop, 2); // Get function list. - LispError.checkArgument(aEnvironment, aStackTop, functionListPointer.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, functionListPointer.getCons() != null, 1, "TraceExcept"); ConsPointer result = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result , functionListPointer); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, result , functionListPointer); String functionNamesString = (String) result.car(); - LispError.checkArgument(aEnvironment, aStackTop, functionNamesString != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, functionNamesString != null, 1, "TraceExcept"); //Place function names into a List and then set this as the trace function list in Evaluator. @@ -71,7 +71,7 @@ //Evaluate expresstion with tracing on. Evaluator.traceOn(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), bodyPointer); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), bodyPointer); Evaluator.traceOff(); Evaluator.setTraceExceptFunctionList(null); @@ -83,11 +83,11 @@ /* -%mathpiper_docs,name="TraceExcept" +%mathpiper_docs,name="TraceExcept",categories="Programmer Functions;Built In;Debugging",access="experimental" *CMD TraceExcept --- trace all the functions but the given functions an expression *CORE *CALL - TraceExcept("function_name,function_name,function_name,...", expression) + TraceExcept("function_name,function_name,function_name,...") expression *PARMS @@ -103,8 +103,8 @@ *E.G. -In> In> TraceExcept("",2+3-6) //An empty function list means trace all functions. -Result> True TraceExcept("") 2+3-6 //An empty function list means trace all functions. +Result> True Side Effects> Enter<**** user rulebase>{(-,2+3-6); Enter<**** user rulebase>{(+,2+3); @@ -141,7 +141,7 @@ Leave<**** user rulebase>}(2+3-6->-1); -In> TraceExcept("IsList, IsNumber",2+3-6) +In> TraceExcept("IsList, IsNumber") 2+3-6 Result> True Side Effects> Enter<**** user rulebase>{(-,2+3-6); @@ -164,7 +164,7 @@ Leave<**** user rulebase>}(2+3-6->-1); - *SEE TraceSome + *SEE TraceSome, StackTrace, StackTraceOn, StackTraceOff, TraceOff %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceOff.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceOff.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceOff.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceOff.java 2010-05-30 07:12:14.000000000 +0000 @@ -31,7 +31,7 @@ public class TraceOff extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), @@ -46,3 +46,21 @@ Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } } + + + + +/* +%mathpiper_docs,name="TraceOff",categories="Programmer Functions;Built In;Debugging",access="experimental" +*CMD TraceOff --- disables a complete trace of all the functions that are called when an expression is evaluated +*CALL + TraceOff() + +*DESC +This function disables a complete trace of all the functions that are called when an expression is evaluated. + +See TraceOn for more information. + +*SEE StackTrace, StackTraceOn, StackTraceOff, TraceSome, TraceExcept, TraceOn +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceOn.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceOn.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceOn.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceOn.java 2010-05-30 07:12:14.000000000 +0000 @@ -13,9 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.builtin.functions.optional; import org.mathpiper.builtin.BuiltinFunction; @@ -28,20 +26,82 @@ * * */ -public class TraceOn extends BuiltinFunction -{ +public class TraceOn extends BuiltinFunction { - public void plugIn(Environment aEnvironment) - { + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), "TraceOn"); }//end method. - public void evaluate(Environment aEnvironment, int aStackTop) throws Exception - { - Evaluator.traceOn(); - aEnvironment.write("Tracing is on.\n"); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); - } -} + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + Evaluator.traceOn(); + aEnvironment.write("Tracing is on.\n"); + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="TraceOn",categories="Programmer Functions;Built In;Debugging",access="experimental" +*CMD TraceOn --- enables a complete trace of all the functions that are called when an expression is evaluated +*CALL + TraceOn() + +*DESC +This function enables a complete trace of all the functions that are called when an expression is evaluated. +The tracing output can become very long, very quickly so this form of complete tracing is only useful +for tracing relatively simple expressions. TraceSome and TraceExcept can be used as an alternative to reduce +the amount of tracing output that is generated. + +The first time a function is called during a MathPiper session, it needs to be loaded +and converted into Lisp code. If tracing is enabled when functions are being loaded, the loading code +will also be traced. This loading code can be caused to not appear in the trace by simply evaluating the +expression to be traced once with tracing off and then evaluating it again with tracing on. + +In the example below, the {output} attribute of the {%mathpiper} fold is set to {trace} so that the output +is placed into a {%mathpiper_trace} fold. This will enable the trace output to be syntax highlighted. + +*E.G. +/%mathpiper,output="trace" + +TraceOn(); + +2 + 3; + +TraceOff(); + +/%/mathpiper + + /%mathpiper_trace,preserve="false" + Result: True + + Side Effects: + Tracing is on. + Enter<**** user rulebase>{(+, 2+3); + Arg(arg1 -> 2); + Arg(arg2 -> 3); + Enter{(IsNumber, IsNumber(x)); + Arg(parameter1 -> 2); + Leave}(IsNumber(x) -> True, Local variables: y -> 3, x -> 2, arg2 -> 3, arg1 -> 2, ); + Enter{(IsNumber, IsNumber(y)); + Arg(parameter1 -> 3); + Leave}(IsNumber(y) -> True, Local variables: y -> 3, x -> 2, arg2 -> 3, arg1 -> 2, ); + **** Rule in function (+) matched: Precedence: 50, Parameters: arg1, arg2, Predicates: (Pattern) IsNumber(x), IsNumber(y), True, Variables: x, y, Types: Variable, Variable, Body: AddN(x, y) + Enter{(AddN, AddN(x,y)); + Arg(parameter1 -> 2); + Arg(parameter2 -> 3); + Leave}(AddN(x,y) -> 5, Local variables: y -> 3, x -> 2, arg2 -> 3, arg1 -> 2, ); + Leave<**** user rulebase>}(2+3 -> 5, Local variables: y -> 3, x -> 2, arg2 -> 3, arg1 -> 2, ); + Enter{(TraceOff, TraceOff()); + Tracing is off. + +. /%/mathpiper_trace + +*SEE StackTrace, StackTraceOn, StackTraceOff, TraceSome, TraceExcept, TraceOff +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceSome.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceSome.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceSome.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceSome.java 2010-12-21 23:06:59.000000000 +0000 @@ -34,7 +34,7 @@ public class TraceSome extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), @@ -49,11 +49,11 @@ ConsPointer bodyPointer = getArgumentPointer(aEnvironment, aStackTop, 2); // Get function list. - LispError.checkArgument(aEnvironment, aStackTop, functionListPointer.getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, functionListPointer.getCons() != null, 1, "TraceSome"); ConsPointer result = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result , functionListPointer); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, result , functionListPointer); String functionNamesString = (String) result.car(); - LispError.checkArgument(aEnvironment, aStackTop, functionNamesString != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, functionNamesString != null, 1, "TraceSome"); //Place function names into a List and then set this as the trace function list in Evaluator. @@ -69,7 +69,7 @@ //Evaluate expresstion with tracing on. Evaluator.traceOn(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop), bodyPointer); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, getTopOfStackPointer(aEnvironment, aStackTop), bodyPointer); Evaluator.traceOff(); Evaluator.setTraceFunctionList(null); @@ -85,11 +85,11 @@ /* -%mathpiper_docs,name="TraceSome" +%mathpiper_docs,name="TraceSome",categories="Programmer Functions;Built In;Debugging",access="experimental" *CMD TraceSome --- trace the given functions which are evaluated in the given expression *CORE *CALL - TraceSome("function_name,function_name,function_name,...", expression) + TraceSome("function_name,function_name,function_name,...") expression *PARMS @@ -103,8 +103,7 @@ *E.G. - -In> TraceSome("Factors,FactorizeInt",Factor(8)) +In> TraceSome("Factors,FactorizeInt") Factor(8) Result> True Side Effects> Enter<**** user rulebase>{(Factors,Factors(p)); @@ -117,7 +116,7 @@ Leave<**** user rulebase>}(Factors(p)->{{2,3}}); - *SEE TraceExcept +*SEE TraceExcept, StackTrace, StackTraceOn, StackTraceOff, TraceOff %/mathpiper_docs */ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceToStdio.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceToStdio.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/TraceToStdio.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/TraceToStdio.java 2010-12-22 06:09:14.000000000 +0000 @@ -0,0 +1,52 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.optional; + +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Evaluator; +import org.mathpiper.lisp.Utility; + +/** + * + * + */ +public class TraceToStdio extends BuiltinFunction +{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "TraceToStdio"); + }//end method. + + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + Evaluator.TRACE_TO_STANDARD_OUT = true; + + aEnvironment.write("Tracing to stdio is on.\n"); + + Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + } +} + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewEnvironment.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewEnvironment.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewEnvironment.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewEnvironment.java 2010-07-05 06:56:22.000000000 +0000 @@ -18,10 +18,12 @@ package org.mathpiper.builtin.functions.optional; +import javax.swing.JFrame; import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.JavaObject; import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.BuiltinObjectCons; /** * @@ -30,7 +32,7 @@ public class ViewEnvironment extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), @@ -40,7 +42,44 @@ public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { org.mathpiper.ui.gui.EnvironmentViewer viewer = new org.mathpiper.ui.gui.EnvironmentViewer(); - viewer.getViewerFrame(aEnvironment); - Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); + + JFrame frame = viewer.getViewerFrame(aEnvironment); + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); } } + + + + +/* +%mathpiper_docs,name="ViewEnvironment",categories="User Functions;Built In" +*CMD ViewEnvironment --- show the console window +*CORE +*CALL + ViewEnvironment() + +*DESC + +Shows the MathPiper environment. + +*E.G. +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewEnvironment() +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewGraphicConsole.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewGraphicConsole.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewGraphicConsole.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewGraphicConsole.java 2010-07-08 07:52:35.000000000 +0000 @@ -0,0 +1,102 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.optional; + +import java.awt.Dimension; +import java.awt.BorderLayout; +import java.awt.Container; +import javax.swing.JFrame; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.ui.gui.consoles.GraphicConsole; + +/** + * + * + */ +public class ViewGraphicConsole extends BuiltinFunction +{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ViewGraphicConsole"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + GraphicConsole console = new GraphicConsole(); + + JFrame frame = new javax.swing.JFrame(); + Container contentPane = frame.getContentPane(); + contentPane.add(console, BorderLayout.CENTER); + //frame.setAlwaysOnTop(true); + frame.setSize(new Dimension(800, 600)); + frame.setDefaultCloseOperation(frame.DISPOSE_ON_CLOSE); + //frame.setResizable(false); + frame.setTitle("Graphic Console"); + frame.setPreferredSize(new Dimension(800, 600)); + frame.setLocationRelativeTo(null); // added + frame.pack(); + frame.setVisible(true); + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="ViewGraphicConsole",categories="User Functions;Built In",access="experimental" +*CMD ViewConsole --- show the console window +*CORE +*CALL + ViewGraphicConsole() + +*DESC + +Shows the graphic console window. + +*E.G. +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewGraphicConsole() +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewHelp.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewHelp.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewHelp.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewHelp.java 2010-07-05 06:56:22.000000000 +0000 @@ -0,0 +1,119 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.builtin.functions.optional; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.io.FileNotFoundException; +import javax.swing.JFrame; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.ui.gui.help.FunctionTreePanel; + +/** + * + * + */ +public class ViewHelp extends BuiltinFunction +{ + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ViewHelp"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception + { + JFrame frame = new javax.swing.JFrame(); + + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + FunctionTreePanel functionTreePanel = null; + + try { + + functionTreePanel = new FunctionTreePanel(); + + Container contentPane = frame.getContentPane(); + contentPane.add(functionTreePanel.getToolPanel(), BorderLayout.NORTH); + contentPane.add(functionTreePanel, BorderLayout.CENTER); + + frame.pack(); + + frame.setTitle("MathPiper Help"); + frame.setSize(new Dimension(700, 700)); + //frame.setResizable(false); + frame.setPreferredSize(new Dimension(700, 700)); + frame.setLocationRelativeTo(null); // added + + frame.setVisible(true); + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + + } catch (FileNotFoundException fnfe) { + LispError.raiseError("The help application data file was not found.", "ViewHelp", aStackTop, aEnvironment); + } + + + + }//end method. + +}//end class. + + + + +/* +%mathpiper_docs,name="ViewHelp",categories="User Functions;Built In" +*CMD ViewHelp --- display the function help window +*CORE +*CALL + ViewHelp() + +*DESC + +Displays the function help window. + +*E.G. +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewHelp() +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewHtml.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewHtml.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewHtml.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewHtml.java 2010-12-20 20:11:34.000000000 +0000 @@ -0,0 +1,153 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.optional; + +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import org.mathpiper.builtin.BuiltinContainer; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.ui.gui.help.FunctionTreePanel; + +/** + * + * + */ +public class ViewHtml extends BuiltinFunction { + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ViewHtml"); + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + String htmlText = null; + + ConsPointer consPointer = null; + + Object argument = getArgumentPointer(aEnvironment, aStackTop, 1).car(); + + if (argument instanceof String) + { + htmlText = (String) argument; + + htmlText = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, htmlText); + } + else if (argument instanceof BuiltinContainer) + { + BuiltinContainer builtinContainer = (BuiltinContainer) argument; + LispError.check(builtinContainer.typeName().equals("java.lang.String"), "Argument must be a MathPiper string or a Java String object.", "ViewHtml", aStackTop, aEnvironment); + htmlText = (String) builtinContainer.getObject(); + } + else + { + LispError.raiseError("Argument must be a MathPiper string or a Java String object.", "ViewHtml", aStackTop, aEnvironment); + }//end else. + + htmlText = FunctionTreePanel.processLatex(htmlText); + + JFrame frame = new JFrame(); + Container contentPane = frame.getContentPane(); + contentPane.setLayout(new java.awt.BorderLayout()); + JEditorPane editorPane = new JEditorPane(); + editorPane.setEditorKit(new javax.swing.text.html.HTMLEditorKit()); + JScrollPane editorScrollPane = new JScrollPane(editorPane); + editorScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + editorPane.setEditable(false); + editorPane.setText(htmlText); + contentPane.add(editorScrollPane); + frame.pack(); + frame.setAlwaysOnTop(false); + frame.setTitle("MathPiper"); + frame.setSize(new Dimension(750, 650)); + frame.setResizable(true); + //frame.setPreferredSize(new Dimension(400, 400)); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + + }//end method. +}//end class. + + + + +/* +%mathpiper_docs,name="ViewHtml",categories="User Functions;Built In;Visualization" +*CMD ViewHtml --- display rendered HTML code + +*CALL + ViewHtml(string) + +*Params +{string} -- a string which contains HTML code + +*DESC +Display rendered HTML code. + +*E.G. +/%html + + + HTML Demo + + + +

HTML demo 1.

+ + +

LaTeX math formulas can be placed into the HTML code.

+ \$x_{j}\$ + + + +/%/html + + + +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewHtml("Hello") +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewLatex.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewLatex.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewLatex.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewLatex.java 2010-12-29 01:32:10.000000000 +0000 @@ -0,0 +1,222 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.optional; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.Box; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.ConsPointer; + +import java.awt.Color; + +import javax.swing.JLabel; + +import javax.swing.JPanel; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.ui.gui.worksheets.LatexRenderingController; +import org.mathpiper.ui.gui.worksheets.ScreenCapturePanel; +import org.scilab.forge.jlatexmath.TeXFormula; +import org.scilab.forge.jlatexmath.DefaultTeXFont; + +import org.scilab.forge.jlatexmath.cyrillic.CyrillicRegistration; +import org.scilab.forge.jlatexmath.greek.GreekRegistration; + +/** + * + * + */ +public class ViewLatex extends BuiltinFunction { + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ViewLatexInternal"); + + String[] parameters = new String[] {"expression","size"}; + Utility.declareFunction("ViewLatex", parameters, "ViewLatexInternal(expression, size);", aEnvironment, LispError.TODO); + + + parameters = new String[] {"expression"}; + Utility.declareFunction("ViewLatex", parameters, "ViewLatexInternal(expression, 2);", aEnvironment, LispError.TODO); + + + DefaultTeXFont.registerAlphabet(new CyrillicRegistration()); + DefaultTeXFont.registerAlphabet(new GreekRegistration()); + + + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + String latexString = null; + + ConsPointer consPointer = null; + + Object expressionPointer = getArgumentPointer(aEnvironment, aStackTop, 1).car(); + + if (expressionPointer instanceof String) + { + latexString = (String) expressionPointer; + + latexString = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, latexString); + + latexString = Utility.stripEndDollarSigns(latexString); + } + else + { + LispError.raiseError("The first argument must be a string which contains Latex code.", "ViewLatex", aStackTop, aEnvironment); + }//end else. + + + + ConsPointer resultPointer = new ConsPointer(); + + ConsPointer viewScalePointer = new ConsPointer(); + viewScalePointer.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, resultPointer, viewScalePointer); + BigNumber viewScale = (BigNumber) resultPointer.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + LispError.checkArgument(aEnvironment, aStackTop, viewScale != null, 1, "ViewLatex"); + + /*sHotEqn hotEqn = new sHotEqn(); + hotEqn.setFontsizes(18,18,18,18); + hotEqn.setEquation(latexString); + JScrollPane hotEqnScrollPane = new JScrollPane(hotEqn,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + */ + + + + + //MathPiper built-in math viewer. + /*TexParser parser = new TexParser(); + SymbolBox sBoxExpression = parser.parse(latexString); + MathPanel mathPanel = new MathPanel(sBoxExpression, viewScale.toDouble()); + MathPanelController mathPanelScaler = new MathPanelController(mathPanel, viewScale.toDouble()); + JScrollPane mathPiperScrollPane = new JScrollPane(mathPanel,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + */ + + JFrame frame = new JFrame(); + Container contentPane = frame.getContentPane(); + frame.setBackground(Color.WHITE); + contentPane.setBackground(Color.WHITE); + + /* + DebugGraphics.setFlashCount(10); + DebugGraphics.setFlashColor(Color.red); + DebugGraphics.setFlashTime(1000); + RepaintManager.currentManager(panel).setDoubleBufferingEnabled(false); + panel.setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION); + panel.setDebugGraphicsOptions(DebugGraphics.LOG_OPTION); + */ + + Box box = Box.createVerticalBox(); + + + //JLateXMath + TeXFormula formula = new TeXFormula(latexString); + JLabel latexLabel = new JLabel(); + JPanel latexPanelController = new LatexRenderingController(formula, latexLabel, 100); + + JPanel screenCapturePanel = new ScreenCapturePanel(); + + screenCapturePanel.add(latexLabel); + + JScrollPane jMathTexScrollPane = new JScrollPane(screenCapturePanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + jMathTexScrollPane.getViewport().setBackground(Color.WHITE); + box.add(jMathTexScrollPane); + + contentPane.add(box); + + contentPane.add(latexPanelController, BorderLayout.NORTH); + + //box.add(mathPiperScrollPane); + + frame.setAlwaysOnTop(false); + frame.setTitle("MathPiper"); + frame.setSize(new Dimension(300, 200)); + frame.setResizable(true); + frame.setLocationRelativeTo(null); + + frame.pack(); + frame.setVisible(true); + + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + + + }//end method. + + +}//end class. + + + + + +/* +%mathpiper_docs,name="ViewLatex",categories="User Functions;Visualization" +*CMD ViewLatex --- display rendered Latex code + +*CALL + ViewLatex(string) + +*Params +{string} -- a string which contains Latex code + +*DESC +Display rendered Latex code. Note: backslashes must be escaped +with a backslash. + +*E.G. +In> ViewLatex("2\\sum_{i=1}^n a_i") +Result: javax.swing.JFrame + + + +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewLatex("2\\sum_{i=1}^n a_i") +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +*SEE ViewMath +%/mathpiper_docs +*/ + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewList.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewList.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewList.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewList.java 2010-12-29 01:32:10.000000000 +0000 @@ -0,0 +1,110 @@ +package org.mathpiper.builtin.functions.optional; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.ui.gui.worksheets.ListPanel; +import org.mathpiper.ui.gui.worksheets.MathPanelController; +import org.mathpiper.ui.gui.worksheets.ScreenCapturePanel; + +public class ViewList extends BuiltinFunction { + + public void plugIn(Environment aEnvironment) throws Exception { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), + "ViewList"); + }//end method. + + + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + ConsPointer expressionPointer = getArgumentPointer(aEnvironment, aStackTop, 1); + + JFrame frame = new JFrame(); + Container contentPane = frame.getContentPane(); + frame.setBackground(Color.WHITE); + contentPane.setBackground(Color.WHITE); + + ListPanel listPanel = new ListPanel(aEnvironment, aStackTop, expressionPointer, 2); + + MathPanelController mathPanelScaler = new MathPanelController(listPanel, 2.0); + + JPanel screenCapturePanel = new ScreenCapturePanel(); + + screenCapturePanel.add(listPanel); + + JScrollPane scrollPane = new JScrollPane(screenCapturePanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + + contentPane.add(scrollPane); + contentPane.add(mathPanelScaler, BorderLayout.NORTH); + + frame.setAlwaysOnTop(false); + frame.setTitle("List Viewer"); + frame.setSize(new Dimension(300, 200)); + frame.setResizable(true); + frame.setLocationRelativeTo(null); + + frame.pack(); + frame.setVisible(true); + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + + }//end method. + +}//end class. + + + + + +/* +%mathpiper_docs,name="ViewList",categories="User Functions;Built In;Visualization" +*CMD ViewList --- display an expression in Lisp box diagram form + +*CALL + ViewList(expression) + +*Params +{expression} -- an expression to view + +*DESC +Display an expression in Lisp box diagram form. + +*E.G. +In> ViewList(x^2) + +In> ViewList(2*x^3+14*x^2+24*x) + + + +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewList(x^2) +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +*SEE LispForm, ViewMath +%/mathpiper_docs +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewMath.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewMath.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewMath.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewMath.java 2010-12-29 01:32:10.000000000 +0000 @@ -0,0 +1,254 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.builtin.functions.optional; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.Box; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.BuiltinFunctionEvaluator; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.SublistCons; + +import javax.swing.JLabel; + +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.cons.BuiltinObjectCons; +import org.mathpiper.ui.gui.worksheets.LatexRenderingController; +import org.mathpiper.ui.gui.worksheets.ScreenCapturePanel; +import org.scilab.forge.jlatexmath.TeXFormula; + +/** + * + * + */ +public class ViewMath extends BuiltinFunction { + + public void plugIn(Environment aEnvironment) throws Exception + { + aEnvironment.getBuiltinFunctions().setAssociation( + new BuiltinFunctionEvaluator(this, 2, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Macro), + "ViewMathInternal"); + + String[] parameters = new String[] {"expression","size"}; + Utility.declareFunction("ViewMath", parameters, "ViewMathInternal(expression, size);", aEnvironment, LispError.TODO); + + + parameters = new String[] {"expression"}; + Utility.declareFunction("ViewMath", parameters, "ViewMathInternal(expression, 2);", aEnvironment, LispError.TODO); + + + }//end method. + + public void evaluate(Environment aEnvironment, int aStackTop) throws Exception { + + //Utility.lispEvaluate(aEnvironment, "TeXForm(x^2);"); + + Cons head = SublistCons.getInstance(aEnvironment, AtomCons.getInstance(aEnvironment, aStackTop, "TeXForm")); + + ((ConsPointer) head.car()).cdr().setCons(getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); + + + ConsPointer resultPointer = new ConsPointer(); + + ConsPointer viewScalePointer = new ConsPointer(); + viewScalePointer.setCons(getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, resultPointer, viewScalePointer); + BigNumber viewScale = (BigNumber) resultPointer.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + LispError.checkArgument(aEnvironment, aStackTop, viewScale != null, 1, "ViewMath"); + + + + + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, resultPointer, new ConsPointer(head)); + + String texString = (String) resultPointer.car(); + texString = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, texString); + texString = texString.substring(1, texString.length()); + texString = texString.substring(0, texString.length() - 1); + + + + JFrame frame = new JFrame(); + Container contentPane = frame.getContentPane(); + frame.setBackground(Color.WHITE); + contentPane.setBackground(Color.WHITE); + + + + + /* + DebugGraphics.setFlashCount(10); + DebugGraphics.setFlashColor(Color.red); + DebugGraphics.setFlashTime(1000); + RepaintManager.currentManager(panel).setDoubleBufferingEnabled(false); + panel.setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION); + panel.setDebugGraphicsOptions(DebugGraphics.LOG_OPTION); + */ + + + + /* + //MathPiper built-in math viewer. + TexParser parser = new TexParser(); + SymbolBox sBoxExpression = parser.parse(texString); + JTabbedPane tabbedPane = new JTabbedPane(); + //Math viewer. + JPanel mathControllerPanel = new JPanel(); + mathControllerPanel.setLayout(new BorderLayout()); + MathPanel mathPanel = new MathPanel(sBoxExpression, viewScale.toDouble()); + MathPanelController mathPanelScaler = new MathPanelController(mathPanel, viewScale.toDouble()); + JScrollPane scrollPane = new JScrollPane(mathPanel,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + mathControllerPanel.add(scrollPane); + mathControllerPanel.add(mathPanelScaler, BorderLayout.NORTH); + tabbedPane.addTab("Math Form", null, mathControllerPanel, "Math expression viewer."); + //Tree viewer. + JPanel treeControllerPanel = new JPanel(); + treeControllerPanel.setLayout(new BorderLayout()); + TreePanel treePanel = new TreePanel(sBoxExpression,viewScale.toDouble()); + MathPanelController treePanelScaler = new MathPanelController(treePanel,viewScale.toDouble()); + JScrollPane treeScrollPane = new JScrollPane(treePanel,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + treeControllerPanel.add(treeScrollPane); + treeControllerPanel.add(treePanelScaler, BorderLayout.NORTH); + tabbedPane.addTab("Parse Tree", null, treeControllerPanel, "Parse tree viewer.."); + */ + + + + + + Box box = Box.createVerticalBox(); + + + + //JLatexMath + TeXFormula formula = new TeXFormula(texString); + JLabel latexLabel = new JLabel(); + JPanel latexPanelController = new LatexRenderingController(formula, latexLabel, 100); + + JPanel screenCapturePanel = new ScreenCapturePanel(); + + screenCapturePanel.add(latexLabel); + + JScrollPane jMathTexScrollPane = new JScrollPane(screenCapturePanel,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + jMathTexScrollPane.getViewport().setBackground(Color.WHITE); + box.add(jMathTexScrollPane); + + + //box.add(tabbedPane); //MathPiper's built-in math viewer. + + + contentPane.add(box); + + contentPane.add(latexPanelController, BorderLayout.NORTH); + + + frame.setAlwaysOnTop(false); + frame.setTitle("Math Viewer"); + frame.setSize(new Dimension(300, 200)); + frame.setResizable(true); + frame.setLocationRelativeTo(null); + + frame.pack(); + frame.setVisible(true); + + + //getTopOfStackPointer(aEnvironment, aStackTop).setCons(resultPointer.getCons()); //This use to print Latex code. + + JavaObject response = new JavaObject(frame); + + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, response)); + + }//end method. + + +}//end class. + + + + +/* +%mathpiper_docs,name="ViewMath",categories="User Functions;Built In;Visualization" +*CMD ViewMath --- display an expression in traditional form + +*CALL + ViewMath(expression) + +*Params +{expression} -- an expression to view + +*DESC +Display an expression in traditional form. + +*E.G. +In> ViewMath(Expand((2*x)*(x+3)*(x+4))); + +In> ViewMath(15*x^2 * Hold(Integrate(x,0,Infinity)Exp(-x^2))); + + + +/%mathpiper + +index := 1; + +expressionsList := {}; + +While(index <= 9) +[ + expressionsList := Append(expressionsList, RandomPoly(x,3,1,10)); + + index++; +]; + +matrix := Partition(expressionsList,3); + +ViewMath(matrix); + +/%/mathpiper + + + +The ViewXXX functions all return a reference to the Java JFrame windows which they are displayed in. +This JFrame instance can be used to hide, show, and dispose of the window. + +In> frame := ViewMath(x^2) +Result: javax.swing.JFrame + +In> JavaCall(frame, "hide") +Result: True + +In> JavaCall(frame, "show") +Result: True + +In> JavaCall(frame, "dispose") +Result: True + +*SEE ViewList, ViewLatex +%/mathpiper_docs +*/ + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewSimulator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewSimulator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/optional/ViewSimulator.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/optional/ViewSimulator.java 2010-02-09 09:09:05.000000000 +0000 @@ -33,7 +33,7 @@ public class ViewSimulator extends BuiltinFunction { - public void plugIn(Environment aEnvironment) + public void plugIn(Environment aEnvironment) throws Exception { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 0, BuiltinFunctionEvaluator.Fixed | BuiltinFunctionEvaluator.Function), @@ -44,7 +44,7 @@ { org.mathpiper.ui.gui.simulator.SimulatorFrame simulator = new org.mathpiper.ui.gui.simulator.SimulatorFrame(); JavaObject javaObject = new JavaObject(simulator); - aEnvironment.setGlobalVariable("Simulator", new ConsPointer(BuiltinObjectCons.getInstance(aEnvironment, javaObject)), false); + aEnvironment.setGlobalVariable(aStackTop, "Simulator", new ConsPointer( BuiltinObjectCons.getInstance(aEnvironment, aStackTop, javaObject)), false); Utility.putTrueInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/BarChart.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/BarChart.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/BarChart.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/BarChart.java 2010-02-09 09:09:05.000000000 +0000 @@ -45,7 +45,8 @@ private Map defaultOptions; - public void plugIn(Environment aEnvironment) { + public void plugIn(Environment aEnvironment) throws Exception + { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), "BarChart"); @@ -69,21 +70,21 @@ ConsPointer argumentsPointer = getArgumentPointer(aEnvironment, aStackTop, 1); - LispError.check(Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT, "BarChart"); - argumentsPointer.goSub(); //Go to sub list. + argumentsPointer.goSub(aStackTop, aEnvironment); //Go to sub list. - argumentsPointer.goNext(); //Strip List tag. + argumentsPointer.goNext(aStackTop, aEnvironment); //Strip List tag. - LispError.check(Utility.isList(argumentsPointer), LispError.NOT_A_LIST); + LispError.check(aEnvironment, aStackTop, Utility.isList(argumentsPointer), LispError.NOT_A_LIST, "BarChart"); ConsPointer dataListPointer = (ConsPointer) argumentsPointer.car(); //Grab the first member of the list. ConsPointer optionsPointer = (ConsPointer) argumentsPointer.cdr(); - Map userOptions = ChartUtility.optionsListToJavaMap(optionsPointer, defaultOptions); + Map userOptions = ChartUtility.optionsListToJavaMap(aEnvironment, aStackTop, optionsPointer, defaultOptions); - IntervalXYDataset dataSet = ChartUtility.listToIntervalXYDataset(dataListPointer, userOptions); + IntervalXYDataset dataSet = ChartUtility.listToIntervalXYDataset(aEnvironment, aStackTop, dataListPointer, userOptions); JFreeChart chart = ChartFactory.createXYBarChart( @@ -120,11 +121,70 @@ Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); return; } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment,new JavaObject(new ChartPanel(chart)))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, new JavaObject(new ChartPanel(chart)))); return; }//end if/else. }//end method. + }//end class. + + + + + + +/* +%mathpiper_docs,name="BarChart",categories="User Functions;Visualization" +*CMD BarChart --- displays a graphic bar chart +*CORE +*CALL + BarChart({x_axis_list, y_axis_list}, option, option, option...) + BarChart({x_axis_list_1, y_axis_list_1, x_axis_list_2, y_axis_list_2,...}, option, option, option...) + +*PARMS + +{x_axis_list} -- a list which contains the x axis values + +{y_axis_list} -- a list which contains the y axis values that go with the x axis values + +{title} -- the title of the scatter plot + +{xAxisLabel} -- the label for the x axis + +{yAxisLabel} -- the label for the y axis + +{seriesTitle} -- the title for a single data series + +{seriesTitle} -- the title for more than one series. can be 1, 2, 3, etc. + +*DESC + +Creates either a single bar chart or multiple bar charts on the same plot. Options are entered using the -> operator. +For example, here is how to set the {title} option: {title -> "Example Title"}. + +*E.G. +/%mathpiper,title="" + +claim := 1 .. 40; +days := {48,41,35,36,37,26,36,46,35,47,35,34,36,42,43,36,56,32,46,30,37,43,17,26,28,27,45,33,22,27,16,22,33,30,24,23,22,30,31,17}; +BarChart({claim, days}, title -> "Bar Chart", series1Title -> "Series 1", xAxisLabel -> "Claim", yAxisLabel -> "Days"); + +/%/mathpiper + + +/%mathpiper,title="" + +claim := 1 .. 40; +days1 := {48,41,35,36,37,26,36,46,35,47,35,34,36,42,43,36,56,32,46,30,37,43,17,26,28,27,45,33,22,27,16,22,33,30,24,23,22,30,31,17}; +days2 := RandomIntegerVector(Length(claim), 20, 50); +BarChart({claim, days1, claim, days2}, title -> "Bar Chart", series1Title -> "Series 1", series2Title -> "Series 2", xAxisLabel -> "Claim", yAxisLabel -> "Days"); + +/%/mathpiper + + +%/mathpiper_docs +*/ + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/ChartUtility.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/ChartUtility.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/ChartUtility.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/ChartUtility.java 2010-02-06 21:01:49.000000000 +0000 @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.jfree.chart.plot.PlotOrientation; @@ -27,20 +26,19 @@ import org.jfree.data.xy.DefaultXYDataset; import org.jfree.data.xy.IntervalXYDataset; import org.jfree.data.xy.XYBarDataset; -import org.mathpiper.builtin.BigNumber; import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.Utility; import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.NumberCons; public class ChartUtility { - public static Map optionsListToJavaMap(ConsPointer argumentsPointer, Map defaultOptions) throws Exception { + public static Map optionsListToJavaMap(Environment aEnvironment, int aStackTop, ConsPointer argumentsPointer, Map defaultOptions) throws Exception { - Map userOptions = Utility.optionsListToJavaMap(argumentsPointer, defaultOptions); + Map userOptions = Utility.optionsListToJavaMap(aEnvironment, aStackTop, argumentsPointer, defaultOptions); if (userOptions.containsKey("orientation")) { @@ -58,18 +56,18 @@ - public static HistogramDataset listToHistogramDataset(ConsPointer dataListPointer, Map userOptions) throws Exception { + public static HistogramDataset listToHistogramDataset(Environment aEnvironment, int aStackTop, ConsPointer dataListPointer, Map userOptions) throws Exception { HistogramDataset dataSet = new HistogramDataset(); - if (Utility.isNestedList(dataListPointer)) { + if (Utility.isNestedList(aEnvironment, aStackTop, dataListPointer)) { List dataSeriesList = new ArrayList(); List seriesTotalList = new ArrayList(); - dataListPointer.goNext(); //Strip List tag. + dataListPointer.goNext(aStackTop, aEnvironment); //Strip List tag. int seriesIndex = 1; while (dataListPointer.getCons() != null) { - double[] dataValues = JavaObject.LispListToJavaDoubleArray((ConsPointer) dataListPointer.car()); + double[] dataValues = JavaObject.lispListToJavaDoubleArray(aEnvironment, aStackTop, (ConsPointer) dataListPointer.car()); String seriesTitle = ""; if (userOptions.containsKey("series" + seriesIndex + "Title")) { seriesTitle = (String) userOptions.get("series" + seriesIndex + "Title"); @@ -81,7 +79,7 @@ seriesTotalList.add(dataValues[index++]); }//end while seriesIndex++; - dataListPointer.goNext(); + dataListPointer.goNext(aStackTop, aEnvironment); }//end while. double minimumValue = Double.MAX_VALUE; @@ -117,7 +115,7 @@ }//end if. - double[] dataValues = JavaObject.LispListToJavaDoubleArray(dataListPointer); + double[] dataValues = JavaObject.lispListToJavaDoubleArray(aEnvironment, aStackTop, dataListPointer); Double binMinimum = (Double) userOptions.get("binMinimum"); @@ -137,9 +135,9 @@ }//end method. - public static XYBarDataset listToCumulativeDataset(ConsPointer dataListPointer, Map userOptions) throws Exception { + public static XYBarDataset listToCumulativeDataset(Environment aEnvironment, int aStackTop, ConsPointer dataListPointer, Map userOptions) throws Exception { - LispError.check(!Utility.isNestedList(dataListPointer), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, !Utility.isNestedList(aEnvironment, aStackTop, dataListPointer), LispError.INVALID_ARGUMENT, "ChartUtility"); int numberOfBins = 15; @@ -150,7 +148,7 @@ }//end if. - double[] dataValues = JavaObject.LispListToJavaDoubleArray(dataListPointer); + double[] dataValues = JavaObject.lispListToJavaDoubleArray(aEnvironment, aStackTop, dataListPointer); Arrays.sort(dataValues); @@ -218,30 +216,30 @@ - public static DefaultXYDataset listToXYDataset(ConsPointer dataListPointer, Map userOptions) throws Exception { + public static DefaultXYDataset listToXYDataset(Environment aEnvironment, int aStackTop, ConsPointer dataListPointer, Map userOptions) throws Exception { - LispError.check(Utility.isNestedList(dataListPointer), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, Utility.isNestedList(aEnvironment, aStackTop, dataListPointer), LispError.INVALID_ARGUMENT, "ChartUtility"); DefaultXYDataset dataSet = new DefaultXYDataset(); - dataListPointer.goNext(); //Strip List tag. + dataListPointer.goNext(aStackTop, aEnvironment); //Strip List tag. int seriesIndex = 1; while (dataListPointer.getCons() != null) { - double[] dataXValues = JavaObject.LispListToJavaDoubleArray((ConsPointer) dataListPointer.car()); - dataListPointer.goNext(); - double[] dataYValues = JavaObject.LispListToJavaDoubleArray((ConsPointer) dataListPointer.car()); + double[] dataXValues = JavaObject.lispListToJavaDoubleArray(aEnvironment, aStackTop, (ConsPointer) dataListPointer.car()); + dataListPointer.goNext(aStackTop, aEnvironment); + double[] dataYValues = JavaObject.lispListToJavaDoubleArray(aEnvironment, aStackTop, (ConsPointer) dataListPointer.car()); String seriesTitle = "series" + seriesIndex; if (userOptions.containsKey("series" + seriesIndex + "Title")) { seriesTitle = (String) userOptions.get("series" + seriesIndex + "Title"); } - LispError.check(dataXValues.length == dataYValues.length, LispError.LIST_LENGTHS_MUST_BE_EQUAL); + LispError.check(aEnvironment, aStackTop, dataXValues.length == dataYValues.length, LispError.LIST_LENGTHS_MUST_BE_EQUAL, "ChartUtility"); dataSet.addSeries(seriesTitle, new double[][]{dataXValues, dataYValues}); seriesIndex++; - dataListPointer.goNext(); + dataListPointer.goNext(aStackTop, aEnvironment); }//end while. @@ -251,12 +249,12 @@ - public static IntervalXYDataset listToIntervalXYDataset(ConsPointer dataListPointer, Map userOptions) throws Exception { + public static IntervalXYDataset listToIntervalXYDataset(Environment aEnvironment, int aStackTop, ConsPointer dataListPointer, Map userOptions) throws Exception { - DefaultXYDataset xYDataset = listToXYDataset(dataListPointer, userOptions); + DefaultXYDataset xYDataset = listToXYDataset(aEnvironment, aStackTop, dataListPointer, userOptions); int seriesCount = xYDataset.getSeriesCount(); - LispError.check(seriesCount != 0, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, seriesCount != 0, LispError.INVALID_ARGUMENT, "ChartUtility"); //int seriesItemCount = xYDataset.getItemCount(0); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/CumulativePlot.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/CumulativePlot.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/CumulativePlot.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/CumulativePlot.java 2010-02-09 09:09:05.000000000 +0000 @@ -45,7 +45,8 @@ private Map defaultOptions; - public void plugIn(Environment aEnvironment) { + public void plugIn(Environment aEnvironment) throws Exception + { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), "CumulativePlot"); @@ -69,22 +70,22 @@ ConsPointer argumentsPointer = getArgumentPointer(aEnvironment, aStackTop, 1); - LispError.check(Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT, "CumulativePlot"); - argumentsPointer.goSub(); //Go to sub list. + argumentsPointer.goSub(aStackTop, aEnvironment); //Go to sub list. - argumentsPointer.goNext(); //Strip List tag. + argumentsPointer.goNext(aStackTop, aEnvironment); //Strip List tag. - LispError.check(Utility.isList(argumentsPointer), LispError.NOT_A_LIST); + LispError.check(aEnvironment, aStackTop, Utility.isList(argumentsPointer), LispError.NOT_A_LIST, "CumulativePlot"); ConsPointer dataListPointer = (ConsPointer) argumentsPointer.car(); //Grab the first member of the list. ConsPointer optionsPointer = (ConsPointer) argumentsPointer.cdr(); - Map userOptions = ChartUtility.optionsListToJavaMap(optionsPointer, defaultOptions); + Map userOptions = ChartUtility.optionsListToJavaMap(aEnvironment, aStackTop, optionsPointer, defaultOptions); - IntervalXYDataset dataSet = ChartUtility.listToCumulativeDataset(dataListPointer, userOptions); + IntervalXYDataset dataSet = ChartUtility.listToCumulativeDataset(aEnvironment, aStackTop, dataListPointer, userOptions); //createXYBarChart(java.lang.String title, java.lang.String xAxisLabel, boolean dateAxis, java.lang.String yAxisLabel, IntervalXYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) @@ -120,11 +121,69 @@ Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); return; } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment,new JavaObject(new ChartPanel(chart)))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, new JavaObject(new ChartPanel(chart)))); return; }//end if/else. }//end method. + }//end class. + + + + + + +/* +%mathpiper_docs,name="CumulativePlot",categories="User Functions;Visualization" +*CMD CumulativePlot --- displays a graphic cumulative plot +*CORE +*CALL + CumulativePlot(list, option, option, option...) + +*PARMS + +{list} -- a list which contains the values + +{numberOfBins} -- the number of bins in the histogram + +{title} -- the title of the histogram + +{xAxisLabel} -- the label for the x axis + +{yAxisLabel} -- the label for the y axis + +{seriesTitle} -- the title for a single data series + + +*DESC + +Creates a cumulative plot. Options are entered using the -> operator. +For example, here is how to set the {title} option: {title -> "Example Title"}. + +*E.G. +/%mathpiper,title="" + +samples := { +438,413,444,468,445,472,474,454,455,449, +450,450,450,459,466,470,457,441,450,445, +487,430,446,450,456,433,455,459,423,455, +451,437,444,453,434,454,448,435,432,441, +452,465,466,473,471,464,478,446,459,464, +441,444,458,454,437,443,465,435,444,457, +444,471,471,458,459,449,462,460,445,437, +461,453,452,438,445,435,454,428,454,434, +432,431,455,447,454,435,425,449,449,452, +471,458,445,463,423,451,440,442,441,439 +}; + +CumulativePlot(samples,numberOfBins -> 10, title -> "Cumulative Plot", xAxisLabel -> "X Axis", yAxisLabel -> "Y Axis", seriesTitle -> "Series Title"); + +/%/mathpiper + + +%/mathpiper_docs +*/ + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/Histogram.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/Histogram.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/Histogram.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/Histogram.java 2010-02-09 09:09:05.000000000 +0000 @@ -47,7 +47,8 @@ private Map defaultOptions; - public void plugIn(Environment aEnvironment) { + public void plugIn(Environment aEnvironment) throws Exception + { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), "Histogram"); @@ -71,23 +72,23 @@ ConsPointer argumentsPointer = getArgumentPointer(aEnvironment, aStackTop, 1); - LispError.check(Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT, "Histogram"); - argumentsPointer.goSub(); //Go to sub list. + argumentsPointer.goSub(aStackTop, aEnvironment); //Go to sub list. - argumentsPointer.goNext(); //Strip List tag. + argumentsPointer.goNext(aStackTop, aEnvironment); //Strip List tag. - LispError.check(Utility.isList(argumentsPointer), LispError.NOT_A_LIST); + LispError.check(aEnvironment, aStackTop, Utility.isList(argumentsPointer), LispError.NOT_A_LIST, "Histogram"); ConsPointer dataListPointer = (ConsPointer) argumentsPointer.car(); //Grab the first member of the list. ConsPointer optionsPointer = (ConsPointer) argumentsPointer.cdr(); - Map userOptions = ChartUtility.optionsListToJavaMap(optionsPointer, defaultOptions); + Map userOptions = ChartUtility.optionsListToJavaMap(aEnvironment, aStackTop, optionsPointer, defaultOptions); - HistogramDataset dataSet = ChartUtility.listToHistogramDataset(dataListPointer, userOptions); + HistogramDataset dataSet = ChartUtility.listToHistogramDataset(aEnvironment, aStackTop, dataListPointer, userOptions); JFreeChart chart = ChartFactory.createHistogram( (String) userOptions.get("title"), //title. @@ -118,11 +119,97 @@ Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); return; } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment,new JavaObject(new ChartPanel(chart)))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, new JavaObject(new ChartPanel(chart)))); return; }//end if/else. }//end method. + }//end class. + + + + +/* +%mathpiper_docs,name="Histogram",categories="User Functions;Visualization" +*CMD Histogram --- displays a graphic histogram +*CORE +*CALL + Histogram(list, option, option, option...) + Histogram({list1, list2, list3...}, option, option, option...) + +*PARMS + +{list} -- a list which contains the values + +{list1, list2, list3...} -- the data for multiple histograms is passed in as a list of lists + +{binMinimum} -- the minimum bin value + +{binMaximum} -- the maximum bin value + +{numberOfBins} -- the number of bins in the histogram + +{title} -- the title of the histogram + +{xAxisLabel} -- the label for the x axis + +{yAxisLabel} -- the label for the y axis + +{seriesTitle} -- the title for a single data series + +{seriesTitle} -- the title for more than one series. can be 1, 2, 3, etc. + +*DESC + +Creates either a single histogram or multiple histograms on the same plot. Options are entered using the -> operator. +For example, here is how to set the {title} option: {title -> "Example Title"}. + +*E.G. +/%mathpiper + +Histogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}); + +/%/mathpiper + + +/%mathpiper + +Histogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0, 4.2}, seriesTitle -> "Options Example", xAxisLabel -> "X Axis", yAxisLabel -> "Y Axis"); + +/%/mathpiper + + +/%mathpiper + +Histogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0, 4.2}, orientation -> "horizontal"); + +/%/mathpiper + + +/%mathpiper,title="" + +pileESamples := {16.375,16.375,17.125,16,14.375,17.25,16.625,16,17,17.25,17,15.875,16.625,16.125,17.125,16.875,16.375,16.375,16.875,17.125,17,16.75,17.25,17.125,15.375}; +pileDSamples := {18.25,19.25,18.25,15.625,17.625,17.5,17.125,17.125,17.5,14.5,17.375,16.875,17.75,18.875,14.875,19.25,18.125,16.25,16.125,16.75,17.25,17.375,17.125,17.5,16.625}; + +Histogram({pileDSamples, pileESamples}, title -> "Wood Piles", series1Title -> "Pile D", series2Title -> "Pile E"); + +/%/mathpiper + + +/%mathpiper,title="" + +numberOfRoles := 1000; + +dieRolesList := RandomIntegerVector(numberOfRoles,1,6); + +Histogram(dieRolesList, binMinimum -> .5, binMaximum -> 6.5, numberOfBins -> 6, title -> "Single Die Rolls", xAxisLabel -> "Number Rolled", yAxisLabel -> "Frequency", seriesTitle -> String(numberOfRoles) : " Roles"); + +/%/mathpiper + + +%/mathpiper_docs +*/ + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/LineChart.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/LineChart.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/LineChart.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/LineChart.java 2010-02-09 09:09:05.000000000 +0000 @@ -45,7 +45,8 @@ private Map defaultOptions; - public void plugIn(Environment aEnvironment) { + public void plugIn(Environment aEnvironment) throws Exception + { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), "LineChart"); @@ -69,21 +70,21 @@ ConsPointer argumentsPointer = getArgumentPointer(aEnvironment, aStackTop, 1); - LispError.check(Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT, "LineChart"); - argumentsPointer.goSub(); //Go to sub list. + argumentsPointer.goSub(aStackTop, aEnvironment); //Go to sub list. - argumentsPointer.goNext(); //Strip List tag. + argumentsPointer.goNext(aStackTop, aEnvironment); //Strip List tag. - LispError.check(Utility.isList(argumentsPointer), LispError.NOT_A_LIST); + LispError.check(aEnvironment, aStackTop, Utility.isList(argumentsPointer), LispError.NOT_A_LIST, "LineChart"); ConsPointer dataListPointer = (ConsPointer) argumentsPointer.car(); //Grab the first member of the list. ConsPointer optionsPointer = (ConsPointer) argumentsPointer.cdr(); - Map userOptions = ChartUtility.optionsListToJavaMap(optionsPointer, defaultOptions); + Map userOptions = ChartUtility.optionsListToJavaMap(aEnvironment, aStackTop, optionsPointer, defaultOptions); - IntervalXYDataset dataSet = ChartUtility.listToIntervalXYDataset(dataListPointer, userOptions); + IntervalXYDataset dataSet = ChartUtility.listToIntervalXYDataset(aEnvironment, aStackTop, dataListPointer, userOptions); JFreeChart chart = ChartFactory.createXYLineChart( @@ -117,11 +118,68 @@ Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); return; } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment,new JavaObject(new ChartPanel(chart)))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, new JavaObject(new ChartPanel(chart)))); return; }//end if/else. }//end method. + }//end class. + + + + + +/* +%mathpiper_docs,name="LineChart",categories="User Functions;Visualization" +*CMD LineChart --- displays a graphic line chart +*CORE +*CALL + LineChart({domain_list, range_list}, option, option, option...) + LineChart({domain_list_1, range_list_1, domain_list_2, range_list_2,...}, option, option, option...) + +*PARMS + +{domain_list} -- a list which contains the domain values + +{range_list} -- a list which contains the range values that go with the domain_list values + +{title} -- the title of the line chart + +{xAxisLabel} -- the label for the x axis + +{yAxisLabel} -- the label for the y axis + +{seriesTitle} -- the title for a single data series + +{seriesTitle} -- the title for more than one series. can be 1, 2, 3, etc. + +*DESC + +Creates either a single line chart or multiple line charts on the same plot. Options are entered using the -> operator. +For example, here is how to set the {title} option: {title -> "Example Title"}. + +*E.G. +/%mathpiper,title="" + +claim := 1 .. 40; +days := {48,41,35,36,37,26,36,46,35,47,35,34,36,42,43,36,56,32,46,30,37,43,17,26,28,27,45,33,22,27,16,22,33,30,24,23,22,30,31,17}; +LineChart({claim, days}, title -> "Line Chart", series1Title -> "Series 1", xAxisLabel -> "Claim", yAxisLabel -> "Days"); + +/%/mathpiper + + +/%mathpiper,title="" + +claim := 1 .. 40; +days1 := {48,41,35,36,37,26,36,46,35,47,35,34,36,42,43,36,56,32,46,30,37,43,17,26,28,27,45,33,22,27,16,22,33,30,24,23,22,30,31,17}; +days2 := RandomIntegerVector(Length(claim), 20, 50); +LineChart({claim, days1, claim, days2}, title -> "Line Chart", series1Title -> "Series 1", series2Title -> "Series 2", xAxisLabel -> "Claim", yAxisLabel -> "Days"); + +/%/mathpiper + + +%/mathpiper_docs +*/ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/ScatterPlot.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/ScatterPlot.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/functions/plugins/jfreechart/ScatterPlot.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/functions/plugins/jfreechart/ScatterPlot.java 2010-02-09 09:09:05.000000000 +0000 @@ -42,7 +42,8 @@ private Map defaultOptions; - public void plugIn(Environment aEnvironment) { + public void plugIn(Environment aEnvironment) throws Exception + { aEnvironment.getBuiltinFunctions().setAssociation( new BuiltinFunctionEvaluator(this, 1, BuiltinFunctionEvaluator.Variable | BuiltinFunctionEvaluator.Function), "ScatterPlot"); @@ -65,21 +66,21 @@ ConsPointer argumentsPointer = getArgumentPointer(aEnvironment, aStackTop, 1); - LispError.check(Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, Utility.isSublist(argumentsPointer), LispError.INVALID_ARGUMENT, "ScatterPlot"); - argumentsPointer.goSub(); //Go to sub list. + argumentsPointer.goSub(aStackTop, aEnvironment); //Go to sub list. - argumentsPointer.goNext(); //Strip List tag. + argumentsPointer.goNext(aStackTop, aEnvironment); //Strip List tag. - LispError.check(Utility.isList(argumentsPointer), LispError.NOT_A_LIST); + LispError.check(aEnvironment, aStackTop, Utility.isList(argumentsPointer), LispError.NOT_A_LIST, "ScatterPlot"); ConsPointer dataListPointer = (ConsPointer) argumentsPointer.car(); //Grab the first member of the list. ConsPointer optionsPointer = (ConsPointer) argumentsPointer.cdr(); - Map userOptions = ChartUtility.optionsListToJavaMap(optionsPointer, defaultOptions); + Map userOptions = ChartUtility.optionsListToJavaMap(aEnvironment, aStackTop, optionsPointer, defaultOptions); - XYDataset dataSet = ChartUtility.listToXYDataset(dataListPointer, userOptions); + XYDataset dataSet = ChartUtility.listToXYDataset(aEnvironment, aStackTop, dataListPointer, userOptions); JFreeChart chart = ChartFactory.createScatterPlot( (String) userOptions.get("title"), //title. @@ -111,11 +112,68 @@ Utility.putFalseInPointer(aEnvironment, getTopOfStackPointer(aEnvironment, aStackTop)); return; } else { - getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment,new JavaObject(new ChartPanel(chart)))); + getTopOfStackPointer(aEnvironment, aStackTop).setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, new JavaObject(new ChartPanel(chart)))); return; }//end if/else. }//end method. + }//end class. + + + + +/* +%mathpiper_docs,name="ScatterPlot",categories="User Functions;Visualization" +*CMD ScatterPlot --- displays a graphic scatter plot +*CORE +*CALL + ScatterPlot({domain_list, range_list}, option, option, option...) + ScatterPlot({domain_list_1, range_list_1, domain_list_2, range_list_2,...}, option, option, option...) + +*PARMS + +{domain_list} -- a list which contains the domain values + +{range_list} -- a list which contains the range values that go with the domain_list values + +{title} -- the title of the scatter plot + +{xAxisLabel} -- the label for the x axis + +{yAxisLabel} -- the label for the y axis + +{seriesTitle} -- the title for a single data series + +{seriesTitle} -- the title for more than one series. can be 1, 2, 3, etc. + +*DESC + +Creates either a single scatter plot or multiple scatter plots on the same plot. Options are entered using the -> operator. +For example, here is how to set the {title} option: {title -> "Example Title"}. + +*E.G. +/%mathpiper,title="" + +claim := 1 .. 40; +days := {48,41,35,36,37,26,36,46,35,47,35,34,36,42,43,36,56,32,46,30,37,43,17,26,28,27,45,33,22,27,16,22,33,30,24,23,22,30,31,17}; +ScatterPlot({claim, days}, title -> "Scatter Plot", series1Title -> "Series 1", xAxisLabel -> "Claim", yAxisLabel -> "Days"); + +/%/mathpiper + + +/%mathpiper,title="" + +claim := 1 .. 40; +days1 := {48,41,35,36,37,26,36,46,35,47,35,34,36,42,43,36,56,32,46,30,37,43,17,26,28,27,45,33,22,27,16,22,33,30,24,23,22,30,31,17}; +days2 := RandomIntegerVector(Length(claim), 20, 50); +ScatterPlot({claim, days1, claim, days2}, title -> "Scatter Plot", series1Title -> "Series 1", series2Title -> "Series 2", xAxisLabel -> "Claim", yAxisLabel -> "Days"); + +/%/mathpiper + + +%/mathpiper_docs +*/ + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/JavaObject.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/JavaObject.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/JavaObject.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/JavaObject.java 2010-04-09 07:43:02.000000000 +0000 @@ -21,9 +21,9 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.Cons; import org.mathpiper.lisp.cons.ConsPointer; public class JavaObject extends BuiltinContainer { @@ -34,194 +34,8 @@ this.javaObject = javaObject; } - public String send(ArgumentList aArgList) { - return null; - } - - // Narrow a type from String to the - // narrowest possible type - public static Object narrow(Object argument) { - //System.out.println("XXXXXXX argstring: " + argstring); - if (argument instanceof String) { - - String argstring = (String) argument; - // Try integer - try { - return Integer.valueOf(argstring); - } catch (NumberFormatException nfe) { - } - - // Try double - try { - return Double.valueOf(argstring); - } catch (NumberFormatException nfe) { - } - - // Try boolean - if (argstring.equalsIgnoreCase("true")) { - return Boolean.TRUE; - } else if (argstring.equalsIgnoreCase("false")) { - return Boolean.FALSE; - } - - // Try null - if (argstring.equals("null")) { - return null; - } - - //Try class - try { - Object clas = Class.forName(argstring); - return clas; - } catch (ClassNotFoundException cnfe) { - } - }//end if - - // Give up -- it's a string - return argument; - } - - // Narrow the the arguments - public static Object[] narrow(Object argstrings[]) { - Object narrowed[] = new Object[argstrings.length]; - - for (int i = 0; i < narrowed.length; ++i) { - narrowed[i] = narrow(argstrings[i]); - } - - return narrowed; - } - - // Get an array of the types of the give - // array of objects - public static Class[] getTypes(Object objs[]) { - Class types[] = new Class[objs.length]; - - for (int i = 0; i < objs.length; ++i) { - - if (objs[i] == null) { - //types[i] = Class.forName("java.awt.Component"); - try { - types[i] = Class.forName("java.awt.Component"); - - } catch (ClassNotFoundException cnfe) { - } - } else { - types[i] = objs[i].getClass(); - - // Convert wrapper types (like Double) - // to primitive types (like double) - - if (types[i] == Double.class) { - types[i] = double.class; - } - if (types[i] == Integer.class) { - types[i] = int.class; - } - - if (types[i] == Boolean.class) { - types[i] = boolean.class; - } - - }//end if. - }//end for. - - return types; - } - - public static JavaObject instantiate(String className, Object[] parameters) throws Exception { - - // Narrow the arguments - Object args[] = narrow(parameters); - Class types[] = getTypes(args); - - try { - // Find the specified class - Class clas = Class.forName(className); - - Constructor constructor = clas.getConstructor(types); - - Object newObject = constructor.newInstance(args); - - JavaObject newObjectWrapper = new JavaObject(newObject); - - return newObjectWrapper; - - } catch (ClassNotFoundException cnfe) { - throw new Exception( - "Can't find class " + className); - } catch (InstantiationException nsme) { - throw new Exception( - "Can't instantiate " + className); - } catch (IllegalAccessException iae) { - throw new Exception( - "Not allowed to instantiate " + className); - } catch (InvocationTargetException ite) { - // If the method itself throws an exception, we want to save it - throw (Exception) new Exception( - "Exception while executing command").initCause(ite); - }//end catch. - } - - public JavaObject execute(String methodName, Object parameters[]) throws Exception { - - - String className = javaObject.getClass().getName(); - - try { - Class clas; - if (className.equals("java.lang.Class")) { - clas = (Class) this.javaObject; - className = clas.getName(); - } else { - clas = Class.forName(className); - } - - - // Narrow the arguments - Object args[] = narrow(parameters); - Class types[] = getTypes(args); - - - - - - /* - System.out.println("XXXXX " + methodName); - for(Object ob:types) - { - System.out.println("XXXXX " + ob.toString()); - } - */ - - // Find the specified method - - Method method = clas.getMethod(methodName, types); - - // Invoke the method on the narrowed arguments - Object retval = method.invoke(javaObject, args); - - return new JavaObject(retval); - - } catch (ClassNotFoundException cnfe) { - throw new Exception( - "Can't find class " + className); - } catch (NoSuchMethodException nsme) { - throw new Exception( - "Can't find method " + methodName + " in " + className); - } catch (IllegalAccessException iae) { - throw new Exception( - "Not allowed to call method " + methodName + " in " + className); - } catch (InvocationTargetException ite) { - // If the method itself throws an exception, we want to save it - throw (Exception) new Exception( - "Exception while executing command").initCause(ite); - }//end catch. - - }//end class - public String typeName() { return javaObject.getClass().getName(); }//end method. @@ -231,20 +45,21 @@ return javaObject; }//end method. - public static List LispListToJavaList(ConsPointer lispList) throws Exception { - LispError.check(Utility.isList(lispList), LispError.NOT_A_LIST); + + public static List lispListToJavaList(Environment aEnvironment, int aStackTop,ConsPointer lispList) throws Exception { + LispError.check(aEnvironment, aStackTop, Utility.isList(lispList), LispError.NOT_A_LIST, "INTERNAL"); - lispList.goNext(); + lispList.goNext(aStackTop, aEnvironment); ArrayList javaList = new ArrayList(); while (lispList.getCons() != null) { Object item = lispList.car(); - item = narrow(item); + //item = narrow(item); javaList.add(item); - lispList.goNext(); + lispList.goNext(aStackTop, aEnvironment); }//end while. @@ -252,29 +67,28 @@ }//end method. + public static double[] lispListToJavaDoubleArray(Environment aEnvironment, int aStackTop, ConsPointer lispListPointer) throws Exception { + LispError.check(aEnvironment, aStackTop, Utility.isList(lispListPointer), LispError.NOT_A_LIST, "INTERNAL"); - public static double[] LispListToJavaDoubleArray(ConsPointer lispListPointer) throws Exception { - LispError.check(Utility.isList(lispListPointer), LispError.NOT_A_LIST); - - lispListPointer.goNext(); //Remove List designator. + lispListPointer.goNext(aStackTop, aEnvironment); //Remove List designator. - double[] values = new double[Utility.listLength(lispListPointer)]; + double[] values = new double[Utility.listLength(aEnvironment, aStackTop, lispListPointer)]; int index = 0; while (lispListPointer.getCons() != null) { Object item = lispListPointer.car(); - LispError.check(item instanceof String, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, item instanceof String, LispError.INVALID_ARGUMENT, "INTERNAL"); String itemString = (String) item; try { values[index++] = Double.parseDouble(itemString); } catch (NumberFormatException nfe) { - LispError.raiseError("Can not convert into a double." ); + LispError.raiseError("Can not convert into a double." , "INTERNAL", aStackTop, aEnvironment); }//end try/catch. - lispListPointer.goNext(); + lispListPointer.goNext(aStackTop, aEnvironment); }//end while. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/E.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/E.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/E.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/E.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,48 @@ +package org.mathpiper.builtin.javareflection; + +import org.mathpiper.lisp.LispError; + + +/** + Error routines. +**/ + +public class E { + + /** Throw an error message with an associated object. **/ + public static Object error(String message, Object x) throws Exception { + //throw new SchemeException(message,x); + LispError.raiseError(message, "", -2, null); + return null; + } + + + public static Object error(String message) throws Exception{ + return error(message,null); + } + + /** Call error, complaining that we got the wrong type. **/ + public static Object typeError(String type, Object x) throws Exception{ + return error("expected object of type " + type + ", but got: ", x); + } + + /** Print a warning. **/ + public static Object warn(String message) { + //Scheme.currentEvaluator().getError().println("** WARNING: " + message); + return message; + } + + /** Print a warning. **/ + public static Object warn(String message, Object x) { + return warn(message + shortStringify(x)); + } + + /** It's nice to get an error, but not one large enough to choke EMACS. **/ + public static String shortStringify(Object x) { + //String s = U.stringify(x); + //if (s.length() > 1000) return s.substring(0,1000) + "..."; + //return s; todo:tk. + return ""; + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Importer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Importer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Importer.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Importer.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,8 @@ +package org.mathpiper.builtin.javareflection; + +/** Used by Import. One for each (import) expression. **/ +public interface Importer { + public Class classNamed(String name); + public void reset(); +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Import.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Import.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Import.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Import.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,212 @@ +package org.mathpiper.builtin.javareflection; + +/** + Class importing. + + @author Ken R. Anderson, Copyright 2000, kanderso@bbn.com,
license + subsequently modified by Jscheme project members + licensed under zlib licence (see license.txt) + +

Import provides support for Scheme's (import) + procedure. It is roughly like Java's import statement, with + important differences described below. + +

(import) can be used to import a single class, such as: +

+   (import "java.util.Date")
+   
+ + Or all the classes of a package using the wildcard "*": + +
+   (import "java.util.*")
+   
+ +

However, using wildcard imports is not recommend + (deprecated) for the following reasons: + +

    + +
  • Class name lookup using wildcards requires generating class names + that do not exits. While this is fast for an application, it can + take about a second for each lookup in an applet. + +
  • Conflicts between imports are identified at (import) time, + rather than later in runtime. +
+ +**/ +import java.util.Hashtable; +import java.util.Vector; +import java.util.Enumeration; + +public class Import { + + private static ClassLoader CLASSLOADER = Import.class.getClassLoader(); + static { + try { + Thread.currentThread().setContextClassLoader + (Import.class.getClassLoader());} + catch (Exception e) {;} + } + + /** Get the ClassLoader used to look up classes. **/ + public static synchronized ClassLoader getClassLoader() { + return CLASSLOADER; + } + /** Set the ClassLoader used to look up classes. **/ + public static synchronized void setClassLoader(ClassLoader cl) { + CLASSLOADER = cl; + Thread.currentThread().setContextClassLoader(cl); + } + + /** + Fields singles and wilds should be HashSets which won't exist + until JDK 1.2. So we simulate them with Vectors, which existed + since JDK 1.0. + **/ + public static final Vector singles = new Vector(50); + public static final Vector wilds = new Vector(50); + public static final Hashtable table = new Hashtable (200); + + // KRA 17AUG01: Eventually add these as singles and wilds. + static { + addImport("java.lang.Object"); + addImport("java.lang.*"); + addImport("java.lang.reflect.*"); + addImport("java.util.*"); + addImport("jsint.*"); + } + + /** Add an import, clearing the cache if it's wild. **/ + public static synchronized void addImport(String name) { + // System.out.println("addImport: " + name); + if (name.endsWith("*")) { + addNew(wilds, new WildImporter(name)); + table.clear(); + } else addNew(singles, new SingleImporter(name)); + } + + /* Use Vector to simulate a HashSet. */ + private static void addNew(Vector v, Object x) { + if (x != null &&!v.contains(x)) v.addElement(x); + } + + /** + Find a Class named name either relative to imports, or + absolute, or error. Names of the form $name are + interpreted as absolute specifications for package-less classes + for historical reasons. + **/ + public static Class classNamed(String name) throws Exception { + Class c = maybeClassNamed(name); + return (c == null) ? + (Class) E.error("Can't find class " + name + "."): + c; + } + + /** Returns a class or return null. **/ + public static synchronized Class maybeClassNamed(String name) throws Exception { + Class c = ((Class) table.get(name)); // Cached? + if (c != null) return c; + c = classNamedLookup(name); + if (c != null) table.put(name, c); + return c; + } + + private static Class classNamedLookup(String name) throws Exception { + if (name.endsWith("[]")) + return classNamedArray(name.substring(0, name.length() - "[]".length())); + Class c = classNamedImported(name); + if (c != null) return c; + return primitiveClassNamed(name); + } + + /** + Search for class named name looking in singles. + Search packageless classes and wilds only if necessary. + **/ + private static Class classNamedImported(String name) { + Vector classes = find(singles, name, new Vector(5)); + if (name.lastIndexOf(".") == -1) { // No package prefix. + if (classes.size() == 0) classes = classNamedNoPackage(name, classes); + if (classes.size() == 0) classes = find(wilds, name, classes); + } else addNew(classes, Import.forName(name)); + return returnClass(name, classes); + } + + private static Class returnClass(String name, Vector classes) { + int L = classes.size(); + if (L == 0) return null; + if (L == 1) return ((Class) classes.elementAt(0)); + else + return ((Class) E.warn("Class " + name + " is ambiguous " + classes + + " choosing " + ((Class) classes.elementAt(0)))); + } + + private static Vector classNamedNoPackage(String name, Vector classes) { + addNew(classes, Import.forName((name.startsWith("$")) + ? name.substring(1,name.length()) + : name)); + return classes; + } + + public static Vector find(Vector imports, String name, Vector classes) { + Enumeration is = imports.elements(); + while (is.hasMoreElements()) + addNew(classes, ((Importer) is.nextElement()).classNamed(name)); + return classes; + } + + /** name is the name of the component class. **/ + private static Class classNamedArray(String name) throws Exception { + Class c = classNamed(name); + if (c.isPrimitive()) return classNamedArrayPrimitive(c); + if (c.isArray()) return Import.forName("[" + c.getName()); + else return Import.forName("[L" + c.getName() + ";"); + } + + /** Ask the ClassLoader for a class given its full name. **/ + public static Class forName(String name) { + ClassLoader loader = getClassLoader(); + if (loader == null) + try { return Class.forName(name);} + catch (ClassNotFoundException e) { return null;} + else + try { return loader.loadClass(name); } + catch (ClassNotFoundException e) { return null; } + // KRA 28JUN00: Renu found this! + catch (NoClassDefFoundError e) { return null; } + } + + /** Class.forName() doesn't work for primitive types. **/ + private static Class primitiveClassNamed(String name) { + return + name.equals("void") ? Void.TYPE : + name.equals("boolean") ? Boolean.TYPE : + name.equals("byte") ? Byte.TYPE : + name.equals("char") ? Character.TYPE : + name.equals("short") ? Short.TYPE : + name.equals("int") ? Integer.TYPE : + name.equals("long") ? Long.TYPE : + name.equals("float") ? Float.TYPE : + name.equals("double") ? Double.TYPE : + null; + } + + private static Class classNamedArrayPrimitive(Class c) { + return + // (c == void.class) ? void[].class : + (c == boolean.class) ? boolean[].class : + (c == byte.class) ? byte[].class : + (c == char.class) ? char[].class : + (c == short.class) ? short[].class : + (c == int.class) ? int[].class : + (c == long.class) ? long[].class : + (c == float.class) ? float[].class : + (c == double.class) ? double[].class : + null; + } + + private Import() {} // Don't make one yourself. +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Invoke.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Invoke.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Invoke.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Invoke.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,553 @@ +package org.mathpiper.builtin.javareflection; + +/** + * @author Ken R. Anderson, Copyright 2000, kanderso@bbn.com, license + * subsequently modified by Jscheme project members + * licensed under zlib licence (see license.txt) + */ + +//import java.lang.reflect.AccessibleObject; // only in JDK1.2 revision: +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Member; +import java.lang.reflect.Modifier; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import org.mathpiper.builtin.JavaObject; +import org.mathpiper.lisp.cons.ConsPointer; + +/** + Provides dynamic Java method invocation through Java's Reflection + interface. For a good discussion of a Scheme implementation, and + the issues involved with dynamic method invocation in Java see: + +

Michael Travers, Java Q & A, Dr. Dobb's Journal, Jan., 2000, + p. 103-112. + +

Primitive types are not widened because it would make method + selection more ambiguous. By memoizing constructorTable() and + methodTable() dynamic method lookup can be done without consing. + +

You'll notice that Java doesn't make this very easy. For + example it would be nice if Method and Constructor shared an + Invokable interface. + +

Privileged methods can be invoked if the JVM allows it. + +

The name of a method to be invoked can be any nonnull Object + with a .toString() that names a method. It should probably be + changed to String. + **/ + +public class Invoke { + + /** Each bucket in an method table contains a Class[] of + parameterTypes and the corresponding method or constructor. **/ + public static final int BUCKET_SIZE = 2; + + public static Object peek(Object target, String name) throws Exception { + return peek0(target.getClass(), name, target); + } + + public static Object peekStatic(Class c, String name) throws Exception { + return peek0(c, name, c); + } + + private static Object peek0(Class c, String name, Object target) throws Exception { + try { + return c.getField(name).get(target); + } catch (NoSuchFieldException e) { + return E.error(target + " has no field named " + name); + } catch (IllegalAccessException e) { + return E.error("Can't access the " + name + " field of " + target); + } + } + + public static Object poke(Object target, String name, Object value) throws Exception { + return poke0(target.getClass(), name, target, value); + } + + public static Object pokeStatic(Class c, String name, Object value) throws Exception { + return poke0(c, name, c, value); + } + + private static Object poke0(Class c, String name, Object target, + Object value) throws Exception { + try { + c.getField(name).set(target, value); + return value; + } catch (NoSuchFieldException e) { + return E.error(target + " has no field named " + name); + } catch (IllegalAccessException e) { + return E.error("Can't access the " + name + " field of " + target); + } + } + + public static Object invokeConstructor(String c, Object[] args) throws Exception{ + Object[] ms = constructorTable(c, false); + return invokeRawConstructor (((Constructor) findMethod(ms, args)), args); + } + + public static Object invokeRawConstructor(Constructor m, Object[] args) throws Exception{ + try { + return m.newInstance(args); + } catch (InvocationTargetException e) { + //throw new BacktraceException(e.getTargetException(),new Object[]{m,args}); + throw e; //todo:tk. + } catch (InstantiationException e) { + return E.error("Error during instantiation: ", U.list(e, m, args)); + } catch (IllegalAccessException e) { + return E.error("Bad constructor application:", U.list(e, m, args)); + } + } + + public static Object invokeStatic(Class c, String name, Object[] args) throws Exception{ + return invokeMethod(c, c, name, args, true, false); + } + + public static Object invokeInstance(Object target, String name, + Object[] args,boolean isPrivileged) throws Exception{ + return invokeMethod(target.getClass(), target, name, args, false, + isPrivileged); + } + + public static Object invokeMethod(Class c, Object target, String name, + Object[] args, boolean isStatic, + boolean isPrivileged) throws Exception{ + Object[] ms = methodTable(c, name, isStatic,isPrivileged); + return invokeRawMethod((Method) findMethod(ms, args), target, args); + } + + public static Object invokeRawMethod(Method m, Object target, Object[] args) throws Exception{ + try { + return m.invoke(target, args); + } catch (InvocationTargetException e) { + //throw new BacktraceException(e.getTargetException(),new Object[]{m,target,args}); + throw e; //todo:tk. + } catch (IllegalAccessException e) { + return E.error("Bad method application from a private class: ", U.list(e, m, args)); + } catch (java.lang.IllegalArgumentException e) { + if (args == null) return E.error(e + "\n " + m.toString() + "\n called with target: " + U.stringify(target) + " and a null argument vector."); + else return E.error(e + "\nARGUMENT MISMATCH for method \n\n "+m.toString() +"\n called with " + U.vectorToList(args)); + } + } + public static final Hashtable constructorCache = new Hashtable(50); + public static final Hashtable constructorCachePriv = new Hashtable(50); + + /** Return the constructor table for the named class. **/ + public static Object[] constructorTable(String c, boolean isPrivileged) throws Exception { + if (isPrivileged) return constructorTable0Priv(c); + else return constructorTable0(c); + } + + public static Object[] constructorTable0Priv(String c) throws Exception { + Object[] result = ((Object[]) constructorCachePriv.get(c)); + if (result == null) { + try{ + result = methodArray(makeAccessible(Import.classNamed(c). + getDeclaredConstructors())); + }catch(Exception e){ + result = methodArray(Import.classNamed(c).getConstructors());} + constructorCachePriv.put(c, result); + } + if (result.length == 0) + return((Object[]) E.error("Constructor " + c + + " has no methods.")); + else return result; + } + + public static Object[] constructorTable0(String c) throws Exception { + Object[] result = ((Object[]) constructorCache.get(c)); + if (result == null) { + result = methodArray(Import.classNamed(c).getConstructors()); + constructorCache.put(c, result); + } + if (result.length == 0) + return((Object[]) E.error("Constructor " + c + + " has no methods.")); + else return result; + } + /** Static method name -> Class -> parameter[]/method array. **/ + public static final Hashtable staticCache = new Hashtable(50); + /** Instance method name -> Class -> parameter[]/method array. **/ + public static final Hashtable instanceCache = new Hashtable(100); + private static Hashtable getMethodCache(boolean isStatic) { + return (isStatic) ? staticCache : instanceCache; + } + + private static Hashtable getNameTable(Hashtable table, String name) { + Hashtable nameTable = ((Hashtable) table.get(name)); + if (nameTable != null) return ((Hashtable) nameTable); + else { + nameTable = new Hashtable(10); + table.put(name, nameTable); + return ((Hashtable) nameTable); + } + } + + /** Returns a Class -> prameter[]/method array for the method named + * name. **/ + public static Hashtable getClassTable (String name, boolean isStatic) { + return getNameTable(getMethodCache(isStatic), name); + } + + public static Object[] getCachedMethodTable + (Class c, String name, boolean isStatic) { + return ((Object[]) getNameTable(getMethodCache(isStatic), name) .get(c)); + } + + public static void putCachedMethodTable + (Class c, String name, boolean isStatic, Object value) { + getNameTable(getMethodCache(isStatic), name).put(c, value); + } + + public static Object[] methodTable0 + (Class c, String name, boolean isStatic,boolean isPrivileged) { + String internalName = isPrivileged?name.concat("#"):name; + Object[] result1 = getCachedMethodTable(c, internalName, isStatic); + if (result1 == null) { + result1 = methodTableLookup(c, name, isStatic,isPrivileged); + putCachedMethodTable(c, internalName, isStatic, result1); + } + return result1; + } + + public static Object[] methodTable + (Class c, String name, boolean isStatic,boolean isPrivileged) throws Exception { + Object[] result1 = methodTable0(c, name, isStatic,isPrivileged); + if (result1 == null || result1.length == 0) + if (isStatic) + return ((Object[]) E.error ("ERROR: \nNO STATIC METHOD OF TYPE \n\n ("+ c.getName()+"."+ name+ " ...)")); + else + return ((Object[]) E.error("ERROR: \nNO INSTANCE METHOD OF TYPE \n\n (."+ name+ " "+ c.getName() +" ...)")); + else return result1; + } + + public static Object[] methodTableLookup(Class c, String name,boolean isStatic,boolean isPrivileged) { + if (isStatic) return methodTableLookupStatic(c, name,isPrivileged); + else return methodTableLookupInstance(c, name, isPrivileged); + } + + public static Object[] methodTableLookupStatic(Class c, String name, boolean isPrivileged) { + Method[] ms = getMethods(c,isPrivileged); + Vector result = new Vector(ms.length); + for(int i = 0; i < ms.length; i++) { + Method m = ms[i]; + if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) + result.addElement(m); + } + Object[] result1 = new Object[result.size()]; + result.copyInto(result1); + return methodArray(result1); + } + + public static Object[] methodTableLookupInstance(Class c, String name) { + return methodTableLookupInstance(c, name,false); + } + + public static Object[] methodTableLookupInstance(Class c, String name, + boolean isPrivileged) { + Vector result = methodVector(c, name, isPrivileged); + Object[] result1 = new Object[result.size()]; + result.copyInto(result1); + return methodArray(result1); + } + + public static Vector methodVector(Class c, String name) { + return methodVector(c,name,false); + } + + public static Vector methodVector(Class c, String name, boolean isPrivileged) { + return methodVectorMerge(c, name, new Vector(10),isPrivileged); + } + + /** Add new methods to your superclasses table. **/ + public static Vector methodVectorMerge(Class c, String name, Vector result) { + return methodVectorMerge(c, name, result, false); + } + + public static Vector methodVectorMerge(Class c, String name, Vector result,boolean isPrivileged) { + Class s = c.getSuperclass(); + + if (s != null) result = methodVectorMerge(s, name, result,isPrivileged); + Class[] is = c.getInterfaces(); + for (int i = 0; i < is.length; i = i + 1) + result = methodVectorMerge(is[i], name, result,isPrivileged); + + Method[] ms = getMethods(c,isPrivileged); + for(int i = 0; i < ms.length; i++) { + Method m = ms[i]; + if ((!Modifier.isStatic(m.getModifiers())) && + // KRA 25OCT04: Fixes problem with .append in JDK 1.5.0 + ((isPrivileged || + (Modifier.isPublic(m.getModifiers()) && + Modifier.isPublic(m.getDeclaringClass().getModifiers()))) + && + m.getName().equals(name))) + maybeAdd(result, m); + + } + return result; + } + + /** Only add an instance method if no superclass provides one. **/ + private static void maybeAdd(Vector result, Method m1) { + for(int i = 0; i < result.size(); i++) { + Method m2 = ((Method) result.elementAt(i)); + if(parameterTypesMatch(getParameterTypes(m1), getParameterTypes(m2))) + return; + } + result.addElement(m1); + } + + private static Class[] getParameterTypes(Object m) { + return (m instanceof Method) ? ((Method) m).getParameterTypes() : + ((Constructor) m).getParameterTypes(); + } + + /** Returns Object[] of parameterType, method pairs. **/ + private static Object[] methodArray(Object[] v) { + Object[] result = new Object[v.length*BUCKET_SIZE]; + for(int i = 0; i < v.length; i++) { + result[i*BUCKET_SIZE] = getParameterTypes(v[i]); + result[i*BUCKET_SIZE+1] = v[i]; + } + return result; + } + + /** Do the paramter types of an instance method match? **/ + public static boolean parameterTypesMatch(Class[] p1, Class[] p2) { + if (p1.length == p2.length) { + for (int i = 0; i < p1.length; i++) + if (p1[i] != p2[i]) return false; + return true; + } else return false; + } + + /** Find the most applicable method. For instance methods + getMethods() has already handled the "this" argument, so + instance and static methods are matched the same way. **/ + + public static Object findMethod(Object[] methods, Object[] args) throws Exception { + if (methods.length == BUCKET_SIZE) + return methods[1]; // Hope it works! + return findMethodNoOpt(methods,args); + } + + static Object findMethodNoOpt(Object[] methods, Object[] args) throws Exception { + int best = -1; + for(int m1 = 0; m1 < methods.length; m1 = m1 + BUCKET_SIZE) { + Class[] p1 = ((Class[]) methods[m1]); + if (isApplicable(p1, args) && + (best == -1 || !moreApplicable(((Class[]) methods[best]), p1))) + best = m1; + } + if (best != -1) return methods[best+1]; + + // print debugging info + StringBuffer alts = new StringBuffer(); + for(int m1 = 0; m1 < methods.length; m1 = m1 + BUCKET_SIZE) + if (methods[m1+1] instanceof Member) + alts.append(" * "+methods[m1+1] +"\n"); + else { + Class[] ts=(Class[]) methods[m1]; + alts.append(" * "+methods[m1+1]+" ( "); + for (int i=0;iThis is only used by (method). + **/ + public static Method findMethod(String name, Object target, ConsPointer types) throws Exception { + try { + return U.toClass(target).getMethod(name, toClassArray(types, 0)); + } catch(NoSuchMethodException e) { + return ((Method) E.error("No method: ", U.list(name, target, types))); + } + } + + /** Look up a particular constructor given its name, and the name of its + declaring class, and a list of argument type names. +

This is only used by (constructor). + **/ + public static Constructor findConstructor(Object target, ConsPointer types) throws Exception{ + try { + return U.toClass(target).getConstructor(toClassArray(types, 0)); + } catch(NoSuchMethodException e) { + return ((Constructor) E.error("No constructor: ", U.list(target, types))); + } + } + + public static Constructor findConstructor(String target, Object[] arguments) throws Exception{ + Class[] argumentsArray = new Class[arguments.length]; + + for(int index = 0; index < arguments.length; index++) + { + Object argument = arguments[index]; + if(argument instanceof JavaObject) + { + argument = ((JavaObject)argument).getObject(); + } + + argumentsArray[index] = U.toClass(argument.getClass()); + }//for. + + Constructor constructor = U.toClass(target).getConstructor(argumentsArray); + + return constructor; + } + + public static Class[] toClassArray(ConsPointer types, int n) throws Exception{ + if (types.getCons() == null /*types == Pair.EMPTY*/) return new Class[n]; + else { + Class[] cs = toClassArray(((ConsPointer) types.getCons().cdr()), n + 1); + cs[n] = U.toClass(types.car()); + return cs; + } + } + + /** Return all the methods for this class. If you can't get all, for + * some reason,, just return the public ones. +

Memoizable. + **/ + public static Method[] getMethods(Class c,boolean isPrivileged) { + Method[] methods = getAllMethods(c,isPrivileged); + return (methods == null) ? c.getMethods() : methods; + } + + /** Return all the methods on this class, and make them accessable. + If you can't for some reason, return null; + **/ + private static Method[] getAllMethods(Class c) { + return getAllMethods(c,false); + } + + private static Method[] getAllMethods(Class c,boolean isPrivileged) { + if (isPrivileged) + try{return ((Method[]) makeAccessible(getAllMethods0(c)));} + catch(Exception e){return null;} + else return null; + } + + /** + In some situations you may not be able to get declared methods. + We only try once. + **/ + static final boolean ALLOW_PRIVATE_ACCESS=true; + private static boolean CAN_GET_DECLARED_METHODS = ALLOW_PRIVATE_ACCESS + ? canGetDeclaredMethods() : false; + private static boolean canGetDeclaredMethods () { + try { + Invoke.class.getDeclaredMethods(); + return true; + } catch (Exception e) {return false;}} + + private static Method[] getAllMethods0 (Class c) { + if (CAN_GET_DECLARED_METHODS) { + Hashtable table = new Hashtable(35); + collectDeclaredMethods(c, table); + Enumeration e = ((Enumeration) table.elements()); + Method[] ms = new Method[table.size()]; + for (int i=0; e.hasMoreElements(); i++) + ms[i] = ((Method)e.nextElement()); + return ms; + } + else return null; + } + + private static void collectDeclaredMethods(Class c, Hashtable h) { + Method[] ms = c.getDeclaredMethods(); + for (int i = 0; i < ms.length; i++) h.put(ms[i], ms[i]); + Class[] is = c.getInterfaces(); + for (int j = 0; j < is.length; j++) collectDeclaredMethods(is[j], h); + Class sup = c.getSuperclass(); + if (sup != null) collectDeclaredMethods(sup, h); + } + + /** + Check that this JVM has AccessibleObject. + We only try once. + **/ + static Method SETACCESSIBLE = getSetAccessibleMethod(); + private static Method getSetAccessibleMethod() { + try { + Class c = Class.forName("java.lang.reflect.AccessibleObject"); + Class ca = Class.forName("[Ljava.lang.reflect.AccessibleObject;"); + return c.getMethod("setAccessible", new Class[] { ca, Boolean.TYPE }); + } catch (Exception e) {return null;}} + + /** Items should be of type AccessibleObject[] but we can't say that + on JVM's older than JDK 1.2 +

Also used by JavaField. + **/ + static Object[] makeAccessible(Object[] items) { + if (items != null && SETACCESSIBLE != null) { + // AccessibleObject.setAccessible(items, true); + try { + SETACCESSIBLE.invoke(null, new Object[] { items, Boolean.TRUE }); + } catch (Exception e) {} + } + return items; + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/JavaConstructor.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/JavaConstructor.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/JavaConstructor.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/JavaConstructor.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,51 @@ +package org.mathpiper.builtin.javareflection; +import java.lang.reflect.Constructor; + +/** Provides dynamic constructors. + * @author Peter Norvig, Copyright 1998, peter@norvig.com, license + * subsequently modified by Jscheme project members + * licensed under zlib licence (see license.txt) + **/ + +public class JavaConstructor extends StaticReflector { + + private transient Object[] methods; + + /** Depricated! **/ + public JavaConstructor(Class c) throws Exception { + this(c.getName()); + } + + public JavaConstructor(String c, boolean isPrivileged) throws Exception { + this.name = c; + this.isPrivileged = isPrivileged; + this.reset(); + } + + public JavaConstructor(String c) throws Exception { + this(c,false); + } + + public Object apply(Object[] args) throws Exception{ + return Invoke.invokeRawConstructor + (((Constructor) Invoke.findMethod(methods, args)), args); + } + + protected synchronized void reset() throws Exception { + methods = Invoke.constructorTable(name, isPrivileged); + + int min = Integer.MAX_VALUE; + int max = 0; + + for(int i = 0; i < methods.length; i = i + Invoke.BUCKET_SIZE) { + int n = ((Object[]) methods[i]).length; + if (n < min) min = n; + if (n > max) max = n; + } + minArgs = min; + maxArgs = max; + } + + /** Code is like (vector Hashtable. 10), ie the first element is the + Constructor. **/ +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/JavaField.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/JavaField.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/JavaField.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/JavaField.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,192 @@ +package org.mathpiper.builtin.javareflection; +import java.lang.reflect.*; +import java.util.Hashtable; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Utility; + +/** + * Provides dynamic field access. + + If the field is static (or a Class is given) we cache the Field. + Otherwise, we cache a class-> field map. + * @author Peter Norvig, Copyright 1998, peter@norvig.com, license + * subsequently modified by Jscheme project members + * licensed under zlib licence (see license.txt) +**/ + +public class JavaField extends Reflector { + + /** Maps field name -> Class -> Field **/ + static final Hashtable fieldTable = new Hashtable(20); + static final Hashtable fieldTablePriv = new Hashtable(20); + + static Hashtable fieldTable0(boolean isPrivileged) { + if (isPrivileged) return fieldTablePriv; + else return fieldTable; + } + + /** + Return the field named name in Class c. + Priviledged fields are made accessible if the JVM allows it. +

Memoized. + **/ + public static Field getField(Class c, String name, boolean isPrivileged) throws Exception { + try{ + return isPrivileged + ? getDeclaredField(c, name) + : c.getField(name); + } catch(NoSuchFieldException e2) { + return((Field)E.error("no such field: " + c+"."+name)); + } catch(Exception e) { + return((Field)E.error + ("error accessing field: " + c+"."+name+ " is "+e)); + } + } + + private static Hashtable getFieldClassTable + (String name, boolean isPrivileged) { + Hashtable ft = fieldTable0(isPrivileged); + Hashtable table = ((Hashtable) ft.get(name)); + if (table == null) { + table = new Hashtable(3); + ft.put(name, table); + } + return table; + } + + /** Wander over the declared fields, returning the first named + name **/ + private static Field getDeclaredField (Class c, String name) + throws NoSuchFieldException { + try{ + Field[] fs = ((Field[]) Invoke.makeAccessible(c.getDeclaredFields())); + for (int i = 0; i < fs.length; i++) + if (fs[i].getName().equals(name)) return fs[i]; + Class s = c.getSuperclass(); + if (s != null) return getDeclaredField(s, name); + else return ((Field) E.error + ("\n\nERROR: no field: \""+name+"\" for class \""+c+"\"")); + }catch(Exception e) { + return c.getField(name);} + } + + String className; + transient Field f; + boolean isStatic = false; + /** Map Class -> Field **/ + transient Hashtable classTable; + + public JavaField(String name, Class c) throws Exception { + this(name, c, false); + } + + public JavaField(String name, Class c, boolean isPrivileged) throws Exception { + this.name = name; + this.isPrivileged=isPrivileged; + if (c != null) this.className = c.getName(); + reset(); + } + + protected synchronized void reset() throws Exception { + Class c = (className == null) ? null : Import.classNamed(className); + if (c != null) { + f = getField(c, name, isPrivileged); + isStatic = Modifier.isStatic(f.getModifiers()); + minArgs = (isStatic) ? 0 : 1; + maxArgs = (Modifier.isFinal(f.getModifiers())) ? minArgs : minArgs+1; + } else { + classTable = getFieldClassTable(name, isPrivileged); + minArgs = 1; + maxArgs = 2; + }} + + + /* + public Object[] makeArgArray(Object[] code, + Evaluator eval, + LexicalEnvironment lexenv) { + int L = code.length - 1; + if (L == 0 && isStatic) return StaticReflector.args0; + else if (L == 1) + return new Object[] { eval.execute(code[1], lexenv) }; + else if (L == 2 && !isStatic) + return new Object[] { eval.execute(code[1], lexenv), + eval.execute(code[2], lexenv) }; + else return ((Object[]) E.error("Wrong number of arguments to field " + + this + " " + U.stringify(code))); + }*/ + + + /* + public Object[] makeArgArray (ConsPointer args) throws Exception{ + int L = Utility.listLength(null, -1, args);// args.length(); + if (L == 0 && isStatic) return StaticReflector.args0; + else if (L == 1) return new Object[] { args.cdr() }; + else if (L == 2 && !isStatic) + return new Object[] { args.cdr(), args.second() }; + else return ((Object[]) E.error("Wrong number of arguments to field " + + this + " " + U.stringify(args))); + }*/ + + public Object apply(Object[] args) throws Exception { + int L = args.length; + if (isStatic) { + if (L == 1) return setStaticFieldValue(f, args[0]); + else return getStaticFieldValue(f); + } else { + if (L == 1) return getFieldValue(args[0], getTargetField(args[0])); + else return setFieldValue(args[0], + getTargetField(args[0]), + args[1]); + } + } + + public Field getTargetField(Object target) throws Exception { + if (f != null) return f; + Class c = target.getClass(); + Field it = ((Field) classTable.get(c)); + if (it != null) return it; + it = getField(c, this.name, this.isPrivileged); + if (it == null) return (Field) E.error(U.stringify(target) + + " does not have a field " + + this.name); + classTable.put(c, it); + return it; + } + + public Object getFieldValue(Object target, Field f) throws Exception { + try { return f.get(target); } + catch (IllegalAccessException e) { + return ((Object) E.error("Illegal Access to field: " + f + " in " + + U.stringify(target))); + }} + + public Object setFieldValue(Object target, Field f, Object value) { + try { + Object old = f.get(target); + f.set(target, value); + return old; + } catch (IllegalAccessException e) { + return null; // Sorry. + } + } + + public Object getStaticFieldValue(Field f) { + try { + return f.get(null); + } catch(IllegalAccessException e) { + return null; // Sorry. + } + } + + public Object setStaticFieldValue(Field f, Object value) { + try { + Object old = f.get(null); + f.set(null, value); + return old; + } catch(IllegalAccessException e) { + return null; // Sorry. + } + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/JavaMethod.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/JavaMethod.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/JavaMethod.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/JavaMethod.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,144 @@ +package org.mathpiper.builtin.javareflection; + +import java.lang.reflect.Method; +import java.util.Hashtable; +import org.mathpiper.lisp.cons.ConsPointer; + +/** This class allows you to call any Java method, just by naming it, + * and doing the dispatch at runtime. + * @author Peter Norvig, Copyright 1998, peter@norvig.com, license + * subsequently modified by Jscheme project members + * licensed under zlib licence (see license.txt) +**/ + +public class JavaMethod extends Reflector { + + public static final Object[] ZERO_ARGS = new Object[0]; + + private String methodClass; + /** Parameter/method table for a specific method. **/ + private transient Object[] methodTable; + private boolean isStatic; + /** Do we know the Class that this method applies to? **/ + private boolean isSpecific; + /** Class -> methodTable map. **/ + private transient Hashtable classMethodTable; + + public boolean isStatic() { return this.isStatic;} + + /** + + If the method is static then Class c is not null. For instance + methods, if Class c is not null, then it is used at construction + time to create a method table. Otherwise, the class of the + method is determined at call time from the target, and the method + table is constructed then and cached. Examples (see DynamicVariable.java): + +

+      new JavaMethod("getProperties", System.class, true) - static method
+      new JavaMethod("put", Hashtable.class,false)        - specific instance method.
+      new JavaMethod("put", null, false)                  - unspecified instance method
+      
+ **/ + + public JavaMethod(String name, Class c, boolean isStatic, boolean isPrivileged) throws Exception { + this.name = name; + if (c != null) this.methodClass = c.getName(); + this.isStatic = isStatic; + this.isSpecific = (c!=null); + this.minArgs = isStatic ? 0 : 1; + this.isPrivileged=isPrivileged; + reset(); + } + + public JavaMethod(String name, Class c, boolean isStatic) throws Exception { + this(name,c,isStatic,false); + } + + public JavaMethod(String name, Class c) throws Exception { + this(name,c,(c!=null)); + } + + protected synchronized void reset() throws Exception { + if (isSpecific) { + methodTable = Invoke.methodTable0(Import.classNamed(methodClass), + name, + isStatic, + isPrivileged); + if (methodTable.length == 0) { + methodTable = null; + E.warn( "No such "+ (isStatic?" static ":" instance ") + + " method \"" + name + (isSpecific?("\" in class "+methodClass):"")); + } + } else classMethodTable = new Hashtable(5); + } + + public Object[] instanceMethodTable(Class c) throws Exception { + Object[] ms = ((Object[]) classMethodTable.get(c)); + if (ms != null) return ms; + ms = Invoke.methodTable0(c, name, isStatic, isPrivileged); + if (ms != null && ms.length > 0) { + classMethodTable.put(c, ms); + return ms; + } else return (Object[]) E.error(c + " has no methods for " + this.name); + } + + /** + For a static method, args is an Object[] of arguments. + For an instance method, args is (vector target (vector arguments)); + **/ + public Object apply(Object[] args) throws Exception{ + if (!(isSpecific)) { + Object[] methodTable = instanceMethodTable(args[0].getClass()); + Object[] as = (Object[]) args[1]; + Method m = (Method) Invoke.findMethod(methodTable, as); + return Invoke.invokeRawMethod(m, args[0], as); + } else { + if (methodTable == null) return E.error(this + " has no methods"); + if (isStatic) { + Method m = (Method) Invoke.findMethod(methodTable, args); + return Invoke.invokeRawMethod(m, null, args); + } else { + Object[] as = (Object[]) args[1]; + Method m = (Method) Invoke.findMethod(methodTable, as); + return Invoke.invokeRawMethod(m, args[0], as); + } + } + } + + + /* + public Object[] makeArgArray(Object[] code, + Evaluator eval, + LexicalEnvironment lexenv) { + if (isStatic) { + int L = code.length - 1; + if (L == 0) return ZERO_ARGS; + + Object[] args = new Object[L]; + for (int i = 0; i < L; i++) + args[i] = eval.execute(code[i+1], lexenv); + return args; + } else { + int L = code.length - 2; + if (L < 0) + return ((Object[]) + E.error("Wrong number of arguments in application: " + + U.stringify(code))); + Object target = eval.execute(code[1], lexenv); + if (L == 0) return new Object[] { target, ZERO_ARGS }; + + Object[] args = new Object[L]; + for (int i = 0; i < L; i++) + args[i] = eval.execute(code[i+2], lexenv); + return new Object[] { target, args }; + } + } + + public Object[] makeArgArray (ConsPointer args) { + if (isStatic) return U.listToVector(args); + else return new Object[] { args.first, U.listToVector(args.rest)} ; + } + + */ +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Reflector.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Reflector.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/Reflector.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/Reflector.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,45 @@ +package org.mathpiper.builtin.javareflection; + +import java.util.Enumeration; +import java.util.Vector; + +/** A Reflector contains one or more Java metaobjects that are cached. + They need to be reset() when the classpath is reset. +**/ + + +public abstract class Reflector { // todo:tk extends { Procedure { + + //todo:tk:added these variables because they were inherited from Procedure. + public String name = "??"; + public int minArgs = 0; + public int maxArgs = Integer.MAX_VALUE; + + + public static final Vector reflectors = new Vector(100); + + /** Reset all know reflectors **/ + public static void resetAll() throws Exception { + Enumeration i = reflectors.elements(); + while (i.hasMoreElements()) + ((Reflector) i.nextElement()).reset(); + } + + public boolean isPrivileged = false; + + /** Add yourself to the reflectors **/ + public Reflector() { + reflectors.addElement(this); + } + + /** Reset your classpath dependent state. This method can't be + abstract. + **/ + protected synchronized void reset() throws Exception {} + + protected Object readResolve() throws Exception { + reset(); + return this; + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/SingleImporter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/SingleImporter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/SingleImporter.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/SingleImporter.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,31 @@ +package org.mathpiper.builtin.javareflection; + +/** An Importer that knows how to import a single class. **/ +public class SingleImporter implements Importer { + String fullName; + Class c; + + public SingleImporter(String fullName) { + this.fullName = fullName; + reset(); + } + + public Class classNamed(String name) { + /* An import may occur before the class is on the classpath, + so Import.forName() will return null. **/ + if (c == null) reset(); + return (fullName.equals(name) || fullName.endsWith("."+name)) + ? c : null; + } + + public boolean equals(Object x) { + return this.getClass() == x.getClass() && + this.fullName == ((SingleImporter)x).fullName; + } + + public int hashCode() {return this.fullName.hashCode();} + + public String toString() {return "(import " + fullName + ")";} + + public void reset() {this.c = Import.forName(fullName);} +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/StaticReflector.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/StaticReflector.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/StaticReflector.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/StaticReflector.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,34 @@ +package org.mathpiper.builtin.javareflection; +import java.lang.reflect.Constructor; + +/** StaticReflector's like JavaConstructor and Generic can share this behavior. + * @author Peter Norvig, Copyright 1998, peter@norvig.com, license + * subsequently modified by Jscheme project members + * licensed under zlib licence (see license.txt) + **/ + +public abstract class StaticReflector extends Reflector { + + public static final Object[] args0 = new Object[0]; + + /** Code is an Object[] who's first element is a JavaConstructor, and + * remaining elements are arguments. + **/ + /* + public Object[] makeArgArray(Object[] code, + Evaluator eval, + LexicalEnvironment lexenv) { + int L = code.length - 1; + if (L == 0) return args0; + + Object[] args = new Object[L]; + for (int i = 0; i < L; i++) + args[i] = eval.execute(code[i+1], lexenv); + return args; + } + + public Object[] makeArgArray (ConsPointer args) { + return U.listToVector(args); + } + * */ +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/U.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/U.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/U.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/U.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,72 @@ + + +package org.mathpiper.builtin.javareflection; + +import org.mathpiper.lisp.cons.ConsPointer; + + +public class U { + + public static Class toClass(Object c) throws Exception { + if (c instanceof Class) return (Class) c; + else return Import.classNamed(stringify(c, false)); + } + + + + /** Convert x to a String giving its external representation. + * Strings and characters are quoted. **/ + public static String stringify(Object x) { return stringify(x, true); } + + /** Convert x to a String giving its external representation. + * Strings and characters are quoted iff quoted is true.. **/ + public static String stringify(Object x, boolean quoted) { + // Handle these cases without consing: + if (x instanceof String && !quoted) return ((String) x); + /*else if (x instanceof Symbol) return ((Symbol) x).toString(); + else return stringify(x, quoted, new StringBuffer()).toString();*/ + + return ""; + }//end method + + + /** Creates a three element list. **/ + public static ConsPointer list(Object a, Object b, Object c) { + //return new Pair(a, new Pair(b, new Pair(c, Pair.EMPTY))); + return null; + } + + /** Creates a two element list. **/ + public static ConsPointer list(Object a, Object b) { + //return new Pair(a, new Pair(b, Pair.EMPTY)); + return null; + } + + /** Creates a one element list. **/ + public static ConsPointer list(Object a) { + //return new Pair(a, Pair.EMPTY); + return null; + } + + + public static Object[] listToVector(Object x) { + /*Pair list = toList(x); + int L = list.length(); + Object[] result = new Object[L]; + for (int i = 0; isPair(list); i++, list = toList(list.rest)) + result[i] = first(list); + return result; todo:tk */ + return null; + } + + + public static ConsPointer vectorToList(Object vec) { + /*Pair result = Pair.EMPTY; + for (int i = Array.getLength(vec)-1; i>=0; i--) { + result = new Pair(Array.get(vec, i), result); + } + return result;*/ + return null; + } + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/WildImporter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/WildImporter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/javareflection/WildImporter.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/javareflection/WildImporter.java 2010-04-08 05:55:58.000000000 +0000 @@ -0,0 +1,39 @@ +package org.mathpiper.builtin.javareflection; + +import java.util.Hashtable; + +/** An Importer that can handle a wildcard, like "java.io.*". **/ +public class WildImporter implements Importer { + String prefix; + + public WildImporter(String name) { + this.prefix = name.substring(0, name.length() - "*".length()); + } + + public Class classNamed(String name) { + try { + return (name.startsWith(prefix)) + ? Import.forName(name) + : (name.indexOf(".") == -1) + ? Import.forName(prefix + name) + : null; + } catch (java.lang.SecurityException se) { + // Can come back from Netscape. Assume the guessed name doesn't exist. + return null; + } catch (Throwable t) { + E.warn(this + " " + name + " " + t); + return null; + } + } + + public boolean equals(Object x) { + return this.getClass() == x.getClass() && + this.prefix == ((WildImporter)x).prefix; + } + + public int hashCode() {return this.prefix.hashCode();} + + public String toString() {return "(import " + prefix + "*)";} + + public void reset() {} +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Constants.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Constants.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Constants.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Constants.java 2009-11-22 07:57:56.000000000 +0000 @@ -0,0 +1,61 @@ +/* +Copyright © 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ + +package org.mathpiper.builtin.library.cern; + +/** + * Defines some useful constants. + */ +public class Constants { + /* + * machine constants + */ + protected static final double MACHEP = 1.11022302462515654042E-16; + protected static final double MAXLOG = 7.09782712893383996732E2; + protected static final double MINLOG = -7.451332191019412076235E2; + protected static final double MAXGAM = 171.624376956302725; + protected static final double SQTPI = 2.50662827463100050242E0; + protected static final double SQRTH = 7.07106781186547524401E-1; + protected static final double LOGPI = 1.14472988584940017414; + + protected static final double big = 4.503599627370496e15; + protected static final double biginv = 2.22044604925031308085e-16; + + + /* + * MACHEP = 1.38777878078144567553E-17 2**-56 + * MAXLOG = 8.8029691931113054295988E1 log(2**127) + * MINLOG = -8.872283911167299960540E1 log(2**-128) + * MAXNUM = 1.701411834604692317316873e38 2**127 + * + * For IEEE arithmetic (IBMPC): + * MACHEP = 1.11022302462515654042E-16 2**-53 + * MAXLOG = 7.09782712893383996843E2 log(2**1024) + * MINLOG = -7.08396418532264106224E2 log(2**-1022) + * MAXNUM = 1.7976931348623158E308 2**1024 + * + * The global symbols for mathematical constants are + * PI = 3.14159265358979323846 pi + * PIO2 = 1.57079632679489661923 pi/2 + * PIO4 = 7.85398163397448309616E-1 pi/4 + * SQRT2 = 1.41421356237309504880 sqrt(2) + * SQRTH = 7.07106781186547524401E-1 sqrt(2)/2 + * LOG2E = 1.4426950408889634073599 1/log(2) + * SQ2OPI = 7.9788456080286535587989E-1 sqrt( 2/pi ) + * LOGE2 = 6.93147180559945309417E-1 log(2) + * LOGSQ2 = 3.46573590279972654709E-1 log(2)/2 + * THPIO4 = 2.35619449019234492885 3*pi/4 + * TWOOPI = 6.36619772367581343075535E-1 2/pi + */ + +/** + * Makes this class non instantiable, but still let's others inherit from it. + */ +protected Constants() {} +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Gamma.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Gamma.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Gamma.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Gamma.java 2009-11-22 07:57:56.000000000 +0000 @@ -0,0 +1,630 @@ +package org.mathpiper.builtin.library.cern; + +/* +Copyright © 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ + + +/** + * Gamma and Beta functions. + *

+ * Implementation: + *

+ * Some code taken and adapted from the Java 2D Graph Package 2.4, + * which in turn is a port from the Cephes 2.2 Math Library (C). + * Most Cephes code (missing from the 2D Graph Package) directly ported. + * + * @author wolfgang.hoschek@cern.ch + * @version 0.9, 22-Jun-99 + */ +public class Gamma extends Constants { +/** + * Makes this class non instantiable, but still let's others inherit from it. + */ +protected Gamma() {} +/** + * Returns the beta function of the arguments. + *
+ *                   -     -
+ *                  | (a) | (b)
+ * beta( a, b )  =  -----------.
+ *                     -
+ *                    | (a+b)
+ * 
+ */ +static public double beta(double a, double b) throws ArithmeticException { + double y; + + y = a + b; + y = gamma(y); + if( y == 0.0 ) return 1.0; + + if( a > b ) { + y = gamma(a)/y; + y *= gamma(b); + } + else { + y = gamma(b)/y; + y *= gamma(a); + } + + return(y); +} +/** + * Returns the Gamma function of the argument. + */ +static public double gamma(double x) throws ArithmeticException { + +double P[] = { + 1.60119522476751861407E-4, + 1.19135147006586384913E-3, + 1.04213797561761569935E-2, + 4.76367800457137231464E-2, + 2.07448227648435975150E-1, + 4.94214826801497100753E-1, + 9.99999999999999996796E-1 + }; +double Q[] = { + -2.31581873324120129819E-5, + 5.39605580493303397842E-4, + -4.45641913851797240494E-3, + 1.18139785222060435552E-2, + 3.58236398605498653373E-2, + -2.34591795718243348568E-1, + 7.14304917030273074085E-2, + 1.00000000000000000320E0 + }; +//double MAXGAM = 171.624376956302725; +//double LOGPI = 1.14472988584940017414; + +double p, z; +int i; + +double q = Math.abs(x); + +if( q > 33.0 ) { + if( x < 0.0 ) { + p = Math.floor(q); + if( p == q ) throw new ArithmeticException("gamma: overflow"); + i = (int)p; + z = q - p; + if( z > 0.5 ) { + p += 1.0; + z = q - p; + } + z = q * Math.sin( Math.PI * z ); + if( z == 0.0 ) throw new ArithmeticException("gamma: overflow"); + z = Math.abs(z); + z = Math.PI/(z * stirlingFormula(q) ); + + return -z; + } else { + return stirlingFormula(x); + } + } + + z = 1.0; + while( x >= 3.0 ) { + x -= 1.0; + z *= x; + } + + while( x < 0.0 ) { + if( x == 0.0 ) { + throw new ArithmeticException("gamma: singular"); + } else + if( x > -1.E-9 ) { + return( z/((1.0 + 0.5772156649015329 * x) * x) ); + } + z /= x; + x += 1.0; + } + + while( x < 2.0 ) { + if( x == 0.0 ) { + throw new ArithmeticException("gamma: singular"); + } else + if( x < 1.e-9 ) { + return( z/((1.0 + 0.5772156649015329 * x) * x) ); + } + z /= x; + x += 1.0; +} + + if( (x == 2.0) || (x == 3.0) ) return z; + + x -= 2.0; + p = Polynomial.polevl( x, P, 6 ); + q = Polynomial.polevl( x, Q, 7 ); + return z * p / q; + +} +/** + * Returns the Incomplete Beta Function evaluated from zero to xx; formerly named ibeta. + * + * @param aa the alpha parameter of the beta distribution. + * @param bb the beta parameter of the beta distribution. + * @param xx the integration end point. + */ +public static double incompleteBeta( double aa, double bb, double xx ) throws ArithmeticException { + double a, b, t, x, xc, w, y; + boolean flag; + + if( aa <= 0.0 || bb <= 0.0 ) throw new + ArithmeticException("ibeta: Domain error!"); + + if( (xx <= 0.0) || ( xx >= 1.0) ) { + if( xx == 0.0 ) return 0.0; + if( xx == 1.0 ) return 1.0; + throw new ArithmeticException("ibeta: Domain error!"); + } + + flag = false; + if( (bb * xx) <= 1.0 && xx <= 0.95) { + t = powerSeries(aa, bb, xx); + return t; + } + + w = 1.0 - xx; + + /* Reverse a and b if x is greater than the mean. */ + if( xx > (aa/(aa+bb)) ) { + flag = true; + a = bb; + b = aa; + xc = xx; + x = w; + } else { + a = aa; + b = bb; + xc = w; + x = xx; + } + + if( flag && (b * x) <= 1.0 && x <= 0.95) { + t = powerSeries(a, b, x); + if( t <= MACHEP ) t = 1.0 - MACHEP; + else t = 1.0 - t; + return t; + } + + /* Choose expansion for better convergence. */ + y = x * (a+b-2.0) - (a-1.0); + if( y < 0.0 ) + w = incompleteBetaFraction1( a, b, x ); + else + w = incompleteBetaFraction2( a, b, x ) / xc; + + /* Multiply w by the factor + a b _ _ _ + x (1-x) | (a+b) / ( a | (a) | (b) ) . */ + + y = a * Math.log(x); + t = b * Math.log(xc); + if( (a+b) < MAXGAM && Math.abs(y) < MAXLOG && Math.abs(t) < MAXLOG ) { + t = Math.pow(xc,b); + t *= Math.pow(x,a); + t /= a; + t *= w; + t *= gamma(a+b) / (gamma(a) * gamma(b)); + if( flag ) { + if( t <= MACHEP ) t = 1.0 - MACHEP; + else t = 1.0 - t; + } + return t; + } + /* Resort to logarithms. */ + y += t + logGamma(a+b) - logGamma(a) - logGamma(b); + y += Math.log(w/a); + if( y < MINLOG ) + t = 0.0; + else + t = Math.exp(y); + + if( flag ) { + if( t <= MACHEP ) t = 1.0 - MACHEP; + else t = 1.0 - t; + } + return t; + } +/** + * Continued fraction expansion #1 for incomplete beta integral; formerly named incbcf. + */ +static double incompleteBetaFraction1( double a, double b, double x ) throws ArithmeticException { + double xk, pk, pkm1, pkm2, qk, qkm1, qkm2; + double k1, k2, k3, k4, k5, k6, k7, k8; + double r, t, ans, thresh; + int n; + + k1 = a; + k2 = a + b; + k3 = a; + k4 = a + 1.0; + k5 = 1.0; + k6 = b - 1.0; + k7 = k4; + k8 = a + 2.0; + + pkm2 = 0.0; + qkm2 = 1.0; + pkm1 = 1.0; + qkm1 = 1.0; + ans = 1.0; + r = 1.0; + n = 0; + thresh = 3.0 * MACHEP; + do { + xk = -( x * k1 * k2 )/( k3 * k4 ); + pk = pkm1 + pkm2 * xk; + qk = qkm1 + qkm2 * xk; + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + xk = ( x * k5 * k6 )/( k7 * k8 ); + pk = pkm1 + pkm2 * xk; + qk = qkm1 + qkm2 * xk; + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + if( qk != 0 ) r = pk/qk; + if( r != 0 ) { + t = Math.abs( (ans - r)/r ); + ans = r; + } else + t = 1.0; + + if( t < thresh ) return ans; + + k1 += 1.0; + k2 += 1.0; + k3 += 2.0; + k4 += 2.0; + k5 += 1.0; + k6 -= 1.0; + k7 += 2.0; + k8 += 2.0; + + if( (Math.abs(qk) + Math.abs(pk)) > big ) { + pkm2 *= biginv; + pkm1 *= biginv; + qkm2 *= biginv; + qkm1 *= biginv; + } + if( (Math.abs(qk) < biginv) || (Math.abs(pk) < biginv) ) { + pkm2 *= big; + pkm1 *= big; + qkm2 *= big; + qkm1 *= big; + } + } while( ++n < 300 ); + + return ans; + } +/** + * Continued fraction expansion #2 for incomplete beta integral; formerly named incbd. + */ +static double incompleteBetaFraction2( double a, double b, double x ) throws ArithmeticException { + double xk, pk, pkm1, pkm2, qk, qkm1, qkm2; + double k1, k2, k3, k4, k5, k6, k7, k8; + double r, t, ans, z, thresh; + int n; + + k1 = a; + k2 = b - 1.0; + k3 = a; + k4 = a + 1.0; + k5 = 1.0; + k6 = a + b; + k7 = a + 1.0; + k8 = a + 2.0; + + pkm2 = 0.0; + qkm2 = 1.0; + pkm1 = 1.0; + qkm1 = 1.0; + z = x / (1.0-x); + ans = 1.0; + r = 1.0; + n = 0; + thresh = 3.0 * MACHEP; + do { + xk = -( z * k1 * k2 )/( k3 * k4 ); + pk = pkm1 + pkm2 * xk; + qk = qkm1 + qkm2 * xk; + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + xk = ( z * k5 * k6 )/( k7 * k8 ); + pk = pkm1 + pkm2 * xk; + qk = qkm1 + qkm2 * xk; + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + if( qk != 0 ) r = pk/qk; + if( r != 0 ) { + t = Math.abs( (ans - r)/r ); + ans = r; + } else + t = 1.0; + + if( t < thresh ) return ans; + + k1 += 1.0; + k2 -= 1.0; + k3 += 2.0; + k4 += 2.0; + k5 += 1.0; + k6 += 1.0; + k7 += 2.0; + k8 += 2.0; + + if( (Math.abs(qk) + Math.abs(pk)) > big ) { + pkm2 *= biginv; + pkm1 *= biginv; + qkm2 *= biginv; + qkm1 *= biginv; + } + if( (Math.abs(qk) < biginv) || (Math.abs(pk) < biginv) ) { + pkm2 *= big; + pkm1 *= big; + qkm2 *= big; + qkm1 *= big; + } + } while( ++n < 300 ); + + return ans; + } +/** + * Returns the Incomplete Gamma function; formerly named igamma. + * @param a the parameter of the gamma distribution. + * @param x the integration end point. + */ +static public double incompleteGamma(double a, double x) + throws ArithmeticException { + + + double ans, ax, c, r; + + if( x <= 0 || a <= 0 ) return 0.0; + + if( x > 1.0 && x > a ) return 1.0 - incompleteGammaComplement(a,x); + + /* Compute x**a * exp(-x) / gamma(a) */ + ax = a * Math.log(x) - x - logGamma(a); + if( ax < -MAXLOG ) return( 0.0 ); + + ax = Math.exp(ax); + + /* power series */ + r = a; + c = 1.0; + ans = 1.0; + + do { + r += 1.0; + c *= x/r; + ans += c; + } + while( c/ans > MACHEP ); + + return( ans * ax/a ); + + } +/** + * Returns the Complemented Incomplete Gamma function; formerly named igamc. + * @param a the parameter of the gamma distribution. + * @param x the integration start point. + */ +static public double incompleteGammaComplement( double a, double x ) throws ArithmeticException { + double ans, ax, c, yc, r, t, y, z; + double pk, pkm1, pkm2, qk, qkm1, qkm2; + + if( x <= 0 || a <= 0 ) return 1.0; + + if( x < 1.0 || x < a ) return 1.0 - incompleteGamma(a,x); + + ax = a * Math.log(x) - x - logGamma(a); + if( ax < -MAXLOG ) return 0.0; + + ax = Math.exp(ax); + + /* continued fraction */ + y = 1.0 - a; + z = x + y + 1.0; + c = 0.0; + pkm2 = 1.0; + qkm2 = x; + pkm1 = x + 1.0; + qkm1 = z * x; + ans = pkm1/qkm1; + + do { + c += 1.0; + y += 1.0; + z += 2.0; + yc = y * c; + pk = pkm1 * z - pkm2 * yc; + qk = qkm1 * z - qkm2 * yc; + if( qk != 0 ) { + r = pk/qk; + t = Math.abs( (ans - r)/r ); + ans = r; + } else + t = 1.0; + + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + if( Math.abs(pk) > big ) { + pkm2 *= biginv; + pkm1 *= biginv; + qkm2 *= biginv; + qkm1 *= biginv; + } + } while( t > MACHEP ); + + return ans * ax; + } +/** + * Returns the natural logarithm of the gamma function; formerly named lgamma. + */ +public static double logGamma(double x) throws ArithmeticException { + double p, q, w, z; + + double A[] = { + 8.11614167470508450300E-4, + -5.95061904284301438324E-4, + 7.93650340457716943945E-4, + -2.77777777730099687205E-3, + 8.33333333333331927722E-2 + }; + double B[] = { + -1.37825152569120859100E3, + -3.88016315134637840924E4, + -3.31612992738871184744E5, + -1.16237097492762307383E6, + -1.72173700820839662146E6, + -8.53555664245765465627E5 + }; + double C[] = { + /* 1.00000000000000000000E0, */ + -3.51815701436523470549E2, + -1.70642106651881159223E4, + -2.20528590553854454839E5, + -1.13933444367982507207E6, + -2.53252307177582951285E6, + -2.01889141433532773231E6 + }; + + if( x < -34.0 ) { + q = -x; + w = logGamma(q); + p = Math.floor(q); + if( p == q ) throw new ArithmeticException("lgam: Overflow"); + z = q - p; + if( z > 0.5 ) { + p += 1.0; + z = p - q; + } + z = q * Math.sin( Math.PI * z ); + if( z == 0.0 ) throw new + ArithmeticException("lgamma: Overflow"); + z = LOGPI - Math.log( z ) - w; + return z; + } + + if( x < 13.0 ) { + z = 1.0; + while( x >= 3.0 ) { + x -= 1.0; + z *= x; + } + while( x < 2.0 ) { + if( x == 0.0 ) throw new + ArithmeticException("lgamma: Overflow"); + z /= x; + x += 1.0; + } + if( z < 0.0 ) z = -z; + if( x == 2.0 ) return Math.log(z); + x -= 2.0; + p = x * Polynomial.polevl( x, B, 5 ) / Polynomial.p1evl( x, C, 6); + return( Math.log(z) + p ); + } + + if( x > 2.556348e305 ) throw new + ArithmeticException("lgamma: Overflow"); + + q = ( x - 0.5 ) * Math.log(x) - x + 0.91893853320467274178; + //if( x > 1.0e8 ) return( q ); + if( x > 1.0e8 ) return( q ); + + p = 1.0/(x*x); + if( x >= 1000.0 ) + q += (( 7.9365079365079365079365e-4 * p + - 2.7777777777777777777778e-3) *p + + 0.0833333333333333333333) / x; + else + q += Polynomial.polevl( p, A, 4 ) / x; + return q; + } +/** + * Power series for incomplete beta integral; formerly named pseries. + * Use when b*x is small and x not too close to 1. + */ +static double powerSeries( double a, double b, double x ) throws ArithmeticException { + double s, t, u, v, n, t1, z, ai; + + ai = 1.0 / a; + u = (1.0 - b) * x; + v = u / (a + 1.0); + t1 = v; + t = u; + n = 2.0; + s = 0.0; + z = MACHEP * ai; + while( Math.abs(v) > z ) { + u = (n - b) * x / n; + t *= u; + v = t / (a + n); + s += v; + n += 1.0; + } + s += t1; + s += ai; + + u = a * Math.log(x); + if( (a+b) < MAXGAM && Math.abs(u) < MAXLOG ) { + t = Gamma.gamma(a+b)/(Gamma.gamma(a)*Gamma.gamma(b)); + s = s * t * Math.pow(x,a); + } else { + t = Gamma.logGamma(a+b) - Gamma.logGamma(a) - Gamma.logGamma(b) + u + Math.log(s); + if( t < MINLOG ) s = 0.0; + else s = Math.exp(t); + } + return s; +} +/** + * Returns the Gamma function computed by Stirling's formula; formerly named stirf. + * The polynomial STIR is valid for 33 <= x <= 172. + */ +static double stirlingFormula(double x) throws ArithmeticException { + double STIR[] = { + 7.87311395793093628397E-4, + -2.29549961613378126380E-4, + -2.68132617805781232825E-3, + 3.47222221605458667310E-3, + 8.33333333333482257126E-2, + }; + double MAXSTIR = 143.01608; + + double w = 1.0/x; + double y = Math.exp(x); + + w = 1.0 + w * Polynomial.polevl( w, STIR, 4 ); + + if( x > MAXSTIR ) { + /* Avoid overflow in Math.pow() */ + double v = Math.pow( x, 0.5 * x - 0.25 ); + y = v * (v / y); + } else { + y = Math.pow( x, x - 0.5 ) / y; + } + y = SQTPI * y * w; + return y; + } +} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Polynomial.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Polynomial.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Polynomial.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Polynomial.java 2009-11-22 07:57:56.000000000 +0000 @@ -0,0 +1,82 @@ +package org.mathpiper.builtin.library.cern; + + +/* +Copyright © 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ + + + +/** + * Polynomial functions. + */ +public class Polynomial extends Constants { +/** + * Makes this class non instantiable, but still let's others inherit from it. + */ +protected Polynomial() {} +/** + * Evaluates the given polynomial of degree N at x, assuming coefficient of N is 1.0. + * Otherwise same as polevl(). + *
+ *                     2          N
+ * y  =  C  + C x + C x  +...+ C x
+ *        0    1     2          N
+ *
+ * where C  = 1 and hence is omitted from the array.
+ *        N
+ *
+ * Coefficients are stored in reverse order:
+ *
+ * coef[0] = C  , ..., coef[N-1] = C  .
+ *            N-1                   0
+ *
+ * Calling arguments are otherwise the same as polevl().
+ * 
+ * In the interest of speed, there are no checks for out of bounds arithmetic. + * + * @param x argument to the polynomial. + * @param coef the coefficients of the polynomial. + * @param N the degree of the polynomial. + */ +public static double p1evl( double x, double coef[], int N ) throws ArithmeticException { + double ans; + + ans = x + coef[0]; + + for(int i=1; iN at x. + *
+ *                     2          N
+ * y  =  C  + C x + C x  +...+ C x
+ *        0    1     2          N
+ *
+ * Coefficients are stored in reverse order:
+ *
+ * coef[0] = C  , ..., coef[N] = C  .
+ *            N                   0
+ * 
+ * In the interest of speed, there are no checks for out of bounds arithmetic. + * + * @param x argument to the polynomial. + * @param coef the coefficients of the polynomial. + * @param N the degree of the polynomial. + */ +public static double polevl( double x, double coef[], int N ) throws ArithmeticException { + double ans; + ans = coef[0]; + + for(int i=1; i<=N; i++) ans = ans*x+coef[i]; + + return ans; +} +} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Probability.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Probability.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/cern/Probability.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/cern/Probability.java 2009-11-22 07:57:56.000000000 +0000 @@ -0,0 +1,767 @@ +package org.mathpiper.builtin.library.cern; + +/* +Copyright © 1999 CERN - European Organization for Nuclear Research. +Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose +is hereby granted without fee, provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in supporting documentation. +CERN makes no representations about the suitability of this software for any purpose. +It is provided "as is" without expressed or implied warranty. +*/ + + + +/** + * Custom tailored numerical integration of certain probability distributions. + *

+ * Implementation: + *

+ * Some code taken and adapted from the Java 2D Graph Package 2.4, + * which in turn is a port from the Cephes 2.2 Math Library (C). + * Most Cephes code (missing from the 2D Graph Package) directly ported. + * + * @author peter.gedeck@pharma.Novartis.com + * @author wolfgang.hoschek@cern.ch + * @version 0.91, 08-Dec-99 + */ +public class Probability extends Constants { + /************************************************* + * COEFFICIENTS FOR METHOD normalInverse() * + *************************************************/ + /* approximation for 0 <= |y - 0.5| <= 3/8 */ + protected static final double P0[] = { + -5.99633501014107895267E1, + 9.80010754185999661536E1, + -5.66762857469070293439E1, + 1.39312609387279679503E1, + -1.23916583867381258016E0, + }; + protected static final double Q0[] = { + /* 1.00000000000000000000E0,*/ + 1.95448858338141759834E0, + 4.67627912898881538453E0, + 8.63602421390890590575E1, + -2.25462687854119370527E2, + 2.00260212380060660359E2, + -8.20372256168333339912E1, + 1.59056225126211695515E1, + -1.18331621121330003142E0, + }; + + + /* Approximation for interval z = sqrt(-2 log y ) between 2 and 8 + * i.e., y between exp(-2) = .135 and exp(-32) = 1.27e-14. + */ + protected static final double P1[] = { + 4.05544892305962419923E0, + 3.15251094599893866154E1, + 5.71628192246421288162E1, + 4.40805073893200834700E1, + 1.46849561928858024014E1, + 2.18663306850790267539E0, + -1.40256079171354495875E-1, + -3.50424626827848203418E-2, + -8.57456785154685413611E-4, + }; + protected static final double Q1[] = { + /* 1.00000000000000000000E0,*/ + 1.57799883256466749731E1, + 4.53907635128879210584E1, + 4.13172038254672030440E1, + 1.50425385692907503408E1, + 2.50464946208309415979E0, + -1.42182922854787788574E-1, + -3.80806407691578277194E-2, + -9.33259480895457427372E-4, + }; + + /* Approximation for interval z = sqrt(-2 log y ) between 8 and 64 + * i.e., y between exp(-32) = 1.27e-14 and exp(-2048) = 3.67e-890. + */ + protected static final double P2[] = { + 3.23774891776946035970E0, + 6.91522889068984211695E0, + 3.93881025292474443415E0, + 1.33303460815807542389E0, + 2.01485389549179081538E-1, + 1.23716634817820021358E-2, + 3.01581553508235416007E-4, + 2.65806974686737550832E-6, + 6.23974539184983293730E-9, + }; + protected static final double Q2[] = { + /* 1.00000000000000000000E0,*/ + 6.02427039364742014255E0, + 3.67983563856160859403E0, + 1.37702099489081330271E0, + 2.16236993594496635890E-1, + 1.34204006088543189037E-2, + 3.28014464682127739104E-4, + 2.89247864745380683936E-6, + 6.79019408009981274425E-9, + }; + +/** + * Makes this class non instantiable, but still let's others inherit from it. + */ +protected Probability() {} +/** + * Returns the area from zero to x under the beta density + * function. + *
+ *                          x
+ *            -             -
+ *           | (a+b)       | |  a-1      b-1
+ * P(x)  =  ----------     |   t    (1-t)    dt
+ *           -     -     | |
+ *          | (a) | (b)   -
+ *                         0
+ * 
+ * This function is identical to the incomplete beta + * integral function Gamma.incompleteBeta(a, b, x). + * + * The complemented function is + * + * 1 - P(1-x) = Gamma.incompleteBeta( b, a, x ); + * + */ +static public double beta(double a, double b, double x ) { + return Gamma.incompleteBeta( a, b, x ); +} +/** + * Returns the area under the right hand tail (from x to + * infinity) of the beta density function. + * + * This function is identical to the incomplete beta + * integral function Gamma.incompleteBeta(b, a, x). + */ +static public double betaComplemented(double a, double b, double x ) { + return Gamma.incompleteBeta( b, a, x ); +} +/** + * Returns the sum of the terms 0 through k of the Binomial + * probability density. + *
+ *   k
+ *   --  ( n )   j      n-j
+ *   >   (   )  p  (1-p)
+ *   --  ( j )
+ *  j=0
+ * 
+ * The terms are not summed directly; instead the incomplete + * beta integral is employed, according to the formula + *

+ * y = binomial( k, n, p ) = Gamma.incompleteBeta( n-k, k+1, 1-p ). + *

+ * All arguments must be positive, + * @param k end term. + * @param n the number of trials. + * @param p the probability of success (must be in (0.0,1.0)). + */ +static public double binomial(int k, int n, double p) { + if( (p < 0.0) || (p > 1.0) ) throw new IllegalArgumentException(); + if( (k < 0) || (n < k) ) throw new IllegalArgumentException(); + + if( k == n ) return( 1.0 ); + if( k == 0 ) return Math.pow( 1.0-p, n-k ); + + return Gamma.incompleteBeta( n-k, k+1, 1.0 - p ); +} +/** + * Returns the sum of the terms k+1 through n of the Binomial + * probability density. + *

+ *   n
+ *   --  ( n )   j      n-j
+ *   >   (   )  p  (1-p)
+ *   --  ( j )
+ *  j=k+1
+ * 
+ * The terms are not summed directly; instead the incomplete + * beta integral is employed, according to the formula + *

+ * y = binomialComplemented( k, n, p ) = Gamma.incompleteBeta( k+1, n-k, p ). + *

+ * All arguments must be positive, + * @param k end term. + * @param n the number of trials. + * @param p the probability of success (must be in (0.0,1.0)). + */ +static public double binomialComplemented(int k, int n, double p) { + if( (p < 0.0) || (p > 1.0) ) throw new IllegalArgumentException(); + if( (k < 0) || (n < k) ) throw new IllegalArgumentException(); + + if( k == n ) return( 0.0 ); + if( k == 0 ) return 1.0 - Math.pow( 1.0-p, n-k ); + + return Gamma.incompleteBeta( k+1, n-k, p ); +} +/** + * Returns the area under the left hand tail (from 0 to x) + * of the Chi square probability density function with + * v degrees of freedom. + *

+ *                                  inf.
+ *                                    -
+ *                        1          | |  v/2-1  -t/2
+ *  P( x | v )   =   -----------     |   t      e     dt
+ *                    v/2  -       | |
+ *                   2    | (v/2)   -
+ *                                   x
+ * 
+ * where x is the Chi-square variable. + *

+ * The incomplete gamma integral is used, according to the + * formula + *

+ * y = chiSquare( v, x ) = incompleteGamma( v/2.0, x/2.0 ). + *

+ * The arguments must both be positive. + * + * @param v degrees of freedom. + * @param x integration end point. + */ +static public double chiSquare(double v, double x) throws ArithmeticException { + if( x < 0.0 || v < 1.0 ) return 0.0; + return Gamma.incompleteGamma( v/2.0, x/2.0 ); +} +/** + * Returns the area under the right hand tail (from x to + * infinity) of the Chi square probability density function + * with v degrees of freedom. + *

+ *                                  inf.
+ *                                    -
+ *                        1          | |  v/2-1  -t/2
+ *  P( x | v )   =   -----------     |   t      e     dt
+ *                    v/2  -       | |
+ *                   2    | (v/2)   -
+ *                                   x
+ * 
+ * where x is the Chi-square variable. + * + * The incomplete gamma integral is used, according to the + * formula + * + * y = chiSquareComplemented( v, x ) = incompleteGammaComplement( v/2.0, x/2.0 ). + * + * + * The arguments must both be positive. + * + * @param v degrees of freedom. + */ +static public double chiSquareComplemented(double v, double x) throws ArithmeticException { + if( x < 0.0 || v < 1.0 ) return 0.0; + return Gamma.incompleteGammaComplement( v/2.0, x/2.0 ); +} +/** + * Returns the error function of the normal distribution; formerly named erf. + * The integral is + *
+ *                           x
+ *                            -
+ *                 2         | |          2
+ *   erf(x)  =  --------     |    exp( - t  ) dt.
+ *              sqrt(pi)   | |
+ *                          -
+ *                           0
+ * 
+ * Implementation: + * For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise + * erf(x) = 1 - erfc(x). + *

+ * Code adapted from the Java 2D Graph Package 2.4, + * which in turn is a port from the Cephes 2.2 Math Library (C). + * + * @param a the argument to the function. + */ +static public double errorFunction(double x) throws ArithmeticException { + double y, z; + final double T[] = { + 9.60497373987051638749E0, + 9.00260197203842689217E1, + 2.23200534594684319226E3, + 7.00332514112805075473E3, + 5.55923013010394962768E4 + }; + final double U[] = { + //1.00000000000000000000E0, + 3.35617141647503099647E1, + 5.21357949780152679795E2, + 4.59432382970980127987E3, + 2.26290000613890934246E4, + 4.92673942608635921086E4 + }; + + if( Math.abs(x) > 1.0 ) return( 1.0 - errorFunctionComplemented(x) ); + z = x * x; + y = x * Polynomial.polevl( z, T, 4 ) / Polynomial.p1evl( z, U, 5 ); + return y; +} +/** + * Returns the complementary Error function of the normal distribution; formerly named erfc. + *

+ *  1 - erf(x) =
+ *
+ *                           inf.
+ *                             -
+ *                  2         | |          2
+ *   erfc(x)  =  --------     |    exp( - t  ) dt
+ *               sqrt(pi)   | |
+ *                           -
+ *                            x
+ * 
+ * Implementation: + * For small x, erfc(x) = 1 - erf(x); otherwise rational + * approximations are computed. + *

+ * Code adapted from the Java 2D Graph Package 2.4, + * which in turn is a port from the Cephes 2.2 Math Library (C). + * + * @param a the argument to the function. + */ +static public double errorFunctionComplemented(double a) throws ArithmeticException { + double x,y,z,p,q; + + double P[] = { + 2.46196981473530512524E-10, + 5.64189564831068821977E-1, + 7.46321056442269912687E0, + 4.86371970985681366614E1, + 1.96520832956077098242E2, + 5.26445194995477358631E2, + 9.34528527171957607540E2, + 1.02755188689515710272E3, + 5.57535335369399327526E2 + }; + double Q[] = { + //1.0 + 1.32281951154744992508E1, + 8.67072140885989742329E1, + 3.54937778887819891062E2, + 9.75708501743205489753E2, + 1.82390916687909736289E3, + 2.24633760818710981792E3, + 1.65666309194161350182E3, + 5.57535340817727675546E2 + }; + + double R[] = { + 5.64189583547755073984E-1, + 1.27536670759978104416E0, + 5.01905042251180477414E0, + 6.16021097993053585195E0, + 7.40974269950448939160E0, + 2.97886665372100240670E0 + }; + double S[] = { + //1.00000000000000000000E0, + 2.26052863220117276590E0, + 9.39603524938001434673E0, + 1.20489539808096656605E1, + 1.70814450747565897222E1, + 9.60896809063285878198E0, + 3.36907645100081516050E0 + }; + + if( a < 0.0 ) x = -a; + else x = a; + + if( x < 1.0 ) return 1.0 - errorFunction(a); + + z = -a * a; + + if( z < -MAXLOG ) { + if( a < 0 ) return( 2.0 ); + else return( 0.0 ); + } + + z = Math.exp(z); + + if( x < 8.0 ) { + p = Polynomial.polevl( x, P, 8 ); + q = Polynomial.p1evl( x, Q, 8 ); + } else { + p = Polynomial.polevl( x, R, 5 ); + q = Polynomial.p1evl( x, S, 6 ); + } + + y = (z * p)/q; + + if( a < 0 ) y = 2.0 - y; + + if( y == 0.0 ) { + if( a < 0 ) return 2.0; + else return( 0.0 ); + } + + return y; +} +/** + * Returns the integral from zero to x of the gamma probability + * density function. + *

+ *                x
+ *        b       -
+ *       a       | |   b-1  -at
+ * y =  -----    |    t    e    dt
+ *       -     | |
+ *      | (b)   -
+ *               0
+ * 
+ * The incomplete gamma integral is used, according to the + * relation + * + * y = Gamma.incompleteGamma( b, a*x ). + * + * @param a the paramater a (alpha) of the gamma distribution. + * @param b the paramater b (beta, lambda) of the gamma distribution. + * @param x integration end point. + */ +static public double gamma(double a, double b, double x ) { + if( x < 0.0 ) return 0.0; + return Gamma.incompleteGamma(b, a*x); +} +/** + * Returns the integral from x to infinity of the gamma + * probability density function: + *
+ *               inf.
+ *        b       -
+ *       a       | |   b-1  -at
+ * y =  -----    |    t    e    dt
+ *       -     | |
+ *      | (b)   -
+ *               x
+ * 
+ * The incomplete gamma integral is used, according to the + * relation + *

+ * y = Gamma.incompleteGammaComplement( b, a*x ). + * + * @param a the paramater a (alpha) of the gamma distribution. + * @param b the paramater b (beta, lambda) of the gamma distribution. + * @param x integration end point. + */ +static public double gammaComplemented(double a, double b, double x ) { + if( x < 0.0 ) return 0.0; + return Gamma.incompleteGammaComplement(b, a*x); +} +/** + * Returns the sum of the terms 0 through k of the Negative Binomial Distribution. + *

+ *   k
+ *   --  ( n+j-1 )   n      j
+ *   >   (       )  p  (1-p)
+ *   --  (   j   )
+ *  j=0
+ * 
+ * In a sequence of Bernoulli trials, this is the probability + * that k or fewer failures precede the n-th success. + *

+ * The terms are not computed individually; instead the incomplete + * beta integral is employed, according to the formula + *

+ * y = negativeBinomial( k, n, p ) = Gamma.incompleteBeta( n, k+1, p ). + * + * All arguments must be positive, + * @param k end term. + * @param n the number of trials. + * @param p the probability of success (must be in (0.0,1.0)). + */ +static public double negativeBinomial(int k, int n, double p) { + if( (p < 0.0) || (p > 1.0) ) throw new IllegalArgumentException(); + if(k < 0) return 0.0; + + return Gamma.incompleteBeta( n, k+1, p ); +} +/** + * Returns the sum of the terms k+1 to infinity of the Negative + * Binomial distribution. + *

+ *   inf
+ *   --  ( n+j-1 )   n      j
+ *   >   (       )  p  (1-p)
+ *   --  (   j   )
+ *  j=k+1
+ * 
+ * The terms are not computed individually; instead the incomplete + * beta integral is employed, according to the formula + *

+ * y = negativeBinomialComplemented( k, n, p ) = Gamma.incompleteBeta( k+1, n, 1-p ). + * + * All arguments must be positive, + * @param k end term. + * @param n the number of trials. + * @param p the probability of success (must be in (0.0,1.0)). + */ +static public double negativeBinomialComplemented(int k, int n, double p) { + if( (p < 0.0) || (p > 1.0) ) throw new IllegalArgumentException(); + if(k < 0) return 0.0; + + return Gamma.incompleteBeta( k+1, n, 1.0-p ); +} +/** + * Returns the area under the Normal (Gaussian) probability density + * function, integrated from minus infinity to x (assumes mean is zero, variance is one). + *

+ *                            x
+ *                             -
+ *                   1        | |          2
+ *  normal(x)  = ---------    |    exp( - t /2 ) dt
+ *               sqrt(2pi)  | |
+ *                           -
+ *                          -inf.
+ *
+ *             =  ( 1 + erf(z) ) / 2
+ *             =  erfc(z) / 2
+ * 
+ * where z = x/sqrt(2). + * Computation is via the functions errorFunction and errorFunctionComplement. + */ +static public double normal( double a) throws ArithmeticException { + double x, y, z; + + x = a * SQRTH; + z = Math.abs(x); + + if( z < SQRTH ) y = 0.5 + 0.5 * errorFunction(x); + else { + y = 0.5 * errorFunctionComplemented(z); + if( x > 0 ) y = 1.0 - y; + } + + return y; +} +/** + * Returns the area under the Normal (Gaussian) probability density + * function, integrated from minus infinity to x. + *
+ *                            x
+ *                             -
+ *                   1        | |                 2
+ *  normal(x)  = ---------    |    exp( - (t-mean) / 2v ) dt
+ *               sqrt(2pi*v)| |
+ *                           -
+ *                          -inf.
+ *
+ * 
+ * where v = variance. + * Computation is via the functions errorFunction. + * + * @param mean the mean of the normal distribution. + * @param variance the variance of the normal distribution. + * @param x the integration limit. + */ +static public double normal(double mean, double variance, double x) throws ArithmeticException { + if (x>0) + return 0.5 + 0.5*errorFunction((x-mean)/Math.sqrt(2.0*variance)); + else + return 0.5 - 0.5*errorFunction((-(x-mean))/Math.sqrt(2.0*variance)); +} +/** + * Returns the value, x, for which the area under the + * Normal (Gaussian) probability density function (integrated from + * minus infinity to x) is equal to the argument y (assumes mean is zero, variance is one); formerly named ndtri. + *

+ * For small arguments 0 < y < exp(-2), the program computes + * z = sqrt( -2.0 * log(y) ); then the approximation is + * x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). + * There are two rational functions P/Q, one for 0 < y < exp(-32) + * and the other for y up to exp(-2). + * For larger arguments, + * w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). + * + */ +static public double normalInverse( double y0) throws ArithmeticException { + double x, y, z, y2, x0, x1; + int code; + + final double s2pi = Math.sqrt(2.0*Math.PI); + + if( y0 <= 0.0 ) throw new IllegalArgumentException(); + if( y0 >= 1.0 ) throw new IllegalArgumentException(); + code = 1; + y = y0; + if( y > (1.0 - 0.13533528323661269189) ) { /* 0.135... = exp(-2) */ + y = 1.0 - y; + code = 0; + } + + if( y > 0.13533528323661269189 ) { + y = y - 0.5; + y2 = y * y; + x = y + y * (y2 * Polynomial.polevl( y2, P0, 4)/Polynomial.p1evl( y2, Q0, 8 )); + x = x * s2pi; + return(x); + } + + x = Math.sqrt( -2.0 * Math.log(y) ); + x0 = x - Math.log(x)/x; + + z = 1.0/x; + if( x < 8.0 ) /* y > exp(-32) = 1.2664165549e-14 */ + x1 = z * Polynomial.polevl( z, P1, 8 )/Polynomial.p1evl( z, Q1, 8 ); + else + x1 = z * Polynomial.polevl( z, P2, 8 )/Polynomial.p1evl( z, Q2, 8 ); + x = x0 - x1; + if( code != 0 ) + x = -x; + return( x ); +} +/** + * Returns the sum of the first k terms of the Poisson distribution. + *

+ *   k         j
+ *   --   -m  m
+ *   >   e    --
+ *   --       j!
+ *  j=0
+ * 
+ * The terms are not summed directly; instead the incomplete + * gamma integral is employed, according to the relation + *

+ * y = poisson( k, m ) = Gamma.incompleteGammaComplement( k+1, m ). + * + * The arguments must both be positive. + * + * @param k number of terms. + * @param mean the mean of the poisson distribution. + */ +static public double poisson(int k, double mean) throws ArithmeticException { + if( mean < 0 ) throw new IllegalArgumentException(); + if( k < 0 ) return 0.0; + return Gamma.incompleteGammaComplement((double)(k+1) ,mean); +} +/** + * Returns the sum of the terms k+1 to Infinity of the Poisson distribution. + *

+ *  inf.       j
+ *   --   -m  m
+ *   >   e    --
+ *   --       j!
+ *  j=k+1
+ * 
+ * The terms are not summed directly; instead the incomplete + * gamma integral is employed, according to the formula + *

+ * y = poissonComplemented( k, m ) = Gamma.incompleteGamma( k+1, m ). + * + * The arguments must both be positive. + * + * @param k start term. + * @param mean the mean of the poisson distribution. + */ +static public double poissonComplemented(int k, double mean) throws ArithmeticException { + if( mean < 0 ) throw new IllegalArgumentException(); + if( k < -1 ) return 0.0; + return Gamma.incompleteGamma((double)(k+1),mean); +} +/** + * Returns the integral from minus infinity to t of the Student-t + * distribution with k > 0 degrees of freedom. + *

+ *                                      t
+ *                                      -
+ *                                     | |
+ *              -                      |         2   -(k+1)/2
+ *             | ( (k+1)/2 )           |  (     x   )
+ *       ----------------------        |  ( 1 + --- )        dx
+ *                     -               |  (      k  )
+ *       sqrt( k pi ) | ( k/2 )        |
+ *                                   | |
+ *                                    -
+ *                                   -inf.
+ * 
+ * Relation to incomplete beta integral: + *

+ * 1 - studentT(k,t) = 0.5 * Gamma.incompleteBeta( k/2, 1/2, z ) + * where z = k/(k + t**2). + *

+ * Since the function is symmetric about t=0, the area under the + * right tail of the density is found by calling the function + * with -t instead of t. + * + * @param k degrees of freedom. + * @param t integration end point. + */ +static public double studentT(double k, double t) throws ArithmeticException { + if( k <= 0 ) throw new IllegalArgumentException(); + if( t == 0 ) return( 0.5 ); + + double cdf = 0.5 * Gamma.incompleteBeta( 0.5*k, 0.5, k / (k + t * t) ); + + if (t >= 0) cdf = 1.0 - cdf; // fixes bug reported by stefan.bentink@molgen.mpg.de + + return cdf; +} +/** + * Returns the value, t, for which the area under the + * Student-t probability density function (integrated from + * minus infinity to t) is equal to 1-alpha/2. + * The value returned corresponds to usual Student t-distribution lookup + * table for talpha[size]. + *

+ * The function uses the studentT function to determine the return + * value iteratively. + * + * @param alpha probability + * @param size size of data set + */ +public static double studentTInverse(double alpha, int size) { + double cumProb = 1-alpha/2; // Cumulative probability + double f1,f2,f3; + double x1,x2,x3; + double g,s12; + + cumProb = 1-alpha/2; // Cumulative probability + x1 = normalInverse(cumProb); + + // Return inverse of normal for large size + if (size > 200) { + return x1; + } + + // Find a pair of x1,x2 that braket zero + f1 = studentT(size,x1)-cumProb; + x2 = x1; f2 = f1; + do { + if (f1>0) { + x2 = x2/2; + } else { + x2 = x2+x1; + } + f2 = studentT(size,x2)-cumProb; + } while (f1*f2>0); + + // Find better approximation + // Pegasus-method + do { + // Calculate slope of secant and t value for which it is 0. + s12 = (f2-f1)/(x2-x1); + x3 = x2 - f2/s12; + + // Calculate function value at x3 + f3 = studentT(size,x3)-cumProb; + if (Math.abs(f3)<1e-8) { // This criteria needs to be very tight! + // We found a perfect value -> return + return x3; + } + + if (f3*f2<0) { + x1=x2; f1=f2; + x2=x3; f2=f3; + } else { + g = f2/(f2+f3); + f1=g*f1; + x2=x3; f2=f3; + } + } while(Math.abs(x2-x1)>0.001); + + if (Math.abs(f2)<=Math.abs(f1)) { + return x2; + } else { + return x1; + } +} +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JasAccess2.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JasAccess2.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JasAccess2.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JasAccess2.java 2010-05-17 04:27:36.000000000 +0000 @@ -0,0 +1,160 @@ +package org.mathpiper.builtin.library.jas; + +//------------------------------------------------------------------------ +// Factoring polynomials over Ring of Integer +// Version for interfacing with MathPiper +// (sherm experiments in here) +//------------------------------------------------------------------------ +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.List; +import java.util.Set; +import java.util.Iterator; + +import edu.jas.ufd.Factorization; +import edu.jas.ufd.FactorFactory; +import edu.jas.arith.BigInteger; +import edu.jas.arith.BigRational; +//import edu.jas.arith.BigComplex; +import edu.jas.kern.ComputerThreads; +import edu.jas.poly.GenPolynomial; +import edu.jas.poly.GenPolynomialRing; +import edu.jas.poly.TermOrder; +import edu.jas.util.StringUtil; + +//----------------------------------------------- +public class JasAccess2 { + + private boolean debug = false; + + private BigInteger bi; + + private Factorization fEngineBI; + + private GenPolynomial polyp; + + public JasAccess2() { + // define the "nominal" BigInteger as type prototype + bi = new BigInteger(1); + + // create a factorization engine suitable for BigInteger coefficient type + fEngineBI = FactorFactory.getImplementation(bi); + + }//end constructor. + + + + public Set factorPolyInt(String poly, String vars) { + if (debug) { + System.out.println(" poly = " + poly); + System.out.println(" vars = " + vars); + } + + // convert string of variable names to array of strings as required + String[] jvars = StringUtil.variableList(vars); + int nvars = jvars.length; + if (debug) { + System.out.print("\n number of variables: "); + System.out.println(nvars); + for (int i = 0; i < nvars; i++) { + System.out.print(" " + jvars[i]); + } + System.out.println(); + } + + // make sure term-order is INVLEX, as required + //TermOrder to = new TermOrder(TermOrder.INVLEX); + //if (debug) { + // System.out.println(" term-order = " + to); + //} + + + Factorization fEngine = fEngineBI; + if (debug) { + System.out.println("\nFactorization: fEngineBI = " + fEngineBI); + } + + // create appropriate Ring for BigIntegers with specified variable names + //GenPolynomialRing biRing = new GenPolynomialRing(bi, nvars, to, jvars); + GenPolynomialRing biRing = new GenPolynomialRing(bi, nvars, jvars); + if (debug) { + System.out.println("polynomial ring = " + biRing); + int nvars2 = biRing.nvar; + System.out.println(" number of variables for ring = " + nvars2); + String varNames = biRing.varsToString(); + System.out.println(" names of variables for ring = " + varNames); + } + + // --- Create polynomial in chosen Ring, from given string -- + if (debug) { + System.out.println("\nstrPoly = " + poly); + } + polyp = biRing.parse(poly); + //System.out.println("\npoly = " + polyp); + if (debug) { + int lenPoly = polyp.length(); + System.out.println(" length of poly = " + lenPoly); + int numVars = polyp.numberOfVariables(); + System.out.println(" number of variables in poly = " + numVars); + long degree = polyp.degree(); + System.out.println(" maximal degree of poly = " + degree); + } + + // --- JasAccess the polynomial --- + SortedMap, Long> Sm = fEngineBI.factors(polyp); + + // print info about factorization + /*int numFactors = Sm.size(); + System.out.println(" number of factors: " + numFactors); + */ + + // --- Print out all factors and their multiplicities --- + /*for (Map.Entry, Long> f : Sm.entrySet()) { + GenPolynomial factor = f.getKey(); + Long multiplicity = f.getValue(); + System.out.println(" ( " + factor + " , " + multiplicity + " )"); + }*/ + + + return (Set) Sm.entrySet(); + + + } // end method. + + + + public long maxDegree() { + return this.polyp.degree(); + } // end method + + + public void terminate() + { + ComputerThreads.terminate(); + } + + public boolean isDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + + + public static void main(String[] args) { + JasAccess2 jas = new JasAccess2(); + + jas.setDebug(true); + + Set resultSet = jas.factorPolyInt("x**2-9", "x"); + + jas.terminate(); + + }//end main. + + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JasAccess.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JasAccess.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JasAccess.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JasAccess.java 2010-05-05 07:19:54.000000000 +0000 @@ -0,0 +1,151 @@ +package org.mathpiper.builtin.library.jas; + +//------------------------------------------------------------------------ +// Factoring polynomials over Ring of Integer +// Version for interfacing with MathPiper +//------------------------------------------------------------------------ +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.List; +import java.util.Set; +import java.util.Iterator; + +import edu.jas.ufd.Factorization; +import edu.jas.ufd.FactorFactory; +import edu.jas.arith.BigInteger; +import edu.jas.arith.BigRational; +//import edu.jas.arith.BigComplex; +import edu.jas.kern.ComputerThreads; +import edu.jas.poly.GenPolynomial; +import edu.jas.poly.GenPolynomialRing; +import edu.jas.poly.TermOrder; +import edu.jas.util.StringUtil; + +//----------------------------------------------- +public class JasAccess { + + private boolean debug = false; + + private BigInteger bi; + + private Factorization fEngineBI; + + public JasAccess() { + // define the "nominal" BigInteger as type prototype + bi = new BigInteger(1); + + // create a factorization engine suitable for BigInteger coefficient type + fEngineBI = FactorFactory.getImplementation(bi); + + }//end constructor. + + + + public Set factorPolyInt(String poly, String vars) { + if (debug) { + System.out.println(" poly = " + poly); + System.out.println(" vars = " + vars); + } + + // convert string of variable names to array of strings as required + String[] jvars = StringUtil.variableList(vars); + int nvars = jvars.length; + if (debug) { + System.out.print("\n number of variables: "); + System.out.println(nvars); + for (int i = 0; i < nvars; i++) { + System.out.print(" " + jvars[i]); + } + System.out.println(); + } + + // make sure term-order is INVLEX, as required + TermOrder to = new TermOrder(TermOrder.INVLEX); + if (debug) { + System.out.println(" term-order = " + to); + } + + + Factorization fEngine = fEngineBI; + if (debug) { + System.out.println("\nFactorization: fEngineBI = " + fEngineBI); + } + + // create appropriate Ring for BigIntegers with specified variable names + GenPolynomialRing biRing = new GenPolynomialRing(bi, nvars, to, jvars); + if (debug) { + System.out.println("polynomial ring = " + biRing); + int nvars2 = biRing.nvar; + System.out.println(" number of variables for ring = " + nvars2); + String varNames = biRing.varsToString(); + System.out.println(" names of variables for ring = " + varNames); + } + + // --- Create polynomial in chosen Ring, from given string -- + if (debug) { + System.out.println("\nstrPoly = " + poly); + } + GenPolynomial polyp = biRing.parse(poly); + //System.out.println("\npoly = " + polyp); + if (debug) { + int lenPoly = polyp.length(); + System.out.println(" length of poly = " + lenPoly); + int numVars = polyp.numberOfVariables(); + System.out.println(" number of variables in poly = " + numVars); + long degree = polyp.degree(); + System.out.println(" maximal degree of poly = " + degree); + } + + // --- JasAccess the polynomial --- + SortedMap, Long> Sm = fEngineBI.factors(polyp); + + // print info about factorization + /*int numFactors = Sm.size(); + System.out.println(" number of factors: " + numFactors); + */ + + // --- Print out all factors and their multiplicities --- + /*for (Map.Entry, Long> f : Sm.entrySet()) { + GenPolynomial factor = f.getKey(); + Long multiplicity = f.getValue(); + System.out.println(" ( " + factor + " , " + multiplicity + " )"); + }*/ + + + return (Set) Sm.entrySet(); + + + }//end method. + + + + public void terminate() + { + ComputerThreads.terminate(); + } + + public boolean isDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + + + public static void main(String[] args) { + JasAccess jas = new JasAccess(); + + jas.setDebug(true); + + Set resultSet = jas.factorPolyInt("x**2-9", "x"); + + jas.terminate(); + + }//end main. + + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JasPolynomial.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JasPolynomial.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JasPolynomial.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JasPolynomial.java 2010-06-08 16:46:22.000000000 +0000 @@ -0,0 +1,212 @@ +package org.mathpiper.builtin.library.jas; + +//------------------------------------------------------------------------ +// Operations on JAS Polynomials of various types +// Version for interfacing with MathPiper +// Initial version: 05/13/2010 +// Modifications: through 05/20/2010 +//------------------------------------------------------------------------ +import java.util.Collections; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.List; +import java.util.Set; +import java.util.Iterator; + +import edu.jas.ufd.Factorization; +import edu.jas.ufd.FactorFactory; +import edu.jas.arith.BigInteger; +import edu.jas.arith.BigRational; +import edu.jas.arith.BigComplex; +import edu.jas.kern.ComputerThreads; +import edu.jas.poly.GenPolynomial; +import edu.jas.poly.GenPolynomialRing; +import edu.jas.poly.TermOrder; +import edu.jas.util.StringUtil; + +//------------------------------------------------------------------------ + +public class JasPolynomial { + + private boolean debug = true; + + private String ringName; + + private BigInteger bint; + private BigRational brat; + private BigComplex bcmplx; + + private GenPolynomialRing polyRing; + //private GenPolynomialRing polyRingExt; + + private GenPolynomial poly; + + private Factorization fEngine; + + private SortedMap factorsMap; + + // ----- CONSTRUCTORS ----- + + // no-argument constructor -- not to be used + protected JasPolynomial() { + } + + + // one-argument constructor -- specify polynomial Ring only + public JasPolynomial(String ringType) { + this(ringType,"x"); + } + + + // two-argument constructor -- specify polynomial Ring and varaible-names string + // varNames string looks like this: "x,y" + public JasPolynomial(String ringType, String varNames) { + this(ringType,varNames,"x^2-1"); + } + + + // three-argument constructor -- + // specify polynomial Ring, varaible-names string, and polynomial string + // varNames string looks like this: "x,y" + // polyString looks like this: "3*x^2-5*x+4" + public JasPolynomial(String ringType, String varNames, String polyString) { + ringName = ringType; + String [] varList = varNames.split(","); + if (ringName.equals("Integer")) { + bint = new BigInteger(1); + GenPolynomialRing bintRing = new GenPolynomialRing(bint,varList); + polyRing = (GenPolynomialRing)bintRing; + poly = polyRing.parse(polyString); + fEngine = FactorFactory.getImplementation(bint); + } + else if ( ringName.equals("Rational")) { + brat = new BigRational(1); + GenPolynomialRing bratRing = new GenPolynomialRing(brat,varList); + polyRing = (GenPolynomialRing)bratRing; + poly = polyRing.parse(polyString); + fEngine = FactorFactory.getImplementation(brat); + } + else if ( ringName.equals("Complex")) { + bcmplx = new BigComplex(1); + GenPolynomialRing cmplxRing = new GenPolynomialRing(bcmplx,varList); + polyRing = (GenPolynomialRing)cmplxRing; + poly = polyRing.parse(polyString); + fEngine = FactorFactory.getImplementation(bcmplx); + } + } + + + // ------ ACCESSORS ------ ------ ------ ------ ------ ------ + + // Get + + public boolean isDebug() { + return debug; + } + + public GenPolynomialRing getRing() { + return polyRing; + } + + public GenPolynomial getPolynomial() { + return poly; + } + + public Factorization getFactorizationEngine() { + return fEngine; + } + + public String getRingVariables() { + return polyRing.varsToString(); + } + + public boolean isIrreducible() { + return fEngine.isIrreducible(poly); + } + + public boolean isIrreducible( GenPolynomial p ) { + return fEngine.isIrreducible(p); + } + + + // Set + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public void addVars(String newVarsString) { + String[] newVars = newVarsString.split(","); + polyRing = polyRing.extend(newVars); + } + + public void setPolynomial(String polyString) { + poly = polyRing.parse(polyString); + } + + public void setPolynomial(String polyString, String newPolyVars) { + this.addVars(newPolyVars); + poly = polyRing.parse(polyString); + } + + + + // Other ------ --------------- --------------- ----------------- + + // factorization of this.poly + public SortedMap factors() { + if ( debug ) { + System.out.println(" DEBUG: in method factors()"); + System.out.flush(); + } + factorsMap = fEngine.factors(poly); + if ( debug ) { + System.out.println(" map of factors: " + factorsMap); + System.out.flush(); + } + return factorsMap; + } + + + // factorization of a new poly + + public SortedMap factorNewPolynomial(String polyString) { + if ( debug ) { + System.out.println(" DEBUG: in method factorNewPolynomial1()"); + System.out.flush(); + } + setPolynomial(polyString); + if ( debug ) { + System.out.println("\n the poly was changed to: " + getPolynomial().toScript()); + System.out.flush(); + } + factorsMap = factors(); + return factorsMap; + } + + + public SortedMap factorNewPolynomial(String polyString, String newPolyVars) { + if ( debug ) { + System.out.println(" DEBUG: in method factorNewPolynomial2()"); + System.out.flush(); + } + setPolynomial(polyString, newPolyVars); + if ( debug ) { + System.out.println("\n the poly was changed to: " + getPolynomial().toScript()); + System.out.println(" the ring variables are " + getRing().varsToString()); + System.out.flush(); + } + factorsMap = factors(); + return factorsMap; + } + + + // termination of all working threads + public void terminate(){ + ComputerThreads.terminate(); + } + + +}//end class JasPolynomial + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JFactorsPolyInt.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JFactorsPolyInt.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/JFactorsPolyInt.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/JFactorsPolyInt.java 2010-05-30 17:01:32.000000000 +0000 @@ -0,0 +1,108 @@ +package org.mathpiper.builtin.library.jas; + +//------------------------------------------------------------------------ +// Factor Polynomial over Integers, using JAS Library +// Version for interfacing with MathPiper +// Initial version: 05/24/2010 +//------------------------------------------------------------------------ +import java.util.Collections; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.List; +import java.util.Set; +import java.util.Iterator; + +import edu.jas.ufd.FactorInteger; +import edu.jas.arith.BigInteger; +import edu.jas.kern.ComputerThreads; +import edu.jas.poly.GenPolynomial; +import edu.jas.poly.GenPolynomialRing; +import edu.jas.poly.TermOrder; +import edu.jas.util.StringUtil; + +//------------------------------------------------------------------------ + +public class JFactorsPolyInt { + + private boolean debug = false; + private String ringName; + private BigInteger bint; + private GenPolynomialRing polyRing; + private GenPolynomial poly; + private FactorInteger fEngine; + private SortedMap factorsMap; + + // ----- CONSTRUCTORS ----- + + // no-argument constructor -- not to be used + protected JFactorsPolyInt() { + } + + // two-argument constructor -- + // specify polynomial as string, and varaible-names as string + // polyString looks like this: "3*x^2-5*x+4" + // varNames string looks like this: "x,y" + public JFactorsPolyInt(String polyString, String varNames) { + if ( debug ) { + System.out.println("JFactorsPolyInt " + polyString + " " + varNames); + } + String [] varList = varNames.split(","); + bint = new BigInteger(1); + GenPolynomialRing bintRing = new GenPolynomialRing(bint,varList); + poly = bintRing.parse(polyString); + fEngine = new FactorInteger(); + } + + + // factorization of this.poly + public SortedMap factors() { + factorsMap = fEngine.factors(poly); + return factorsMap; + } + + + // reducibility of this.poly + public boolean isReducible() { + return fEngine.isReducible(poly); + } + + + // termination of all working threads + public void terminate(){ + ComputerThreads.terminate(); + } + +/* + // M A I N + public static void main(String[] args) { + + boolean iDebug = false; + long T1 = System.currentTimeMillis(); + + String polyString = args[0]; + String varNames = args[1]; + + if ( iDebug ) { + System.out.println(" poly " + polyString); + System.out.println(" vars " + varNames); + System.out.flush(); + } + + JFactorsPolyInt jPoly = new JFactorsPolyInt(polyString,varNames); + SortedMap factorsMap = jPoly.factors(); + System.out.println("\nfactorsMap: " + factorsMap); + + System.out.println("\nisReducible: " + jPoly.isReducible()); + + jPoly.terminate(); + + long T2 = System.currentTimeMillis(); + float elapsedTimeSec = (T2-T1)/1000F; + System.out.println(" elapsed time : " + elapsedTimeSec + " sec\n"); + + } +*/ + +}//end class JFactorsPolyInt + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/Ring.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/Ring.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jas/Ring.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jas/Ring.java 2010-04-09 07:47:11.000000000 +0000 @@ -0,0 +1,61 @@ +package org.mathpiper.builtin.library.jas; + +//Represents a JAS polynomial ring: GenPolynomialRing. +import edu.jas.poly.GenPolynomialRing; +import edu.jas.poly.GenPolynomialTokenizer; +import edu.jas.poly.PolynomialList; +import edu.jas.ufd.FactorAbstract; +import edu.jas.ufd.FactorFactory; +import edu.jas.ufd.GCDFactory; +import edu.jas.ufd.GreatestCommonDivisorAbstract; +import edu.jas.ufd.SquarefreeAbstract; +import edu.jas.ufd.SquarefreeFactory; +import java.io.StringReader; +import java.util.List; +import org.mathpiper.lisp.Environment; + +//Methods to create ideals and ideals with parametric coefficients. +public class Ring { + + private Environment iEnvironment; + private PolynomialList pset; + private GenPolynomialRing ring; + private GreatestCommonDivisorAbstract engine; + private SquarefreeAbstract sqf; + private FactorAbstract factor; + + public Ring(Environment aEnvironment, String ringstr) throws Exception { + + this.iEnvironment = aEnvironment; + StringReader sr = new StringReader(ringstr); + GenPolynomialTokenizer tok = new GenPolynomialTokenizer(sr); + pset = tok.nextPolynomialSet(); + ring = pset.ring; + + engine = GCDFactory.getProxy(ring.coFac); + + sqf = SquarefreeFactory.getImplementation(ring.coFac); + + factor = FactorFactory.getImplementation(ring.coFac); + + }//end method. + + public List gens() throws Exception { + + /* + List genericPolynomials = ring.generators(); + List returnList = new ArrayList(); + for(GenPolynomial genericPolynomial: genericPolynomials) + { + returnList.add(new RingElem(genericPolynomial)); + }*/ + + return ring.generators(); + + } +}//end class. + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/AbstractMath.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/AbstractMath.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/AbstractMath.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/AbstractMath.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,12 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The AbstractMath superclass provides an abstract encapsulation of maths. +* All classes with a postfix of Math should extend this class. +* @version 1.0 +* @author Mark Hale +*/ +public abstract class AbstractMath extends Object { + protected AbstractMath() {} +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/BetaDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/BetaDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/BetaDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/BetaDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,66 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The BetaDistribution class provides an object for encapsulating beta distributions. +* @version 1.0 +* @author Jaco van Kooten +*/ +public final class BetaDistribution extends ProbabilityDistribution { + private double p,q; + + /** + * Constructs a beta distribution. + * @param dgrP degrees of freedom p. + * @param dgrQ degrees of freedom q. + */ + public BetaDistribution(double dgrP,double dgrQ) { + if(dgrP<=0 || dgrQ<=0) + throw new OutOfRangeException("The degrees of freedom must be greater than zero."); + p=dgrP; + q=dgrQ; + } + /** + * Returns the degrees of freedom p. + */ + public double getDegreesOfFreedomP() { + return p; + } + /** + * Returns the degrees of freedom q. + */ + public double getDegreesOfFreedomQ() { + return q; + } + /** + * Probability density function of a beta distribution. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X); + if(X==0.0 || X==1.0) + return 0.0; + return Math.exp(-SpecialMath.logBeta(p,q)+(p-1.0)*Math.log(X)+(q-1.0)*Math.log(1.0-X)); + } + /** + * Cumulative beta distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X); + return SpecialMath.incompleteBeta(X,p,q); + } + /** + * Inverse of the cumulative beta distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + if(probability==0.0) + return 0.0; + if(probability==1.0) + return 1.0; + return findRoot(probability, 0.5, 0.0, 1.0); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/BinomialDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/BinomialDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/BinomialDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/BinomialDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,80 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The BinomialDistribution class provides an object for encapsulating binomial distributions. +* @version 0.1 +* @author Mark Hale +*/ +public final class BinomialDistribution extends ProbabilityDistribution { + private int n; + private double p; + + /** + * Constructs a binomial distribution. + * @param trials the number of trials. + * @param prob the probability. + */ + public BinomialDistribution(int trials,double prob) { + if(trials<=0) + throw new OutOfRangeException("The number of trials should be (strictly) positive."); + n=trials; + if(prob<0.0 || prob>1.0) + throw new OutOfRangeException("The probability should be between 0 and 1."); + p=prob; + } + /** + * Returns the number of trials. + */ + public int getTrialsParameter() { + return n; + } + /** + * Returns the probability. + */ + public double getProbabilityParameter() { + return p; + } + /** + * Returns the mean. + */ + public double getMean() { + return n*p; + } + /** + * Returns the variance. + */ + public double getVariance() { + return n*p*(1.0-p); + } + /** + * Probability density function of a binomial distribution. + * @param X should be integer-valued. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,n); + return ExtraMath.binomial(n,X)*Math.pow(p,X)*Math.pow(1.0-p,n-X); + } + /** + * Cumulative binomial distribution function. + * @param X should be integer-valued. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,n); + double sum=0.0; + for(double i=0.0;i<=X;i++) + sum+=probability(i); + return sum; + } + /** + * Inverse of the cumulative binomial distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + return Math.floor(findRoot(probability,n/2.0,0.0,n)); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/CauchyDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/CauchyDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/CauchyDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/CauchyDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,66 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The CauchyDistribution class provides an object for encapsulating Cauchy distributions. +* @version 0.2 +* @author Mark Hale +*/ +public final class CauchyDistribution extends ProbabilityDistribution { + private double alpha; + private double gamma; + + /** + * Constructs the standard Cauchy distribution. + */ + public CauchyDistribution() { + this(0.0,1.0); + } + /** + * Constructs a Cauchy distribution. + * @param location the location parameter. + * @param scale the scale parameter. + */ + public CauchyDistribution(double location,double scale) { + if(scale<0.0) + throw new OutOfRangeException("The scale parameter should be positive."); + alpha=location; + gamma=scale; + } + /** + * Returns the location parameter. + */ + public double getLocationParameter() { + return alpha; + } + /** + * Returns the scale parameter. + */ + public double getScaleParameter() { + return gamma; + } + /** + * Probability density function of a Cauchy distribution. + * P(X) = Gamma/(pi(Gamma2+(X-alpha)2)). + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + final double y=X-alpha; + return gamma/(Math.PI*(gamma*gamma+y*y)); + } + /** + * Cumulative Cauchy distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + return 0.5+Math.atan((X-alpha)/gamma)/Math.PI; + } + /** + * Inverse of the cumulative Cauchy distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + return alpha-gamma/Math.tan(Math.PI*probability); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ChiSqrDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ChiSqrDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ChiSqrDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ChiSqrDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,56 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The ChiSqrDistribution class provides an object for encapsulating chi-squared distributions. +* @version 1.0 +* @author Jaco van Kooten +*/ +public final class ChiSqrDistribution extends ProbabilityDistribution { + private double r; +// The ChiSqr and Gamma distributions are closely related. + private GammaDistribution gamma; + + /** + * Constructs a chi-squared distribution. + * @param dgr degrees of freedom. + */ + public ChiSqrDistribution(double dgr) { + if(dgr<=0.0) + throw new OutOfRangeException("The degrees of freedom must be greater than zero."); + r=dgr; + gamma=new GammaDistribution(0.5*r); + } + /** + * Returns the degrees of freedom. + */ + public double getDegreesOfFreedom() { + return r; + } + /** + * Probability density function of a chi-squared distribution. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + return 0.5*gamma.probability(0.5*X); + } + /** + * Cumulative chi-squared distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return SpecialMath.incompleteGamma(0.5*r,0.5*X); + } + /** + * Inverse of the cumulative chi-squared distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + if(probability==1.0) + return Double.MAX_VALUE; + else + return 2.0*gamma.inverse(probability); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ExponentialDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ExponentialDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ExponentialDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ExponentialDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,80 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The ExponentialDistribution class provides an object for encapsulating exponential distributions. +* @version 0.2 +* @author Mark Hale +*/ +public final class ExponentialDistribution extends ProbabilityDistribution { + private double lambda; + + /** + * Constructs the standard exponential distribution. + */ + public ExponentialDistribution() { + this(1.0); + } + /** + * Constructs an exponential distribution. + * @param decay the scale parameter. + */ + public ExponentialDistribution(double decay) { + if(decay<0.0) + throw new OutOfRangeException("The scale parameter should be positive."); + lambda=decay; + } + /** + * Constructs an exponential distribution from a data set. + * @param array a sample. + */ + public ExponentialDistribution(double array[]) { + double sumX=array[0]; + for(int i=1;ie-lambdaX. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return lambda*Math.exp(-lambda*X); + } + /** + * Cumulative exponential distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return 1.0-Math.exp(-lambda*X); + } + /** + * Inverse of the cumulative exponential distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + return -Math.log(1.0-probability)/lambda; + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ExtraMath.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ExtraMath.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ExtraMath.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ExtraMath.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,346 @@ +package org.mathpiper.builtin.library.jscistats; + +/** + * The extra math library. + * Provides extra functions not in java.lang.Math class. + * This class cannot be subclassed or instantiated because all methods are static. + * @version 1.2 + * @author Mark Hale + */ +public final class ExtraMath extends AbstractMath { + private ExtraMath() {} + + /** + * Rounds a number to so many significant figures. + * @param x a number to be rounded. + * @param significant number of significant figures to round to. + */ + public static double round(final double x, final int significant) { + if(x == 0.0) + return x; + else if(significant == 0) + return 0.0; + final double signedExp = log10(Math.abs(x)) - significant; + if(signedExp < 0.0) { + // keep the exponent positive so factor is representable + final double factor = Math.pow(10.0, Math.floor(-signedExp)); + return Math.round(x*factor)/factor; + } else { + final double factor = Math.pow(10.0, Math.ceil(signedExp)); + return Math.round(x/factor)*factor; + } + } + /** + * Returns a random number within a specified range. + */ + public static double random(double min, double max) { + return (max-min)*Math.random()+min; + } + /** + * Returns the sign of a number. + * @return 1 if x>0.0, -1 if x<0.0, else 0. + */ + public static int sign(double x) { + if(x > 0.0) + return 1; + else if(x < 0.0) + return -1; + else + return 0; + } + /** + * Returns sqrt(x2+y2). + */ + public static double hypot(final double x,final double y) { + final double xAbs=Math.abs(x); + final double yAbs=Math.abs(y); + if(xAbs==0.0 && yAbs==0.0) + return 0.0; + else if(xAbsb. + * @param a an integer. + * @param b a positive integer. + */ + public static int pow(int a, int b) { + if(b < 0) { + throw new IllegalArgumentException(b+" must be a positive integer."); + } else if(b == 0) { + return 1; + } else { + if(a == 0) { + return 0; + } else if(a == 1) { + return 1; + } else if(a == 2) { + return 1<a. + * @param a a positive integer. + */ + public static int pow2(int a) { + return 1<double value. + *

The identity is: + *

coth(x) = (ex + e-x)/(ex - e-x), + + * in other words, {@linkplain Math#cosh cosh(x)}/{@linkplain Math#sinh sinh(x)}. + *

Special cases: + *

    + *
  • If the argument is NaN, then the result is NaN. + *
  • If the argument is zero, then the result is an infinity with the same sign as the argument. + *
  • If the argument is positive infinity, then the result is +1.0. + *
  • If the argument is negative infinity, then the result is -1.0. + *
+ * @param x The number whose hyperbolic cotangent is sought + * @return The hyperbolic cotangent of x + */ + public static double + coth(double x) { + return 1.0D/tanh(x); + } //coth + + /** + * Returns the hyperbolic cosecant of a double value. + *

The identity is: + *

csch(x) = (2/(ex - e-x), + * in other words, 1/{@linkplain Math#sinh sinh(x)}. + *

Special cases: + *

    + *
  • If the argument is NaN, then the result is NaN. + *
  • If the argument is zero, then the result is an infinity with the same sign as the argument. + *
  • If the argument is positive infinity, then the result is +0.0. + *
  • If the argument is negative infinity, then the result is -0.0. + *
+ * @param x The number whose hyperbolic cosecant is sought + * @return The hyperbolic cosecant of x + */ + public static double + csch(double x) { + return 1.0D/sinh(x); + } //csch + + /** + * Returns the hyperbolic secant of a double value. + *

The identity is: + *

sech(x) = (2/(ex + e-x), + * in other words, 1/{@linkplain Math#cosh cosh(x)}. + *

Special cases: + *

    + *
  • If the argument is NaN, then the result is NaN. + *
  • If the argument is an infinity (positive or negative), then the result is +0.0. + *
+ * @param x The number whose hyperbolic secant is sought + * @return The hyperbolic secant of x + */ + public static double + sech(double x) { + return 1.0D/cosh(x); + } //sech + + /** + * Returns the inverse hyperbolic sine of a double value. + *

The identity is: + *

asinh(x) = ln(x + sqrt(x2 + 1)) + *

Special cases: + *

    + *
  • If the argument is NaN, then the result is NaN. + *
  • If the argument is infinite, then the result is an infinity with the same sign as the argument. + *
  • If the argument is zero, then the result is a zero with the same sign as the argument. + *
+ * @param x The number whose inverse hyperbolic sine is sought + * @return The inverse hyperbolic sine of x + */ + public static double + asinh(double x) { + //Math.hypot(Double.NEGATIVE_INFINITY, 1.0D) is Double.POSITIVE_INFINITY + //return Double.isInfinite(x) ? x : (x == 0.0) ? x : Math.log(x + Math.hypot(x, 1.0D)); + return Double.isInfinite(x) ? x : (x == 0.0) ? x : Math.log(x+Math.sqrt(x*x+1.0)); + } //asinh + + /** + * Returns the inverse hyperbolic cosine of a double value. + * Note that cosh(�acosh(x)) = x; this function arbitrarily returns the positive branch. + *

The identity is: + *

acosh(x) = ln(x � sqrt(x2 - 1)) + *

Special cases: + *

    + *
  • If the argument is NaN or less than one, then the result is NaN. + *
  • If the argument is a positive infinity, then the result is (positive) infinity. + *
  • If the argument is one, then the result is (positive) zero. + *
+ * @param x The number whose inverse hyperbolic cosine is sought + * @return The inverse hyperbolic cosine of x + */ + public static double + acosh(double x) { + return Math.log(x + Math.sqrt(x*x - 1.0D)); + } //acosh + + /** + * Returns the inverse hyperbolic tangent of a double value. + *

The identity is: + *

atanh(x) = (1/2)*ln((1 + x)/(1 - x)) + *

Special cases: + *

    + *
  • If the argument is NaN, an infinity, or has a modulus of greater than one, then the result is NaN. + *
  • If the argument is plus or minus one, then the result is infinity with the same sign as the argument. + *
  • If the argument is zero, then the result is a zero with the same sign as the argument. + *
+ * @param x A double specifying the value whose inverse hyperbolic tangent is sought + * @return A double specifying the inverse hyperbolic tangent of x + */ + public static double + atanh(double x) { + //return (Math.log1p(x) - Math.log1p(-x))/2.0D; + return (x != 0.0) ? (Math.log(1.0D + x)-Math.log(1.0D - x))/2.0D : x; + } //atanh + + /** + * Returns the inverse hyperbolic cotangent of a double value. + *

The identity is: + *

acoth(x) = (1/2)*ln((x + 1)/(x - 1)) + *

Special cases: + *

    + *
  • If the argument is NaN or a modulus of less than one, then the result is NaN. + *
  • If the argument is an infinity, then the result is zero with the same sign as the argument. + *
  • If the argument is plus or minus one, then the result is infinity with the same sign as the argument. + *
+ * @param x The number whose inverse hyperbolic cotangent is sought + * @return The inverse hyperbolic cotangent of x + */ + public static double + acoth(double x) { +// return (Math.log1p(x) - Math.log(x - 1.0D))/2.0D; // Difference of two same-sign infinities is NaN + if (Double.isInfinite(x)) return (x < 0.0) ? -0.0D : +0.0D; + //return (x == -1.0D) ? Double.NEGATIVE_INFINITY : (Math.log1p(x) - Math.log(x - 1.0D))/2.0D; + return (x == -1.0D) ? Double.NEGATIVE_INFINITY : (Math.log(x+1.0) - Math.log(x - 1.0D))/2.0D; + } //acoth + + /** + * Returns the inverse hyperbolic cosecant of a double value. + *

The identity is: + *

acsch(x) = ln((1 - sqrt(1 + x2))/x) for x < 0; + *

acsch(x) = ln((1 + sqrt(1 + x2))/x) for x > 0. + *

Special cases: + *

    + *
  • If the argument is NaN, then the result is NaN. + *
  • If the argument is an infinity, then the result is zero with the same sign as the argument. + *
  • If the argument is zero, then the result is infinity with the same sign as the argument. + *
+ * @param x The number whose inverse hyperbolic cosecant is sought + * @return The inverse hyperbolic cosecant of x + */ + public static double + acsch(double x) { +// return (x < 0) ? Math.log((1.0D - Math.sqrt(Math.hypot(1.0, x)))/x) : Math.log((1.0D + Math.sqrt(1.0, x))/x); + + if (Double.isInfinite(x)) return (x < 0.0) ? -0.0D : +0.0D; + //log(+infinity) is +infinity, but log(-infinity) is NaN + return (x == 0.0D) ? 1.0/x : Math.log((1.0D + sign(x)*Math.sqrt(x*x+1.0))/x); + } //acsch + + /** + * Returns the inverse hyperbolic secant of a double value. + * Note that sech(�asech(x)) = x; this function arbitrarily returns the positive branch. + *

The identity is: + *

asech(x) = ln((1 + sqrt(1 - x2))/x). + *

Special cases: + *

    + *
  • If the argument is NaN, less than zero, or greater than one, then the result is NaN. + *
  • If the argument is zero, then the result is infinity with the same sign as the argument. + *
+ * @param x The number whose hyperbolic secant is sought + * @return The hyperbolic secant of x + */ + public static double + asech(double x) { + //log(+infinity) is +infinity, but log(-infinity) is NaN + return (x == 0.0D) ? 1.0/x : Math.log((1.0D + Math.sqrt(1.0D - x*x))/x); + } //asech +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/FDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/FDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/FDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/FDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,73 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The FDistribution class provides an object for encapsulating F-distributions. +* @version 1.0 +* @author Jaco van Kooten +*/ +public final class FDistribution extends ProbabilityDistribution { + private double p,q; +// We make use of the fact that when x has an F-distibution then +// y = p*x/(q+p*x) has a beta distribution with parameters p/2 and q/2. + private BetaDistribution beta; + + /** + * Constructs an F-distribution. + * @param dgrP degrees of freedom p. + * @param dgrQ degrees of freedom q. + */ + public FDistribution(double dgrP, double dgrQ) { + if(dgrP<=0.0 || dgrQ<=0.0) + throw new OutOfRangeException("The degrees of freedom must be greater than zero."); + p=dgrP; + q=dgrQ; + beta=new BetaDistribution(p/2.0, q/2.0); + } + /** + * Returns the degrees of freedom p. + */ + public double getDegreesOfFreedomP() { + return p; + } + /** + * Returns the degrees of freedom q. + */ + public double getDegreesOfFreedomQ() { + return q; + } + /** + * Probability density function of an F-distribution. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + final double y = q/(q+(p*X)); + return beta.probability(1.0-y)*y*y*p/q; + } + /** + * Cumulative F-distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return beta.cumulative((p*X)/(q+(p*X))); + } + /** + * Inverse of the cumulative F-distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + if(probability==0.0) + return 0.0; + if(probability==1.0) + return Double.MAX_VALUE; + final double y=beta.inverse(probability); + if(y<2.23e-308) //avoid overflow + return Double.MAX_VALUE; + else + return (q/p)*(y/(1.0-y)); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/GammaDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/GammaDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/GammaDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/GammaDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,72 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The GammaDistribution class provides an object for encapsulating gamma distributions. +* @version 1.0 +* @author Jaco van Kooten +*/ +public final class GammaDistribution extends ProbabilityDistribution { + private double shape; + + /** + * Constructs a gamma distribution. + * @param s the shape parameter. + */ + public GammaDistribution(double s) { + if(s<=0.0) + throw new OutOfRangeException("The shape parameter should be (strictly) positive."); + shape=s; + } + /** + * Returns the shape parameter. + */ + public double getShapeParameter() { + return shape; + } + /** + * Returns the mean. + */ + public double getMean() { + return shape; + } + /** + * Returns the variance. + */ + public double getVariance() { + return shape; + } + /** + * Probability density function of a gamma distribution. + * P(X) = Xs-1 e-X/Gamma(s). + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + if(X==0.0) + return 0.0; + else + return Math.exp(-SpecialMath.logGamma(shape)-X+(shape-1)*Math.log(X)); + } + /** + * Cumulative gamma distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return SpecialMath.incompleteGamma(shape,X); + } + /** + * Inverse of the cumulative gamma distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + if(probability==0.0) + return 0.0; + if(probability==1.0) + return Double.MAX_VALUE; + return findRoot(probability, shape, 0.0, Double.MAX_VALUE); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/GeometricDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/GeometricDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/GeometricDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/GeometricDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,68 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The GeometricDistribution class provides an object for encapsulating geometric distributions. +* @version 0.2 +* @author Mark Hale +*/ +public final class GeometricDistribution extends ProbabilityDistribution { + private double success; + private double failure; + + /** + * Constructs a geometric distribution. + * @param prob the probability of success. + */ + public GeometricDistribution(double prob) { + if(prob<0.0 || prob>1.0) + throw new OutOfRangeException("The probability should be between 0.0 and 1.0."); + success=prob; + failure=1.0-prob; + } + /** + * Returns the success parameter. + */ + public double getSuccessParameter() { + return success; + } + /** + * Returns the mean. + */ + public double getMean() { + return 1.0/success; + } + /** + * Returns the variance. + */ + public double getVariance() { + return failure/(success*success); + } + /** + * Probability density function of a geometric distribution. + * P(X) = p (1-p)X-1. + * @param X should be integer-valued. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return success*Math.pow(failure,X-1); + } + /** + * Cumulative geometric distribution function. + * @param X should be integer-valued. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return 1.0-Math.pow(failure,X); + } + /** + * Inverse of the cumulative geometric distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + return Math.log(1.0-probability)/Math.log(failure); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/LognormalDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/LognormalDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/LognormalDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/LognormalDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,61 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The LognormalDistribution class provides an object for encapsulating lognormal distributions. +* @version 0.1 +* @author Mark Hale +*/ +public final class LognormalDistribution extends ProbabilityDistribution { + private NormalDistribution normal; + + /** + * Constructs a standard lognormal distribution. + */ + public LognormalDistribution() { + this(0.0,1.0); + } + /** + * Constructs a lognormal distribution. + * @param mu the mu parameter. + * @param sigma the sigma parameter. + */ + public LognormalDistribution(double mu,double sigma) { + normal=new NormalDistribution(mu,sigma*sigma); + } + /** + * Returns the mu parameter. + */ + public double getMuParameter() { + return normal.getMean(); + } + /** + * Returns the sigma parameter. + */ + public double getSigmaParameter() { + return Math.sqrt(normal.getVariance()); + } + /** + * Probability density function of a lognormal distribution. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return normal.probability(Math.log(X))/X; + } + /** + * Cumulative lognormal distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return normal.cumulative(Math.log(X)); + } + /** + * Inverse of the cumulative lognormal distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + return Math.exp(normal.inverse(probability)); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/NormalDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/NormalDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/NormalDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/NormalDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,103 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The NormalDistribution class provides an object for encapsulating normal distributions. +* @version 1.1 +* @author Jaco van Kooten +*/ +public final class NormalDistribution extends ProbabilityDistribution implements NumericalConstants { + private double mean,variance; + private double pdfDenominator,cdfDenominator; + + /** + * Constructs the standard normal distribution (zero mean and unity variance). + */ + public NormalDistribution() { + this(0.0,1.0); + } + /** + * Constructs a normal distribution. + * @param mu the mean. + * @param var the variance. + */ + public NormalDistribution(double mu,double var) { + mean=mu; + if(var<=0.0) + throw new OutOfRangeException("The variance should be (strictly) positive."); + variance=var; + pdfDenominator=SQRT2PI*Math.sqrt(variance); + cdfDenominator=SQRT2*Math.sqrt(variance); + } + /** + * Constructs a normal distribution from a data set. + * @param array a sample. + * @author Mark Hale + */ + public NormalDistribution(double array[]) { + double sumX=array[0]; + double sumX2=array[0]*array[0]; + for(int i=1;i. + * @jsci.planetmath Pi + */ + double TWO_PI=6.2831853071795864769252867665590057683943387987502; + /** + * Square root of 2pi. + */ + double SQRT2PI=2.5066282746310005024157652848110452530069867406099; + /** + * Natural logarithm of 10. + */ + double LOG10=2.30258509299404568401799145468436420760110148862877; + /** + * Euler's gamma constant. + * @jsci.planetmath EulersConstant + */ + double GAMMA=0.57721566490153286060651209008240243104215933593992; + /** + * Golden ratio. + * @jsci.planetmath GoldenRatio + */ + double GOLDEN_RATIO=1.6180339887498948482045868343656381177203091798058; +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/OutOfRangeException.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/OutOfRangeException.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/OutOfRangeException.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/OutOfRangeException.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,21 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* This exception occurs if an argument in a statistics function is out-of-range. +* @version 1.0 +* @author Jaco van Kooten +*/ +public class OutOfRangeException extends IllegalArgumentException { + /** + * Constructs an OutOfRangeException with no detail message. + */ + public OutOfRangeException() { + } + /** + * Constructs an OutOfRangeException with the specified detail message. + */ + public OutOfRangeException(String s) { + super(s); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ParetoDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ParetoDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ParetoDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ParetoDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,77 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The ParetoDistribution class provides an object for encapsulating Pareto distributions. +* @version 0.2 +* @author Mark Hale +*/ +public final class ParetoDistribution extends ProbabilityDistribution { + private double shape; + private double scale; + + /** + * Constructs a Pareto distribution. + * @param sh the shape. + * @param sc the scale. + */ + public ParetoDistribution(double sh,double sc) { + if(sh<0.0) + throw new OutOfRangeException("The shape parameter should be positive."); + shape=sh; + if(sc<0.0) + throw new OutOfRangeException("The scale paremeter should be positive."); + scale=sc; + } + /** + * Returns the shape parameter. + */ + public double getShapeParameter() { + return shape; + } + /** + * Returns the scale parameter. + */ + public double getScaleParameter() { + return scale; + } + /** + * Returns the mean. + */ + public double getMean() { + return shape*scale/(shape-1.0); + } + /** + * Returns the variance. + */ + public double getVariance() { + return shape*scale*scale/((shape-2.0)*(shape-1.0)*(shape-1.0)); + } + /** + * Probability density function of a Pareto distribution. + * P(X) = (a/X) (s/X)a. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + if(XXe-lambda/X!. + * @param X should be integer-valued. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return Math.exp(X*Math.log(lambda)-lambda-ExtraMath.logFactorial(X)); + } + /** + * Cumulative Poisson distribution function. + * @param X should be integer-valued. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + double sum=0.0; + for(double i=0.0;i<=X;i++) + sum+=probability(i); + return sum; + } + /** + * Inverse of the cumulative Poisson distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + return Math.round(findRoot(probability,lambda,0.0,Double.MAX_VALUE)); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ProbabilityDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ProbabilityDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/ProbabilityDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/ProbabilityDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,83 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The ProbabilityDistribution superclass provides an object for encapsulating probability distributions. +* @version 1.0 +* @author Jaco van Kooten +*/ +public abstract class ProbabilityDistribution extends Object { + /** + * Constructs a probability distribution. + */ + public ProbabilityDistribution() {} + /** + * Probability density function. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public abstract double probability(double X); + /** + * Cumulative distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public abstract double cumulative(double X); + /** + * Inverse of the cumulative distribution function. + * @return the value X for which P(x<X). + */ + public abstract double inverse(double probability); + /** + * Check if the range of the argument of the distribution method is between lo and hi. + * @exception OutOfRangeException If the argument is out of range. + */ + protected final void checkRange(double x, double lo, double hi) { + if(xhi) + throw new OutOfRangeException("The argument of the distribution method should be between "+lo+" and "+hi+"."); + } + /** + * Check if the range of the argument of the distribution method is between 0.0 and 1.0. + * @exception OutOfRangeException If the argument is out of range. + */ + protected final void checkRange(double x) { + if(x<0.0 || x>1.0) + throw new OutOfRangeException("The argument of the distribution method should be between 0.0 and 1.0."); + } + + private static final double FINDROOT_ACCURACY = 1.0e-15; + private static final int FINDROOT_MAX_ITERATIONS = 150; + /** + * This method approximates the value of X for which P(x<X)=prob. + * It applies a combination of a Newton-Raphson procedure and bisection method + * with the value guess as a starting point. Furthermore, to ensure convergency + * and stability, one should supply an inverval [xLo,xHi] in which the probalility + * distribution reaches the value prob. The method does no checking, it will produce + * bad results if wrong values for the parameters are supplied - use it with care. + */ + protected final double findRoot(double prob,double guess,double xLo,double xHi) { + double x=guess,xNew=guess; + double error,pdf,dx=1.0; + int i=0; + while(Math.abs(dx)>FINDROOT_ACCURACY && i++xHi || pdf==0.0) { + xNew=(xLo+xHi)/2.0; + dx=xNew-x; + } + x=xNew; + } + return x; + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/SpecialMath.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/SpecialMath.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/SpecialMath.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/SpecialMath.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,1564 @@ +package org.mathpiper.builtin.library.jscistats; + +/** +* The special function math library. +* This class cannot be subclassed or instantiated because all methods are static. +* @version 1.2 +* @author Mark Hale +*/ +public final class SpecialMath extends AbstractMath implements NumericalConstants { + private SpecialMath() {} + +// Some IEEE machine constants + /** + * Relative machine precision. + */ + private final static double EPS=2.22e-16; + /** + * The smallest positive floating-point number such that 1/xminin is machine representable. + */ + private final static double XMININ=2.23e-308; + + +// CHEBYSHEV SERIES + +// series for ai0 on the interval 1.25000d-01 to 3.33333d-01 +// with weighted error 7.87e-17 +// log weighted error 16.10 +// significant figures required 14.69 +// decimal places required 16.76 + + private final static double ai0cs[]={ + 0.07575994494023796, + 0.00759138081082334, + 0.00041531313389237, + 0.00001070076463439, + -0.00000790117997921, + -0.00000078261435014, + 0.00000027838499429, + 0.00000000825247260, + -0.00000001204463945, + 0.00000000155964859, + 0.00000000022925563, + -0.00000000011916228, + 0.00000000001757854, + 0.00000000000112822, + -0.00000000000114684, + 0.00000000000027155, + -0.00000000000002415, + -0.00000000000000608, + 0.00000000000000314, + -0.00000000000000071, + 0.00000000000000007}; + +// series for ai02 on the interval 0. to 1.25000d-01 +// with weighted error 3.79e-17 +// log weighted error 16.42 +// significant figures required 14.86 +// decimal places required 17.09 + private final static double ai02cs[]={ + 0.05449041101410882, + 0.00336911647825569, + 0.00006889758346918, + 0.00000289137052082, + 0.00000020489185893, + 0.00000002266668991, + 0.00000000339623203, + 0.00000000049406022, + 0.00000000001188914, + -0.00000000003149915, + -0.00000000001321580, + -0.00000000000179419, + 0.00000000000071801, + 0.00000000000038529, + 0.00000000000001539, + -0.00000000000004151, + -0.00000000000000954, + 0.00000000000000382, + 0.00000000000000176, + -0.00000000000000034, + -0.00000000000000027, + 0.00000000000000003}; + +// series for ai1 on the interval 1.25000d-01 to 3.33333d-01 +// with weighted error 6.98e-17 +// log weighted error 16.16 +// significant figures required 14.53 +// decimal places required 16.82 + + private final static double ai1cs[]={ + -0.02846744181881479, + -0.01922953231443221, + -0.00061151858579437, + -0.00002069971253350, + 0.00000858561914581, + 0.00000104949824671, + -0.00000029183389184, + -0.00000001559378146, + 0.00000001318012367, + -0.00000000144842341, + -0.00000000029085122, + 0.00000000012663889, + -0.00000000001664947, + -0.00000000000166665, + 0.00000000000124260, + -0.00000000000027315, + 0.00000000000002023, + 0.00000000000000730, + -0.00000000000000333, + 0.00000000000000071, + -0.00000000000000006}; + +// series for ai12 on the interval 0. to 1.25000d-01 +// with weighted error 3.55e-17 +// log weighted error 16.45 +// significant figures required 14.69 +// decimal places required 17.12 + + private final static double ai12cs[]={ + 0.02857623501828014, + -0.00976109749136147, + -0.00011058893876263, + -0.00000388256480887, + -0.00000025122362377, + -0.00000002631468847, + -0.00000000383538039, + -0.00000000055897433, + -0.00000000001897495, + 0.00000000003252602, + 0.00000000001412580, + 0.00000000000203564, + -0.00000000000071985, + -0.00000000000040836, + -0.00000000000002101, + 0.00000000000004273, + 0.00000000000001041, + -0.00000000000000382, + -0.00000000000000186, + 0.00000000000000033, + 0.00000000000000028, + -0.00000000000000003}; + +// series for aif on the interval -1.00000d+00 to 1.00000d+00 +// with weighted error 1.09e-19 +// log weighted error 18.96 +// significant figures required 17.76 +// decimal places required 19.44 + + private final static double aifcs[]={ + -0.03797135849666999750, + 0.05919188853726363857, + 0.00098629280577279975, + 0.00000684884381907656, + 0.00000002594202596219, + 0.00000000006176612774, + 0.00000000000010092454, + 0.00000000000000012014, + 0.00000000000000000010}; + +// series for aig on the interval -1.00000d+00 to 1.00000d+00 +// with weighted error 1.51e-17 +// log weighted error 16.82 +// significant figures required 15.19 +// decimal places required 17.27 + + private final static double aigcs[]={ + 0.01815236558116127, + 0.02157256316601076, + 0.00025678356987483, + 0.00000142652141197, + 0.00000000457211492, + 0.00000000000952517, + 0.00000000000001392, + 0.00000000000000001}; + +// series for aip on the interval 0. to 1.00000d+00 +// with weighted error 5.10e-17 +// log weighted error 16.29 +// significant figures required 14.41 +// decimal places required 17.06 + + private final static double aipcs[]={ + -0.0187519297793868, + -0.0091443848250055, + 0.0009010457337825, + -0.0001394184127221, + 0.0000273815815785, + -0.0000062750421119, + 0.0000016064844184, + -0.0000004476392158, + 0.0000001334635874, + -0.0000000420735334, + 0.0000000139021990, + -0.0000000047831848, + 0.0000000017047897, + -0.0000000006268389, + 0.0000000002369824, + -0.0000000000918641, + 0.0000000000364278, + -0.0000000000147475, + 0.0000000000060851, + -0.0000000000025552, + 0.0000000000010906, + -0.0000000000004725, + 0.0000000000002076, + -0.0000000000000924, + 0.0000000000000417, + -0.0000000000000190, + 0.0000000000000087, + -0.0000000000000040, + 0.0000000000000019, + -0.0000000000000009, + 0.0000000000000004, + -0.0000000000000002, + 0.0000000000000001, + -0.0000000000000000}; + +// series for am21 on the interval -1.25000d-01 to 0. +// with weighted error 2.89e-17 +// log weighted error 16.54 +// significant figures required 14.15 +// decimal places required 17.34 + + private final static double am21cs[]={ + 0.0065809191761485, + 0.0023675984685722, + 0.0001324741670371, + 0.0000157600904043, + 0.0000027529702663, + 0.0000006102679017, + 0.0000001595088468, + 0.0000000471033947, + 0.0000000152933871, + 0.0000000053590722, + 0.0000000020000910, + 0.0000000007872292, + 0.0000000003243103, + 0.0000000001390106, + 0.0000000000617011, + 0.0000000000282491, + 0.0000000000132979, + 0.0000000000064188, + 0.0000000000031697, + 0.0000000000015981, + 0.0000000000008213, + 0.0000000000004296, + 0.0000000000002284, + 0.0000000000001232, + 0.0000000000000675, + 0.0000000000000374, + 0.0000000000000210, + 0.0000000000000119, + 0.0000000000000068, + 0.0000000000000039, + 0.0000000000000023, + 0.0000000000000013, + 0.0000000000000008, + 0.0000000000000005, + 0.0000000000000003, + 0.0000000000000001, + 0.0000000000000001, + 0.0000000000000000, + 0.0000000000000000, + 0.0000000000000000}; + +// series for ath1 on the interval -1.25000d-01 to 0. +// with weighted error 2.53e-17 +// log weighted error 16.60 +// significant figures required 15.15 +// decimal places required 17.38 + + private final static double ath1cs[]={ + -0.07125837815669365, + -0.00590471979831451, + -0.00012114544069499, + -0.00000988608542270, + -0.00000138084097352, + -0.00000026142640172, + -0.00000006050432589, + -0.00000001618436223, + -0.00000000483464911, + -0.00000000157655272, + -0.00000000055231518, + -0.00000000020545441, + -0.00000000008043412, + -0.00000000003291252, + -0.00000000001399875, + -0.00000000000616151, + -0.00000000000279614, + -0.00000000000130428, + -0.00000000000062373, + -0.00000000000030512, + -0.00000000000015239, + -0.00000000000007758, + -0.00000000000004020, + -0.00000000000002117, + -0.00000000000001132, + -0.00000000000000614, + -0.00000000000000337, + -0.00000000000000188, + -0.00000000000000105, + -0.00000000000000060, + -0.00000000000000034, + -0.00000000000000020, + -0.00000000000000011, + -0.00000000000000007, + -0.00000000000000004, + -0.00000000000000002}; + +// series for am22 on the interval -1.00000d+00 to -1.25000d-01 +// with weighted error 2.99e-17 +// log weighted error 16.52 +// significant figures required 14.57 +// decimal places required 17.28 + + private final static double am22cs[]={ + -0.01562844480625341, + 0.00778336445239681, + 0.00086705777047718, + 0.00015696627315611, + 0.00003563962571432, + 0.00000924598335425, + 0.00000262110161850, + 0.00000079188221651, + 0.00000025104152792, + 0.00000008265223206, + 0.00000002805711662, + 0.00000000976821090, + 0.00000000347407923, + 0.00000000125828132, + 0.00000000046298826, + 0.00000000017272825, + 0.00000000006523192, + 0.00000000002490471, + 0.00000000000960156, + 0.00000000000373448, + 0.00000000000146417, + 0.00000000000057826, + 0.00000000000022991, + 0.00000000000009197, + 0.00000000000003700, + 0.00000000000001496, + 0.00000000000000608, + 0.00000000000000248, + 0.00000000000000101, + 0.00000000000000041, + 0.00000000000000017, + 0.00000000000000007, + 0.00000000000000002}; + +// series for ath2 on the interval -1.00000d+00 to -1.25000d-01 +// with weighted error 2.57e-17 +// log weighted error 16.59 +// significant figures required 15.07 +// decimal places required 17.34 + + private final static double ath2cs[]={ + 0.00440527345871877, + -0.03042919452318455, + -0.00138565328377179, + -0.00018044439089549, + -0.00003380847108327, + -0.00000767818353522, + -0.00000196783944371, + -0.00000054837271158, + -0.00000016254615505, + -0.00000005053049981, + -0.00000001631580701, + -0.00000000543420411, + -0.00000000185739855, + -0.00000000064895120, + -0.00000000023105948, + -0.00000000008363282, + -0.00000000003071196, + -0.00000000001142367, + -0.00000000000429811, + -0.00000000000163389, + -0.00000000000062693, + -0.00000000000024260, + -0.00000000000009461, + -0.00000000000003716, + -0.00000000000001469, + -0.00000000000000584, + -0.00000000000000233, + -0.00000000000000093, + -0.00000000000000037, + -0.00000000000000015, + -0.00000000000000006, + -0.00000000000000002}; + +// series for bi0 on the interval 0. to 9.00000d+00 +// with weighted error 2.46e-18 +// log weighted error 17.61 +// significant figures required 17.90 +// decimal places required 18.15 + + private final static double bi0cs[]={ + -0.07660547252839144951, + 1.927337953993808270, + 0.2282644586920301339, + 0.01304891466707290428, + 0.00043442709008164874, + 0.00000942265768600193, + 0.00000014340062895106, + 0.00000000161384906966, + 0.00000000001396650044, + 0.00000000000009579451, + 0.00000000000000053339, + 0.00000000000000000245}; + +// series for bj0 on the interval 0. to 1.60000d+01 +// with weighted error 7.47e-18 +// log weighted error 17.13 +// significant figures required 16.98 +// decimal places required 17.68 + + private final static double bj0cs[]={ + 0.100254161968939137, + -0.665223007764405132, + 0.248983703498281314, + -0.0332527231700357697, + 0.0023114179304694015, + -0.0000991127741995080, + 0.0000028916708643998, + -0.0000000612108586630, + 0.0000000009838650793, + -0.0000000000124235515, + 0.0000000000001265433, + -0.0000000000000010619, + 0.0000000000000000074}; + +// series for bm0 on the interval 0. to 6.25000d-02 +// with weighted error 4.98e-17 +// log weighted error 16.30 +// significant figures required 14.97 +// decimal places required 16.96 + + private final static double bm0cs[]={ + 0.09284961637381644, + -0.00142987707403484, + 0.00002830579271257, + -0.00000143300611424, + 0.00000012028628046, + -0.00000001397113013, + 0.00000000204076188, + -0.00000000035399669, + 0.00000000007024759, + -0.00000000001554107, + 0.00000000000376226, + -0.00000000000098282, + 0.00000000000027408, + -0.00000000000008091, + 0.00000000000002511, + -0.00000000000000814, + 0.00000000000000275, + -0.00000000000000096, + 0.00000000000000034, + -0.00000000000000012, + 0.00000000000000004}; + +// series for bth0 on the interval 0. to 6.25000d-02 +// with weighted error 3.67e-17 +// log weighted error 16.44 +// significant figures required 15.53 +// decimal places required 17.13 + + private final static double bth0cs[]={ + -0.24639163774300119, + 0.001737098307508963, + -0.000062183633402968, + 0.000004368050165742, + -0.000000456093019869, + 0.000000062197400101, + -0.000000010300442889, + 0.000000001979526776, + -0.000000000428198396, + 0.000000000102035840, + -0.000000000026363898, + 0.000000000007297935, + -0.000000000002144188, + 0.000000000000663693, + -0.000000000000215126, + 0.000000000000072659, + -0.000000000000025465, + 0.000000000000009229, + -0.000000000000003448, + 0.000000000000001325, + -0.000000000000000522, + 0.000000000000000210, + -0.000000000000000087, + 0.000000000000000036}; + +// series for by0 on the interval 0. to 1.60000d+01 +// with weighted error 1.20e-17 +// log weighted error 16.92 +// significant figures required 16.15 +// decimal places required 17.48 + + private final static double by0cs[]={ + -0.011277839392865573, + -0.12834523756042035, + -0.10437884799794249, + 0.023662749183969695, + -0.002090391647700486, + 0.000103975453939057, + -0.000003369747162423, + 0.000000077293842676, + -0.000000001324976772, + 0.000000000017648232, + -0.000000000000188105, + 0.000000000000001641, + -0.000000000000000011}; + +// series for bi1 on the interval 0. to 9.00000d+00 +// with weighted error 2.40e-17 +// log weighted error 16.62 +// significant figures required 16.23 +// decimal places required 17.14 + + private final static double bi1cs[]={ + -0.001971713261099859, + 0.40734887667546481, + 0.034838994299959456, + 0.001545394556300123, + 0.000041888521098377, + 0.000000764902676483, + 0.000000010042493924, + 0.000000000099322077, + 0.000000000000766380, + 0.000000000000004741, + 0.000000000000000024}; + +// series for bj1 on the interval 0. to 1.60000d+01 +// with weighted error 4.48e-17 +// log weighted error 16.35 +// significant figures required 15.77 +// decimal places required 16.89 + + private final static double bj1cs[]={ + -0.11726141513332787, + -0.25361521830790640, + 0.050127080984469569, + -0.004631514809625081, + 0.000247996229415914, + -0.000008678948686278, + 0.000000214293917143, + -0.000000003936093079, + 0.000000000055911823, + -0.000000000000632761, + 0.000000000000005840, + -0.000000000000000044}; + +// series for bm1 on the interval 0. to 6.25000d-02 +// with weighted error 5.61e-17 +// log weighted error 16.25 +// significant figures required 14.97 +// decimal places required 16.91 + + private final static double bm1cs[]={ + 0.1047362510931285, + 0.00442443893702345, + -0.00005661639504035, + 0.00000231349417339, + -0.00000017377182007, + 0.00000001893209930, + -0.00000000265416023, + 0.00000000044740209, + -0.00000000008691795, + 0.00000000001891492, + -0.00000000000451884, + 0.00000000000116765, + -0.00000000000032265, + 0.00000000000009450, + -0.00000000000002913, + 0.00000000000000939, + -0.00000000000000315, + 0.00000000000000109, + -0.00000000000000039, + 0.00000000000000014, + -0.00000000000000005}; + +// series for bth1 on the interval 0. to 6.25000d-02 +// with weighted error 4.10e-17 +// log weighted error 16.39 +// significant figures required 15.96 +// decimal places required 17.08 + + private final static double bth1cs[]={ + 0.74060141026313850, + -0.004571755659637690, + 0.000119818510964326, + -0.000006964561891648, + 0.000000655495621447, + -0.000000084066228945, + 0.000000013376886564, + -0.000000002499565654, + 0.000000000529495100, + -0.000000000124135944, + 0.000000000031656485, + -0.000000000008668640, + 0.000000000002523758, + -0.000000000000775085, + 0.000000000000249527, + -0.000000000000083773, + 0.000000000000029205, + -0.000000000000010534, + 0.000000000000003919, + -0.000000000000001500, + 0.000000000000000589, + -0.000000000000000237, + 0.000000000000000097, + -0.000000000000000040}; + +// series for by1 on the interval 0. to 1.60000d+01 +// with weighted error 1.87e-18 +// log weighted error 17.73 +// significant figures required 17.83 +// decimal places required 18.30 + + private final static double by1cs[]={ + 0.03208047100611908629, + 1.262707897433500450, + 0.00649996189992317500, + -0.08936164528860504117, + 0.01325088122175709545, + -0.00089790591196483523, + 0.00003647361487958306, + -0.00000100137438166600, + 0.00000001994539657390, + -0.00000000030230656018, + 0.00000000000360987815, + -0.00000000000003487488, + 0.00000000000000027838, + -0.00000000000000000186}; + + + + /** + * Evaluates a Chebyshev series. + * @param x value at which to evaluate series + * @param series the coefficients of the series + */ + public static double chebyshev(double x, double series[]) { + double twox,b0=0.0,b1=0.0,b2=0.0; + twox=2*x; + for(int i=series.length-1;i>-1;i--) { + b2=b1; + b1=b0; + b0=twox*b1-b2+series[i]; + } + return 0.5*(b0-b2); + } + /** + * Airy function. + * Based on the NETLIB Fortran function ai written by W. Fullerton. + */ + public static double airy(double x) { + if(x<-1.0) { + return airyModPhase(x); + } else if(x>1.0) + return expAiry(x)*Math.exp(-2.0*x*Math.sqrt(x)/3.0); + else { + final double z=x*x*x; + return 0.375+(chebyshev(z,aifcs)-x*(0.25+chebyshev(z,aigcs))); + } + } + /** + * Airy modulus and phase. + * Based on the NETLIB Fortran subroutine r9aimp written by W. Fullerton. + * @return the real part, i.e. modulus*cos(phase). + */ + private static double airyModPhase(double x) { + double modulus, phase; + if(x < -2.0) { + double z = 16.0/(x*x*x)+1.0; + modulus = 0.3125+chebyshev(z, am21cs); + phase = -0.625+chebyshev(z, ath1cs); + } else { + double z = (16.0/(x*x*x)+9.0)/7.0; + modulus = 0.3125+chebyshev(z, am22cs); + phase = -0.625+chebyshev(z, ath2cs); + } + final double sqrtx = Math.sqrt(-x); + modulus = Math.sqrt(modulus/sqrtx); + phase = Math.PI/4.0-x*sqrtx*phase; + return modulus*Math.cos(phase); + } + /** + * Exponential scaled Airy function. + * Based on the NETLIB Fortran function aie written by W. Fullerton. + */ + private static double expAiry(double x) { + if(x<-1.0) { + return airyModPhase(x); + } else if(x<=1.0) { + final double z=x*x*x; + return 0.375+(chebyshev(z,aifcs)-x*(0.25+chebyshev(z,aigcs)))*Math.exp(2.0*x*Math.sqrt(x)/3.0); + } else { + final double sqrtx=Math.sqrt(x); + final double z=2.0/(x*sqrtx)-1.0; + return (0.28125+chebyshev(z,aipcs))/Math.sqrt(sqrtx); + } + } + /** + * Bessel function of first kind, order zero. + * Based on the NETLIB Fortran function besj0 written by W. Fullerton. + */ + public static double besselFirstZero(double x) { + double y=Math.abs(x); + if(y>4.0) { + final double z=32/(y*y)-1; + final double amplitude=(0.75+chebyshev(z,bm0cs))/Math.sqrt(y); + final double theta=y-Math.PI/4.0+chebyshev(z,bth0cs)/y; + return amplitude*Math.cos(theta); + } else if(y==0.0) + return 1.0; + else + return chebyshev(0.125*y*y-1,bj0cs); + } + /** + * Modified Bessel function of first kind, order zero. + * Based on the NETLIB Fortran function besi0 written by W. Fullerton. + */ + public static double modBesselFirstZero(double x) { + double y=Math.abs(x); + if(y>3.0) + return Math.exp(y)*expModBesselFirstZero(x); + else + return 2.75+chebyshev(y*y/4.5-1.0, bi0cs); + } + /** + * Exponential scaled modified Bessel function of first kind, order zero. + * Based on the NETLIB Fortran function besi0e written by W. Fullerton. + */ + private static double expModBesselFirstZero(double x) { + final double y=Math.abs(x); + if(y>3.0) { + if(y>8.0) + return (0.375+chebyshev(16.0/y-1.0, ai02cs))/Math.sqrt(y); + else + return (0.375+chebyshev((48.0/y-11.0)/5.0, ai0cs))/Math.sqrt(y); + } else + return Math.exp(-y)*(2.75+chebyshev(y*y/4.5-1.0, bi0cs)); + } + /** + * Bessel function of first kind, order one. + * Based on the NETLIB Fortran function besj1 written by W. Fullerton. + */ + public static double besselFirstOne(double x) { + double y=Math.abs(x); + if(y>4.0) { + final double z=32.0/(y*y)-1.0; + final double amplitude=(0.75+chebyshev(z, bm1cs))/Math.sqrt(y); + final double theta=y-3.0*Math.PI/4.0+chebyshev(z, bth1cs)/y; + return Math.abs(amplitude)*x*Math.cos(theta)/Math.abs(x); + } else if(y==0.0) + return 0.0; + else + return x*(0.25+chebyshev(0.125*y*y-1.0, bj1cs)); + } + /** + * Modified Bessel function of first kind, order one. + * Based on the NETLIB Fortran function besi1 written by W. Fullerton. + */ + public static double modBesselFirstOne(double x) { + final double y=Math.abs(x); + if(y>3.0) + return Math.exp(y)*expModBesselFirstOne(x); + else if(y==0.0) + return 0.0; + else + return x*(0.875+chebyshev(y*y/4.5-1.0, bi1cs)); + } + /** + * Exponential scaled modified Bessel function of first kind, order one. + * Based on the NETLIB Fortran function besi1e written by W. Fullerton. + */ + private static double expModBesselFirstOne(double x) { + final double y=Math.abs(x); + if(y>3.0) { + if(y>8.0) + return x/y*(0.375+chebyshev(16.0/y-1.0, ai12cs))/Math.sqrt(y); + else + return x/y*(0.375+chebyshev((48.0/y-11.0)/5.0, ai1cs))/Math.sqrt(y); + } else if(y==0.0) + return 0.0; + else + return Math.exp(-y)*x*(0.875+chebyshev(y*y/4.5-1.0, bi1cs)); + } + /** + * Bessel function of second kind, order zero. + * Based on the NETLIB Fortran function besy0 written by W. Fullerton. + */ + public static double besselSecondZero(double x) { + if(x>4.0) { + final double z=32.0/(x*x)-1.0; + final double amplitude=(0.75+chebyshev(z, bm0cs))/Math.sqrt(x); + final double theta=x-Math.PI/4+chebyshev(z, bth0cs)/x; + return amplitude*Math.sin(theta); + } else + return (Math.log(0.5)+Math.log(x))*besselFirstZero(x)+0.375+chebyshev(0.125*x*x-1.0,by0cs)*2.0/Math.PI; + } + /** + * Bessel function of second kind, order one. + * Based on the NETLIB Fortran function besy1 written by W. Fullerton. + */ + public static double besselSecondOne(double x) { + if(x>4.0) { + final double z=32.0/(x*x)-1.0; + final double amplitude=(0.75+chebyshev(z, bm1cs))/Math.sqrt(x); + final double theta=x-3.0*Math.PI/4.0+chebyshev(z, bth1cs)/x; + return amplitude*Math.sin(theta); + } else + return 2.0*Math.log(0.5*x)*besselFirstOne(x)/Math.PI+(0.5+chebyshev(0.125*x*x-1.0, by1cs))/x; + } + + private final static double LOGSQRT2PI=Math.log(SQRT2PI); + +// Gamma function related constants + private final static double g_p[] = { -1.71618513886549492533811, + 24.7656508055759199108314, -379.804256470945635097577, + 629.331155312818442661052, 866.966202790413211295064, + -31451.2729688483675254357, -36144.4134186911729807069, + 66456.1438202405440627855 }; + private final static double g_q[] = { -30.8402300119738975254353, + 315.350626979604161529144, -1015.15636749021914166146, + -3107.77167157231109440444, 22538.1184209801510330112, + 4755.84627752788110767815, -134659.959864969306392456, + -115132.259675553483497211 }; + private final static double g_c[] = { -0.001910444077728,8.4171387781295e-4, + -5.952379913043012e-4, 7.93650793500350248e-4, + -0.002777777777777681622553, 0.08333333333333333331554247, + 0.0057083835261 }; + /** + * The largest argument for which gamma(x) is representable in the machine. + */ + public final static double GAMMA_X_MAX_VALUE = 171.624; + + /** + * Gamma function. + * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz
+ * Applied Mathematics Division
+ * Argonne National Laboratory
+ * Argonne, IL 60439
+ *

+ * References: + *

    + *
  1. "An Overview of Software Development for Special Functions", W. J. Cody, Lecture Notes in Mathematics, 506, Numerical Analysis Dundee, 1975, G. A. Watson (ed.), Springer Verlag, Berlin, 1976. + *
  2. Computer Approximations, Hart, Et. Al., Wiley and sons, New York, 1968. + *

+ * From the original documentation: + *

+ * This routine calculates the GAMMA function for a real argument X. + * Computation is based on an algorithm outlined in reference 1. + * The program uses rational functions that approximate the GAMMA + * function to at least 20 significant decimal digits. Coefficients + * for the approximation over the interval (1,2) are unpublished. + * Those for the approximation for X .GE. 12 are from reference 2. + * The accuracy achieved depends on the arithmetic system, the + * compiler, the intrinsic functions, and proper selection of the + * machine-dependent constants. + *

+ * Error returns:
+ * The program returns the value XINF for singularities or when overflow would occur. + * The computation is believed to be free of underflow and overflow. + *

+ * @return Double.MAX_VALUE if overflow would occur, i.e. if abs(x) > 171.624 + * @jsci.planetmath GammaFunction + * @author Jaco van Kooten + */ + public static double gamma(double x) { + double fact=1.0, xden, xnum; + int i, n=0; + double y=x, z, y1; + boolean parity=false; + double res, sum, ysq; + + if (y <= 0.0) { +// ---------------------------------------------------------------------- +// Argument is negative +// ---------------------------------------------------------------------- + y = -(x); + y1 = (int)y; + res = y - y1; + if (res != 0.0) { + if (y1 != (((int)(y1*0.5)) * 2.0)) + parity = true; + fact = -Math.PI/ Math.sin(Math.PI * res); + y++; + } else + return Double.MAX_VALUE; + } +// ---------------------------------------------------------------------- +// Argument is positive +// ---------------------------------------------------------------------- + if (y < EPS) { +// ---------------------------------------------------------------------- +// Argument .LT. EPS +// ---------------------------------------------------------------------- + if (y >= XMININ) + res = 1.0 / y; + else + return Double.MAX_VALUE; + } else if (y < 12.0) { + y1 = y; + if (y < 1.0) { +// ---------------------------------------------------------------------- +// 0.0 .LT. argument .LT. 1.0 +// ---------------------------------------------------------------------- + z = y; + y++; + } else { +// ---------------------------------------------------------------------- +// 1.0 .LT. argument .LT. 12.0, reduce argument if necessary +// ---------------------------------------------------------------------- + n = (int)y - 1; + y -= (double) n; + z = y - 1.0; + } +// ---------------------------------------------------------------------- +// Evaluate approximation for 1.0 .LT. argument .LT. 2.0 +// ---------------------------------------------------------------------- + xnum = 0.0; + xden = 1.0; + for (i = 0; i < 8; ++i) { + xnum = (xnum + g_p[i]) * z; + xden = xden * z + g_q[i]; + } + res = xnum / xden + 1.0; + if (y1 < y) +// ---------------------------------------------------------------------- +// Adjust result for case 0.0 .LT. argument .LT. 1.0 +// ---------------------------------------------------------------------- + res /= y1; + else if (y1 > y) { +// ---------------------------------------------------------------------- +// Adjust result for case 2.0 .LT. argument .LT. 12.0 +// ---------------------------------------------------------------------- + for (i = 0; i < n; ++i) { + res *= y; + y++; + } + } + } else { +// ---------------------------------------------------------------------- +// Evaluate for argument .GE. 12.0 +// ---------------------------------------------------------------------- + if (y <= GAMMA_X_MAX_VALUE) { + ysq = y * y; + sum = g_c[6]; + for (i = 0; i < 6; ++i) + sum = sum / ysq + g_c[i]; + sum = sum / y - y + LOGSQRT2PI; + sum += (y - 0.5) * Math.log(y); + res = Math.exp(sum); + } else + return Double.MAX_VALUE; + } +// ---------------------------------------------------------------------- +// Final adjustments and return +// ---------------------------------------------------------------------- + if (parity) + res = -res; + if (fact != 1.0) + res = fact / res; + return res; + } + + /** + * The largest argument for which logGamma(x) is representable in the machine. + */ + public final static double LOG_GAMMA_X_MAX_VALUE = 2.55e305; + +// Log Gamma related constants + private final static double lg_d1 = -0.5772156649015328605195174; + private final static double lg_d2 = 0.4227843350984671393993777; + private final static double lg_d4 = 1.791759469228055000094023; + private final static double lg_p1[] = { 4.945235359296727046734888, + 201.8112620856775083915565, 2290.838373831346393026739, + 11319.67205903380828685045, 28557.24635671635335736389, + 38484.96228443793359990269, 26377.48787624195437963534, + 7225.813979700288197698961 }; + private final static double lg_q1[] = { 67.48212550303777196073036, + 1113.332393857199323513008, 7738.757056935398733233834, + 27639.87074403340708898585, 54993.10206226157329794414, + 61611.22180066002127833352, 36351.27591501940507276287, + 8785.536302431013170870835 }; + private final static double lg_p2[] = { 4.974607845568932035012064, + 542.4138599891070494101986, 15506.93864978364947665077, + 184793.2904445632425417223, 1088204.76946882876749847, + 3338152.967987029735917223, 5106661.678927352456275255, + 3074109.054850539556250927 }; + private final static double lg_q2[] = { 183.0328399370592604055942, + 7765.049321445005871323047, 133190.3827966074194402448, + 1136705.821321969608938755, 5267964.117437946917577538, + 13467014.54311101692290052, 17827365.30353274213975932, + 9533095.591844353613395747 }; + private final static double lg_p4[] = { 14745.02166059939948905062, + 2426813.369486704502836312, 121475557.4045093227939592, + 2663432449.630976949898078, 29403789566.34553899906876, + 170266573776.5398868392998, 492612579337.743088758812, + 560625185622.3951465078242 }; + private final static double lg_q4[] = { 2690.530175870899333379843, + 639388.5654300092398984238, 41355999.30241388052042842, + 1120872109.61614794137657, 14886137286.78813811542398, + 101680358627.2438228077304, 341747634550.7377132798597, + 446315818741.9713286462081 }; + private final static double lg_c[] = { -0.001910444077728,8.4171387781295e-4, + -5.952379913043012e-4, 7.93650793500350248e-4, + -0.002777777777777681622553, 0.08333333333333333331554247, + 0.0057083835261 }; +// Rough estimate of the fourth root of logGamma_xBig + private final static double lg_frtbig = 2.25e76; + private final static double pnt68 = 0.6796875; + +// Function cache for logGamma + private static final ThreadLocal logGammaCache_res=new ThreadLocal() { + protected Object initialValue() { + return new Double(0.0); + } + + }; + private static final ThreadLocal logGammaCache_x=new ThreadLocal() { + protected Object initialValue() { + return new Double(0.0); + } + }; + + /** + * The natural logarithm of the gamma function. + * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz
+ * Applied Mathematics Division
+ * Argonne National Laboratory
+ * Argonne, IL 60439
+ *

+ * References: + *

    + *
  1. W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203. + *
  2. K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969. + *
  3. Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968. + *

+ * From the original documentation: + *

+ * This routine calculates the LOG(GAMMA) function for a positive real argument X. + * Computation is based on an algorithm outlined in references 1 and 2. + * The program uses rational functions that theoretically approximate LOG(GAMMA) + * to at least 18 significant decimal digits. The approximation for X > 12 is from reference 3, + * while approximations for X < 12.0 are similar to those in reference 1, but are unpublished. + * The accuracy achieved depends on the arithmetic system, the compiler, the intrinsic functions, + * and proper selection of the machine-dependent constants. + *

+ * Error returns:
+ * The program returns the value XINF for X .LE. 0.0 or when overflow would occur. + * The computation is believed to be free of underflow and overflow. + *

+ * @return Double.MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305 + * @author Jaco van Kooten + */ + public static double logGamma(double x) { + double xden, corr, xnum; + int i; + double y, xm1, xm2, xm4, res, ysq; + + if (x == ((Double) logGammaCache_x.get()).doubleValue()) + return ((Double) logGammaCache_res.get()).doubleValue(); + + y = x; + if (y > 0.0 && y <= LOG_GAMMA_X_MAX_VALUE) { + if (y <= EPS) { + res = -Math.log(y); + } else if (y <= 1.5) { +// ---------------------------------------------------------------------- +// EPS .LT. X .LE. 1.5 +// ---------------------------------------------------------------------- + if (y < pnt68) { + corr = -Math.log(y); + xm1 = y; + } else { + corr = 0.0; + xm1 = y - 1.0; + } + if (y <= 0.5 || y >= pnt68) { + xden = 1.0; + xnum = 0.0; + for (i = 0; i < 8; i++) { + xnum = xnum * xm1 + lg_p1[i]; + xden = xden * xm1 + lg_q1[i]; + } + res = corr + xm1 * (lg_d1 + xm1 * (xnum / xden)); + } else { + xm2 = y - 1.0; + xden = 1.0; + xnum = 0.0; + for (i = 0; i < 8; i++) { + xnum = xnum * xm2 + lg_p2[i]; + xden = xden * xm2 + lg_q2[i]; + } + res = corr + xm2 * (lg_d2 + xm2 * (xnum / xden)); + } + } else if (y <= 4.0) { +// ---------------------------------------------------------------------- +// 1.5 .LT. X .LE. 4.0 +// ---------------------------------------------------------------------- + xm2 = y - 2.0; + xden = 1.0; + xnum = 0.0; + for (i = 0; i < 8; i++) { + xnum = xnum * xm2 + lg_p2[i]; + xden = xden * xm2 + lg_q2[i]; + } + res = xm2 * (lg_d2 + xm2 * (xnum / xden)); + } else if (y <= 12.0) { +// ---------------------------------------------------------------------- +// 4.0 .LT. X .LE. 12.0 +// ---------------------------------------------------------------------- + xm4 = y - 4.0; + xden = -1.0; + xnum = 0.0; + for (i = 0; i < 8; i++) { + xnum = xnum * xm4 + lg_p4[i]; + xden = xden * xm4 + lg_q4[i]; + } + res = lg_d4 + xm4 * (xnum / xden); + } else { +// ---------------------------------------------------------------------- +// Evaluate for argument .GE. 12.0 +// ---------------------------------------------------------------------- + res = 0.0; + if (y <= lg_frtbig) { + res = lg_c[6]; + ysq = y * y; + for (i = 0; i < 6; i++) + res = res / ysq + lg_c[i]; + } + res /= y; + corr = Math.log(y); + res = res + LOGSQRT2PI - 0.5 * corr; + res += y * (corr - 1.0); + } + } else { +// ---------------------------------------------------------------------- +// Return for bad arguments +// ---------------------------------------------------------------------- + res = Double.MAX_VALUE; + } +// ---------------------------------------------------------------------- +// Final adjustments and return +// ---------------------------------------------------------------------- + logGammaCache_x.set(new Double(x)); + logGammaCache_res.set(new Double(res)); + return res; + } + + private final static int MAX_ITERATIONS = 1000000000; + // lower value = higher precision + private final static double PRECISION = 4.0*EPS; + + /** + * Incomplete gamma function. + * The computation is based on approximations presented in Numerical Recipes, Chapter 6.2 (W.H. Press et al, 1992). + * @param a require a>=0 + * @param x require x>=0 + * @return 0 if x<0, a<=0 or a>2.55E305 to avoid errors and over/underflow + * @author Jaco van Kooten + */ + public static double incompleteGamma(double a, double x) { + if (x <= 0.0 || a <= 0.0 || a > LOG_GAMMA_X_MAX_VALUE) + return 0.0; + if (x < (a+1.0)) + return gammaSeriesExpansion(a,x); + else + return 1.0-gammaFraction(a,x); + } + /** + * @author Jaco van Kooten + */ + private static double gammaSeriesExpansion(double a, double x) { + double ap = a; + double del = 1.0/a; + double sum = del; + for (int n=1; n < MAX_ITERATIONS; n++) { + ++ap; + del *= x/ap; + sum += del; + if (del < sum*PRECISION) + return sum*Math.exp(-x + a*Math.log(x) - logGamma(a)); + } + throw new RuntimeException("Maximum iterations exceeded: please file a bug report."); + } + /** + * @author Jaco van Kooten + */ + private static double gammaFraction(double a, double x) { + double b=x+1.0-a; + double c=1.0/XMININ; + double d=1.0/b; + double h=d; + double del=0.0; + double an; + for (int i=1; iPRECISION; i++) { + an = -i*(i-a); + b += 2.0; + d=an*d+b; + c=b+an/c; + if (Math.abs(c) < XMININ) + c=XMININ; + if (Math.abs(d) < XMININ) + c=XMININ; + d=1.0/d; + del=d*c; + h *= del; + } + return Math.exp(-x + a*Math.log(x) - logGamma(a))*h; + } + /** + * Beta function. + * @param p require p>0 + * @param q require q>0 + * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow + * @author Jaco van Kooten + */ + public static double beta(double p, double q) { + if (p <= 0.0 || q <= 0.0 || (p+q) > LOG_GAMMA_X_MAX_VALUE) + return 0.0; + else + return Math.exp(logBeta(p,q)); + } + +// Function cache for logBeta + private static final ThreadLocal logBetaCache_res=new ThreadLocal() { + protected Object initialValue() { + return new Double(0.0); + } + }; + private static final ThreadLocal logBetaCache_p=new ThreadLocal() { + protected Object initialValue() { + return new Double(0.0); + } + }; + private static final ThreadLocal logBetaCache_q=new ThreadLocal() { + protected Object initialValue() { + return new Double(0.0); + } + }; + + /** + * The natural logarithm of the beta function. + * @param p require p>0 + * @param q require q>0 + * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow + * @author Jaco van Kooten + */ + public static double logBeta(double p, double q) { + if (p != ((Double) logBetaCache_p.get()).doubleValue() + || q != ((Double) logBetaCache_q.get()).doubleValue()) { + logBetaCache_p.set(new Double(p)); + logBetaCache_q.set(new Double(q)); + double res; + if (p <= 0.0 || q <= 0.0 || (p+q) > LOG_GAMMA_X_MAX_VALUE) + res = 0.0; + else + res = logGamma(p)+logGamma(q)-logGamma(p+q); + logBetaCache_res.set(new Double(res)); + return res; + } else { + return ((Double) logBetaCache_res.get()).doubleValue(); + } + } + /** + * Incomplete beta function. + * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992). + * @param x require 0<=x<=1 + * @param p require p>0 + * @param q require q>0 + * @return 0 if x<0, p<=0, q<=0 or p+q>2.55E305 and 1 if x>1 to avoid errors and over/underflow + * @author Jaco van Kooten + */ + public static double incompleteBeta(double x, double p, double q) { + if (x <= 0.0) + return 0.0; + else if (x >= 1.0) + return 1.0; + else if (p <= 0.0 || q <= 0.0 || (p+q) > LOG_GAMMA_X_MAX_VALUE) + return 0.0; + else { + final double beta_gam=Math.exp(-logBeta(p,q) + p*Math.log(x) + q*Math.log(1.0-x)); + if (x < (p+1.0)/(p+q+2.0)) + return beta_gam*betaFraction(x,p,q)/p; + else + return 1.0-(beta_gam*betaFraction(1.0-x,q,p)/q); + } + } + /** + * Evaluates of continued fraction part of incomplete beta function. + * Based on an idea from Numerical Recipes (W.H. Press et al, 1992). + * @author Jaco van Kooten + */ + private static double betaFraction(double x, double p, double q) { + int m, m2; + double sum_pq, p_plus, p_minus, c =1.0 , d, delta, h, frac; + sum_pq = p + q; + p_plus = p + 1.0; + p_minus = p - 1.0; + h=1.0-sum_pq*x/p_plus; + if (Math.abs(h) < XMININ) + h=XMININ; + h=1.0/h; + frac = h; + m=1; + delta = 0.0; + while (m <= MAX_ITERATIONS && Math.abs(delta-1.0) > PRECISION ) { + m2=2*m; + // even index for d + d=m*(q-m)*x/((p_minus+m2)*(p+m2)); + h=1.0+d*h; + if (Math.abs(h) < XMININ) + h=XMININ; + h=1.0/h; + c=1.0+d/c; + if (Math.abs(c) < XMININ) + c=XMININ; + frac *= h*c; + // odd index for d + d = -(p+m)*(sum_pq+m)*x/((p+m2)*(p_plus+m2)); + h=1.0+d*h; + if (Math.abs(h) < XMININ) + h=XMININ; + h=1.0/h; + c=1.0+d/c; + if (Math.abs(c) < XMININ) + c=XMININ; + delta=h*c; + frac *= delta; + m++; + } + return frac; + } + +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunSoft, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== +// +// x +// 2 |\ +// erf(x) = --------- | exp(-t*t)dt +// sqrt(pi) \| +// 0 +// +// erfc(x) = 1-erf(x) +// Note that +// erf(-x) = -erf(x) +// erfc(-x) = 2 - erfc(x) +// +// Method: +// 1. For |x| in [0, 0.84375] +// erf(x) = x + x*R(x^2) +// erfc(x) = 1 - erf(x) if x in [-.84375,0.25] +// = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] +// where R = P/Q where P is an odd poly of degree 8 and +// Q is an odd poly of degree 10. +// -57.90 +// | R - (erf(x)-x)/x | <= 2 +// +// +// Remark. The formula is derived by noting +// erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) +// and that +// 2/sqrt(pi) = 1.128379167095512573896158903121545171688 +// is close to one. The interval is chosen because the fix +// point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is +// near 0.6174), and by some experiment, 0.84375 is chosen to +// guarantee the error is less than one ulp for erf. +// +// 2. For |x| in [0.84375,1.25], let s = |x| - 1, and +// c = 0.84506291151 rounded to single (24 bits) +// erf(x) = sign(x) * (c + P1(s)/Q1(s)) +// erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 +// 1+(c+P1(s)/Q1(s)) if x < 0 +// |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 +// Remark: here we use the taylor series expansion at x=1. +// erf(1+s) = erf(1) + s*Poly(s) +// = 0.845.. + P1(s)/Q1(s) +// That is, we use rational approximation to approximate +// erf(1+s) - (c = (single)0.84506291151) +// Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] +// where +// P1(s) = degree 6 poly in s +// Q1(s) = degree 6 poly in s +// +// 3. For x in [1.25,1/0.35(~2.857143)], +// erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) +// erf(x) = 1 - erfc(x) +// where +// R1(z) = degree 7 poly in z, (z=1/x^2) +// S1(z) = degree 8 poly in z +// +// 4. For x in [1/0.35,28] +// erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 +// = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 +// erf(x) = sign(x) *(1 - tiny) (raise inexact) +// erfc(x) = tiny*tiny (raise underflow) if x > 0 +// = 2 - tiny if x<0 +// +// 7. Special case: +// erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, +// erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, +// erfc/erf(NaN) is NaN +// + +// Coefficients for approximation to erf on [0,0.84375] + private final static double e_efx=1.28379167095512586316e-01; +// private final static double efx8=1.02703333676410069053e00; + private final static double ePp[]={ + 1.28379167095512558561e-01, + -3.25042107247001499370e-01, + -2.84817495755985104766e-02, + -5.77027029648944159157e-03, + -2.37630166566501626084e-05}; + private final static double eQq[]={ + 3.97917223959155352819e-01, + 6.50222499887672944485e-02, + 5.08130628187576562776e-03, + 1.32494738004321644526e-04, + -3.96022827877536812320e-06}; +// Coefficients for approximation to erf in [0.84375,1.25] + private final static double ePa[]={ + -2.36211856075265944077e-03, + 4.14856118683748331666e-01, + -3.72207876035701323847e-01, + 3.18346619901161753674e-01, + -1.10894694282396677476e-01, + 3.54783043256182359371e-02, + -2.16637559486879084300e-03}; + private final static double eQa[]={ + 1.06420880400844228286e-01, + 5.40397917702171048937e-01, + 7.18286544141962662868e-02, + 1.26171219808761642112e-01, + 1.36370839120290507362e-02, + 1.19844998467991074170e-02}; + private final static double e_erx=8.45062911510467529297e-01; + + /** + * Error function. + * Based on C-code for the error function developed at Sun Microsystems. + * @author Jaco van Kooten + */ + public static double error(double x) { + double P,Q,s,retval; + final double abs_x = (x >= 0.0 ? x : -x); + if ( abs_x < 0.84375 ) { // 0 < |x| < 0.84375 + if (abs_x < 3.7252902984619141e-9 ) // |x| < 2**-28 + retval = abs_x + abs_x*e_efx; + else { + s = x*x; + P = ePp[0]+s*(ePp[1]+s*(ePp[2]+s*(ePp[3]+s*ePp[4]))); + Q = 1.0+s*(eQq[0]+s*(eQq[1]+s*(eQq[2]+s*(eQq[3]+s*eQq[4])))); + retval = abs_x + abs_x*(P/Q); + } + } else if (abs_x < 1.25) { // 0.84375 < |x| < 1.25 + s = abs_x-1.0; + P = ePa[0]+s*(ePa[1]+s*(ePa[2]+s*(ePa[3]+s*(ePa[4]+s*(ePa[5]+s*ePa[6]))))); + Q = 1.0+s*(eQa[0]+s*(eQa[1]+s*(eQa[2]+s*(eQa[3]+s*(eQa[4]+s*eQa[5]))))); + retval = e_erx + P/Q; + } else if (abs_x >= 6.0) + retval = 1.0; + else // 1.25 < |x| < 6.0 + retval = 1.0-complementaryError(abs_x); + return (x >= 0.0) ? retval : -retval; + } + +// Coefficients for approximation to erfc in [1.25,1/.35] + private final static double eRa[]={ + -9.86494403484714822705e-03, + -6.93858572707181764372e-01, + -1.05586262253232909814e01, + -6.23753324503260060396e01, + -1.62396669462573470355e02, + -1.84605092906711035994e02, + -8.12874355063065934246e01, + -9.81432934416914548592e00}; + private final static double eSa[]={ + 1.96512716674392571292e01, + 1.37657754143519042600e02, + 4.34565877475229228821e02, + 6.45387271733267880336e02, + 4.29008140027567833386e02, + 1.08635005541779435134e02, + 6.57024977031928170135e00, + -6.04244152148580987438e-02}; +// Coefficients for approximation to erfc in [1/.35,28] + private final static double eRb[]={ + -9.86494292470009928597e-03, + -7.99283237680523006574e-01, + -1.77579549177547519889e01, + -1.60636384855821916062e02, + -6.37566443368389627722e02, + -1.02509513161107724954e03, + -4.83519191608651397019e02}; + private final static double eSb[]={ + 3.03380607434824582924e01, + 3.25792512996573918826e02, + 1.53672958608443695994e03, + 3.19985821950859553908e03, + 2.55305040643316442583e03, + 4.74528541206955367215e02, + -2.24409524465858183362e01}; + + /** + * Complementary error function. + * Based on C-code for the error function developed at Sun Microsystems. + * @author Jaco van Kooten + */ + public static double complementaryError(double x) { + double s,retval,R,S; + final double abs_x =(x>=0.0 ? x : -x); + if (abs_x < 1.25) + retval = 1.0-error(abs_x); + else if (abs_x > 28.0) + retval=0.0; + else { // 1.25 < |x| < 28 + s = 1.0/(abs_x*abs_x); + if (abs_x < 2.8571428) { // ( |x| < 1/0.35 ) + R=eRa[0]+s*(eRa[1]+s*(eRa[2]+s*(eRa[3]+s*(eRa[4]+s*(eRa[5]+s*(eRa[6]+s*eRa[7])))))); + S=1.0+s*(eSa[0]+s*(eSa[1]+s*(eSa[2]+s*(eSa[3]+s*(eSa[4]+s*(eSa[5]+s*(eSa[6]+s*eSa[7]))))))); + } else { // ( |x| > 1/0.35 ) + R=eRb[0]+s*(eRb[1]+s*(eRb[2]+s*(eRb[3]+s*(eRb[4]+s*(eRb[5]+s*eRb[6]))))); + S=1.0+s*(eSb[0]+s*(eSb[1]+s*(eSb[2]+s*(eSb[3]+s*(eSb[4]+s*(eSb[5]+s*eSb[6])))))); + } + retval = Math.exp(-x*x - 0.5625 + R/S)/abs_x; + } + return (x >= 0.0) ? retval : 2.0-retval; + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/TDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/TDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/TDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/TDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,61 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The TDistribution class provides an object for encapsulating student's t-distributions. +* @version 1.0 +* @author Jaco van Kooten +*/ +public final class TDistribution extends ProbabilityDistribution { + private int dgrFreedom; + private double logPdfFreedom; + + /** + * Constructor for student's t-distribution. + * @param r degrees of freedom. + */ + public TDistribution(int r) { + if(r<=0) + throw new OutOfRangeException("The degrees of freedom must be greater than zero."); + dgrFreedom=r; + logPdfFreedom=-SpecialMath.logBeta(0.5*dgrFreedom,0.5)-0.5*Math.log(dgrFreedom); + } + /** + * Returns the degrees of freedom. + */ + public int getDegreesOfFreedom() { + return dgrFreedom; + } + /** + * Probability density function of a student's t-distribution. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + double logPdf=logPdfFreedom; + logPdf-=(0.5*(dgrFreedom+1))*Math.log(1.0+(X*X)/dgrFreedom); + return Math.exp(logPdf); + } + /** + * Cumulative student's t-distribution function. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + double A=0.5*SpecialMath.incompleteBeta((dgrFreedom)/(dgrFreedom+X*X),0.5*dgrFreedom,0.5); + return X>0 ? 1-A : A; + } + /** + * Inverse of the cumulative student's t-distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + if(probability==0.0) + return -Double.MAX_VALUE; + if(probability==1.0) + return Double.MAX_VALUE; + if(probability==0.5) + return 0.0; + return findRoot(probability, 0.0, -0.5*Double.MAX_VALUE, 0.5*Double.MAX_VALUE); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/WeibullDistribution.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/WeibullDistribution.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/jscistats/WeibullDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/jscistats/WeibullDistribution.java 2010-01-16 04:03:17.000000000 +0000 @@ -0,0 +1,68 @@ +package org.mathpiper.builtin.library.jscistats; + + +/** +* The WeibullDistribution class provides an object for encapsulating Weibull distributions. +* @version 0.2 +* @author Mark Hale +*/ +public final class WeibullDistribution extends ProbabilityDistribution { + private double shape; + + /** + * Constructs a Weibull distribution. + * @param sh the shape. + */ + public WeibullDistribution(double sh) { + if(sh<=0.0) + throw new OutOfRangeException("The shape parameter should be positive."); + shape=sh; + } + /** + * Returns the shape parameter. + */ + public double getShapeParameter() { + return shape; + } + /** + * Returns the mean. + */ + public double getMean() { + return SpecialMath.gamma(1.0+1.0/shape); + } + /** + * Returns the variance. + */ + public double getVariance() { + return SpecialMath.gamma(1.0+2.0/shape)-getMean()*getMean(); + } + /** + * Probability density function of a Weibull distribution. + * P(X) = s Xs-1 exp(-Xs). + * @param X should be integer-valued. + * @return the probability that a stochastic variable x has the value X, i.e. P(x=X). + */ + public double probability(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + final double XpowShape=Math.pow(X,shape); + return shape*XpowShape/X*Math.exp(-XpowShape); + } + /** + * Cumulative Weibull distribution function. + * @param X should be integer-valued. + * @return the probability that a stochastic variable x is less then X, i.e. P(x<X). + */ + public double cumulative(double X) { + checkRange(X,0.0,Double.MAX_VALUE); + return 1.0-Math.exp(-Math.pow(X,shape)); + } + /** + * Inverse of the cumulative Weibull distribution function. + * @return the value X for which P(x<X). + */ + public double inverse(double probability) { + checkRange(probability); + return Math.pow(-Math.log(1.0-probability),1.0/shape); + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Beta.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Beta.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Beta.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Beta.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,571 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Beta + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double a, double b); + * + * DESCRIPTION + * + * The density of the Beta distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double a, double b) + { + double y; + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + if (Double.isNaN(x) || Double.isNaN(a) || Double.isNaN(b)) return x + a + b; + /*!* #endif /*4!*/ + if (a <= 0.0 || b <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x < 0) + return 0; + if (x > 1) + return 0; + y = Misc.beta(a, b); +/*!* a = pow(x, a - 1); *!*/ + a = java.lang.Math.pow(x, a - 1); +/*!* b = pow(1.0 - x, b - 1.0); *!*/ + b = java.lang.Math.pow(1.0 - x, b - 1.0); + /*!* #ifndef IEEE_754 /*4!*/ + // if(errno) return Double.NaN; + /*!* #endif /*4!*/ + return a * b / y; + } + + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double pin, double qin); + * + * DESCRIPTION + * + * Returns distribution function of the Beta distribution. + * (The incomplete Beta ratio). + * + * NOTES + * + * This routine is a translation into C of a Fortran subroutine + * by W. Fullerton of Los Alamos Scientific Laboratory. + * + * REFERENCE + * + * Bosten and Battiste (1974). + * Remark on Algorithm 179, + * CACM 17, p153, (1974). + */ + + /*!* #include "DistLib.h" /*4!*/ + + + + static double pbeta_raw(double x, double pin, double qin) + { + double ans, c, finsum, p, ps, p1, q, term, xb, xi, y; + int n, i, ib; + double eps = 0; + double alneps = 0; + double sml = 0; + double alnsml = 0; + + if (eps == 0) { + eps = Misc.d1mach(3); +/*!* alneps = log(eps); *!*/ + alneps = java.lang.Math.log(eps); + sml = Misc.d1mach(1); +/*!* alnsml = log(sml); *!*/ + alnsml = java.lang.Math.log(sml); + } + + y = x; + p = pin; + q = qin; + + /* swap tails if x is greater than the mean */ + + if (p / (p + q) < x) { + y = 1 - y; + p = qin; + q = pin; + } + + if ((p + q) * y / (p + 1) < eps) { + + /* tail approximation */ + + ans = 0; +/*!* xb = p * log(Math.max(y, sml)) - log(p) - Misc.lbeta(p, q); *!*/ + xb = p * java.lang.Math.log(Math.max(y, sml)) - java.lang.Math.log(p) - Misc.lbeta(p, q); + if (xb > alnsml && y != 0) +/*!* ans = exp(xb); *!*/ + ans = java.lang.Math.exp(xb); + if (y != x || p != pin) + ans = 1 - ans; + } + else { + + /* evaluate the infinite sum first. term will equal */ + /* y^p / Beta(ps, p) * (1 - ps)-sub-i * y^i / fac(i) */ + +/*!* ps = q - floor(q); *!*/ + ps = q - java.lang.Math.floor(q); + if (ps == 0) + ps = 1; +/*!* xb = p * log(y) - Misc.lbeta(ps, p) - log(p); *!*/ + xb = p * java.lang.Math.log(y) - Misc.lbeta(ps, p) - java.lang.Math.log(p); + ans = 0; + if (xb >= alnsml) { +/*!* ans = exp(xb); *!*/ + ans = java.lang.Math.exp(xb); + term = ans * p; + if (ps != 1) { + n = (int) Math.max(alneps/java.lang.Math.log(y), 4.0); + for(i=1 ; i<= n ; i++) { + xi = i; + term = term * (xi - ps) * y / xi; + ans = ans + term / (p + xi); + } + } + } + + /* now evaluate the finite sum, maybe. */ + + if (q > 1) { +/*!* xb = p * log(y) + q * log(1 - y) - Misc.lbeta(p, q) - log(q); *!*/ + xb = p * java.lang.Math.log(y) + q * java.lang.Math.log(1 - y) - Misc.lbeta(p, q) - java.lang.Math.log(q); + ib = (int) Math.max(xb / alnsml, 0.0); +/*!* term = exp(xb - ib * alnsml); *!*/ + term = java.lang.Math.exp(xb - ib * alnsml); + c = 1 / (1 - y); + p1 = q * c / (p + q - 1); + + finsum = 0; + n = (int) q; + if (q == n) + n = n - 1; + for(i=1 ; i<=n ; i++) { + if (p1 <= 1 && term / eps <= finsum) + break; + xi = i; + term = (q - xi + 1) * c * term / (p + q - xi); + if (term > 1) { + ib = ib - 1; + term = term * sml; + } + if (ib == 0) + finsum = finsum + term; + } + ans = ans + finsum; + } + if (y != x || p != pin) + ans = 1 - ans; + ans = Math.max(Math.min(ans, 1.0), 0.0); + } + return ans; + } + + public static double cumulative(double x, double pin, double qin) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(pin) || Double.isNaN(qin)) + return x + pin + qin; + /*!* #endif /*4!*/ + + if (pin <= 0 || qin <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x <= 0) + return 0; + if (x >= 1) + return 1; + return pbeta_raw(x, pin, qin); + } + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + + * Reference: + * Cran, G. W., K. J. Martin and G. E. Thomas (1977). + * Remark AS R19 and Algorithm AS 109, + * Applied Statistics, 26(1), 111-114. + * Remark AS R83 (v.39, 309-310) and the correction (v.40(1) p.236) + * have been incorporated in this version. + */ + + + /*!* #include "DistLib.h" /*4!*/ + + static double zero = 0.0; + + /* set the exponent of accu to -2r-2 for r digits of accuracy */ + /*!* #ifdef OLD + static double acu = 1.0e-32; + static double lower = 0.0001; + static double upper = 0.9999; + *4!*/ + /*!* #else/*---- NEW ---- -- still fails for p = 1e11, q=.5*/ /*4!*/ + + static double fpu = 3e-308; + /* acu_min: Minimal value for accuracy 'acu' which will depend on (a,p); + acu_min >= fpu ! */ + static double acu_min = 1e-300; + static double lower = fpu; + static double upper = 1-2.22e-16; + + /*!* #endif /*4!*/ + + static double const1 = 2.30753; + static double const2 = 0.27061; + static double const3 = 0.99229; + static double const4 = 0.04481; + + static volatile double xtrunc; + + public static double quantile(double alpha, double p, double q) + { + int swap_tail, i_pb, i_inn; + double a, adj, logbeta, g, h, pp, prev, qq, r, s, t, tx, w, y, yprev; + double acu; + double xinbta; + + /* define accuracy and initialize */ + + xinbta = alpha; + + /* test for admissibility of parameters */ + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(p) || Double.isNaN(q) || Double.isNaN(alpha)) + return p + q + alpha; + /*!* #endif /*4!*/ + if(p < zero || q < zero || alpha < zero || alpha > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (alpha == zero || alpha == 1) + return alpha; + + logbeta = Misc.lbeta(p, q); + + /* change tail if necessary; afterwards 0 < a <= 1/2 */ + if (alpha <= 0.5) { + a = alpha; pp = p; qq = q; swap_tail = 0; + } else { /* change tail, swap p <-> q :*/ + a = 1 - alpha; pp = q; qq = p; swap_tail = 1; + } + + /* calculate the initial approximation */ + +/*!* r = sqrt(-log(a * a)); *!*/ + r = java.lang.Math.sqrt(-java.lang.Math.log(a * a)); + y = r - (const1 + const2 * r) / (1 + (const3 + const4 * r) * r); + if (pp > 1 && qq > 1) { + r = (y * y - 3) / 6; + s = 1 / (pp + pp - 1); + t = 1 / (qq + qq - 1); + h = 2 / (s + t); +/*!* w = y * sqrt(h + r) / h - (t - s) * (r + 5 / 6 - 2 / (3 * h)); *!*/ + w = y * java.lang.Math.sqrt(h + r) / h - (t - s) * (r + 5 / 6 - 2 / (3 * h)); +/*!* xinbta = pp / (pp + qq * exp(w + w)); *!*/ + xinbta = pp / (pp + qq * java.lang.Math.exp(w + w)); + } else { + r = qq + qq; + t = 1 / (9 * qq); +/*!* t = r * pow(1 - t + y * sqrt(t), 3); *!*/ + t = r * java.lang.Math.pow(1 - t + y * java.lang.Math.sqrt(t), 3); + if (t <= zero) +/*!* xinbta = 1 - exp((log((1 - a) * qq) + logbeta) / qq); *!*/ + xinbta = 1 - java.lang.Math.exp((java.lang.Math.log((1 - a) * qq) + logbeta) / qq); + else { + t = (4 * pp + r - 2) / t; + if (t <= 1) +/*!* xinbta = exp((log(a * pp) + logbeta) / pp); *!*/ + xinbta = java.lang.Math.exp((java.lang.Math.log(a * pp) + logbeta) / pp); + else + xinbta = 1 - 2 / (t + 1); + } + } + + /* solve for x by a modified newton-raphson method, */ + /* using the function pbeta_raw */ + + r = 1 - pp; + t = 1 - qq; + yprev = zero; + adj = 1; + if (xinbta < lower) + xinbta = lower; + else if (xinbta > upper) + xinbta = upper; + + /* Desired accuracy should depend on (a,p) + * This is from Remark .. on AS 109, adapted. + * However, it's not clear if this is "optimal" for IEEE double prec. + + * acu = Math.max(acu_min, pow(10., -25. - 5./(pp * pp) - 1./(a * a))); + + * NEW: 'acu' accuracy NOT for squared adjustment, but simple; + * ---- i.e., "new acu" = sqrt(old acu) + + */ + acu = Math.max(acu_min, java.lang.Math.pow(10., -13 - 2.5/(pp * pp) - 0.5/(a * a))); + tx = prev = zero; /* keep -Wall happy */ + +L_converged: { + for (i_pb=0; i_pb < 1000; i_pb++) { + y = pbeta_raw(xinbta, pp, qq); + /* y = pbeta_raw2(xinbta, pp, qq, logbeta); */ + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(y)) + /*!* #else /*4!*/ + // if (errno) + /*!* #endif /*4!*/ + // { throw new java.lang.ArithmeticException("Math Error: DOMAIN"); return Double.NaN; } + y = (y - a) * +/*!* exp(logbeta + r * log(xinbta) + t * log(1 - xinbta)); *!*/ + java.lang.Math.exp(logbeta + r * java.lang.Math.log(xinbta) + t * java.lang.Math.log(1 - xinbta)); + if (y * yprev <= zero) + prev = Math.max(java.lang.Math.abs(adj),fpu); + g = 1; + for (i_inn=0; i_inn < 1000;i_inn++) { + adj = g * y; + if (java.lang.Math.abs(adj) < prev) { + tx = xinbta - adj; /* trial new x */ + if (tx >= zero && tx <= 1) { + if (prev <= acu) break L_converged; + if (java.lang.Math.abs(y) <= acu) break L_converged; + if (tx != zero && tx != 1) + break; + } + } + g /= 3; + } + xtrunc = tx; /* this prevents trouble with excess FPU */ + /* precision on some machines. */ + if (xtrunc == xinbta) + break L_converged; + xinbta = tx; + yprev = y; + } + /*-- NOT converged: Iteration count --*/ + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + } + + if (swap_tail==1) + xinbta = 1 - xinbta; + return xinbta; + } + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /* Reference: + * R. C. H. Cheng (1978). + * Generating Beta variates with nonintegral shape parameters. + * Communications of the ACM 21, 317-322. + * (Algorithms BB and BC) + */ + + /*!* #include "DistLib.h" /*4!*/ + +/*!* double random(double aa, double bb) *!*/ + public static double random(double aa, double bb, Uniform uniformDistribution) + { + int qsame; + + double expmax = 0.0; + double a=0.0, b=0.0, delta=0.0, r=0.0, s=0.0, t=0.0, u1=0.0; + double u2=0.0, v=0.0, w=0.0, y=0.0, z=0.0; + double alpha=0.0, beta=0.0, gamma=0.0, k1=0.0, k2=0.0; + double olda = -1.0; + double oldb = -1.0; + + + + if (expmax == 0.0) +/*!* expmax = log(Double.MAX_VALUE); *!*/ + expmax = java.lang.Math.log(Double.MAX_VALUE); + + /*!* qsame = (olda == aa) && (oldb == bb); *!*/ + qsame = ( (olda == aa) && (oldb == bb) )?1:0; + + if (!(qsame==1)) { + if (aa > 0.0 && bb > 0.0) { + olda = aa; + oldb = bb; + } else { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + } + + deliver: { + + if (Math.min(aa, bb) <= 1.0) { /* Algorithm BC */ + if (!(qsame==1)) { + a = Math.max(aa, bb); + b = Math.min(aa, bb); + alpha = a + b; + beta = 1.0 / b; + delta = 1.0 + a - b; + k1 = delta * (0.0138889 + 0.0416667 * b) / + (a * beta - 0.777778); + k2 = 0.25 + (0.5 + 0.25 / delta) * b; + } + for(;;) { + u1 = uniformDistribution.random(); + u2 = uniformDistribution.random(); + + if (u1 < 0.5) { + y = u1 * u2; + z = u1 * y; + if (0.25 * u2 + z - y >= k1) + continue; + } else { + z = u1 * u1 * u2; + if (z <= 0.25) + break; + if (z >= k2) + continue; + } +/*!* v = Beta * log(u1 / (1.0 - u1)); *!*/ + v = beta * java.lang.Math.log(u1 / (1.0 - u1)); + if (v <= expmax) +/*!* w = a * exp(v); *!*/ + w = a * java.lang.Math.exp(v); + else + w = Double.MAX_VALUE; +/*!* if (alpha * (log(alpha / (b + w)) + v) - 1.3862944 *!*/ + if (alpha * (java.lang.Math.log(alpha / (b + w)) + v) - 1.3862944 +/*!* >= log(z)) *!*/ + >= java.lang.Math.log(z)) + break deliver; + } +/*!* v = Beta * log(u1 / (1.0 - u1)); *!*/ + v = beta * java.lang.Math.log(u1 / (1.0 - u1)); + if (v <= expmax) +/*!* w = a * exp(v); *!*/ + w = a * java.lang.Math.exp(v); + else + w = Double.MAX_VALUE; + } else { /* Algorithm BB */ + if (!(qsame==1)) { + a = Math.min(aa, bb); + b = Math.max(aa, bb); + alpha = a + b; +/*!* Beta = sqrt((alpha - 2.0) / (2.0 * a * b - alpha)); *!*/ + beta = java.lang.Math.sqrt((alpha - 2.0) / (2.0 * a * b - alpha)); + gamma = a + 1.0 / beta; + } + do { +/*!* u1 = uniformDistribution.random(); *!*/ + u1 = uniformDistribution.random(); +/*!* u2 = uniformDistribution.random(); *!*/ + u2 = uniformDistribution.random(); +/*!* v = Beta * log(u1 / (1.0 - u1)); *!*/ + v = beta * java.lang.Math.log(u1 / (1.0 - u1)); + if (v <= expmax) +/*!* w = a * exp(v); *!*/ + w = a * java.lang.Math.exp(v); + else + w = Double.MAX_VALUE; + z = u1 * u1 * u2; + r = gamma * v - 1.3862944; + s = a + r - w; + if (s + 2.609438 >= 5.0 * z) + break; +/*!* t = log(z); *!*/ + t = java.lang.Math.log(z); + if (s > t) + break; + } +/*!* while (r + alpha * log(alpha / (b + w)) < t); *!*/ + while (r + alpha * java.lang.Math.log(alpha / (b + w)) < t); + } + + } // deliver: + return (aa != a) ? b / (b + w) : w / (b + w); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Binomial.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Binomial.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Binomial.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Binomial.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,418 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Binomial + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double n, double p) + * + * DESCRIPTION + * + * The density of the Binomial distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double n, double p) + { + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + if (Double.isNaN(x) || Double.isNaN(n) || Double.isNaN(p)) return x + n + p; + /*!* #endif /*4!*/ +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if(n <= 0 || p < 0 || p > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if (x < 0 || x > n) + return 0; + if (p == 0) + return (x == 0) ? 1 : 0; + if (p == 1) + return (x == n) ? 1 : 0; +/*!* return exp(lfastchoose(n, x) + log(p) * x + (n - x) * log(1 - p)); *!*/ + return java.lang.Math.exp(Misc.lfastchoose(n, x) + java.lang.Math.log(p) * x + (n - x) * java.lang.Math.log(1 - p)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double n, double p) + * + * DESCRIPTION + * + * The distribution function of the Binomial distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double n, double p) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n) || Double.isNaN(p)) + return x + n + p; + if (Double.isInfinite(n) || Double.isInfinite(p)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if(n <= 0 || p < 0 || p > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* x = floor(x); *!*/ + x = java.lang.Math.floor(x); + if (x < 0.0) return 0; + if (n <= x) return 1; + return Beta.cumulative(1.0 - p, n - x, x + 1); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double n, double p); + * + * DESCRIPTION + * + * The quantile function of the Binomial distribution. + * + * NOTES + * + * The function uses the Cornish-Fisher Expansion to include + * a skewness correction to a Normal approximation. This gives + * an initial value which never seems to be off by more than + * 1 or 2. A search is then conducted of values close to + * this initial start point. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double n, double p) + { + double q, mu, sigma, gamma, z, y; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n) || Double.isNaN(p)) + return x + n + p; + if(Double.isInfinite(x) || Double.isInfinite(n) || Double.isInfinite(p)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (x < 0 || x > 1 || p <= 0 || p >= 1 || n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x == 0) return 0.0; + if (x == 1) return n; + q = 1 - p; + mu = n * p; +/*!* sigma = sqrt(n * p * q); *!*/ + sigma = java.lang.Math.sqrt(n * p * q); + gamma = (q-p)/sigma; + z = Normal.quantile(x, 0.0, 1.0); +/*!* y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); *!*/ + y = java.lang.Math.floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); + + z = cumulative(y, n, p); + if(z >= x) { + + /* search to the left */ + + for(;;) { + if((z = cumulative(y - 1, n, p)) < x) + return y; + y = y - 1; + } + } + else { + + /* search to the right */ + + for(;;) { + if((z = cumulative(y + 1, n, p)) >= x) + return y + 1; + y = y + 1; + } + } + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double nin, double pp) + * + * DESCRIPTION + * + * Random variates from the Binomial distribution. + * + * REFERENCE + * + * Kachitvichyanukul, V. and Schmeiser, B. W. (1988). + * Binomial random variate generation. + * Communications of the ACM 31, p216. + * (Algorithm BTPEC). + */ + + /*!* #include "DistLib.h" /*4!*/ + /*!* #include /*4!*/ + + + public static double random(double nin, double pp, Uniform uniformDistribution) + { + double al=0.0, alv=0.0, amaxp=0.0, c=0.0, f=0.0, f1=0.0; + double f2=0.0, ffm=0.0, fm=0.0, g=0.0; + double p1=0.0, p2=0.0, p3=0.0, p4=0.0, qn=0.0, r=0.0; + double u=0.0, v=0.0, w=0.0, w2=0.0; + double x=0.0, x1=0.0, x2=0.0, xl=0.0, xll=0.0, xlr=0.0; + double xm=0.0, xnp=0.0, xnpq=0.0, xr=0.0, ynorm=0.0, z=0.0, z2=0.0; + int i=0, ix=0, ix1=0, k=0, m=0, mp=0, n=0; + double p=0.0, q=0.0; + double psave = -1.0; + int nsave = -1; + + +/*!* n = floor(nin + 0.5); *!*/ + n = (int) java.lang.Math.floor(nin + 0.5); + /* n=0, p=0, p=1 are not errors */ + if ( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isInfinite(n) || Double.isInfinite(pp) || + /*!* #endif /*4!*/ + n < 0.0 || pp < 0.0 || pp > 1.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (n==0.0 || pp==0) return 0; + if (pp==1.0) return n; + + /* setup, perform only when parameters change */ + + L30: { + L20: { + L10: { + if (pp != psave) { + psave = pp; +/*!* p = fmin2(psave, 1.0 - psave); *!*/ + p = Math.min(psave, 1.0 - psave); + q = 1.0 - p; + } else if (n == nsave) { + if (xnp < 30.0) + break L20; + break L10; + } + xnp = n * p; + nsave = n; + if (xnp < 30.0) { + /* inverse cdf logic for mean less than 30 */ +/*!* qn = pow(q, (double) n); *!*/ + qn = java.lang.Math.pow(q, (double) n); + r = p / q; + g = r * (n + 1); + break L20; + } else { + ffm = xnp + p; + m = (int) ffm; + fm = m; + xnpq = xnp * q; +/*!* p1 = (int)(2.195 * sqrt(xnpq) - 4.6 * q) + 0.5; *!*/ + p1 = (int)(2.195 * java.lang.Math.sqrt(xnpq) - 4.6 * q) + 0.5; + xm = fm + 0.5; + xl = xm - p1; + xr = xm + p1; + c = 0.134 + 20.5 / (15.3 + fm); + al = (ffm - xl) / (ffm - xl * p); + xll = al * (1.0 + 0.5 * al); + al = (xr - ffm) / (xr * q); + xlr = al * (1.0 + 0.5 * al); + p2 = p1 * (1.0 + c + c); + p3 = p2 + c / xll; + p4 = p3 + c / xlr; + } + } + // L10: + while(true) { + u = uniformDistribution.random() * p4; + v = uniformDistribution.random(); + /* triangular region */ + if (u <= p1) { + ix = (int) (xm - p1 * v + u); + break L30; + } + /* parallelogram region */ + if (u <= p2) { + x = xl + (u - p1) / c; +/*!* v = v * c + 1.0 - fabs(xm - x) / p1; *!*/ + v = v * c + 1.0 - java.lang.Math.abs(xm - x) / p1; + if (v > 1.0 || v <= 0.) + continue; + ix = (int) x; + } else { + if (u > p3) { /* right tail */ +/*!* ix = xr - log(v) / xlr; *!*/ + ix = (int)( xr - java.lang.Math.log(v) / xlr); + if (ix > n) + continue; + v = v * (u - p3) * xlr; + } else {/* left tail */ +/*!* ix = xl + log(v) / xll; *!*/ + ix = (int) (xl + java.lang.Math.log(v) / xll); + if (ix < 0) + continue; + v = v * (u - p2) * xll; + } + } + /* determine appropriate way to perform accept/reject test */ +/*!* k = abs(ix - m); *!*/ + k = java.lang.Math.abs(ix - m); + if (k <= 20 || k >= xnpq / 2 - 1) { + /* explicit evaluation */ + f = 1.0; + r = p / q; + g = (n + 1) * r; + if (m < ix) { + mp = m + 1; + for (i = mp; i <= ix; i++) + f = f * (g / i - r); + } else if (m != ix) { + ix1 = ix + 1; + for (i = ix1; i <= m; i++) + f = f / (g / i - r); + } + if (v <= f) + break L30; + } else { + /* squeezing using upper and lower bounds */ + /* on log(f(x)) */ + amaxp = (k / xnpq) * ((k * (k / 3.0 + 0.625) + 0.1666666666666) / xnpq + 0.5); + ynorm = -k * k / (2.0 * xnpq); +/*!* alv = log(v); *!*/ + alv = java.lang.Math.log(v); + if (alv < ynorm - amaxp) + break L30; + if (alv <= ynorm + amaxp) { + /* stirling's formula to machine accuracy */ + /* for the final acceptance/rejection test */ + x1 = ix + 1; + f1 = fm + 1.0; + z = n + 1 - fm; + w = n - ix + 1.0; + z2 = z * z; + x2 = x1 * x1; + f2 = f1 * f1; + w2 = w * w; +/*!* if (alv <= xm * log(f1 / x1) + (n - m + 0.5) * log(z / w) + (ix - m) * log(w * p / x1 * q) + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.) *!*/ + if (alv <= xm * java.lang.Math.log(f1 / x1) + (n - m + 0.5) * java.lang.Math.log(z / w) + (ix - m) * java.lang.Math.log(w * p / x1 * q) + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.) + break L30; + } + } + } + } + // L20: + while(true) { + ix = 0; + f = qn; + u = uniformDistribution.random(); + while(true) { + if (u < f) + break L30; + if (ix > 110) + break; + u = u - f; + ix = ix + 1; + f = f * (g / ix - r); + } + } + } + // L30: + if (psave > 0.5) + ix = n - ix; + return (double)ix; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Cauchy.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Cauchy.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Cauchy.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Cauchy.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,199 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Cauchy + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double location, double scale); + * + * DESCRIPTION + * + * The density of the Cauchy distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double location, double scale) + { + double y; + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + if (Double.isNaN(x) || Double.isNaN(location) || Double.isNaN(scale)) + return x + location + scale; + /*!* #endif /*4!*/ + if (scale <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + y = (x - location) / scale; + return 1.0 / (Constants.M_PI * scale * (1.0 + y * y)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double location, double scale); + * + * DESCRIPTION + * + * The distribution function of the Cauchy distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double location, double scale) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(location) || Double.isNaN(scale)) + return x + location + scale; + /*!* #endif /*4!*/ + if (scale <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + x = (x - location) / scale; + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(x)) { + if(x < 0) return 0; + else return 1; + } + /*!* #endif /*4!*/ +/*!* return 0.5 + atan(x) / Constants.M_PI; *!*/ + return 0.5 + java.lang.Math.atan(x) / Constants.M_PI; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double location, double scale); + * + * DESCRIPTION + * + * The quantile function of the Cauchy distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double location, double scale) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(location) || Double.isNaN(scale)) + return x + location + scale; + if(Double.isInfinite(x) || Double.isInfinite(location) || Double.isInfinite(scale)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + + if (scale <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* return location + scale * tan(Constants.M_PI * (x - 0.5)); *!*/ + return location + scale * java.lang.Math.tan(Constants.M_PI * (x - 0.5)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double location, double scale); + * + * DESCRIPTION + * + * Random variates from the normal distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double location, double scale, Uniform uniformDistribution) + { + if ( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isInfinite(location) || Double.isInfinite(scale) || + /*!* #endif /*4!*/ + scale < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* return location + scale * tan(Constants.M_PI * sunif()); *!*/ + return location + scale * java.lang.Math.tan(Constants.M_PI * uniformDistribution.random()); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Chisquare.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Chisquare.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Chisquare.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Chisquare.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,164 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Chisquare + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double df) + * + * DESCRIPTION + * + * The density of the chi-squared disribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double df) + { + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + /*!* #endif /*4!*/ + return Gamma.density(x, df / 2.0, 2.0); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double df); + * + * DESCRIPTION + * + * The disribution function of the chi-squared distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double df) + { + return Gamma.cumulative(x, df / 2.0, 2.0); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double p, double df); + * + * DESCRIPTION + * + * The quantile function of the chi-squared distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double p, double df) + { + return Gamma.quantile(p, 0.5 * df, 2.0); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double df); + * + * DESCRIPTION + * + * Random variates from the chi-squared distribution. + * + * NOTES + * + * Calls rgamma to do the real work. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double df, Uniform uniformDistribution) + { + if ( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isInfinite(df) || + /*!* #endif /*4!*/ + df <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + return Gamma.random(df / 2.0, 2.0, uniformDistribution); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Constants.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Constants.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Constants.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Constants.java 2010-01-27 09:33:28.000000000 +0000 @@ -0,0 +1,95 @@ +/* DistLib : A C Library of Special Functions + * Copyright (C) 1998 R Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * data translated from C using perl script translate.pl + * script version 0.00 + */ + +package org.mathpiper.builtin.library.statdistlib; + +/** + * Class defining constants. + */ + +public class Constants { + + /* 30 Decimal-place constants computed with bc -l (scale=32; proper round) */ + + public static final double M_SQRT_2 = 1.4142135623730950488016887242097; + /* 1/sqrt(2) */ + public static final double M_1_SQRT_2 = 0.707106781186547524400844362105; + /* sqrt(32) */ + public static final double M_SQRT_32 = 5.656854249492380195206754896838; + + public static final double M_LN_2 = 0.693147180559945309417232121458176568; + public static final double M_LOG10_2 = 0.301029995663981195213738894724493027; + + public static final double M_PI = 3.141592653589793238462643383279502884197169399375; + public static final double M_PI_half = 1.570796326794896619231321691640; + + /* 1/pi */ + public static final double M_1_PI = 0.31830988618379067153776752674502872406891929148; + + /* pi/2 */ + public static final double M_PI_2 = 1.57079632679489661923132169163975144209858469969; + + /* sqrt(pi), 1/sqrt(2pi), sqrt(2/pi) : */ + public static final double M_SQRT_PI = 1.772453850905516027298167483341; + public static final double M_1_SQRT_2PI = 0.398942280401432677939946059934; + public static final double M_SQRT_2dPI = 0.79788456080286535587989211986876; + + /* log(sqrt(pi)) = log(pi)/2 : */ + public static final double M_LN_SQRT_PI = 0.5723649429247000870717136756765293558; + /* log(sqrt(2*pi)) = log(2*pi)/2 : */ + public static final double M_LN_SQRT_2PI = 0.91893853320467274178032973640562; + /* log(sqrt(pi/2)) = log(pi/2)/2 : */ + public static final double M_LN_SQRT_PId2 = 0.225791352644727432363097614947441; + + public static final double ME_NONE = 0; + public static final double ME_DOMAIN = 1; + public static final double ME_RANGE = 2; + public static final double ME_NOCONV = 3; + public static final double ME_PRECISION = 4; + public static final double ME_UNDERFLOW = 5; + + /* constants taken from float.h for gcc 2.90.29 for Linux 2.0 i386 */ + /* -- should match Java since both are supposed to be IEEE 754 compliant */ + + /* Radix of exponent representation */ + public static final int FLT_RADIX = 2; + + /* Difference between 1.0 and the minimum float/double greater than 1.0 */ + public static final double FLT_EPSILON = 1.19209290e-07F; + public static final double DBL_EPSILON = 2.2204460492503131e-16; + + /* Number of decimal digits of precision in a float/double */ + public static final int FLT_DIG = 6; + public static final int DBL_DIG = 15; + + /* Number of base-FLT_RADIX digits in the significand of a double */ + public static final int FLT_MANT_DIG = 24; + public static final int DBL_MANT_DIG = 53; + + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ + public static final int FLT_MIN_EXP = -125; + public static final int DBL_MIN_EXP = -1021; + + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ + public static final int FLT_MAX_EXP = 128; + public static final int DBL_MAX_EXP = 1024; + + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Exponential.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Exponential.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Exponential.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Exponential.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,138 @@ +/* DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * data translated from C using perl script translate.pl + * script version 0.00 + */ +package org.mathpiper.builtin.library.statdistlib; + +/** + * Wrapper of functions for the Exponential distribution. + */ + +public class Exponential { + + /** + * Density of the Exponential distribution. + */ + public static double density(double x, double scale) { + if (Double.isNaN(x) || Double.isNaN(scale)) return x + scale; + if (scale <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (x < 0.0) return 0.0; + return java.lang.Math.exp(-x / scale) / scale; + } + + /** + * Distribution function of the Exponential distribution + * + */ + public static double cumulative(double x, double scale) { + if (Double.isNaN(x) || Double.isNaN(scale)) + return x + scale; + if (scale <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (x <= 0.0) return 0.0; + return 1.0 - java.lang.Math.exp(-x / scale); + } + + /** + * quantile function of the Exponential distribution + */ + public static double quantile(double x, double scale) { + if (Double.isNaN(x) || Double.isNaN(scale)) + return x + scale; + if (scale <= 0 || x < 0 || x > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (x <= 0.0) return 0.0; + return - scale * java.lang.Math.log(1.0 - x); + } + + /** + * Random variates from the Exponential distribution + */ + public static double random(double scale, Uniform uniformDistribution) { + if (Double.isInfinite(scale) || scale <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + return scale * random(uniformDistribution); + } + + /** + * Random variates from the standard normal distribution. + * + * Ahrens, J.H. and Dieter, U. (1972). + * Computer methods for sampling from the Exponential and + * normal distributions. + * Comm. ACM, 15, 873-882. + */ + + static private double q[] = { + 0.6931471805599453, + 0.9333736875190459, + 0.9888777961838675, + 0.9984959252914960, + 0.9998292811061389, + 0.9999833164100727, + 0.9999985691438767, + 0.9999998906925558, + 0.9999999924734159, + 0.9999999995283275, + 0.9999999999728814, + 0.9999999999985598, + 0.9999999999999289, + 0.9999999999999968, + 0.9999999999999999, + 1.0000000000000000 + }; + + + public static double random(Uniform uniformDistribution) { + /* q[k-1] = sum(alog(2.0)**k/k!) k=1,..,n, */ + /* The highest n (here 8) is determined by q[n-1] = 1.0 */ + /* within standard precision */ + double a, u, ustar, umin; + int i; + + a = 0.0; + u = uniformDistribution.random(); + for (;;) { + u = u + u; + if (u > 1.0) + break; + a = a + q[0]; + } + u = u - 1.0; + + if (u <= q[0]) + return a + u; + + i = 0; + ustar = uniformDistribution.random(); + umin = ustar; + do { + ustar = uniformDistribution.random(); + if (ustar < umin) + umin = ustar; + i = i + 1; + } while (u > q[i]); + return a + umin * q[0]; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/F.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/F.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/F.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/F.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,201 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class F + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double n1, double n2); + * + * DESCRIPTION + * + * The density function of the F distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double n1, double n2) + { + double a; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n1) || Double.isNaN(n2)) + return x + n1 + n2; + /*!* #endif /*4!*/ + if (n1 <= 0 || n2 <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x <= 0.0) + return 0.0; + a = (n1 / n2) * x; +/*!* return pow(a, 0.5 * n1) * pow(1.0 + a, -0.5 * (n1 + n2)) *!*/ + return java.lang.Math.pow(a, 0.5 * n1) * java.lang.Math.pow(1.0 + a, -0.5 * (n1 + n2)) +/*!* / (x * Beta(0.5 * n1, 0.5 * n2)); *!*/ + / (x * Misc.beta(0.5 * n1, 0.5 * n2)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double n1, double n2); + * + * DESCRIPTION + * + * The distribution function of the F distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double n1, double n2) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n1) || Double.isNaN(n2)) + return x + n2 + n1; + /*!* #endif /*4!*/ + if (n1 <= 0.0 || n2 <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x <= 0.0) + return 0.0; + x = 1.0 - Beta.cumulative(n2 / (n2 + n1 * x), n2 / 2.0, n1 / 2.0); + return !Double.isNaN(x) ? x : Double.NaN; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double n1, double n2); + * + * DESCRIPTION + * + * The quantile function of the F distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double n1, double n2) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n1) || Double.isNaN(n2)) + return x + n1 + n2; + /*!* #endif /*4!*/ + if (n1 <= 0.0 || n2 <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x <= 0.0) + return 0.0; + x = (1.0 / Beta.quantile(1.0 - x, n2 / 2.0, n1 / 2.0) - 1.0) * (n2 / n1); + return !Double.isNaN(x) ? x : Double.NaN; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "mathlib.h" + * double random(double dfn, double dfd); + * + * DESCRIPTION + * + * Pseudo-random variates from an F distribution. + * + * NOTES + * + * This function calls rchisq to do the real work + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double n1, double n2, Uniform uniformDistribution) + { + double v1, v2; + if ( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isNaN(n1) || Double.isNaN(n2) || + /*!* #endif /*4!*/ + n1 <= 0.0 || n2 <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + v1 = !Double.isInfinite(n1) ? (Chisquare.random(n1,uniformDistribution) / n1) : Normal.random(uniformDistribution); + v2 = !Double.isInfinite(n2) ? (Chisquare.random(n2,uniformDistribution) / n2) : Normal.random(uniformDistribution); + return v1 / v2; + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Gamma.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Gamma.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Gamma.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Gamma.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,636 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + +public class Gamma + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double shape, double scale); + * + * DESCRIPTION + * + * Computes the density of the Gamma distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double shape, double scale) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(shape) || Double.isNaN(scale)) + return x + shape + scale; + /*!* #endif /*4!*/ + if (shape <= 0 || scale <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x < 0) + return 0; + if (x == 0) { + if (shape < 1) { + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // return Double.POSITIVE_INFINITY; + } + if (shape > 1) { + return 0; + } + return 1 / scale; + } + x = x / scale; +/*!* return exp((shape - 1) * log(x) - lgammafn(shape) - x) / scale; *!*/ + return java.lang.Math.exp((shape - 1) * java.lang.Math.log(x) - Misc.lgammafn(shape) - x) / scale; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double a, double scale); + * + * DESCRIPTION + * + * This function computes the distribution function for the + * Gamma distribution with shape parameter a and scale parameter + * scale. This is also known as the incomplete Gamma function. + * See Abramowitz and Stegun (6.5.1) for example. + * + * NOTES + * + * This function is an adaptation of Algorithm 239 from the + * Applied Statistics Series. The algorithm is faster than + * those by W. Fullerton in the FNLIB library and also the + * TOMS 542 alorithm of W. Gautschi. It provides comparable + * accuracy to those algorithms and is considerably simpler. + * + * REFERENCES + * + * Algorithm 239, Incomplete Gamma Function + * Applied Statistics 37, 1988. + */ + + /*!* #include "DistLib.h" /*4!*/ + + static private double + third = 1.0 / 3.0, + zero = 0.0, + one = 1.0, + two = 2.0, + oflo = 1.0e+37, + three = 3.0, + nine = 9.0, + xbig = 1.0e+8, + plimit = 1000.0e0, + elimit = -88.0e0; + + public static double cumulative(double x, double p, double scale) + { + double pn1, pn2, pn3, pn4, pn5, pn6, arg, c, rn, a, b, an; + double sum; + + /* check that we have valid values for x and p */ + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(p) || Double.isNaN(scale)) + return x + p + scale; + /*!* #endif /*4!*/ + if(p <= zero || scale <= zero) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + x = x / scale; + if (x <= zero) + return 0.0; + + /* use a Normal approximation if p > plimit */ + + if (p > plimit) { +/*!* pn1 = sqrt(p) * three * (pow(x/p, third) + one / (p * nine) - one); *!*/ + pn1 = java.lang.Math.sqrt(p) * three * (java.lang.Math.pow(x/p, third) + one / (p * nine) - one); + return Normal.cumulative(pn1, 0.0, 1.0); + } + + /* if x is extremely large compared to p then return 1 */ + + if (x > xbig) + return one; + + if (x <= one || x < p) { + + /* use pearson's series expansion. */ + +/*!* arg = p * log(x) - x - lgammafn(p + one); *!*/ + arg = p * java.lang.Math.log(x) - x - Misc.lgammafn(p + one); + c = one; + sum = one; + a = p; + do { + a = a + one; + c = c * x / a; + sum = sum + c; + } while (c > Constants.DBL_EPSILON); +/*!* arg = arg + log(sum); *!*/ + arg = arg + java.lang.Math.log(sum); + sum = zero; + if (arg >= elimit) +/*!* sum = exp(arg); *!*/ + sum = java.lang.Math.exp(arg); + } else { + + /* use a continued fraction expansion */ + +/*!* arg = p * log(x) - x - lgammafn(p); *!*/ + arg = p * java.lang.Math.log(x) - x - Misc.lgammafn(p); + a = one - p; + b = a + x + one; + c = zero; + pn1 = one; + pn2 = x; + pn3 = x + one; + pn4 = x * b; + sum = pn3 / pn4; + for (;;) { + a = a + one; + b = b + two; + c = c + one; + an = a * c; + pn5 = b * pn3 - an * pn1; + pn6 = b * pn4 - an * pn2; +/*!* if (fabs(pn6) > zero) { *!*/ + if (java.lang.Math.abs(pn6) > zero) { + rn = pn5 / pn6; +/*!* if (fabs(sum - rn) <= fmin2(Constants.DBL_EPSILON, Constants.DBL_EPSILON * rn)) *!*/ + if (java.lang.Math.abs(sum - rn) <= Math.min(Constants.DBL_EPSILON, Constants.DBL_EPSILON * rn)) + break; + sum = rn; + } + pn1 = pn3; + pn2 = pn4; + pn3 = pn5; + pn4 = pn6; +/*!* if (fabs(pn5) >= oflo) { *!*/ + if (java.lang.Math.abs(pn5) >= oflo) { + + /* re-scale the terms in continued fraction */ + /* if they are large */ + + pn1 = pn1 / oflo; + pn2 = pn2 / oflo; + pn3 = pn3 / oflo; + pn4 = pn4 / oflo; + } + } +/*!* arg = arg + log(sum); *!*/ + arg = arg + java.lang.Math.log(sum); + sum = one; + if (arg >= elimit) +/*!* sum = one - exp(arg); *!*/ + sum = one - java.lang.Math.exp(arg); + } + return sum; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double p, double shape, double scale); + * + * DESCRIPTION + * + * Compute the quantile function of the Gamma distribution. + * + * NOTES + * + * This function is based on the Applied Statistics + * Algorithm AS 91 and AS 239. + * + * REFERENCES + * + * Best, D. J. and D. E. Roberts (1975). + * Percentage Points of the Chi-Squared Disribution. + * Applied Statistics 24, page 385. + */ + + /*!* #include "DistLib.h" /*4!*/ + + static private double C7 = 4.67; + static private double C8 = 6.66; + static private double C9 = 6.73; + static private double C10 = 13.32; + + static private double C11 = 60; + static private double C12 = 70; + static private double C13 = 84; + static private double C14 = 105; + static private double C15 = 120; + static private double C16 = 127; + static private double C17 = 140; + static private double C18 = 1175; + static private double C19 = 210; + + static private double C20 = 252; + static private double C21 = 2264; + static private double C22 = 294; + static private double C23 = 346; + static private double C24 = 420; + static private double C25 = 462; + static private double C26 = 606; + static private double C27 = 672; + static private double C28 = 707; + static private double C29 = 735; + + static private double C30 = 889; + static private double C31 = 932; + static private double C32 = 966; + static private double C33 = 1141; + static private double C34 = 1182; + static private double C35 = 1278; + static private double C36 = 1740; + static private double C37 = 2520; + static private double C38 = 5040; + + static private double EPS0 = 5e-7/* originally: IDENTICAL to EPS2; not clear why */; + static private double EPS1 = 1e-2; + static private double EPS2 = 5e-7; + static private double MAXIT = 20; + + static private double pMIN = 0.000002; + static private double pMAX = 0.999998; + + public static double quantile(double p, double alpha, double scale) + { + double a, b, c, ch, g, p1, v; + double p2, q, s1, s2, s3, s4, s5, s6, t=0.0, x; + int i; + + /* test arguments and initialise */ + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(p) || Double.isNaN(alpha) || Double.isNaN(scale)) + return p + alpha + scale; + /*!* #endif /*4!*/ + + if (p < 0 || p > 1 || alpha <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (/* 0 <= */ p < pMIN) return 0; + if (/* 1 >= */ p > pMAX) return Double.POSITIVE_INFINITY; + + v = 2*alpha; + + c = alpha-1; +/*!* g = lgammafn(alpha);!!!COMMENT!!! *!*/ + g = Misc.lgammafn(alpha);/* log Gamma(v/2) */ + +/*!* if(v < (-1.24)*log(p)) { *!*/ + if(v < (-1.24)*java.lang.Math.log(p)) { + /* starting approximation for small chi-squared */ + +/*!* ch = pow(p*alpha*exp(g+alpha*Constants.M_LN_2), 1/alpha); *!*/ + ch = java.lang.Math.pow(p*alpha*java.lang.Math.exp(g+alpha*Constants.M_LN_2), 1/alpha); + if(ch < EPS0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + + } else if(v > 0.32) { + + /* starting approximation using Wilson and Hilferty estimate */ + + x = Normal.quantile(p, 0, 1); + p1 = 0.222222/v; +/*!* ch = v*pow(x*sqrt(p1)+1-p1, 3); *!*/ + ch = v*java.lang.Math.pow(x*java.lang.Math.sqrt(p1)+1-p1, 3); + + /* starting approximation for p tending to 1 */ + + if( ch > 2.2*v + 6 ) +/*!* ch = -2*(log(1-p) - c*log(0.5*ch) + g); *!*/ + ch = -2*(java.lang.Math.log(1-p) - c*java.lang.Math.log(0.5*ch) + g); + + } else { /* starting approximation for v <= 0.32 */ + + ch = 0.4; +/*!* a = log(1-p) + g + c*Constants.M_LN_2; *!*/ + a = java.lang.Math.log(1-p) + g + c*Constants.M_LN_2; + do { + q = ch; + p1 = 1+ch*(C7+ch); + p2 = ch*(C9+ch*(C8+ch)); + t = -0.5 +(C7+2*ch)/p1 - (C9+ch*(C10+3*ch))/p2; +/*!* ch -= (1- exp(a+0.5*ch)*p2/p1)/t; *!*/ + ch -= (1- java.lang.Math.exp(a+0.5*ch)*p2/p1)/t; +/*!* } while(fabs(q/ch - 1) > EPS1); *!*/ + } while(java.lang.Math.abs(q/ch - 1) > EPS1); + } + + /* algorithm AS 239 and calculation of seven term taylor series */ + + for( i=1 ; i <= MAXIT ; i++ ) { + q = ch; + p1 = 0.5*ch; + p2 = p - cumulative(p1, alpha, 1); + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(p2)) + /*!* #else /*4!*/ + // if((!!!!fixme!!!!) != 0) + /*!* #endif /*4!*/ + // return Double.NaN; + +/*!* t = p2*exp(alpha*Constants.M_LN_2+g+p1-c*log(ch)); *!*/ + t = p2*java.lang.Math.exp(alpha*Constants.M_LN_2+g+p1-c*java.lang.Math.log(ch)); + b = t/ch; + a = 0.5*t-b*c; + s1 = (C19+a*(C17+a*(C14+a*(C13+a*(C12+C11*a)))))/C24; + s2 = (C24+a*(C29+a*(C32+a*(C33+C35*a))))/C37; + s3 = (C19+a*(C25+a*(C28+C31*a)))/C37; + s4 = (C20+a*(C27+C34*a)+c*(C22+a*(C30+C36*a)))/C38; + s5 = (C13+C21*a+c*(C18+C26*a))/C37; + s6 = (C15+c*(C23+C16*c))/C38; + ch = ch+t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6)))))); +/*!* if(fabs(q/ch-1) > EPS2) *!*/ + if(java.lang.Math.abs(q/ch-1) > EPS2) + return 0.5*scale*ch; + } + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + // return 0.5*scale*ch; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double a, double scale); + * + * DESCRIPTION + * + * Random variates from the Gamma distribution. + * + * REFERENCES + * + * [1] Shape parameter a >= 1. Algorithm GD in: + * + * Ahrens, J.H. and Dieter, U. (1982). + * Generating Gamma variates by a modified + * rejection technique. + * Comm. ACM, 25, 47-54. + * + * + * [2] Shape parameter 0 < a < 1. Algorithm GS in: + * + * Ahrens, J.H. and Dieter, U. (1974). + * Computer methods for sampling from Gamma, beta, + * poisson and binomial distributions. + * Computing, 12, 223-246. + * + * Input: a = parameter (mean) of the standard Gamma distribution. + * Output: a variate from the Gamma(a)-distribution + * + * Coefficients q(k) - for q0 = sum(q(k)*a**(-k)) + * Coefficients a(k) - for q = q0+(t*t/2)*sum(a(k)*v**k) + * Coefficients e(k) - for exp(q)-1 = sum(e(k)*q**k) + */ + + /*!* #include "DistLib.h" /*4!*/ + + static private double a1 = 0.3333333; + static private double a2 = -0.250003; + static private double a3 = 0.2000062; + static private double a4 = -0.1662921; + static private double a5 = 0.1423657; + static private double a6 = -0.1367177; + static private double a7 = 0.1233795; + static private double e1 = 1.0; + static private double e2 = 0.4999897; + static private double e3 = 0.166829; + static private double e4 = 0.0407753; + static private double e5 = 0.010293; + static private double q1 = 0.04166669; + static private double q2 = 0.02083148; + static private double q3 = 0.00801191; + static private double q4 = 0.00144121; + static private double q5 = -7.388e-5; + static private double q6 = 2.4511e-4; + static private double q7 = 2.424e-4; + static private double sqrt32 = 5.656854; + + static private double aa = 0.; + static private double aaa = 0.; + + static private double b, c, d, e, p, q, r, s, t, u, v, w, x; + static private double q0, s2, si; + + + public static double random(double a, double scale, Uniform uniformDistribution) + { + double ret_val; + + if (a < 1.0) { + /* alternate method for parameters a below 1 */ + /* 0.36787944117144232159 = exp(-1) */ + aa = 0.0; + b = 1.0 + 0.36787944117144232159 * a; + while(true) { + p = b * uniformDistribution.random(); + if (p >= 1.0) { +/*!* ret_val = -log((b - p) / a); *!*/ + ret_val = -java.lang.Math.log((b - p) / a); +/*!* if (Exponential.random!!!COMMENT!!!() >= (1.0 - a) * log(ret_val)) *!*/ + if (Exponential.random(uniformDistribution) >= (1.0 - a) * java.lang.Math.log(ret_val)) + break; + } else { +/*!* ret_val = exp(log(p) / a); *!*/ + ret_val = java.lang.Math.exp(java.lang.Math.log(p) / a); + if (Exponential.random(uniformDistribution) >= ret_val) + break; + } + } + return scale * ret_val; + } + /* Step 1: Recalculations of s2, s, d if a has changed */ + if (a != aa) { + aa = a; + s2 = a - 0.5; +/*!* s = sqrt(s2); *!*/ + s = java.lang.Math.sqrt(s2); + d = sqrt32 - s * 12.0; + } + /* Step 2: t = standard Normal deviate, */ + /* x = (s,1/2)-Normal deviate. */ + /* immediate acceptance (i) */ + + t = Normal.random(uniformDistribution); + x = s + 0.5 * t; + ret_val = x * x; + if (t >= 0.0) + return scale * ret_val; + + /* Step 3: u = 0,1 - Uniform sample. squeeze acceptance (s) */ + u = uniformDistribution.random(); + if (d * u <= t * t * t) { + return scale * ret_val; + } + /* Step 4: recalculations of q0, b, si, c if necessary */ + + if (a != aaa) { + aaa = a; + r = 1.0 / a; + q0 = ((((((q7 * r + q6) * r + q5) * r + q4) + * r + q3) * r + q2) * r + q1) * r; + + /* Approximation depending on size of parameter a */ + /* The constants in the expressions for b, si and */ + /* c were established by numerical experiments */ + + if (a <= 3.686) { + b = 0.463 + s + 0.178 * s2; + si = 1.235; + c = 0.195 / s - 0.079 + 0.16 * s; + } else if (a <= 13.022) { + b = 1.654 + 0.0076 * s2; + si = 1.68 / s + 0.275; + c = 0.062 / s + 0.024; + } else { + b = 1.77; + si = 0.75; + c = 0.1515 / s; + } + } + /* Step 5: no quotient test if x not positive */ + + if (x > 0.0) { + /* Step 6: calculation of v and quotient q */ + v = t / (s + s); +/*!* if (fabs(v) <= 0.25) *!*/ + if (java.lang.Math.abs(v) <= 0.25) + q = q0 + 0.5 * t * t * ((((((a7 * v + a6) + * v + a5) * v + a4) * v + a3) + * v + a2) * v + a1) * v; + else + q = q0 - s * t + 0.25 * t * t + (s2 + s2) +/*!* * log(1.0 + v); *!*/ + * java.lang.Math.log(1.0 + v); + + + /* Step 7: quotient acceptance (q) */ + +/*!* if (log(1.0 - u) <= q) *!*/ + if (java.lang.Math.log(1.0 - u) <= q) + return scale * ret_val; + } + /* Step 8: e = standard Exponential deviate */ + /* u= 0,1 -Uniform deviate */ + /* t=(b,si)-double Exponential (laplace) sample */ + + while(true) { + e = Exponential.random(uniformDistribution); + u = uniformDistribution.random(); + u = u + u - 1.0; + if (u < 0.0) + t = b - si * e; + else + t = b + si * e; + /* Step 9: rejection if t < tau(1) = -0.71874483771719 */ + if (t >= -0.71874483771719) { + /* Step 10: calculation of v and quotient q */ + v = t / (s + s); +/*!* if (fabs(v) <= 0.25) *!*/ + if (java.lang.Math.abs(v) <= 0.25) + q = q0 + 0.5 * t * t * ((((((a7 * v + a6) + * v + a5) * v + a4) * v + a3) + * v + a2) * v + a1) * v; + else + q = q0 - s * t + 0.25 * t * t + (s2 + s2) +/*!* * log(1.0 + v); *!*/ + * java.lang.Math.log(1.0 + v); + /* Step 11: hat acceptance (h) */ + /* (if q not positive go to step 8) */ + if (q > 0.0) { + if (q <= 0.5) + w = ((((e5 * q + e4) * q + e3) + * q + e2) * q + e1) * q; + else +/*!* w = exp(q) - 1.0; *!*/ + w = java.lang.Math.exp(q) - 1.0; + /* if t is rejected */ + /* sample again at step 8 */ +/*!* if (c * fabs(u) <= w * exp(e - 0.5 * t * t)) *!*/ + if (c * java.lang.Math.abs(u) <= w * java.lang.Math.exp(e - 0.5 * t * t)) + break; + } + } + } + x = s + 0.5 * t; + return scale * x * x; + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Geometric.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Geometric.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Geometric.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Geometric.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,215 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Geometric + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double p); + * + * DESCRIPTION + * + * The density of the Geometric distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double p) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(p)) return x + p; + /*!* #endif /*4!*/ + if (p <= 0 || p >= 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if (x < 0) + return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(x)) return 1; + /*!* #endif /*4!*/ +/*!* return p * pow(1 - p, x); *!*/ + return p * java.lang.Math.pow(1 - p, x); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double p); + * + * DESCRIPTION + * + * The distribution function of the Geometric distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double p) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(p)) + return x + p; + /*!* #endif /*4!*/ +/*!* x = floor(x); *!*/ + x = java.lang.Math.floor(x); + if(p <= 0 || p >= 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x < 0.0) return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isInfinite(x)) return 1; + /*!* #endif /*4!*/ +/*!* return 1 - pow(1 - p, x + 1); *!*/ + return 1 - java.lang.Math.pow(1 - p, x + 1); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double p); + * + * DESCRIPTION + * + * The quantile function of the Geometric distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double p) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(p)) + return x + p; + if (x < 0 || x > 1 || p <= 0 || p > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x == 1) return Double.POSITIVE_INFINITY; + /*!* #else /*4!*/ + if (x < 0 || x >= 1 || p <= 0 || p > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + if (x == 0) return 0; +/*!* return ceil(log(1 - x) / log(1.0 - p) - 1); *!*/ + return java.lang.Math.ceil(java.lang.Math.log(1 - x) / java.lang.Math.log(1.0 - p) - 1); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka and the R Core Team. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double p); + * + * DESCRIPTION + * + * Random variates from the Geometric distribution. + * + * NOTES + * + * We generate lambda as Exponential with scale parameter + * p / (1 - p). Return a Poisson deviate with mean lambda. + * + * REFERENCE + * + * Devroye, L. (1980). + * Non-Uniform Random Variate Generation. + * New York: Springer-Verlag. + * Page 480. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double p, Uniform uniformDistribution) + { + if ( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isNaN(p) || + /*!* #endif /*4!*/ + p <= 0 || p >= 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + return Poisson.random(Exponential.random( uniformDistribution ) * ((1 - p) / p), uniformDistribution); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Hypergeometric.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Hypergeometric.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Hypergeometric.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Hypergeometric.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,603 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Hypergeometric + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double NR, double NB, double n); + * + * DESCRIPTION + * + * The density of the Hypergeometric distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double NR, double NB, double n) + { + double N; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(NR) || Double.isNaN(NB) || Double.isNaN(n)) + return x + NR + NB + n; + /*!* #endif /*4!*/ +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); +/*!* NR = floor(NR + 0.5); *!*/ + NR = java.lang.Math.floor(NR + 0.5); +/*!* NB = floor(NB + 0.5); *!*/ + NB = java.lang.Math.floor(NB + 0.5); + N = NR + NB; +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (NR < 0 || NB < 0 || n < 0 || n > N) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* if (x < fmax2(0, n - NB) || x > fmin2(n, NR)) *!*/ + if (x < Math.max(0, n - NB) || x > Math.min(n, NR)) + return 0; +/*!* return exp(lfastchoose(NR, x) + lfastchoose(NB, n - x) *!*/ + return java.lang.Math.exp(Misc.lfastchoose(NR, x) + Misc.lfastchoose(NB, n - x) +/*!* - lfastchoose(N, n)); *!*/ + - Misc.lfastchoose(N, n)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double NR, double NB, double n); + * + * DESCRIPTION + * + * The distribution function of the Hypergeometric distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double NR, double NB, double n) + { + double N, xstart, xend, xr, xb, sum, term; + + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isNaN(x) || Double.isNaN(NR) || Double.isNaN(NB) || Double.isNaN(n)) + return x + NR + NB + n; + if(Double.isInfinite(x) || Double.isInfinite(NR) || Double.isInfinite(NB) || Double.isInfinite(n)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + +/*!* x = floor(x); *!*/ + x = java.lang.Math.floor(x); +/*!* NR = floor(NR + 0.5); *!*/ + NR = java.lang.Math.floor(NR + 0.5); +/*!* NB = floor(NB + 0.5); *!*/ + NB = java.lang.Math.floor(NB + 0.5); + N = NR + NB; +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (NR < 0 || NB < 0 || n < 0 || n > N) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* xstart = fmax2(0, n - NB); *!*/ + xstart = Math.max(0, n - NB); +/*!* xend = fmin2(n, NR); *!*/ + xend = Math.min(n, NR); + if(x < xstart) return 0.0; + if(x >= xend) return 1.0; + xr = xstart; + xb = n - xr; +/*!* term = exp(lfastchoose(NR, xr) + lfastchoose(NB, xb) *!*/ + term = java.lang.Math.exp(Misc.lfastchoose(NR, xr) + Misc.lfastchoose(NB, xb) +/*!* - lfastchoose(N, n)); *!*/ + - Misc.lfastchoose(N, n)); + NR = NR - xr; + NB = NB - xb; + sum = 0.0; + while(xr <= x) { + sum += term; + xr++; + NB++; + term *= (NR / xr) * (xb / NB); + xb--; + NR--; + } + return sum; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double NR, double NB, double n); + * + * DESCRIPTION + * + * The quantile function of the Hypergeometric distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double NR, double NB, double n) + { + double N, xstart, xend, xr, xb, sum, term; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(NR) || Double.isNaN(NB) || Double.isNaN(n)) + return x + NR + NB + n; + if(Double.isInfinite(x) || Double.isInfinite(NR) || Double.isInfinite(NB) || Double.isInfinite(n)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ +/*!* NR = floor(NR + 0.5); *!*/ + NR = java.lang.Math.floor(NR + 0.5); +/*!* NB = floor(NB + 0.5); *!*/ + NB = java.lang.Math.floor(NB + 0.5); + N = NR + NB; +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (x < 0 || x > 1 || NR < 0 || NR < 0 || n < 0 || n > N) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* xstart = fmax2(0, n - NB); *!*/ + xstart = Math.max(0, n - NB); +/*!* xend = fmin2(n, NR); *!*/ + xend = Math.min(n, NR); + if(x <= 0) return xstart; + if(x >= 1) return xend; + xr = xstart; + xb = n - xr; +/*!* term = exp(lfastchoose(NR, xr) + lfastchoose(NB, xb) *!*/ + term = java.lang.Math.exp(Misc.lfastchoose(NR, xr) + Misc.lfastchoose(NB, xb) +/*!* - lfastchoose(N, n)); *!*/ + - Misc.lfastchoose(N, n)); + NR = NR - xr; + NB = NB - xb; + sum = term; + while(sum < x && xr < xend) { + xr++; + NB++; + term *= (NR / xr) * (xb / NB); + sum += term; + xb--; + NR--; + } + return xr; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double NR, double NB, double n); + * + * DESCRIPTION + * + * Random variates from the Hypergeometric distribution. + * Returns the number of white balls drawn when kk balls + * are drawn at random from an urn containing nn1 white + * and nn2 black balls. + * + * REFERENCE + * + * V. Kachitvichyanukul and B. Schmeiser (1985). + * ``Computer generation of Hypergeometric random variates,'' + * Journal of Statistical Computation and Simulation 22, 127-145. + */ + + /*!* #include "DistLib.h" /*4!*/ + + /* afc(i) := ln( i! ) [logarithm of the factorial i. + * If (i > 7), use Stirling's approximation, otherwise use table lookup. + */ + + static private double al[] = + { + 0.0, + 0.0,/*ln(0!)=ln(1)*/ + 0.0,/*ln(1!)=ln(1)*/ + 0.69314718055994530941723212145817,/*ln(2) */ + 1.79175946922805500081247735838070,/*ln(6) */ + 3.17805383034794561964694160129705,/*ln(24)*/ + 4.78749174278204599424770093452324, + 6.57925121201010099506017829290394, + 8.52516136106541430016553103634712 + /*, 10.60460290274525022841722740072165*/ + }; + + static private double afc(int i) + { + double di, value; + if (i < 0) { + System.out.println("rhyper.c: afc(i)+ i=%d < 0 -- SHOULD NOT HAPPEN!\n"+i); + return -1;/* unreached (Wall) */ + } else if (i <= 7) { + value = al[i + 1]; + } else { + di = i; +/*!* value = (di + 0.5) * log(di) - di + 0.08333333333333 / di *!*/ + value = (di + 0.5) * java.lang.Math.log(di) - di + 0.08333333333333 / di + - 0.00277777777777 / di / di / di + 0.9189385332; + } + return value; + } + + + static private int ks = -1; + static private int n1s = -1; + static private int n2s = -1; + static private double con = 57.56462733; + static private double deltal = 0.0078; + static private double deltau = 0.0034; + static private double scale = 1e25; + + static private double a; + static private double d, e, f, g; + static private int i, k, m; + static private double p; + static private double r, s, t; + static private double u, v, w; + static private double lamdl, y, lamdr; + static private int minjx, maxjx, n1, n2; + static private double p1, p2, p3, y1, de, dg; + static private boolean setup1, setup2; + static private double gl, kl, ub, nk, dr, nm, gu, kr, ds, dt; + static private int ix; + static private double tn; + static private double xl; + static private double ym, yn, yk, xm; + static private double xr; + static private double xn; + static private boolean reject; + static private double xk; + /* extern double afc(int); */ + static private double alv; + + + public static double random(double nn1in, double nn2in, double kkin, + Uniform uniformDistribution) + { + int nn1, nn2, kk; + + /* check parameter validity */ + + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(nn1in) || Double.isInfinite(nn2in) || Double.isInfinite(kkin)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + +/*!* nn1 = floor(nn1in+0.5); *!*/ + nn1 = (int) java.lang.Math.floor(nn1in+0.5); +/*!* nn2 = floor(nn2in+0.5); *!*/ + nn2 = (int) java.lang.Math.floor(nn2in+0.5); +/*!* kk = floor(kkin+0.5); *!*/ + kk = (int) java.lang.Math.floor(kkin+0.5); + + if (nn1 < 0 || nn2 < 0 || kk < 0 || kk > nn1 + nn2) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /* if new parameter values, initialize */ + + reject = true; + setup1 = false; + setup2 = false; + if (nn1 != n1s || nn2 != n2s) { + setup1 = true; + setup2 = true; + } else if (kk != ks) { + setup2 = true; + } + if (setup1) { + n1s = nn1; + n2s = nn2; + tn = nn1 + nn2; + if (nn1 <= nn2) { + n1 = nn1; + n2 = nn2; + } else { + n1 = nn2; + n2 = nn1; + } + } + if (setup2) { + ks = kk; + if (kk + kk >= tn) { + k = (int) (tn) - kk; + } else { + k = kk; + } + } + if (setup1 || setup2) { + m = (int) ((k + 1.0) * (n1 + 1.0) / (tn + 2.0)); +/*!* minjx = imax2(0, k - n2); *!*/ + minjx = Math.max(0, k - n2); +/*!* maxjx = Math.min(n1, k); *!*/ + maxjx = Math.min(n1, k); + } + /* generate random variate */ + + if (minjx == maxjx) { + /* degenerate distribution */ + ix = maxjx; + /* return ix; + No, need to unmangle */ + /* return appropriate variate */ + + if (kk + kk >= tn) { + if (nn1 > nn2) { + ix = kk - nn2 + ix; + } else { + ix = nn1 - ix; + } + } else { + if (nn1 > nn2) + ix = kk - ix; + } + return ix; + + } else if (m - minjx < 10) { + /* inverse transformation */ + if (setup1 || setup2) { + if (k < n2) { + /*!* w = exp(con + afc(n2) + afc(n1 + n2 - k) *!*/ + w = java.lang.Math.exp(con + afc(n2) + afc(n1 + n2 - k) + - afc(n2 - k) - afc(n1 + n2)); + } else { + /*!* w = exp(con + afc(n1) + afc(k) *!*/ + w = java.lang.Math.exp(con + afc(n1) + afc(k) + - afc(k - n2) - afc(n1 + n2)); + } + } + L10: while(true) { + p = w; + ix = minjx; + u = uniformDistribution.random() * scale; + L20: while(true) { + if (u > p) { + u = u - p; + p = p * (n1 - ix) * (k - ix); + ix = ix + 1; + p = p / ix / (n2 - k + ix); + if (ix > maxjx) + continue L10; + continue L20; + } + break L10; + }} + } else { + /* h2pe */ + + if (setup1 || setup2) { + /*!* s = sqrt((tn - k) * k * n1 * n2 / (tn - 1) / tn / tn); *!*/ + s = java.lang.Math.sqrt((tn - k) * k * n1 * n2 / (tn - 1) / tn / tn); + + /* remark: d is defined in reference without int. */ + /* the truncation centers the cell boundaries at 0.5 */ + + d = (int) (1.5 * s) + .5; + xl = m - d + .5; + xr = m + d + .5; + a = afc(m) + afc(n1 - m) + afc(k - m) + + afc(n2 - k + m); +/*!* kl = exp(a - afc((int) (xl)) - afc((int) (n1 - xl)) *!*/ + kl = java.lang.Math.exp(a - afc((int) (xl)) - afc((int) (n1 - xl)) + - afc((int) (k - xl)) + - afc((int) (n2 - k + xl))); +/*!* kr = exp(a - afc((int) (xr - 1)) *!*/ + kr = java.lang.Math.exp(a - afc((int) (xr - 1)) + - afc((int) (n1 - xr + 1)) + - afc((int) (k - xr + 1)) + - afc((int) (n2 - k + xr - 1))); +/*!* lamdl = -log(xl * (n2 - k + xl) / (n1 - xl + 1) *!*/ + lamdl = -java.lang.Math.log(xl * (n2 - k + xl) / (n1 - xl + 1) + / (k - xl + 1)); +/*!* lamdr = -log((n1 - xr + 1) * (k - xr + 1) *!*/ + lamdr = -java.lang.Math.log((n1 - xr + 1) * (k - xr + 1) + / xr / (n2 - k + xr)); + p1 = d + d; + p2 = p1 + kl / lamdl; + p3 = p2 + kr / lamdr; + } + L30: while(true) { + u = uniformDistribution.random() * p3; + v = uniformDistribution.random(); + if (u < p1) { + /* rectangular region */ + ix = (int) (xl + u); + } else if (u <= p2) { + /* left tail */ +/*!* ix = xl + log(v) / lamdl; *!*/ + ix = (int) (xl + java.lang.Math.log(v) / lamdl); + if (ix < minjx) + continue L30; + v = v * (u - p1) * lamdl; + } else { + /* right tail */ +/*!* ix = xr - log(v) / lamdr; *!*/ + ix = (int) (xr - java.lang.Math.log(v) / lamdr); + if (ix > maxjx) + continue L30; + v = v * (u - p2) * lamdr; + } + + /* acceptance/rejection test */ + + if (m < 100 || ix <= 50) { + /* explicit evaluation */ + f = 1.0; + if (m < ix) { + for (i = m + 1; i <= ix; i++) + f = f * (n1 - i + 1) * (k - i + 1) + / (n2 - k + i) / i; + } else if (m > ix) { + for (i = ix + 1; i <= m; i++) + f = f * i * (n2 - k + i) / (n1 - i) + / (k - i); + } + if (v <= f) { + reject = false; + } + } else { + /* squeeze using upper and lower bounds */ + y = ix; + y1 = y + 1.0; + ym = y - m; + yn = n1 - y + 1.0; + yk = k - y + 1.0; + nk = n2 - k + y1; + r = -ym / y1; + s = ym / yn; + t = ym / yk; + e = -ym / nk; + g = yn * yk / (y1 * nk) - 1.0; + dg = 1.0; + if (g < 0.0) + dg = 1.0 + g; + gu = g * (1.0 + g * (-0.5 + g / 3.0)); + gl = gu - .25 * (g * g * g * g) / dg; + xm = m + 0.5; + xn = n1 - m + 0.5; + xk = k - m + 0.5; + nm = n2 - k + xm; + ub = y * gu - m * gl + deltau + + xm * r * (1. + r * (-0.5 + r / 3.0)) + + xn * s * (1. + s * (-0.5 + s / 3.0)) + + xk * t * (1. + t * (-0.5 + t / 3.0)) + + nm * e * (1. + e * (-0.5 + e / 3.0)); + /* test against upper bound */ +/*!* alv = log(v); *!*/ + alv = java.lang.Math.log(v); + if (alv > ub) { + reject = true; + } else { + /* test against lower bound */ + dr = xm * (r * r * r * r); + if (r < 0.0) + dr = dr / (1.0 + r); + ds = xn * (s * s * s * s); + if (s < 0.0) + ds = ds / (1.0 + s); + dt = xk * (t * t * t * t); + if (t < 0.0) + dt = dt / (1.0 + t); + de = nm * (e * e * e * e); + if (e < 0.0) + de = de / (1.0 + e); + if (alv < ub - 0.25 * (dr + ds + dt + de) + + (y + m) * (gl - gu) - deltal) { + reject = false; + } else { + /* + * stirling's formula to machine + * accuracy + */ + if (alv <= (a - afc(ix) - afc(n1 - ix) + - afc(k - ix) - afc(n2 - k + ix))) { + reject = false; + } else { + reject = true; + } + } + } + } + if (reject) + continue L30; + break L30; + } + } + /* return appropriate variate */ + + if (kk + kk >= tn) { + if (nn1 > nn2) { + ix = kk - nn2 + ix; + } else { + ix = nn1 - ix; + } + } else { + if (nn1 > nn2) + ix = kk - ix; + } + return ix; + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Logistic.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Logistic.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Logistic.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Logistic.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,158 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Logistic + { + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double location, double scale) + { + double e, f; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(location) || Double.isNaN(scale)) + return x + location + scale; + /*!* #endif /*4!*/ + if (scale <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* e = exp(-(x - location) / scale); *!*/ + e = java.lang.Math.exp(-(x - location) / scale); + f = 1.0 + e; + return e / (scale * f * f); + } + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double location, double scale) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(location) || Double.isNaN(scale)) + return x + location + scale; + /*!* #endif /*4!*/ + if (scale <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if(Double.isInfinite(x)) { + if (x > 0) return 1; + else return 0; + } +/*!* return 1.0 / (1.0 + exp(-(x - location) / scale)); *!*/ + return 1.0 / (1.0 + java.lang.Math.exp(-(x - location) / scale)); + } + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double location, double scale) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(location) || Double.isNaN(scale)) + return x + location + scale; + /*!* #endif /*4!*/ + if (scale <= 0.0 || x < 0 || x > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if(x <= 0) return Double.NEGATIVE_INFINITY; + if(x == 1) return Double.POSITIVE_INFINITY; +/*!* return location + scale * log(x / (1.0 - x)); *!*/ + return location + scale * java.lang.Math.log(x / (1.0 - x)); + } + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double location, double scale, Uniform uniformDistribution) + { + double u; + /* #ifndef IEEE_754 */ + if (Double.isInfinite(location) || Double.isInfinite(scale)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /* #endif */ + u = uniformDistribution.random(); +/*!* return location + scale * log(u / (1.0 - u)); *!*/ + return location + scale * java.lang.Math.log(u / (1.0 - u)); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/LogNormal.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/LogNormal.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/LogNormal.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/LogNormal.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,195 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class LogNormal + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * double density(double x, double logmean, double logsd); + * + * DESCRIPTION + * + * The density of the LogNormal distribution. + * + * M_1_SQRT_2PI = 1 / sqrt(2 * pi) + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double logmean, double logsd) + { + double y; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(logmean) || Double.isNaN(logsd)) + return x + logmean + logsd; + /*!* #endif /*4!*/ + if(logsd <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if(x == 0) return 0; +/*!* y = (log(x) - logmean) / logsd; *!*/ + y = (java.lang.Math.log(x) - logmean) / logsd; +/*!* return Constants.M_1_SQRT_2PI * exp(-0.5 * y * y) / (x * logsd); *!*/ + return Constants.M_1_SQRT_2PI * java.lang.Math.exp(-0.5 * y * y) / (x * logsd); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double logmean, double logsd); + * + * DESCRIPTION + * + * The LogNormal distribution function. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double logmean, double logsd) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(logmean) || Double.isNaN(logsd)) + return x + logmean + logsd; + /*!* #endif /*4!*/ + if (logsd <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x > 0) +/*!* return Normal.cumulative!!!COMMENT!!!(log(x), logmean, logsd); *!*/ + return Normal.cumulative(java.lang.Math.log(x), logmean, logsd); + return 0; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double logmean, double logsd); + * + * DESCRIPTION + * + * This the LogNormal quantile function. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double logmean, double logsd) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(logmean) || Double.isNaN(logsd)) + return x + logmean + logsd; + /*!* #endif /*4!*/ + if(x < 0 || x > 1 || logsd <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x == 1) return Double.POSITIVE_INFINITY; +/*!* if (x > 0) return exp(qnorm(x, logmean, logsd)); *!*/ + if (x > 0) return java.lang.Math.exp(Normal.quantile(x, logmean, logsd)); + return 0; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double logmean, double logsd); + * + * DESCRIPTION + * + * Random variates from the LogNormal distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double logmean, double logsd, Uniform uniformDistribution) + { + if( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isInfinite(logmean) || Double.isInfinite(logsd) || + /*!* #endif /*4!*/ + logsd <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* return exp(rnorm(logmean, logsd)); *!*/ + return java.lang.Math.exp(Normal.random(logmean, logsd, uniformDistribution)); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Misc.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Misc.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Misc.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Misc.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,1441 @@ +/* DistLib - A Mathematical Function Library + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * data translated from C using perl script translate.pl + * script version 0.00 + */ +package org.mathpiper.builtin.library.statdistlib; + +/** + * Miscellaneous functions and values. + */ + +public class Misc { + + /** + * Value of the beta function + * evaluated with arguments a and b. + * + * This routine is a translation into C of a Fortran subroutine + * by W. Fullerton of Los Alamos Scientific Laboratory. + * Some modifications have been made so that the routines + * conform to the IEEE 754 standard. + */ + + public static double beta(double a, double b) { + double xmax = 0; + double alnsml = 0; + double val=0.0, xmin=0.0; + double temp[]; + + if (xmax == 0) { + temp = gammalims(xmin, xmax); + xmin = temp[0]; xmax=temp[1]; + alnsml = java.lang.Math.log(d1mach(1)); + } + + if (Double.isNaN(a) || Double.isNaN(b)) return a + b; + + if (a < 0 || b < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + else if (a == 0 || b == 0) { + return Double.POSITIVE_INFINITY; + } + else if (Double.isInfinite(a) || Double.isInfinite(b)) { + return 0; + } + + if (a + b < xmax) + return gammafn(a) * gammafn(b) / gammafn(a+b); + + val = lbeta(a, b); + // check for underflow of beta + if (val < alnsml) { + throw new java.lang.ArithmeticException("Math Error: UNDERFLOW"); + } + return java.lang.Math.exp(val); + } + + /** + * Determine the number of terms for the + * double precision orthogonal Chebyshev series "dos" needed to insure + * the error is no larger than "eta". Ordinarily eta will be + * chosen to be one-tenth machine precision. + * + * These routines are translations into C of Fortran routines + * by W. Fullerton of Los Alamos Scientific Laboratory. + * + * Based on the Fortran routine dcsevl by W. Fullerton. + * Adapted from R. Broucke, Algorithm 446, CACM., 16, 254 (1973). + */ + static int chebyshev_init(double dos[], int nos, double eta) { + if (nos < 1) return 0; + + double err = 0.0; + int i = 0; + for (int ii=1; ii<=nos; ii++) { + i = nos - ii; + err += java.lang.Math.abs(dos[i]); + if (err > eta) { + return i; + } + } + return i; + } + + /** + * evaluate the n-term Chebyshev series + * @param x + * @param a + * @param n + * @return + */ + public static double chebyshev_eval(double x, double a[], int n) { + if (n < 1 || n > 1000) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + if (x < -1.1 || x > 1.1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + double twox = x * 2; + double b2 = 0; + double b1 = 0; + double b0 = 0; + for (int i = 1; i <= n; i++) { + b2 = b1; + b1 = b0; + b0 = twox * b1 - b2 + a[(int) n - i]; + } + return (b0 - b2) * 0.5; + } + + /* + * SYNOPSIS + * + * #include "DistLib.h" + * double choose(double n, double k); + * double fastchoose(double n, double k); + * double lchoose(double n, double k); + * double lfastchoose(double n, double k); + * + * DESCRIPTION + * + * Binomial coefficients. + */ + /*!* #include "DistLib.h" /*4!*/ + + public static double lfastchoose(double n, double k) { + return lgammafn(n + 1.0) - lgammafn(k + 1.0) - lgammafn(n - k + 1.0); + } + + public static double fastchoose(double n, double k) { + return java.lang.Math.exp(lfastchoose(n, k)); + } + + public static double lchoose(double n, double k) { + n = java.lang.Math.floor(n + 0.5); + k = java.lang.Math.floor(k + 0.5); + if (Double.isNaN(n) || Double.isNaN(k)) return n + k; + if (k < 0 || n < k) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + return lfastchoose(n, k); + } + + /** + * binomial coefficient + * @param n + * @param k + * @return + */ + public static double choose(double n, double k) { + n = java.lang.Math.floor(n + 0.5); + k = java.lang.Math.floor(k + 0.5); + if (Double.isNaN(n) || Double.isNaN(k)) return n + k; + if (k < 0 || n < k) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + return java.lang.Math.floor(java.lang.Math.exp(lfastchoose(n, k)) + 0.5); + } + + /** + * machine dependant constants + * @param i + * @return + */ + + public static double d1mach(int i) { + switch (i) { + + case 1: return Double.MIN_VALUE; + case 2: return Double.MAX_VALUE; + case 3: return java.lang.Math.pow((double)i1mach(10), -(double)i1mach(14)); + case 4: return java.lang.Math.pow((double)i1mach(10), 1-(double)i1mach(14)); + case 5: return Math.log(2.0)/Math.log(10.0); + + default: return 0.0; + } + } + + /* + * Returns the cube of its argument. + */ + public static double fcube(double x) { + return x * x * x; + } + + + public static double fmax2(double x, double y) { + if (Double.isNaN(x) || Double.isNaN(y)) + return x + y; + return (x < y) ? y : x; + } + + /*!* #include "DistLib.h" /*4!*/ + + public static double fmin2(double x, double y) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(y)) + return x + y; + /*!* #endif /*4!*/ + return (x < y) ? x : y; + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double fmod(double x, double y); + * + * DESCRIPTION + * + * Floating-point remainder of x / y; + * + * NOTES + * + * It may be better to use the system version of this function, + * but this version is portable. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double fmod(double x, double y) + { + double quot; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(y)) + return x + y; + /*!* #endif /*4!*/ + quot = x / y; +/*!* return x - (quot < 0.0 ? ceil(quot) : floor(quot)) * y; *!*/ + return x - (quot < 0.0 ? java.lang.Math.ceil(quot) : java.lang.Math.floor(quot)) * y; + } + + /** + * Returns the value of x rounded to "digits" significant + * decimal digits. + * + * This routine is a translation into C of a Fortran subroutine + * by W. Fullerton of Los Alamos Scientific Laboratory. + * Some modifications have been made so that the routines + * conform to the IEEE 754 standard. + * + * Improvements by Martin Maechler, May 1997 + * Note that the code could be further improved by using + * java.lang.Math.pow(x, i) instead of pow(x, (double)i) + */ + + static final double MAXPLACES = Constants.DBL_DIG; + + public static double fprec(double x, double digits) { + + if (Double.isNaN(x) || Double.isNaN(digits)) return x + digits; + if (Double.isInfinite(x)) return x; + if (Double.isInfinite(digits)) { + if (digits > 0) return x; + else return 0; + } + + if (x == 0) return x; + + digits = java.lang.Math.floor(digits+0.5); + if (digits > MAXPLACES) return x; + else if (digits < 1) digits = 1; + + double sgn = 1.0; + if (x < 0.0) { + sgn = -sgn; + x = -x; + } + double l10 = Math.log(x) / Math.log(10.0); + // Max.expon. of 10 (=308.2547) + int e10 = (int)(digits-1-java.lang.Math.floor(l10)); + final double max10e = Constants.DBL_MAX_EXP * Constants.M_LOG10_2; + if (Math.abs(l10) < max10e - 2) { + double pow10 = Math.pow(10.0, (double)e10); + return (sgn*Math.floor(x*pow10+0.5)/pow10); + } else { /* -- LARGE or small -- */ + /*!* do_round = max10e - l10 >= pow(10.0, -digits); *!*/ + boolean do_round = max10e - l10 >= Math.pow(10.0, -digits); + int e2 = (e10>0)? 16 : -16; + double p10 = Math.pow(10.0, (double)e2); + x *= p10; + double P10 = Math.pow(10.0, (double)e10-e2); + x *= P10; + /*-- p10 * P10 = 10 ^ e10 */ + if (do_round) x += 0.5; + x = Math.floor(x) / p10; + return (sgn*x/P10); + } + } + + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double fround(double x, double digits); + * + * DESCRIPTION + * + * Rounds "x" to "digits" decimal digits. + */ + + /*!* #include "DistLib.h" /*4!*/ + + /*!* #ifndef HAVE_RINT /*4!*/ + /*!* #define USE_BUILTIN_RINT /*4!*/ + /*!* #endif /*4!*/ + + /*!* #ifdef USE_BUILTIN_RINT /*4!*/ + // final double R_rint = static private_rint; + + /* The largest integer which can be represented */ + /* exactly in floating point form. */ + + static final double BIGGEST = 4503599627370496.0E0; + /* 2^52 for IEEE */ + + static private double Rint(double x) + { + final double biggest = BIGGEST; + double tmp; + + if (x != x) return x; /* NaN */ + +/*!* if (fabs(x) >= biggest) !!!COMMENT!!! *!*/ + if (java.lang.Math.abs(x) >= biggest) /* Already integer */ + return x; + + if(x >= 0) { + tmp = x + biggest; + return tmp - biggest; + } + else { + tmp = x - biggest; + return tmp + biggest; + } + } + + /*!* #else /*4!*/ + //final double R_rint = rint; + /*!* #endif /*4!*/ + + public static double fround(double x, double digits) + { + double pow10, sgn, intx; + final double maxdigits = Constants.DBL_DIG - 1; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(digits)) + return x + digits; + if(Double.isInfinite(x)) return x; + /*!* #endif /*4!*/ + +/*!* digits = floor(digits + 0.5); *!*/ + digits = java.lang.Math.floor(digits + 0.5); + if (digits > maxdigits) + digits = maxdigits; +/*!* pow10 = pow(10.0, digits); *!*/ + pow10 = java.lang.Math.pow(10.0, digits); + sgn = 1.0; + if(x < 0.0) { + sgn = -sgn; + x = -x; + } + if (digits > 0.0) { +/*!* intx = floor(x); *!*/ + intx = java.lang.Math.floor(x); + x = x - intx; + } else { + intx = 0.0; + } + return sgn * (intx + java.lang.Math.rint(x * pow10) / pow10); + } + /* + * SYNOPSIS + * + * #include "DistLib.h" + * double fsign(double x, double y); + * + * DESCRIPTION + * + * This function performs transfer of sign. The result is: + * + * |x| * signum(y) + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double fsign(double x, double y) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(y)) + return x + y; + /*!* #endif /*4!*/ +/*!* return ((y >= 0) ? fabs(x) : -fabs(x)); *!*/ + return ((y >= 0) ? java.lang.Math.abs(x) : -java.lang.Math.abs(x)); + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double fsquare(double x); + * + * DESCRIPTION + * + * This function returns the square of its argument. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double fsquare(double x) + { + return x * x; + } + + /** + * Truncation toward zero. + */ + public static double ftrunc(double x) { + if (x >= 0) return java.lang.Math.floor(x); + else return java.lang.Math.ceil(x); + } + + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double gammafn(double x); + * + * DESCRIPTION + * + * This function computes the value of the gamma function. + * + * NOTES + * + * This function is a translation into C of a Fortran subroutine + * by W. Fullerton of Los Alamos Scientific Laboratory. + * + * The accuracy of this routine compares (very) favourably + * with those of the Sun Microsystems portable mathematical + * library. + */ + + /*!* #include "DistLib.h" /*4!*/ + + static final double gamcs[] = { + +.8571195590989331421920062399942e-2, + +.4415381324841006757191315771652e-2, + +.5685043681599363378632664588789e-1, + -.4219835396418560501012500186624e-2, + +.1326808181212460220584006796352e-2, + -.1893024529798880432523947023886e-3, + +.3606925327441245256578082217225e-4, + -.6056761904460864218485548290365e-5, + +.1055829546302283344731823509093e-5, + -.1811967365542384048291855891166e-6, + +.3117724964715322277790254593169e-7, + -.5354219639019687140874081024347e-8, + +.9193275519859588946887786825940e-9, + -.1577941280288339761767423273953e-9, + +.2707980622934954543266540433089e-10, + -.4646818653825730144081661058933e-11, + +.7973350192007419656460767175359e-12, + -.1368078209830916025799499172309e-12, + +.2347319486563800657233471771688e-13, + -.4027432614949066932766570534699e-14, + +.6910051747372100912138336975257e-15, + -.1185584500221992907052387126192e-15, + +.2034148542496373955201026051932e-16, + -.3490054341717405849274012949108e-17, + +.5987993856485305567135051066026e-18, + -.1027378057872228074490069778431e-18, + +.1762702816060529824942759660748e-19, + -.3024320653735306260958772112042e-20, + +.5188914660218397839717833550506e-21, + -.8902770842456576692449251601066e-22, + +.1527474068493342602274596891306e-22, + -.2620731256187362900257328332799e-23, + +.4496464047830538670331046570666e-24, + -.7714712731336877911703901525333e-25, + +.1323635453126044036486572714666e-25, + -.2270999412942928816702313813333e-26, + +.3896418998003991449320816639999e-27, + -.6685198115125953327792127999999e-28, + +.1146998663140024384347613866666e-28, + -.1967938586345134677295103999999e-29, + +.3376448816585338090334890666666e-30, + -.5793070335782135784625493333333e-31 + }; + + public static double gammafn(double x) + { + int ngam = 0; + double xmin = 0.; + double xmax = 0.; + double xsml = 0.; + double dxrel = 0.; + double temp[]; + + int i, n; + double y; + double sinpiy, value; + + if (ngam == 0) { + ngam = chebyshev_init(gamcs, 42, 0.1 * d1mach(3)); + temp = gammalims(xmin, xmax); + xmin=temp[0]; xmax=temp[1]; +/*!* xsml = exp(fmax2(log(d1mach(1)), -log(d1mach(2)))+0.01); *!*/ + xsml = java.lang.Math.exp(fmax2(java.lang.Math.log(d1mach(1)), -java.lang.Math.log(d1mach(2)))+0.01); +/*!* dxrel = sqrt(d1mach(4)); *!*/ + dxrel = java.lang.Math.sqrt(d1mach(4)); + } + + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isNaN(x)) return x; + /*!* #endif /*4!*/ + +/*!* y = fabs(x); *!*/ + y = java.lang.Math.abs(x); + + if (y <= 10) { + + /* Compute gamma(x) for -10 <= x <= 10. */ + /* Reduce the interval and find gamma(1 + y) for */ + /* 0 <= y < 1 first of all. */ + + n = (int) x; + if(x < 0) --n; + y = x - n;/* n = floor(x) ==> y in [ 0, 1 ) */ + --n; + value = chebyshev_eval(y * 2 - 1, gamcs, ngam) + .9375; + if (n == 0) + return value;/* x = 1.dddd = 1+y */ + + if (n < 0) { + /* compute gamma(x) for -10 <= x < 1 */ + + /* If the argument is exactly zero or a negative integer */ + /* then return NaN. */ + if (x == 0 || (x < 0 && x == n + 2)) { + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // return Double.NaN; + } + + /* The answer is less than half precision */ + /* because x too near a negative integer. */ +/*!* if (x < -0.5 && fabs(x - (int)(x - 0.5) / x) < dxrel) { *!*/ + if (x < -0.5 && java.lang.Math.abs(x - (int)(x - 0.5) / x) < dxrel) { + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + } + + /* The argument is so close to 0 that the result would overflow. */ + if (y < xsml) { + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // if(x > 0) return Double.POSITIVE_INFINITY; + // else return Double.NEGATIVE_INFINITY; + } + + n = -n; + + for (i = 0; i < n; i++) { + value /= (x + i); + } + return value; + } + else { + /* gamma(x) for 2 <= x <= 10 */ + + for (i = 1; i <= n; i++) { + value *= (y + i); + } + return value; + } + } + else { + /* gamma(x) for y = |x| > 10. */ + + if (x > xmax) { /* Overflow */ + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // return Double.POSITIVE_INFINITY; + } + + if (x < xmin) { /* Underflow */ + throw new java.lang.ArithmeticException("Math Error: UNDERFLOW"); + // return (Double.MIN_VALUE * Double.MIN_VALUE); + } + +/*!* value = exp((y - 0.5) * log(y) - y + Constants.M_LN_SQRT_2PI + lgammacor(y)); *!*/ + value = java.lang.Math.exp((y - 0.5) * java.lang.Math.log(y) - y + Constants.M_LN_SQRT_2PI + lgammacor(y)); + + if (x > 0) + return value; + +/*!* if (fabs((x - (int)(x - 0.5))/x) < dxrel){ *!*/ + if (java.lang.Math.abs((x - (int)(x - 0.5))/x) < dxrel){ + + /* The answer is less than half precision because */ + /* the argument is too near a negative integer. */ + + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + } + +/*!* sinpiy = sin(Constants.M_PI * y); *!*/ + sinpiy = java.lang.Math.sin(Constants.M_PI * y); + if (sinpiy == 0) { /* Negative integer arg - overflow */ + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // return Double.POSITIVE_INFINITY; + } + + return -Constants.M_PI / (y * sinpiy * value); + } + } + /* From http://www.netlib.org/specfun/gamma Fortran translated by f2c,... + * ------------------------------##### Martin Maechler, ETH Zurich + * + *=========== was part of ribesl (Bessel I(.)) + *=========== ~~~~~~ + */ + /*!* #include "DistLib.h" /*4!*/ + + public static double gamma_cody(double x) + { + /* ---------------------------------------------------------------------- + + This routine calculates the GAMMA function for a float argument X. + Computation is based on an algorithm outlined in reference [1]. + The program uses rational functions that approximate the GAMMA + function to at least 20 significant decimal digits. Coefficients + for the approximation over the interval (1,2) are unpublished. + Those for the approximation for X >= 12 are from reference [2]. + The accuracy achieved depends on the arithmetic system, the + compiler, the intrinsic functions, and proper selection of the + machine-dependent constants. + + ******************************************************************* + + Error returns + + The program returns the value XINF for singularities or + when overflow would occur. The computation is believed + to be free of underflow and overflow. + + Intrinsic functions required are: + + INT, DBLE, EXP, LOG, REAL, SIN + + + References: + [1] "An Overview of Software Development for Special Functions", + W. J. Cody, Lecture Notes in Mathematics, 506, + Numerical Analysis Dundee, 1975, G. A. Watson (ed.), + Springer Verlag, Berlin, 1976. + + [2] Computer Approximations, Hart, Et. Al., Wiley and sons, New York, 1968. + + Latest modification: October 12, 1989 + + Authors: W. J. Cody and L. Stoltz + Applied Mathematics Division + Argonne National Laboratory + Argonne, IL 60439 + ----------------------------------------------------------------------*/ + + /* ---------------------------------------------------------------------- + Mathematical constants + ----------------------------------------------------------------------*/ + final double sqrtpi = .9189385332046727417803297; /* == ??? */ + + /* ******************************************************************* + + Explanation of machine-dependent constants + + beta - radix for the floating-point representation + maxexp - the smallest positive power of beta that overflows + XBIG - the largest argument for which GAMMA(X) is representable + in the machine, i.e., the solution to the equation + GAMMA(XBIG) = beta**maxexp + XINF - the largest machine representable floating-point number; + approximately beta**maxexp + EPS - the smallest positive floating-point number such that 1.0+EPS > 1.0 + XMININ - the smallest positive floating-point number such that + 1/XMININ is machine representable + + Approximate values for some important machines are: + + beta maxexp XBIG + + CRAY-1 (S.P.) 2 8191 966.961 + Cyber 180/855 + under NOS (S.P.) 2 1070 177.803 + IEEE (IBM/XT, + SUN, etc.) (S.P.) 2 128 35.040 + IEEE (IBM/XT, + SUN, etc.) (D.P.) 2 1024 171.624 + IBM 3033 (D.P.) 16 63 57.574 + VAX D-Format (D.P.) 2 127 34.844 + VAX G-Format (D.P.) 2 1023 171.489 + + XINF EPS XMININ + + CRAY-1 (S.P.) 5.45E+2465 7.11E-15 1.84E-2466 + Cyber 180/855 + under NOS (S.P.) 1.26E+322 3.55E-15 3.14E-294 + IEEE (IBM/XT, + SUN, etc.) (S.P.) 3.40E+38 1.19E-7 1.18E-38 + IEEE (IBM/XT, + SUN, etc.) (D.P.) 1.79D+308 2.22D-16 2.23D-308 + IBM 3033 (D.P.) 7.23D+75 2.22D-16 1.39D-76 + VAX D-Format (D.P.) 1.70D+38 1.39D-17 5.88D-39 + VAX G-Format (D.P.) 8.98D+307 1.11D-16 1.12D-308 + + ******************************************************************* + + ---------------------------------------------------------------------- + Machine dependent parameters + ---------------------------------------------------------------------- + */ + + + final double xbig = 171.624; + /* ML_POSINF == static private double xinf = 1.79e308;*/ + /* Constants.DBL_EPSILON = static private double eps = 2.22e-16;*/ + /* Double.MIN_VALUE == static private double xminin = 2.23e-308;*/ + + /*---------------------------------------------------------------------- + Numerator and denominator coefficients for rational minimax + approximation over (1,2). + ----------------------------------------------------------------------*/ + // final double p[8] = { + final double p[] = { + -1.71618513886549492533811, + 24.7656508055759199108314,-379.804256470945635097577, + 629.331155312818442661052,866.966202790413211295064, + -31451.2729688483675254357,-36144.4134186911729807069, + 66456.1438202405440627855 }; + // final double q[8] = { + final double q[] = { + -30.8402300119738975254353, + 315.350626979604161529144,-1015.15636749021914166146, + -3107.77167157231109440444,22538.1184209801510330112, + 4755.84627752788110767815,-134659.959864969306392456, + -115132.259675553483497211 }; + /*---------------------------------------------------------------------- + Coefficients for minimax approximation over (12, INF). + ----------------------------------------------------------------------*/ + // final double c[7] = { + final double c[] = { + -.001910444077728,8.4171387781295e-4, + -5.952379913043012e-4,7.93650793500350248e-4, + -.002777777777777681622553,.08333333333333333331554247, + .0057083835261 }; + + /* Local variables */ + long i, n; + boolean parity;/*logical*/ + double fact, xden, xnum, y, z, y1, res, sum, ysq; + + parity = false; + fact = 1.; + n = 0; + y = x; + L_end: { + if (y <= 0.) { + /* ------------------------------------------------------------- + Argument is negative + ------------------------------------------------------------- */ + y = -x; + y1 = ftrunc(y); + res = y - y1; + if (res != 0.) { + if (y1 != ftrunc(y1 * .5) * 2.) + parity = true; + /*!* fact = -Constants.M_PI / sin(Constants.M_PI * res); *!*/ + fact = -Constants.M_PI / java.lang.Math.sin(Constants.M_PI * res); + y += 1.; + } else { + res = Double.POSITIVE_INFINITY; + break L_end; + } + } + /* ----------------------------------------------------------------- + Argument is positive + -----------------------------------------------------------------*/ + if (y < Constants.DBL_EPSILON) { + /* -------------------------------------------------------------- + Argument < EPS + -------------------------------------------------------------- */ + if (y >= Double.MIN_VALUE) { + res = 1. / y; + } else { + res = Double.POSITIVE_INFINITY; + break L_end; + } + } else if (y < 12.) { + y1 = y; + if (y < 1.) { + /* --------------------------------------------------------- + EPS < argument < 1 + --------------------------------------------------------- */ + z = y; + y += 1.; + } else { + /* ----------------------------------------------------------- + 1 <= argument < 12, reduce argument if necessary + ----------------------------------------------------------- */ + n = (long) y - 1; + y -= (double) n; + z = y - 1.; + } + /* --------------------------------------------------------- + Evaluate approximation for 1.0 < argument < 2.0 + ---------------------------------------------------------*/ + xnum = 0.; + xden = 1.; + for (i = 0; i < 8; ++i) { + xnum = (xnum + p[(int) i]) * z; + xden = xden * z + q[(int) i]; + } + res = xnum / xden + 1.; + if (y1 < y) { + /* -------------------------------------------------------- + Adjust result for case 0.0 < argument < 1.0 + -------------------------------------------------------- */ + res /= y1; + } else if (y1 > y) { + /* ---------------------------------------------------------- + Adjust result for case 2.0 < argument < 12.0 + ---------------------------------------------------------- */ + for (i = 0; i < n; ++i) { + res *= y; + y += 1.; + } + } + } else { + /* ------------------------------------------------------------- + Evaluate for argument >= 12.0, + ------------------------------------------------------------- */ + if (y <= xbig) { + ysq = y * y; + sum = c[6]; + for (i = 0; i < 6; ++i) { + sum = sum / ysq + c[(int) i]; + } + sum = sum / y - y + sqrtpi; + /*!* sum += (y - .5) * log(y); *!*/ + sum += (y - .5) * java.lang.Math.log(y); + /*!* res = exp(sum); *!*/ + res = java.lang.Math.exp(sum); + } else { + res = Double.POSITIVE_INFINITY; + break L_end; + } + } + /* ---------------------------------------------------------------------- + Final adjustments and return + ----------------------------------------------------------------------*/ + if (parity) + res = -res; + if (fact != 1.) + res = fact / res; + + } // L_end: + return res; + } + + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * void gammalims(double *xmin, double *xmax); + * + * DESCRIPTION + * + * This function alculates the minimum and maximum legal bounds + * for x in gammafn(x). These are not the only bounds, but they + * are the only non-trivial ones to calculate. + * + * NOTES + * + * This routine is a translation into C of a Fortran subroutine + * by W. Fullerton of Los Alamos Scientific Laboratory. + */ + + /*!* #include "DistLib.h" /*4!*/ + + /* FIXME: We need an ifdef'ed version of this which gives */ + /* the exact values when we are using IEEE 754 arithmetic. */ + + static double[] gammalims(double xmin, double xmax) + { + double alnbig, alnsml, xln, xold; + int i; + +/*!* alnsml = log(d1mach(1)); *!*/ + alnsml = java.lang.Math.log(d1mach(1)); + xmin = -alnsml; + find_xmax: { + for (i=1; i<=10; ++i) { + xold = xmin; +/*!* xln = log(*xmin); *!*/ + xln = java.lang.Math.log(xmin); + xmin -= xmin * ((xmin + .5) * xln - xmin - .2258 + alnsml) / + (xmin * xln + .5); +/*!* if (fabs(xmin - xold) < .005) { *!*/ + if (java.lang.Math.abs(xmin - xold) < .005) { + xmin = -(xmin) + .01; + break find_xmax; + } + } + + /* unable to find xmin */ + + throw new java.lang.ArithmeticException("Math Error: NOCONV"); + // xmin = xmax = Double.NaN; + + } // find_xmax: + +/*!* alnbig = log(d1mach(2)); *!*/ + alnbig = java.lang.Math.log(d1mach(2)); + xmax = alnbig; + done: { + for (i=1; i<=10; ++i) { + xold = xmax; +/*!* xln = log(*xmax); *!*/ + xln = java.lang.Math.log(xmax); + xmax -= xmax * ((xmax - .5) * xln - xmax + .9189 - alnbig) / + (xmax * xln - .5); +/*!* if (fabs(xmax - xold) < .005) { *!*/ + if (java.lang.Math.abs(xmax - xold) < .005) { + xmax += -.01; + break done; + } + } + + /* unable to find xmax */ + + throw new java.lang.ArithmeticException("Math Error: NOCONV"); + // xmin = xmax = Double.NaN; + + } // done: + xmin = fmax2(xmin, -(xmax) + 1); + + double retval[] = new double[2]; + retval[0] = xmin; + retval[1] = xmax; + return(retval); + } + + /*!* #include "DistLib.h" /*4!*/ + + public static int i1mach(int i) + { + switch(i) { + + case 1: return 5; + case 2: return 6; + case 3: return 0; + case 4: return 0; + + case 5: /*return CHAR_BIT * sizeof(int);*/ throw new java.lang.RuntimeException("Unimplemented Feature."); + case 6: /*return sizeof(int)/sizeof(char);*/ throw new java.lang.RuntimeException("Unimplemented Feature."); + + case 7: return 2; + case 8: /*return CHAR_BIT * sizeof(int) - 1;*/ throw new java.lang.RuntimeException("Unimplemented Feature."); + case 9: return java.lang.Integer.MAX_VALUE; /*INT_MAX;*/ + + case 10: return Constants.FLT_RADIX; + + case 11: return Constants.FLT_MANT_DIG; + case 12: return Constants.FLT_MIN_EXP; + case 13: return Constants.FLT_MAX_EXP; + + case 14: return Constants.DBL_MANT_DIG; + case 15: return Constants.DBL_MAX_EXP; + case 16: return Constants.DBL_MIN_EXP; + + default: return 0; + } + } + + int i1mach_(int i) + { + return i1mach(i); + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * int imax2(int x, int y); + * + * DESCRIPTION + * + * Compute maximum of two integers. + */ + + /*!* #include "DistLib.h" /*4!*/ + + int imax2(int x, int y) + { + return (x < y) ? y : x; + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * int Math.min(int x, int y); + * + * DESCRIPTION + * + * Compute minimum of two integers. + */ + + /*!* #include "DistLib.h" /*4!*/ + + int imin2(int x, int y) + { + return (x < y) ? x : y; + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double lbeta(double a, double b); + * + * DESCRIPTION + * + * This function returns the value of the log beta function. + * + * NOTES + * + * This routine is a translation into C of a Fortran subroutine + * by W. Fullerton of Los Alamos Scientific Laboratory. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double lbeta(double a, double b) + { + double corr, p, q; + + p = q = a; + if(b < p) p = b;/* := min(a,b) */ + if(b > q) q = b;/* := max(a,b) */ + + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isNaN(a) || Double.isNaN(b)) + return a + b; + /*!* #endif /*4!*/ + + /* both arguments must be >= 0 */ + + if (p < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + else if (p == 0) { + return Double.POSITIVE_INFINITY; + } + /*!* #ifdef IEEE_754 /*4!*/ + else if (Double.isInfinite(q)) { + return Double.NEGATIVE_INFINITY; + } + /*!* #endif /*4!*/ + + if (p >= 10) { + /* p and q are big. */ + corr = lgammacor(p) + lgammacor(q) - lgammacor(p + q); +/*!* return log(q) * -0.5 + Constants.M_LN_SQRT_2PI + corr *!*/ + return java.lang.Math.log(q) * -0.5 + Constants.M_LN_SQRT_2PI + corr +/*!* + (p - 0.5) * log(p / (p + q)) + q * logrelerr(-p / (p + q)); *!*/ + + (p - 0.5) * java.lang.Math.log(p / (p + q)) + q * logrelerr(-p / (p + q)); + } + else if (q >= 10) { + /* p is small, but q is big. */ + corr = lgammacor(q) - lgammacor(p + q); +/*!* return lgammafn(p) + corr + p - p * log(p + q) *!*/ + return lgammafn(p) + corr + p - p * java.lang.Math.log(p + q) + + (q - 0.5) * logrelerr(-p / (p + q)); + } + else + /* p and q are small: p <= q > 10. */ +/*!* return log(gammafn(p) * (gammafn(q) / gammafn(p + q))); *!*/ + return java.lang.Math.log(gammafn(p) * (gammafn(q) / gammafn(p + q))); + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * extern int signgam; + * double lgammafn(double x); + * + * DESCRIPTION + * + * This function computes log|gamma(x)|. At the same time + * the variable "signgam" is set to the sign of the gamma + * function. + * + * NOTES + * + * This routine is a translation into C of a Fortran subroutine + * by W. Fullerton of Los Alamos Scientific Laboratory. + * + * The accuracy of this routine compares (very) favourably + * with those of the Sun Microsystems portable mathematical + * library. + */ + + /*!* #include "DistLib.h" /*4!*/ + + static int signgam; + + public static double lgammafn(double x) + { + double xmax = 0.; + double dxrel = 0.; + double ans, y, sinpiy; + + if (xmax == 0) { +/*!* xmax = d1mach(2)/log(d1mach(2)); *!*/ + xmax = d1mach(2)/java.lang.Math.log(d1mach(2)); + dxrel = java.lang.Math.sqrt (d1mach(4)); + } + + signgam = 1; + + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isNaN(x)) return x; + /*!* #endif /*4!*/ + + if (x <= 0 && x == (int)x) { /* Negative integer argument */ + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // return Double.POSITIVE_INFINITY;/* +Inf, since lgamma(x) = log|gamma(x)| */ + } + +/*!* y = fabs(x); *!*/ + y = java.lang.Math.abs(x); + + if (y <= 10) { +/*!* return log(fabs(gammafn(x))); *!*/ + return java.lang.Math.log(java.lang.Math.abs(gammafn(x))); + } + else { /* y = |x| > 10 */ + + if (y > xmax) { + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // return Double.POSITIVE_INFINITY; + } + + if (x > 0) +/*!* return Constants.M_LN_SQRT_2PI + (x - 0.5) * log(x) - x + lgammacor(y); *!*/ + return Constants.M_LN_SQRT_2PI + (x - 0.5) * java.lang.Math.log(x) - x + lgammacor(y); + + /* else: x < -10 */ +/*!* sinpiy = fabs(sin(Constants.M_PI * y)); *!*/ + sinpiy = java.lang.Math.abs(java.lang.Math.sin(Constants.M_PI * y)); + + if (sinpiy == 0) { /* Negative integer argument === + Now UNNECESSARY: caught above */ + System.out.println(" ** should NEVER happen! *** [lgamma.c: Neg.int+ y=%g]\n"+y); + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + +/*!* ans = Constants.M_LN_SQRT_PId2 + (x - 0.5) * log(y) - x *!*/ + ans = Constants.M_LN_SQRT_PId2 + (x - 0.5) * java.lang.Math.log(y) - x +/*!* - log(sinpiy) - lgammacor(y); *!*/ + - java.lang.Math.log(sinpiy) - lgammacor(y); + +/*!* if(fabs((x - (int)(x - 0.5)) * ans / x) < dxrel) { *!*/ + if(java.lang.Math.abs((x - (int)(x - 0.5)) * ans / x) < dxrel) { + + /* The answer is less than half precision because */ + /* the argument is too near a negative integer. */ + + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + } + + if (x > 0) + return ans; + else if (((int)(-x))%2 == 0) + signgam = -1; + return ans; + } + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double lgammacor(double x); + * + * DESCRIPTION + * + * Compute the log gamma correction factor for x >= 10 so that + * + * log(gamma(x)) = log(sqrt(2*pi))+(x-.5)*log(x)-x+lgammacor(x) + * + * NOTES + * + * This routine is a translation into C of a Fortran subroutine + * written by W. Fullerton of Los Alamos Scientific Laboratory. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double lgammacor(double x) + { + final double algmcs[] /*[15]*/ = { + +.1666389480451863247205729650822e+0, + -.1384948176067563840732986059135e-4, + +.9810825646924729426157171547487e-8, + -.1809129475572494194263306266719e-10, + +.6221098041892605227126015543416e-13, + -.3399615005417721944303330599666e-15, + +.2683181998482698748957538846666e-17, + -.2868042435334643284144622399999e-19, + +.3962837061046434803679306666666e-21, + -.6831888753985766870111999999999e-23, + +.1429227355942498147573333333333e-24, + -.3547598158101070547199999999999e-26, + +.1025680058010470912000000000000e-27, + -.3401102254316748799999999999999e-29, + +.1276642195630062933333333333333e-30 + }; + int nalgm = 0; + double xbig = 0; + double xmax = 0; + double tmp; + + if (nalgm == 0) { + nalgm = chebyshev_init(algmcs, 15, d1mach(3)); +/*!* xbig = 1 / sqrt(d1mach(3)); *!*/ + xbig = 1 / java.lang.Math.sqrt(d1mach(3)); +/*!* xmax = exp(fmin2(log(d1mach(2) / 12), -log(12 * d1mach(1)))); *!*/ + xmax = java.lang.Math.exp(fmin2(java.lang.Math.log(d1mach(2) / 12), -java.lang.Math.log(12 * d1mach(1)))); + } + + if (x < 10) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + else if (x >= xmax) { + throw new java.lang.ArithmeticException("Math Error: UNDERFLOW"); + // return (Double.MIN_VALUE * Double.MIN_VALUE); + } + else if (x < xbig) { + tmp = 10 / x; + return chebyshev_eval(tmp * tmp * 2 - 1, algmcs, nalgm) / x; + } + else return 1 / (x * 12); + } + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double dlnrel(double x); + * + * DESCRIPTION + * + * Compute the relative error logarithm. + * + * log(1 + x) + * + * NOTES + * + * This code is a translation of a Fortran subroutine of the + * same name written by W. Fullerton of Los Alamos Scientific + * Laboratory. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double logrelerr(double x) + { + /* series for alnr on the interval -3.75000e-01 to 3.75000e-01 */ + /* with weighted error 6.35e-32 */ + /* log weighted error 31.20 */ + /* significant figures required 30.93 */ + /* decimal places required 32.01 */ + final double alnrcs[] /*[43]*/ = { + +.10378693562743769800686267719098e+1, + -.13364301504908918098766041553133e+0, + +.19408249135520563357926199374750e-1, + -.30107551127535777690376537776592e-2, + +.48694614797154850090456366509137e-3, + -.81054881893175356066809943008622e-4, + +.13778847799559524782938251496059e-4, + -.23802210894358970251369992914935e-5, + +.41640416213865183476391859901989e-6, + -.73595828378075994984266837031998e-7, + +.13117611876241674949152294345011e-7, + -.23546709317742425136696092330175e-8, + +.42522773276034997775638052962567e-9, + -.77190894134840796826108107493300e-10, + +.14075746481359069909215356472191e-10, + -.25769072058024680627537078627584e-11, + +.47342406666294421849154395005938e-12, + -.87249012674742641745301263292675e-13, + +.16124614902740551465739833119115e-13, + -.29875652015665773006710792416815e-14, + +.55480701209082887983041321697279e-15, + -.10324619158271569595141333961932e-15, + +.19250239203049851177878503244868e-16, + -.35955073465265150011189707844266e-17, + +.67264542537876857892194574226773e-18, + -.12602624168735219252082425637546e-18, + +.23644884408606210044916158955519e-19, + -.44419377050807936898878389179733e-20, + +.83546594464034259016241293994666e-21, + -.15731559416479562574899253521066e-21, + +.29653128740247422686154369706666e-22, + -.55949583481815947292156013226666e-23, + +.10566354268835681048187284138666e-23, + -.19972483680670204548314999466666e-24, + +.37782977818839361421049855999999e-25, + -.71531586889081740345038165333333e-26, + +.13552488463674213646502024533333e-26, + -.25694673048487567430079829333333e-27, + +.48747756066216949076459519999999e-28, + -.92542112530849715321132373333333e-29, + +.17578597841760239233269760000000e-29, + -.33410026677731010351377066666666e-30, + +.63533936180236187354180266666666e-31, + }; + int nlnrel = 0; + double xmin = 0.; + + if (nlnrel == 0) { + nlnrel = chebyshev_init(alnrcs, 43, 0.1 * d1mach(3)); +/*!* xmin = -1.0 + sqrt(d1mach(4)); *!*/ + xmin = -1.0 + java.lang.Math.sqrt(d1mach(4)); + } + + if (x <= -1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + + if (x < xmin) { + /* answer less than half precision because x too near -1 */ + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + } + +/*!* if (fabs(x) <= .375) *!*/ + if (java.lang.Math.abs(x) <= .375) + return x * (1 - x * chebyshev_eval(x / .375, alnrcs, nlnrel)); + else +/*!* return log(x + 1); *!*/ + return java.lang.Math.log(x + 1); + } + + /*!* #include "DistLib.h" /*4!*/ + + /*!* #ifdef IEEE_754 /*4!*/ + /* These are used in IEEE exception handling */ + static double m_zero = 0; + static double m_one = 1; + static double m_tiny = Double.MIN_VALUE; + /*!* #endif /*4!*/ + + /*!* #ifndef IEEE_754 /*4!*/ + + /* + void ml_error(int n) + { + switch(n) { + + case "Math Error: NONE": + (!!!!fixme!!!!) = 0; + break; + + case "Math Error: DOMAIN": + case "Math Error: NOCONV": + (!!!!fixme!!!!) = EDOM; + break; + + case "Math Error: RANGE": + (!!!!fixme!!!!) = ERANGE; + break; + + default: + break; + } + } + + */ + /*!* #endif /*4!*/ + /* + * + * SYNOPSIS + * + * #include "DistLib.h" + * double sign(double x); + * + * DESCRIPTION + * + * This function computes the 'signum(.)' function: + * + * sign(x) = 1 if x > 0 + * sign(x) = 0 if x == 0 + * sign(x) = -1 if x < 0 + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double sign(double x) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x)) + return x; + /*!* #endif /*4!*/ + return ((x > 0) ? 1 : ((x == 0)? 0 : -1)); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NegativeBinomial.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NegativeBinomial.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NegativeBinomial.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NegativeBinomial.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,286 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class NegativeBinomial + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double n, double p); + * + * DESCRIPTION + * + * The density function of the negative binomial distribution. + * + * NOTES + * + * x = the number of failures before the n-th success + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double n, double p) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n) || Double.isNaN(p)) + return x + n + p; + /*!* #endif /*4!*/ +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (n < 1 || p <= 0 || p >= 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x < 0) + return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isInfinite(x)) + return 0; + /*!* #endif /*4!*/ +/*!* return exp(lfastchoose(x + n - 1, x) *!*/ + return java.lang.Math.exp(Misc.lfastchoose(x + n - 1, x) +/*!* + n * log(p) + x * log(1 - p)); *!*/ + + n * java.lang.Math.log(p) + x * java.lang.Math.log(1 - p)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double n, double p); + * + * DESCRIPTION + * + * The distribution function of the negative binomial distribution. + * + * NOTES + * + * x = the number of failures before the n-th success + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double n, double p) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n) || Double.isNaN(p)) + return x + n + p; + if(Double.isInfinite(n) || Double.isInfinite(p)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (n < 1 || p <= 0 || p >= 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x < 0) return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isInfinite(x)) + return 1; + /*!* #endif /*4!*/ + return Beta.cumulative(p, n, x + 1); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double n, double p); + * + * DESCRIPTION + * + * The distribution function of the negative binomial distribution. + * + * NOTES + * + * x = the number of failures before the n-th success + * + * METHOD + * + * Uses the Cornish-Fisher Expansion to include a skewness + * correction to a Normal approximation. This gives an + * initial value which never seems to be off by more than + * 1 or 2. A search is then conducted of values close to + * this initial start point. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double n, double p) + { + double P, Q, mu, sigma, gamma, z, y; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n) || Double.isNaN(p)) + return x + n + p; + if (Double.isInfinite(x)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (x < 0 || x > 1 || p <= 0 || p >= 1 || n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x == 0) return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (x == 1) return Double.POSITIVE_INFINITY; + /*!* #endif /*4!*/ + Q = 1.0 / p; + P = (1.0 - p) * Q; + mu = n * P; +/*!* sigma = sqrt(n * P * Q); *!*/ + sigma = java.lang.Math.sqrt(n * P * Q); + gamma = (Q + P)/sigma; + z = Normal.quantile(x, 0.0, 1.0); +/*!* y = floor(mu + sigma * (z + Gamma * (z*z - 1.0) / 6.0) + 0.5); *!*/ + y = java.lang.Math.floor(mu + sigma * (z + gamma * (z*z - 1.0) / 6.0) + 0.5); + + z = cumulative(y, n, p); + if(z >= x) { + + /* search to the left */ + + for(;;) { + if((z = cumulative(y - 1, n, p)) < x) + return y; + y = y - 1; + } + } + else { + + /* search to the right */ + + for(;;) { + if((z = cumulative(y + 1, n, p)) >= x) + return y + 1; + y = y + 1; + } + } + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double n, double p); + * + * DESCRIPTION + * + * Random variates from the negative binomial distribution. + * + * NOTES + * + * x = the number of failures before the n-th success + * + * REFERENCE + * + * Devroye, L. (1980). + * Non-Uniform Random Variate Generation. + * New York:Springer-Verlag. Page 480. + * + * METHOD + * + * Generate lambda as Gamma with shape parameter n and scale + * parameter p/(1-p). Return a Poisson deviate with mean lambda. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double n, double p, Uniform uniformDistribution) + { +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isInfinite(n) || Double.isInfinite(p) || + /*!* #endif /*4!*/ + n <= 0 || p <= 0 || p >= 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + return Poisson.random(Gamma.random(n, (1 - p) / p, uniformDistribution), uniformDistribution); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NoncentralBeta.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NoncentralBeta.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NoncentralBeta.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NoncentralBeta.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,198 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class NoncentralBeta + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double a, double b, double lambda); + * + * DESCRIPTION + * + * Computes the density of the noncentral Beta distribution with + * noncentrality parameter lambda. The noncentral Beta distribution + * has density: + * + * Inf + * f(x|a,b,d) = SUM p(i) * B(a+i,b) * x^(a+i-1) * (1-x)^(b-1) + * i=0 + * + * where: + * + * p(k) = exp(-lambda) lambda^k / k! + * + * B(a,b) = Gamma(a+b) / (Gamma(a) * Gamma(b)) + * + * + * This can be computed efficiently by using the recursions: + * + * p(k+1) = (lambda/(k+1)) * p(k-1) + * + * B(a+k+1,b) = ((a+b+k)/(a+k)) * B(a+k,b) + * + * The summation of the series continues until + * + * psum = p(0) + ... + p(k) + * + * is close to 1. Here we continue until 1 - psum < epsilon, + * with epsilon set close to the relative machine precision. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double a, double b, double lambda) + { + double k, lambda2, psum, sum, term, weight; + final double eps = 1.e-14; + final int maxiter = 200; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(a) || Double.isNaN(b) || Double.isNaN(lambda)) + return x + a + b + lambda; + /*!* #endif /*4!*/ + + if (lambda < 0 || a <= 0 || b <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isInfinite(a) || Double.isInfinite(b) || Double.isInfinite(lambda)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + + if(x <= 0) return 0; + + term = Beta.density(x, a, b); + if(lambda == 0) + return term; + + lambda2 = 0.5 * lambda; +/*!* weight = exp(- lambda2); *!*/ + weight = java.lang.Math.exp(- lambda2); + sum = weight * term; + psum = weight; + for(k=1 ; k<=maxiter ; k++) { + weight = weight * lambda2 / k; + term = term * x * (a + b) / a; + sum = sum + weight * term; + psum = psum + weight; + a = a + 1; + if(1 - psum < eps) break; + } + return sum; + } + /* + * Algorithm AS 226 Appl. Statist. (1987) Vol. 36, No. 2 + * Incorporates modification AS R84 from AS Vol. 39, pp311-2, 1990 + * + * Returns the cumulative probability of x for the non-central + * Beta distribution with parameters a, b and non-centrality lambda. + * + * Auxiliary routines required: + * lgamma - log-gamma function + * pbeta - incomplete-Beta function + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double a, double b, double lambda) + { + double a0, ans, ax, lbeta, c, errbd, gx, q, sumq, temp, x0; + int j; + + final double zero = 0; + final double one = 1; + final double half = 0.5; + + /* change errmax and itrmax if desired */ + + final double ualpha = 5.0; + final double errmax = 1.0e-6; + final int itrmax = 100; + + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(a) || Double.isNaN(b) || Double.isNaN(lambda)) + return x + a + b + lambda; + /*!* #endif /*4!*/ + + if (lambda < zero || a <= zero || b <= zero) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + + if (x <= zero) return 0; + if(x >= one) return 1; + + c = lambda * half; + + /* initialize the series */ + +/*!* x0 = floor(fmax2(c - ualpha * sqrt(c), zero)); *!*/ + x0 = java.lang.Math.floor(Math.max(c - ualpha * java.lang.Math.sqrt(c), zero)); + a0 = a + x0; +/*!* lbeta = lgammafn(a0) + lgammafn(b) - lgammafn(a0 + b); *!*/ + lbeta = Misc.lgammafn(a0) + Misc.lgammafn(b) - Misc.lgammafn(a0 + b); + temp = Beta.cumulative(x, a0, b); +/*!* gx = exp(a0 * log(x) + b * log(one - x) - lbeta - log(a0)); *!*/ + gx = java.lang.Math.exp(a0 * java.lang.Math.log(x) + b * java.lang.Math.log(one - x) - lbeta - java.lang.Math.log(a0)); + if (a0 > a) +/*!* q = exp(-c + x0 * log(c) - lgammafn(x0 + one)); *!*/ + q = java.lang.Math.exp(-c + x0 * java.lang.Math.log(c) - Misc.lgammafn(x0 + one)); + else +/*!* q = exp(-c); *!*/ + q = java.lang.Math.exp(-c); + + ax = q * temp; + sumq = one - q; + ans = ax; + + /* recur over subsequent terms */ + /* until convergence is achieved */ + j = 0; + do { + j++; + temp += - gx; + gx *= x * (a + b + j - one) / (a + j); + q *= c / j; + sumq += - q; + ax = temp * q; + ans += ax; + errbd = (temp - gx) * sumq; + } + while (errbd > errmax && j < itrmax); + + if (errbd > errmax) { + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + } + return ans; + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NoncentralChiSquare.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NoncentralChiSquare.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NoncentralChiSquare.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NoncentralChiSquare.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,279 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class NoncentralChiSquare + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(x, df, lambda); + * + * DESCRIPTION + * + * The density of the noncentral Chisquare distribution with + * "df" degrees of freedom and noncentrality parameter "lambda". + * + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double df, double lambda) + { + double dens, i, lambda2, psum, sum, weight; + final int maxiter = 100; + final double eps = 1.e-14; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(df) || Double.isNaN(lambda)) + return x + df + lambda; + /*!* #endif /*4!*/ + + if (lambda < 0 || df <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isInfinite(df) || Double.isInfinite(lambda)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + + if(x <= 0) return 0; + + dens = Chisquare.density(x, df); + if(lambda == 0) + return dens; + + lambda2 = 0.5 * lambda; +/*!* weight = exp(-lambda2); *!*/ + weight = java.lang.Math.exp(-lambda2); + sum = weight * dens; + psum = weight; + for(i=1 ; i t=%12g\n",v,x2,f2,t); *!*/ + // REprintf("\t v=java.lang.Math.exp(-th/2)=%12g, x/2=%12g, f/2=%12g ==> t=%12g\n",v,x2,f2,t); + /*!* #endif /*4!*/ + + /* check if (f+2n) is greater than x */ + + flag = false; + n = 1; twon = n*2; + L_End: for(;;) { + /*!* #ifdef DEBUG_pnch /*4!*/ + // REprintf(" _OL_: n=%d",n); + /*!* #endif /*4!*/ + if (!(f + twon - x > zero)) { + /* evaluate the next term of the */ + /* expansion and then the partial sum */ + u *= lam / n; + v += u; + t *= x / (f + twon); + term = v * t; + ans += term; + n++; twon = n*2; + } + else + { + /* find the error bound and check for convergence */ + flag = true; + + for(;;) { + /*!* #ifdef DEBUG_pnch /*4!*/ + // REprintf(" il: n=%d",n); + /*!* #endif /*4!*/ + + bound = t * x / (f + twon - x); + /*!* #ifdef DEBUG_pnch /*4!*/ + // REprintf("\tL10: n=%d; term=%12g; bound=%12g\n",n,term,bound); + /*!* #endif /*4!*/ + if (bound <= errmax || n > itrmax) + break L_End; + /* evaluate the next term of the */ + /* expansion and then the partial sum */ + u *= lam / n; + v += u; + t *= x / (f + twon); + term = v * t; + ans += term; + n++; twon = n*2; + } + + } + }// L_End: + if (bound > errmax) + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + /*!* #ifdef DEBUG_pnch /*4!*/ + // REprintf("\tL_End: n=%d; term=%12g; bound=%12g\n",n,term,bound); + /*!* #endif /*4!*/ + return ans; + } + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double p, double n, double lambda) + { + double ux, lx, nx; + double acu = 1.0e-12; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(p) || Double.isNaN(n) || Double.isNaN(lambda)) + return p + n + lambda; + if (Double.isInfinite(n)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (p < 0 || p >= 1 || n < 1 || lambda < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (p == 0) + return 0; + for (ux = 1.0; cumulative(ux, n, lambda) < p; ux *= 2); + for (lx = ux; cumulative(lx, n, lambda) > p; lx *= 0.5); + do { + nx = 0.5 * (lx + ux); + if (cumulative(nx, n, lambda) > p) + ux = nx; + else + lx = nx; + } + while ((ux - lx) / nx > acu); + return 0.5 * (ux + lx); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NoncentralF.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NoncentralF.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/NoncentralF.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/NoncentralF.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,59 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class NoncentralF + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double n1, double n2, double ncp); + * + * DESCRIPTION + * + * The distribution function of the non-central F distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double n1, double n2, double ncp) + { + double y; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n1) || Double.isNaN(n2) || Double.isNaN(ncp)) + return x + n2 + n1 + ncp; + /*!* #endif /*4!*/ + if (n1 <= 0.0 || n2 <= 0.0 || ncp < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x <= 0.0) + return 0.0; + y = (n1 / n2) * x; + return NoncentralBeta.cumulative(y/(1 + y), n1 / 2.0, n2 / 2.0, ncp); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Noncentral_t.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Noncentral_t.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Noncentral_t.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Noncentral_t.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,113 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Noncentral_t + { + /* + * Algorithm AS 243 Appl. Statist. (1989), Vol.38, No. 1. + * + * Cumulative probability at t of the non-central t-distribution + * with df degrees of freedom (may be fractional) and non-centrality + * parameter delta. + * + * NOTE + * + * Requires the following auxiliary routines: + * + * lgammafn(x) - log gamma function + * Beta.cumulative(x, a, b) - incomplete Beta function + * Normal.cumulative(x) - Normal distribution function + * + * CONSTANTS + * + * M_SQRT_2dPI = 1/ {gamma(1.5) * sqrt(2)} = sqrt(2 / pi) + * M_LN_SQRT_PI = ln(sqrt(pi)) = ln(pi)/2 + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double t, double df, double delta) + { + double a, albeta, b, del, en, errbd, geven, godd; + double lambda, p, q, rxb, s, tnc, tt, x, xeven, xodd; + boolean negdel; + + /* note - itrmax and errmax may be changed to suit one's needs. */ + + final double itrmax = 100.1; + final double errmax = 1.e-12; + + final double zero = 0.0; + final double half = 0.5; + final double one = 1.0; + final double two = 2.0; + + tnc = zero; + if (df <= zero) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + tt = t; + del = delta; + negdel = false; + if (t < zero) { + negdel = true; + tt = -tt; + del = -del; + } + /* initialize twin series */ + /* (guenther, j. statist. computn. simuln. vol.6, 199, 1978). */ + + en = one; + x = t * t / (t * t + df); + if (x > zero) { + lambda = del * del; +/*!* p = half * exp(-half * lambda); *!*/ + p = half * java.lang.Math.exp(-half * lambda); + q = Constants.M_SQRT_2dPI * p * del; + s = half - p; + a = half; + b = half * df; +/*!* rxb = pow(one - x, b); *!*/ + rxb = java.lang.Math.pow(one - x, b); +/*!* albeta = Constants.M_LN_SQRT_PI + lgammafn(b) - lgammafn(a + b); *!*/ + albeta = Constants.M_LN_SQRT_PI + Misc.lgammafn(b) - Misc.lgammafn(a + b); + xodd = Beta.cumulative(x, a, b); +/*!* godd = two * rxb * exp(a * log(x) - albeta); *!*/ + godd = two * rxb * java.lang.Math.exp(a * java.lang.Math.log(x) - albeta); + xeven = one - rxb; + geven = b * x * rxb; + tnc = p * xodd + q * xeven; + + /* while(true) until convergence */ + + do { + a = a + one; + xodd = xodd - godd; + xeven = xeven - geven; + godd = godd * x * (a + b - one) / a; + geven = geven * x * (a + b - half) / (a + half); + p = p * lambda / (two * en); + q = q * lambda / (two * en + one); + s = s - p; + en = en + one; + tnc = tnc + p * xodd + q * xeven; + errbd = two * s * (xodd - godd); + } + while (errbd > errmax && en <= itrmax); + } + if (en <= itrmax) + throw new java.lang.ArithmeticException("Math Error: PRECISION"); + tnc = tnc + Normal.cumulative(- del, zero, one); + if (negdel) + tnc = one - tnc; + return tnc; + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Normal.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Normal.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Normal.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Normal.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,679 @@ +package org.mathpiper.builtin.library.statdistlib; + + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Normal + { + + /* Mathematical Constants */ + static private double SIXTEN = 1.6; /* Magic Cutoff */ + + + /* + * M_1_SQRT_2PI = 1 / sqrt(2 * pi) + */ + + /** The Normal Density Function */ + public static double density(double x, double mu, double sigma) + { + if (Double.isNaN(x) || Double.isNaN(mu) || Double.isNaN(sigma)) + return x + mu + sigma; + if (sigma <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + x = (x - mu) / sigma; + return Constants.M_1_SQRT_2PI * + java.lang.Math.exp(-0.5 * x * x) / sigma; + } + + /** DESCRIPTION + * The main computation evaluates near-minimax approximations derived + * from those in "Rational Chebyshev approximations for the error + * function" by W. J. Cody, Math. Comp., 1969, 631-637. This + * transportable program uses rational functions that theoretically + * approximate the Normal distribution function to at least 18 + * significant decimal digits. The accuracy achieved depends on the + * arithmetic system, the compiler, the intrinsic functions, and + * proper selection of the machine-dependent constants. + * + * REFERENCE + * + * Cody, W. D. (1993). + * ALGORITHM 715: SPECFUN - A Portable FORTRAN Package of + * Special Function Routines and Test Drivers". + * ACM Transactions on Mathematical Software. 19, 22-32. + */ + + public static double cumulative(double x, double mu, double sigma) + { + final double c[] = { + 0.39894151208813466764, + 8.8831497943883759412, + 93.506656132177855979, + 597.27027639480026226, + 2494.5375852903726711, + 6848.1904505362823326, + 11602.651437647350124, + 9842.7148383839780218, + 1.0765576773720192317e-8 + }; + + final double d[] = { + 22.266688044328115691, + 235.38790178262499861, + 1519.377599407554805, + 6485.558298266760755, + 18615.571640885098091, + 34900.952721145977266, + 38912.003286093271411, + 19685.429676859990727 + }; + + final double p[] = { + 0.21589853405795699, + 0.1274011611602473639, + 0.022235277870649807, + 0.001421619193227893466, + 2.9112874951168792e-5, + 0.02307344176494017303 + }; + + final double q[] = { + 1.28426009614491121, + 0.468238212480865118, + 0.0659881378689285515, + 0.00378239633202758244, + 7.29751555083966205e-5 + }; + + final double a[] = { + 2.2352520354606839287, + 161.02823106855587881, + 1067.6894854603709582, + 18154.981253343561249, + 0.065682337918207449113 + }; + + final double b[] = { + 47.20258190468824187, + 976.09855173777669322, + 10260.932208618978205, + 45507.789335026729956 + }; + + double xden, temp, xnum, result, ccum; + double del, min, eps, xsq; + double y; + int i; + + /* Note: The structure of these checks has been */ + /* carefully thought through. For example, if x == mu */ + /* and sigma == 0, we still get the correct answer. */ + + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isNaN(x) || Double.isNaN(mu) || Double.isNaN(sigma)) + return x + mu + sigma; + /*!* #endif /*4!*/ + if (sigma < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + x = (x - mu) / sigma; + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(x)) { + if(x < 0) return 0; + else return 1; + } + /*!* #endif /*4!*/ + + eps = Constants.DBL_EPSILON * 0.5; + min = Double.MIN_VALUE; +/*!* y = fabs(x); *!*/ + y = java.lang.Math.abs(x); + if (y <= 0.66291) { + xsq = 0.0; + if (y > eps) { + xsq = x * x; + } + xnum = a[4] * xsq; + xden = xsq; + for (i = 1; i <= 3; ++i) { + xnum = (xnum + a[i - 1]) * xsq; + xden = (xden + b[i - 1]) * xsq; + } + result = x * (xnum + a[3]) / (xden + b[3]); + temp = result; + result = 0.5 + temp; + ccum = 0.5 - temp; + } + else if (y <= Constants.M_SQRT_32) { + + /* Evaluate pnorm for 0.66291 <= |z| <= sqrt(32) */ + + xnum = c[8] * y; + xden = y; + for (i = 1; i <= 7; ++i) { + xnum = (xnum + c[i - 1]) * y; + xden = (xden + d[i - 1]) * y; + } + result = (xnum + c[7]) / (xden + d[7]); +/*!* xsq = floor(y * SIXTEN) / SIXTEN; *!*/ + xsq = java.lang.Math.floor(y * SIXTEN) / SIXTEN; + del = (y - xsq) * (y + xsq); +/*!* result = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * result; *!*/ + result = java.lang.Math.exp(-xsq * xsq * 0.5) * java.lang.Math.exp(-del * 0.5) * result; + ccum = 1.0 - result; + if (x > 0.0) { + temp = result; + result = ccum; + ccum = temp; + } + } + else if(y < 50) { + + /* Evaluate pnorm for sqrt(32) < |z| < 50 */ + + result = 0.0; + xsq = 1.0 / (x * x); + xnum = p[5] * xsq; + xden = xsq; + for (i = 1; i <= 4; ++i) { + xnum = (xnum + p[i - 1]) * xsq; + xden = (xden + q[i - 1]) * xsq; + } + result = xsq * (xnum + p[4]) / (xden + q[4]); + result = (Constants.M_1_SQRT_2PI - result) / y; +/*!* xsq = floor(x * SIXTEN) / SIXTEN; *!*/ + xsq = java.lang.Math.floor(x * SIXTEN) / SIXTEN; + del = (x - xsq) * (x + xsq); +/*!* result = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * result; *!*/ + result = java.lang.Math.exp(-xsq * xsq * 0.5) * java.lang.Math.exp(-del * 0.5) * result; + ccum = 1.0 - result; + if (x > 0.0) { + temp = result; + result = ccum; + ccum = temp; + } + } + else { + if(x > 0) { + result = 1.0; + ccum = 0.0; + } + else { + result = 0.0; + ccum = 1.0; + } + } + if (result < min) { + result = 0.0; + } + if (ccum < min) { + ccum = 0.0; + } + return result; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * double cumulative(double p, double mu, double sigma); + * + * DESCRIPTION + * + * Compute the quantile function for the Normal distribution. + * + * For small to moderate probabilities, algorithm referenced + * below is used to obtain an initial approximation which is + * polished with a final Newton step. + * + * For very large arguments, an algorithm of Wichura is used. + * + * REFERENCE + * + * Beasley, J. D. and S. G. Springer (1977). + * Algorithm AS 111: The percentage points of the Normal distribution, + * Applied Statistics, 26, 118-121. + */ + + /*!* #include "DistLib.h" /*4!*/ + + + public static double quantile(double p, double mu, double sigma) + { + double q, r, val; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(p) || Double.isNaN(mu) || Double.isNaN(sigma)) + return p + mu + sigma; + /*!* #endif /*4!*/ + if (p < 0.0 || p > 1.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + + q = p - 0.5; + +/*!* if (fabs(q) <= 0.42) { *!*/ + if (java.lang.Math.abs(q) <= 0.42) { + + /* 0.08 < p < 0.92 */ + + r = q * q; + val = q * (((-25.44106049637 * r + 41.39119773534) * r + - 18.61500062529) * r + 2.50662823884) + / ((((3.13082909833 * r - 21.06224101826) * r + + 23.08336743743) * r + -8.47351093090) * r + 1.0); + } + else { + + /* p < 0.08 or p > 0.92, set r = min(p, 1 - p) */ + + r = p; + if (q > 0.0) + r = 1.0 - p; + + if(r > Constants.DBL_EPSILON) { +/*!* r = sqrt(-log(r)); *!*/ + r = java.lang.Math.sqrt(-java.lang.Math.log(r)); + val = (((2.32121276858 * r + 4.85014127135) * r + - 2.29796479134) * r - 2.78718931138) + / ((1.63706781897 * r + 3.54388924762) * r + 1.0); + if (q < 0.0) + val = -val; + } + else if(r > 1e-300) { /* Assuming IEEE here? */ +/*!* val = -2 * log(p); *!*/ + val = -2 * java.lang.Math.log(p); +/*!* r = log(6.283185307179586476925286766552 * val); *!*/ + r = java.lang.Math.log(6.283185307179586476925286766552 * val); + r = r/val + (2 - r)/(val * val) + + (-14 + 6 * r - r * r)/(2 * val * val * val); +/*!* val = sqrt(val * (1 - r)); *!*/ + val = java.lang.Math.sqrt(val * (1 - r)); + if(q < 0.0) + val = -val; + return val; + } + else { + throw new java.lang.ArithmeticException("Math Error: RANGE"); + // if(q < 0.0) { + // return Double.NEGATIVE_INFINITY; + // } + // else { + // return Double.POSITIVE_INFINITY; + // } + } + } + val = val - (cumulative(val, 0.0, 1.0) - p) / Normal.density(val, 0.0, 1.0); + return mu + sigma * val; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double mu, double sigma, Uniform uniformDistribution ); + * + * DESCRIPTION + * + * Random variates from the Normal distribution. + * + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double mu, double sigma, Uniform uniformDistribution) + { + if( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isInfinite(mu) || Double.isInfinite(sigma) || + /*!* #endif /*4!*/ + sigma < 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } else + if (sigma == 0.0) + return mu; + else + return mu + sigma * random(uniformDistribution); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(void); + * + * DESCRIPTION + * + * Random variates from the STANDARD Normal distribution N(0,1). + * + * Is called from random(..), but also rt(), rf(), rgamma(), ... + */ + + /*!* #include "DistLib.h" /*4!*/ + + /*!* #define KINDERMAN_RAMAGE /*4!*/ + + /*!* #ifdef AHRENS_DIETER /*4!*/ + + /* + * REFERENCE + * + * Ahrens, J.H. and Dieter, U. + * Extensions of Forsythe's method for random sampling from + * the Normal distribution. + * Math. Comput. 27, 927-937. + * + * The definitions of the constants a[k], d[k], t[k] and + * h[k] are according to the abovementioned article + */ + public static double random_AhrensDieter( Uniform uniformDistribution ) + { + final double a[] = + { + 0.0000000, 0.03917609, 0.07841241, 0.1177699, + 0.1573107, 0.19709910, 0.23720210, 0.2776904, + 0.3186394, 0.36012990, 0.40225010, 0.4450965, + 0.4887764, 0.53340970, 0.57913220, 0.6260990, + 0.6744898, 0.72451440, 0.77642180, 0.8305109, + 0.8871466, 0.94678180, 1.00999000, 1.0775160, + 1.1503490, 1.22985900, 1.31801100, 1.4177970, + 1.5341210, 1.67594000, 1.86273200, 2.1538750 + }; + + final double d[] = + { + 0.0000000, 0.0000000, 0.0000000, 0.0000000, + 0.0000000, 0.2636843, 0.2425085, 0.2255674, + 0.2116342, 0.1999243, 0.1899108, 0.1812252, + 0.1736014, 0.1668419, 0.1607967, 0.1553497, + 0.1504094, 0.1459026, 0.1417700, 0.1379632, + 0.1344418, 0.1311722, 0.1281260, 0.1252791, + 0.1226109, 0.1201036, 0.1177417, 0.1155119, + 0.1134023, 0.1114027, 0.1095039 + }; + + final double t[] = + { + 7.673828e-4, 0.002306870, 0.003860618, 0.005438454, + 0.007050699, 0.008708396, 0.010423570, 0.012209530, + 0.014081250, 0.016055790, 0.018152900, 0.020395730, + 0.022811770, 0.025434070, 0.028302960, 0.031468220, + 0.034992330, 0.038954830, 0.043458780, 0.048640350, + 0.054683340, 0.061842220, 0.070479830, 0.081131950, + 0.094624440, 0.112300100, 0.136498000, 0.171688600, + 0.227624100, 0.330498000, 0.584703100 + }; + + final double h[] = + { + 0.03920617, 0.03932705, 0.03950999, 0.03975703, + 0.04007093, 0.04045533, 0.04091481, 0.04145507, + 0.04208311, 0.04280748, 0.04363863, 0.04458932, + 0.04567523, 0.04691571, 0.04833487, 0.04996298, + 0.05183859, 0.05401138, 0.05654656, 0.05953130, + 0.06308489, 0.06737503, 0.07264544, 0.07926471, + 0.08781922, 0.09930398, 0.11555990, 0.14043440, + 0.18361420, 0.27900160, 0.70104740 + }; + + double s, u, w, y, ustar, aa, tt; + int i; + + u = uniformDistribution.random(); + s = 0.0; + if (u > 0.5) + s = 1.0; + u = u + u - s; + u *= 32.0; + i = (int) u; + if (i == 32) + i = 31; + deliver: { + if (i != 0) { + ustar = u - i; + aa = a[i - 1]; + while (ustar <= t[i - 1]) { + u = uniformDistribution.random(); + w = u * (a[i] - aa); + tt = (w * 0.5 + aa) * w; + while(true) { + if (ustar > tt) + break deliver; + u = uniformDistribution.random(); + if (ustar < u) + break; + tt = u; + ustar = uniformDistribution.random(); + } + ustar = uniformDistribution.random(); + } + w = (ustar - t[i - 1]) * h[i - 1]; + } + else { + i = 6; + aa = a[31]; + while(true) { + u = u + u; + if (u >= 1.0) + break; + aa = aa + d[i - 1]; + i = i + 1; + } + u = u - 1.0; + jump: while(true) { + w = u * d[i - 1]; + tt = (w * 0.5 + aa) * w; + while(true) { + ustar = uniformDistribution.random(); + if (ustar > tt) + break jump; + u = uniformDistribution.random(); + if (ustar < u) + break; + tt = u; + } + u = uniformDistribution.random(); + } // jump:; + } + + } // deliver: + y = aa + w; + return (s == 1.0) ? -y : y; + + } + + /*!* #endif /*4!*/ + + /*!* #ifdef KINDERMAN_RAMAGE /*4!*/ + + /* + * REFERENCE + * + * Kinderman A. J. and Ramage J. G. (1976). + * Computer generation of Normal random variables. + * JASA 71, 893-896. + */ + + static final double C1 = 0.398942280401433; + static final double C2 = 0.180025191068563; +/*!* /*!* #define g(x) (C1*exp(-x*x/2.0)-C2*(a-fabs(x))) /*4!* *!*/ + static final double a = 2.216035867166471; + + static final double g(double x) + { + return (C1*java.lang.Math.exp(-x*x/2.0)-C2*(a-java.lang.Math.abs(x))) ; + } + + public static double random( Uniform uniformDistribution ) + { + double t, u1, u2, u3; + + u1 = uniformDistribution.random(); + if(u1 < 0.884070402298758) { + u2 = uniformDistribution.random(); + return a*(1.13113163544180*u1+u2-1); + } + + if(u1 >= 0.973310954173898) { + tail: while(true) { + u2 = uniformDistribution.random(); + u3 = uniformDistribution.random(); +/*!* t = (a*a-2*log(u3)); *!*/ + t = (a*a-2*java.lang.Math.log(u3)); + if( u2*u2<(a*a)/t ) +/*!* return (u1 < 0.986655477086949) ? sqrt(t) : -sqrt(t) ; *!*/ + return (u1 < 0.986655477086949) ? java.lang.Math.sqrt(t) : -java.lang.Math.sqrt(t) ; + // continue tail; + } + } + + if(u1 >= 0.958720824790463) { + region3: while(true) { + u2 = uniformDistribution.random(); + u3 = uniformDistribution.random(); +/*!* t = a - 0.630834801921960* fmin2(u2,u3); *!*/ + t = a - 0.630834801921960* Math.min(u2,u3); +/*!* if(fmax2(u2,u3) <= 0.755591531667601) *!*/ + if(Math.max(u2,u3) <= 0.755591531667601) + return (u2= 0.911312780288703) { + region2: { + u2 = uniformDistribution.random(); + u3 = uniformDistribution.random(); +/*!* t = 0.479727404222441+1.105473661022070*fmin2(u2,u3); *!*/ + t = 0.479727404222441+1.105473661022070*Math.min(u2,u3); +/*!* if( fmax2(u2,u3)<=0.872834976671790 ) *!*/ + if( Math.max(u2,u3)<=0.872834976671790 ) + return (u2 testArr[i+1] ) +// { +// temp = testArr[i]; +// testArr[i] = testArr[i+1]; +// testArr[i+1] = temp; +// ordered=false; +// } +// } + +// return true; + +// } + + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Poisson.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Poisson.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Poisson.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Poisson.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,462 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Poisson + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double lambda) + * + * DESCRIPTION + * + * The density function of the Poisson distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double lambda) + { + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isNaN(x) || Double.isNaN(lambda)) + return x + lambda; + /*!* #endif /*4!*/ +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if(lambda <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x < 0) + return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(x)) + return 0; + /*!* #endif /*4!*/ +/*!* return exp(x * log(lambda) - lambda - lgammafn(x + 1)); *!*/ + return java.lang.Math.exp(x * java.lang.Math.log(lambda) - lambda - Misc.lgammafn(x + 1)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double lambda) + * + * DESCRIPTION + * + * The distribution function of the Poisson distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double lambda) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(lambda)) + return x + lambda; + /*!* #endif /*4!*/ +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if(lambda <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x < 0) + return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isInfinite(x)) + return 1; + /*!* #endif /*4!*/ + return 1 - Gamma.cumulative(lambda, x + 1, 1.0); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double lambda) + * + * DESCRIPTION + * + * The quantile function of the Poisson distribution. + * + * METHOD + * + * Uses the Cornish-Fisher Expansion to include a skewness + * correction to a Normal approximation. This gives an + * initial value which never seems to be off by more than + * 1 or 2. A search is then conducted of values close to + * this initial start point. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double lambda) + { + double mu, sigma, gamma, z, y; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(lambda)) + return x + lambda; + if(Double.isInfinite(lambda)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + if(x < 0 || x > 1 || lambda <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x == 0) return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (x == 1) return Double.POSITIVE_INFINITY; + /*!* #endif /*4!*/ + mu = lambda; +/*!* sigma = sqrt(lambda); *!*/ + sigma = java.lang.Math.sqrt(lambda); + gamma = sigma; + z = Normal.quantile(x, 0.0, 1.0); +/*!* y = floor(mu + sigma * (z + Gamma * (z * z - 1) / 6) + 0.5); *!*/ + y = java.lang.Math.floor(mu + sigma * (z + gamma * (z * z - 1) / 6) + 0.5); + z = cumulative(y, lambda); + + if(z >= x) { + + /* search to the left */ + + for(;;) { + if((z = Poisson.cumulative(y - 1, lambda)) < x) + return y; + y = y - 1; + } + } + else { + + /* search to the right */ + + for(;;) { + if((z = Poisson.cumulative(y + 1, lambda)) >= x) + return y + 1; + y = y + 1; + } + } + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double lambda) + * + * DESCRIPTION + * + * Random variates from the Poisson distribution. + * + * REFERENCE + * + * Ahrens, J.H. and Dieter, U. (1982). + * Computer generation of Poisson deviates + * from modified Normal distributions. + * ACM Trans. Math. Software 8, 163-179. + */ + + /* Factorial Table */ + static double fact[] = + { + 1.0, + 1.0, + 2.0, + 6.0, + 24.0, + 120.0, + 720.0, + 5040.0, + 40320.0, + 362880.0 + }; + + static private double a0 = -0.5; + static private double a1 = 0.3333333; + static private double a2 = -0.2500068; + static private double a3 = 0.2000118; + static private double a4 = -0.1661269; + static private double a5 = 0.1421878; + static private double a6 = -0.1384794; + static private double a7 = 0.1250060; + + // static private double while(true) = for(;;); + + /*!* #include "DistLib.h" /*4!*/ + + + static private double /* a0, a1, a2, a3, a4, a5, a6, a7, */ b1, b2; + static private double c, c0, c1, c2, c3, d, del, difmuk, e; + static private double fk, fx, fy, g, omega; + static private double p, p0, px, py, q, s, t, u, v, x, xx; + static private double pp[] = new double[36]; + static private int j, k, kflag, l, m; + static private int ipois; + static private double muprev = 0.0; + static private double muold = 0.0; + + + public static double random(double mu, Uniform uniformDistribution ) + { + throw new java.lang.ArithmeticException("FUNCTION NOT IMPLEMENTED"); + } +} +/****** +/****** if (mu != muprev) { +/****** if (mu >= 10.0) { +/****** /* case a. (recalculation of s,d,l */ +/****** /* if mu has changed) */ +/****** /* the Poisson probabilities pk */ +/****** /* exceed the discrete Normal */ +/****** /* probabilities fk whenever k >= m(mu). */ +/****** /* l=ifix(mu-1.1484) is an upper bound */ +/****** /* to m(mu) for all mu >= 10. */ +/****** muprev = mu; +/****** /*!* s = sqrt(mu); *!*/ +/****** s = java.lang.Math.sqrt(mu); +/****** d = 6.0 * mu * mu; +/****** l = mu - 1.1484; +/****** } else { +/****** /* Case B. (start new table and */ +/****** /* calculate p0 if necessary) */ +/****** muprev = 0.0; +/****** if (mu != muold) { +/****** muold = mu; +/****** /*!* m = imax2(1, (int) mu); *!*/ +/****** m = Math.max(1, (int) mu); +/****** l = 0; +/****** /*!* p = exp(-mu); *!*/ +/****** p = java.lang.Math.exp(-mu); +/****** q = p; +/****** p0 = p; +/****** } +/****** while(true) { +/****** /* Step U. Uniform sample */ +/****** /* for inversion method */ +/****** u = Uniform.random(); +/****** ipois = 0; +/****** if (u <= p0) +/****** return (double)ipois; +/****** /* Step T. table comparison until */ +/****** /* the end pp(l) of the pp-table of */ +/****** /* cumulative Poisson probabilities */ +/****** /* (0.458=pp(9) for mu=10) */ +/****** if (l != 0) { +/****** j = 1; +/****** if (u > 0.458) +/****** /*!* j = Math.min(l, m); *!*/ +/****** j = Math.min(l, m); +/****** for (k = j; k <= l; k++) +/****** if (u <= pp[k]) +/****** return (double)k; +/****** if (l == 35) +/****** continue; +/****** } +/****** /* Step C. creation of new Poisson */ +/****** /* probabilities p and their cumulatives */ +/****** /* q=pp[k] */ +/****** l = l + 1; +/****** for (k = l; k <= 35; k++) { +/****** p = p * mu / k; +/****** q = q + p; +/****** pp[k] = q; +/****** if (u <= q) { +/****** l = k; +/****** return (double)k; +/****** } +/****** } +/****** l = 35; +/****** } +/****** } +/****** } +/****** /* Step N. Normal sample */ +/****** /* Normal.random() for standard Normal deviate */ +/****** g = mu + s * Normal.random(); +/****** if (g >= 0.0) { +/****** ipois = g; +/****** /* Step I. immediate acceptance */ +/****** /* if ipois is large enough */ +/****** if (ipois >= l) +/****** return (double)ipois; +/****** /* Step S. squeeze acceptance */ +/****** /* Uniform.random() for (0,1)-sample u */ +/****** fk = ipois; +/****** difmuk = mu - fk; +/****** u = Uniform.random(); +/****** if (d * u >= difmuk * difmuk * difmuk) +/****** return (double)ipois; +/****** } +/****** /* Step P. preparations for steps Q and H. */ +/****** /* (recalculations of parameters if necessary) */ +/****** /* 0.3989423=(2*pi)**(-0.5) */ +/****** /* 0.416667e-1=1./24. */ +/****** /* 0.1428571=1./7. */ +/****** /* The quantities b1, b2, c3, c2, c1, c0 are for the Hermite */ +/****** /* approximations to the discrete Normal probabilities fk. */ +/****** /* c=.1069/mu guarantees majorization by the 'hat'-function. */ +/****** if (mu != muold) { +/****** muold = mu; +/****** omega = 0.3989423 / s; +/****** b1 = 0.4166667e-1 / mu; +/****** b2 = 0.3 * b1 * b1; +/****** c3 = 0.1428571 * b1 * b2; +/****** c2 = b2 - 15. * c3; +/****** c1 = b1 - 6. * b2 + 45. * c3; +/****** c0 = 1. - b1 + 3. * b2 - 15. * c3; +/****** c = 0.1069 / mu; +/****** } +/****** if (g >= 0.0) { +/****** /* 'Subroutine' F is called (kflag=0 for correct return) */ +/****** kflag = 0; +/****** goto L20; +/****** } +/****** else while(true) { +/****** /* Step E. Exponential Sample */ +/****** /* exponential.random() for standard exponential deviate */ +/****** /* e and sample t from the laplace 'hat' */ +/****** /* (if t <= -0.6744 then pk < fk for all mu >= 10.) */ +/****** e = exponential.random(); +/****** u = Uniform.random(); +/****** u = u + u - 1.0; +/****** /*!* t = 1.8 + fsign(e, u); *!*/ +/****** t = 1.8 + Misc.fsign(e, u); +/****** if (t > -0.6744) { +/****** ipois = mu + s * t; +/****** fk = ipois; +/****** difmuk = mu - fk; +/****** f( +/****** /* 'subroutine' f is called */ +/****** /* (kflag=1 for correct return) */ +/****** kflag = 1; +/****** //********** subroutine_f(kflag) ************** // +/****** +/****** } +/****** } +/****** return (double)ipois; +/****** } +/****** } +/****** +/******double[] subroutine_f ( double px; double mu; double py; double del; double fk; double v; double a7; double a6; double a5; double a4; double a3; double a2; double a1; double a0; double x; double xx; double fx; double omega; double c3; double c2; double c1; double c0; double u; double e; int kflag ) +/****** { +/****** +/****** /* Step f. 'subroutine' f. */ +/****** /* calculation of px,py,fx,fy. */ +/****** /* case ignpoi < 10 uses */ +/****** /* factorials from table fact */ +/****** L20:if (ipois < 10) { +/****** px = -mu; +/****** /*!* py = pow(mu, (double) ipois) / fact[ipois]; *!*/ +/****** py = java.lang.Math.pow(mu, (double) ipois) / fact[ipois]; +/****** } else { +/****** /* Case ipois >= 10 uses polynomial */ +/****** /* approximation a0-a7 for accuracy */ +/****** /* when advisable */ +/****** /* 0.8333333e-1=1./12.0 */ +/****** /* 0.3989423=(2*pi)**(-0.5) */ +/****** del = 0.8333333e-1 / fk; +/****** del = del - 4.8 * del * del * del; +/****** v = difmuk / fk; +/****** /*!* if (fabs(v) <= 0.25) *!*/ +/****** if (java.lang.Math.abs(v) <= 0.25) +/****** px = fk * v * v * (((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v + a0) - del; +/****** else +/****** /*!* px = fk * log(1.0 + v) - difmuk - del; *!*/ +/****** px = fk * java.lang.Math.log(1.0 + v) - difmuk - del; +/****** /*!* py = 0.3989423 / sqrt(fk); *!*/ +/****** py = 0.3989423 / java.lang.Math.sqrt(fk); +/****** } +/****** x = (0.5 - difmuk) / s; +/****** xx = x * x; +/****** fx = -0.5 * xx; +/****** fy = omega * (((c3 * xx + c2) * xx + c1) * xx + c0); +/****** if (kflag > 0) { +/****** /* Step H. hat acceptance */ +/****** /* (e is while(true)ed on rejection) */ +/****** /*!* if (c * fabs(u) <= py * exp(px + e) - fy * exp(fx + e)) *!*/ +/****** if (c * java.lang.Math.abs(u) <= py * java.lang.Math.exp(px + e) - fy * java.lang.Math.exp(fx + e)) +/****** break; +/****** } else +/****** /* step q. quotient acceptance (rare case) */ +/****** /*!* if (fy - u * fy <= py * exp(px - fx)) *!*/ +/****** if (fy - u * fy <= py * java.lang.Math.exp(px - fx)) +/****** break; +/******} +*******/ + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Polygamma.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Polygamma.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Polygamma.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Polygamma.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,567 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Polygamma + { +/***UNUSED*** /* +/***UNUSED*** * DistLib : A C Library of Special Functions +/***UNUSED*** * Copyright (C) 1998 Ross Ihaka +/***UNUSED*** * +/***UNUSED*** * This program is free software; you can redistribute it and/or modify +/***UNUSED*** * it under the terms of the GNU General Public License as published by +/***UNUSED*** * the Free Software Foundation; either version 2 of the License, or +/***UNUSED*** * (at your option) any later version. +/***UNUSED*** * +/***UNUSED*** * This program is distributed in the hope that it will be useful, +/***UNUSED*** * but WITHOUT ANY WARRANTY; without even the implied warranty of +/***UNUSED*** * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/***UNUSED*** * GNU General Public License for more details. +/***UNUSED*** * +/***UNUSED*** * You should have received a copy of the GNU General Public License +/***UNUSED*** * along with this program; if not, write to the Free Software +/***UNUSED*** * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +/***UNUSED*** * +/***UNUSED*** * SYNOPSIS +/***UNUSED*** * +/***UNUSED*** * #include "DistLib.h" +/***UNUSED*** * void dpsifn(double x, int n, int kode, int m, +/***UNUSED*** * double *ans, int *nz, int *ierr) +/***UNUSED*** * double digamma(double x); +/***UNUSED*** * double trigamma(double x) +/***UNUSED*** * double tetragamma(double x) +/***UNUSED*** * double pentagamma(double x) +/***UNUSED*** * +/***UNUSED*** * DESCRIPTION +/***UNUSED*** * +/***UNUSED*** * Compute the derivatives of the psi function +/***UNUSED*** * and Polygamma functions. +/***UNUSED*** * +/***UNUSED*** * The following definitions are used in dpsifn: +/***UNUSED*** * +/***UNUSED*** * Definition 1 +/***UNUSED*** * +/***UNUSED*** * psi(x) = d/dx (ln(gamma(x)), the first derivative of +/***UNUSED*** * the log gamma function. +/***UNUSED*** * +/***UNUSED*** * Definition 2 +/***UNUSED*** * k k +/***UNUSED*** * psi(k,x) = d /dx (psi(x)), the k-th derivative +/***UNUSED*** * of psi(x). +/***UNUSED*** * +/***UNUSED*** * +/***UNUSED*** * "dpsifn" computes a sequence of scaled derivatives of +/***UNUSED*** * the psi function; i.e. for fixed x and m it computes +/***UNUSED*** * the m-member sequence +/***UNUSED*** * +/***UNUSED*** * ((-1)**(k+1)/gamma(k+1))*psi(k,x) +/***UNUSED*** * for k = n,...,n+m-1 +/***UNUSED*** * +/***UNUSED*** * where psi(k,x) is as defined above. For kode=1, dpsifn +/***UNUSED*** * returns the scaled derivatives as described. kode=2 is +/***UNUSED*** * operative only when k=0 and in that case dpsifn returns +/***UNUSED*** * -psi(x) + ln(x). That is, the logarithmic behavior for +/***UNUSED*** * large x is removed when kode=2 and k=0. When sums or +/***UNUSED*** * differences of psi functions are computed the logarithmic +/***UNUSED*** * terms can be combined analytically and computed separately +/***UNUSED*** * to help retain significant digits. +/***UNUSED*** * +/***UNUSED*** * Note that dpsifn(x, 0, 1, 1, ans) results in ans = -psi(x). +/***UNUSED*** * +/***UNUSED*** * INPUT +/***UNUSED*** * +/***UNUSED*** * x - argument, x > 0. +/***UNUSED*** * +/***UNUSED*** * n - first member of the sequence, 0 <= n <= 100 +/***UNUSED*** * n == 0 gives ans(1) = -psi(x) for kode=1 +/***UNUSED*** * -psi(x)+ln(x) for kode=2 +/***UNUSED*** * +/***UNUSED*** * kode - selection parameter +/***UNUSED*** * kode == 1 returns scaled derivatives of the +/***UNUSED*** * psi function. +/***UNUSED*** * kode == 2 returns scaled derivatives of the +/***UNUSED*** * psi function except when n=0. In this case, +/***UNUSED*** * ans(1) = -psi(x) + ln(x) is returned. +/***UNUSED*** * +/***UNUSED*** * m - number of members of the sequence, m >= 1 +/***UNUSED*** * +/***UNUSED*** * OUTPUT +/***UNUSED*** * +/***UNUSED*** * ans - a vector of length at least m whose first m +/***UNUSED*** * components contain the sequence of derivatives +/***UNUSED*** * scaled according to kode. +/***UNUSED*** * +/***UNUSED*** * nz - underflow flag +/***UNUSED*** * nz == 0, a normal return +/***UNUSED*** * nz != 0, underflow, last nz components of ans are +/***UNUSED*** * set to zero, ans(m-k+1)=0.0, k=1,...,nz +/***UNUSED*** * +/***UNUSED*** * ierr - error flag +/***UNUSED*** * ierr=0, a normal return, computation completed +/***UNUSED*** * ierr=1, input error, no computation +/***UNUSED*** * ierr=2, overflow, x too small or n+m-1 too +/***UNUSED*** * large or both +/***UNUSED*** * ierr=3, error, n too large. dimensioned +/***UNUSED*** * array trmr(nmax) is not large enough for n +/***UNUSED*** * +/***UNUSED*** * The nominal computational accuracy is the maximum of unit +/***UNUSED*** * roundoff (d1mach(4)) and 1e-18 since critical constants +/***UNUSED*** * are given to only 18 digits. +/***UNUSED*** * +/***UNUSED*** * The basic method of evaluation is the asymptotic expansion +/***UNUSED*** * for large x >= xmin followed by backward recursion on a two +/***UNUSED*** * term recursion relation +/***UNUSED*** * +/***UNUSED*** * w(x+1) + x**(-n-1) = w(x). +/***UNUSED*** * +/***UNUSED*** * this is supplemented by a series +/***UNUSED*** * +/***UNUSED*** * sum( (x+k)**(-n-1) , k=0,1,2,... ) +/***UNUSED*** * +/***UNUSED*** * which converges rapidly for large n. both xmin and the +/***UNUSED*** * number of terms of the series are calculated from the unit +/***UNUSED*** * roundoff of the machine environment. +/***UNUSED*** * +/***UNUSED*** * AUTHOR +/***UNUSED*** * +/***UNUSED*** * Amos, D. E. (Fortran) +/***UNUSED*** * Ross Ihaka (C Translation) +/***UNUSED*** * +/***UNUSED*** * REFERENCES +/***UNUSED*** * +/***UNUSED*** * Handbook of Mathematical Functions, +/***UNUSED*** * National Bureau of Standards Applied Mathematics Series 55, +/***UNUSED*** * Edited by M. Abramowitz and I. A. Stegun, equations 6.3.5, +/***UNUSED*** * 6.3.18, 6.4.6, 6.4.9 and 6.4.10, pp.258-260, 1964. +/***UNUSED*** * +/***UNUSED*** * D. E. Amos, (1983). "A Portable Fortran Subroutine for +/***UNUSED*** * Derivatives of the Psi Function", Algorithm 610, +/***UNUSED*** * TOMS 9(4), pp. 494-502. +/***UNUSED*** * +/***UNUSED*** * Routines called: d1mach, i1mach. +/***UNUSED*** */ +/***UNUSED*** +/***UNUSED*** /*!* #include "DistLib.h" /*4!*/ +/***UNUSED*** +/***UNUSED*** /* Bernoulli Numbers */ +/***UNUSED*** +/***UNUSED*** static private double b[] = { +/***UNUSED*** 00, /** DUMMY ENTRY SO INDEXING FROM 1 WORKS **/ +/***UNUSED*** 1.00000000000000000e+00, +/***UNUSED*** -5.00000000000000000e-01, +/***UNUSED*** 1.66666666666666667e-01, +/***UNUSED*** -3.33333333333333333e-02, +/***UNUSED*** 2.38095238095238095e-02, +/***UNUSED*** -3.33333333333333333e-02, +/***UNUSED*** 7.57575757575757576e-02, +/***UNUSED*** -2.53113553113553114e-01, +/***UNUSED*** 1.16666666666666667e+00, +/***UNUSED*** -7.09215686274509804e+00, +/***UNUSED*** 5.49711779448621554e+01, +/***UNUSED*** -5.29124242424242424e+02, +/***UNUSED*** 6.19212318840579710e+03, +/***UNUSED*** -8.65802531135531136e+04, +/***UNUSED*** 1.42551716666666667e+06, +/***UNUSED*** -2.72982310678160920e+07, +/***UNUSED*** 6.01580873900642368e+08, +/***UNUSED*** -1.51163157670921569e+10, +/***UNUSED*** 4.29614643061166667e+11, +/***UNUSED*** -1.37116552050883328e+13, +/***UNUSED*** 4.88332318973593167e+14, +/***UNUSED*** -1.92965793419400681e+16 +/***UNUSED*** }; +/***UNUSED*** +/***UNUSED*** // static private double *b = (double *)&bvalues -1; +/***UNUSED*** static private int nmax = 100; +/***UNUSED*** +/***UNUSED*** public static int ierr = 0; +/***UNUSED*** +/***UNUSED*** static double[] dpsifn(double x, int n, int kode, int m, int nz) +/***UNUSED*** { +/***UNUSED*** double ans[] = new double[n+1]; +/***UNUSED*** double retval[] = new double[n]; +/***UNUSED*** int i, j, k, mm, mx, nn, np, nx, fn; +/***UNUSED*** double arg, den, elim, eps, fln, fx, rln, rxsq; +/***UNUSED*** double r1m4, r1m5, s, slope, t, ta, tk, tol, tols, tss, tst; +/***UNUSED*** double tt, t1, t2, wdtol, xdmln, xdmy, xinc, xln, xm, xmin; +/***UNUSED*** double xq, yint; +/***UNUSED*** double trm[] = new double[23], trmr[] = new double[101]; +/***UNUSED*** +/***UNUSED*** ierr = 0; +/***UNUSED*** if (x <= 0.0 || n < 0 || kode < 1 || kode > 2 || m < 1) { +/***UNUSED*** ierr = 1; +/***UNUSED*** return ans; +/***UNUSED*** } +/***UNUSED*** +/***UNUSED*** /* fortran adjustment */ +/***UNUSED*** //ans--; +/***UNUSED*** +/***UNUSED*** nz = 0; +/***UNUSED*** mm = m; +/***UNUSED*** /*!* nx = Math.min(-i1mach(15), i1mach(16)); *!*/ +/***UNUSED*** nx = Math.min(-misc.i1mach(15), misc.i1mach(16)); +/***UNUSED*** /*!* r1m5 = d1mach(5); *!*/ +/***UNUSED*** r1m5 = misc.d1mach(5); +/***UNUSED*** /*!* r1m4 = d1mach(4) * 0.5; *!*/ +/***UNUSED*** r1m4 = misc.d1mach(4) * 0.5; +/***UNUSED*** /*!* wdtol = fmax2(r1m4, 0.5e-18); *!*/ +/***UNUSED*** wdtol = Math.max(r1m4, 0.5e-18); +/***UNUSED*** +/***UNUSED*** /* elim = approximate exponential over and underflow limit */ +/***UNUSED*** +/***UNUSED*** elim = 2.302 * (nx * r1m5 - 3.0); +/***UNUSED*** /*!* xln = log(x); *!*/ +/***UNUSED*** xln = java.lang.Math.log(x); +/***UNUSED*** for(;;) { +/***UNUSED*** nn = n + mm - 1; +/***UNUSED*** fn = nn; +/***UNUSED*** t = (fn + 1) * xln; +/***UNUSED*** +/***UNUSED*** /* overflow and underflow test for small and large x */ +/***UNUSED*** +/***UNUSED*** /*!* if (fabs(t) > elim) { *!*/ +/***UNUSED*** if (java.lang.Math.abs(t) > elim) { +/***UNUSED*** if (t <= 0.0) { +/***UNUSED*** nz = 0; +/***UNUSED*** ierr = 2; +/***UNUSED*** { +/***UNUSED*** for(int count=0; count 7.0 && fln < 15.0) +/***UNUSED*** break; +/***UNUSED*** } +/***UNUSED*** xdmy = x; +/***UNUSED*** xdmln = xln; +/***UNUSED*** xinc = 0.0; +/***UNUSED*** if (x < xmin) { +/***UNUSED*** nx = (int)x; +/***UNUSED*** xinc = xmin - nx; +/***UNUSED*** xdmy = x + xinc; +/***UNUSED*** /*!* xdmln = log(xdmy); *!*/ +/***UNUSED*** xdmln = java.lang.Math.log(xdmy); +/***UNUSED*** } +/***UNUSED*** +/***UNUSED*** /* generate w(n+mm-1, x) by the asymptotic expansion */ +/***UNUSED*** +/***UNUSED*** t = fn * xdmln; +/***UNUSED*** t1 = xdmln + xdmln; +/***UNUSED*** t2 = t + xdmln; +/***UNUSED*** /*!* tk = fmax2(fabs(t), fmax2(fabs(t1), fabs(t2))); *!*/ +/***UNUSED*** tk = Math.max(java.lang.Math.abs(t), Math.max(java.lang.Math.abs(t1), java.lang.Math.abs(t2))); +/***UNUSED*** if (tk <= elim) +/***UNUSED*** break L10; +/***UNUSED*** } +/***UNUSED*** +/***UNUSED*** nz = nz + 1; +/***UNUSED*** ans[mm] = 0.0; +/***UNUSED*** mm = mm - 1; +/***UNUSED*** if (mm == 0) +/***UNUSED*** { +/***UNUSED*** for(int count=0; count n */ +/***UNUSED*** +/***UNUSED*** tol = wdtol / 5.0; +/***UNUSED*** for(j=2 ; j<=mm ; j++) { +/***UNUSED*** t = t / x; +/***UNUSED*** s = t; +/***UNUSED*** tols = t * tol; +/***UNUSED*** den = x; +/***UNUSED*** for(i=1 ; i<=nn ; i++) { +/***UNUSED*** den = den + 1.0; +/***UNUSED*** trm[i] = trm[i] / den; +/***UNUSED*** s = s + trm[i]; +/***UNUSED*** if (trm[i] < tols) +/***UNUSED*** break; +/***UNUSED*** } +/***UNUSED*** ans[j] = s; +/***UNUSED*** } +/***UNUSED*** } +/***UNUSED*** { +/***UNUSED*** for(int count=0; count= tst) { *!*/ +/***UNUSED*** if (java.lang.Math.abs(s) >= tst) { +/***UNUSED*** tk = 2.0; +/***UNUSED*** for(k=4 ; k<=22 ; k++) { +/***UNUSED*** t = t * ((tk + fn + 1)/(tk + 1.0))*((tk + fn)/(tk + 2.0)) * rxsq; +/***UNUSED*** trm[k] = t * b[k]; +/***UNUSED*** /*!* if (fabs(trm[k]) < tst) *!*/ +/***UNUSED*** if (java.lang.Math.abs(trm[k]) < tst) +/***UNUSED*** break; +/***UNUSED*** s = s + trm[k]; +/***UNUSED*** tk = tk + 2.0; +/***UNUSED*** } +/***UNUSED*** } +/***UNUSED*** s = (s + t1) * tss; +/***UNUSED*** if (xinc != 0.0) { +/***UNUSED*** +/***UNUSED*** /* backward recur from xdmy to x */ +/***UNUSED*** +/***UNUSED*** nx = (int)xinc; +/***UNUSED*** np = nn + 1; +/***UNUSED*** if (nx > nmax) { +/***UNUSED*** nz = 0; +/***UNUSED*** ierr = 3; +/***UNUSED*** { +/***UNUSED*** for(int count=0; count= tst) { *!*/ +/***UNUSED*** if (java.lang.Math.abs(s) >= tst) { +/***UNUSED*** tk = 4 + fn; +/***UNUSED*** for(k=4 ; k<=22 ; k++) { +/***UNUSED*** trm[k] = trm[k] * (fn + 1) / tk; +/***UNUSED*** /*!* if (fabs(trm[k]) < tst) *!*/ +/***UNUSED*** if (java.lang.Math.abs(trm[k]) < tst) +/***UNUSED*** break; +/***UNUSED*** s = s + trm[k]; +/***UNUSED*** tk = tk + 2.0; +/***UNUSED*** } +/***UNUSED*** } +/***UNUSED*** s = (s + t1) * tss; +/***UNUSED*** +/***UNUSED*** if (xinc != 0.0) { +/***UNUSED*** if (fn == 0) +/***UNUSED*** break L20; +/***UNUSED*** xm = xinc - 1.0; +/***UNUSED*** fx = x + xm; +/***UNUSED*** for(i=1 ; i<=nx ; i++) { +/***UNUSED*** trmr[i] = trmr[i] * fx; +/***UNUSED*** s = s + trmr[i]; +/***UNUSED*** xm = xm - 1.0; +/***UNUSED*** fx = x + xm; +/***UNUSED*** } +/***UNUSED*** } +/***UNUSED*** mx = mm - j + 1; +/***UNUSED*** ans[mx] = s; +/***UNUSED*** if (fn == 0) +/***UNUSED*** break L30; +/***UNUSED*** } +/***UNUSED*** { +/***UNUSED*** for(int count=0; count>16); + i_seed[0]= 18000*(i_seed[0] & 0177777) + (i_seed[0]>>16); + return (do32bits(i1_seed << 16) ^ (i_seed[0] & 0177777)) * i2_32m1; /* in [0,1) */ + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/rng/Rand.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/rng/Rand.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/rng/Rand.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/rng/Rand.java 2010-01-15 06:08:51.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * Created on Apr 17, 2007 + */ +package org.mathpiper.builtin.library.statdistlib.rng; + +import java.util.Random; + +import org.mathpiper.builtin.library.statdistlib.StdUniformRng; + + +public class Rand implements StdUniformRng { + + Random random; + + public Rand() { + random = new Random(); + } + + public void fixupSeeds() { + ; // do nothing since seeds are managed + } + + public double random() { + return random.nextDouble(); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/rng/SuperDuper.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/rng/SuperDuper.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/rng/SuperDuper.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/rng/SuperDuper.java 2010-01-15 06:08:51.000000000 +0000 @@ -0,0 +1,42 @@ +/** + * Standard random deviates via + * Reeds et al (1984) implementation; + * modified using __unsigned__ seeds instead of signed ones. + * + * Created on Apr 17, 2007 + */ +package org.mathpiper.builtin.library.statdistlib.rng; + +import org.mathpiper.builtin.library.statdistlib.StdUniformRng; + + +public class SuperDuper implements StdUniformRng { + + private int i1_seed; + private int[] i_seed; + + static private double i2_32m1 = 2.328306437080797e-10; /* = 1/(2^32 - 1) */ + static private int do32bits(int N) { return (N); } + + public SuperDuper() { + i1_seed = 123; + i_seed = new int[1]; + fixupSeeds(); + } + public void fixupSeeds() { + if (i1_seed==0) i1_seed++; + for(int j=0; j < i_seed.length; j++) { + if (i_seed[j]==0) i_seed[j]++; + } + i_seed[0] |= 1; // seed must be odd + } + + public double random() { + i1_seed ^= ((i1_seed >> 15) & 0377777); /* Tausworthe */ + i1_seed ^= do32bits(i1_seed << 17); + i_seed[0] *= 69069; /* Congruential */ + i_seed[0] = do32bits(69069 * i_seed[0]); + return (i1_seed^i_seed[0]) * i2_32m1;/* in [0,1) */ + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/rng/WichmannHill.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/rng/WichmannHill.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/rng/WichmannHill.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/rng/WichmannHill.java 2010-01-15 06:08:51.000000000 +0000 @@ -0,0 +1,54 @@ +/** + * Wichmann-Hill algorithm for random variates from the + * standard uniform distribution, U(0,1). + *

+ * Wichmann, B. A. and I. D. Hill (1982). + * Algorithm AS 183: An efficient and portable + * pseudo-random number generator, + * Applied Statistics, 31, 188. + * + * Created on Apr 16, 2007 + */ +package org.mathpiper.builtin.library.statdistlib.rng; + +import org.mathpiper.builtin.library.statdistlib.StdUniformRng; + +public class WichmannHill implements StdUniformRng { + + int i1_seed; + int[] i_seed; + static final int c0 = 30269; + static final int c1 = 30307; + static final int c2 = 30323; + + public WichmannHill() { + i1_seed = 123; + i_seed = new int[2]; + fixupSeeds(); + } + + public void fixupSeeds() { + // exclude 0 as seed + if (i1_seed==0) i1_seed++; + for (int j=0; j < i_seed.length; j++) { + if (i_seed[j]==0) i_seed[j]++; + } + if (i1_seed >= c0 || + i_seed[0] >= c1 || + i_seed[1] >= c2) { + random(); + } + } + + public double random() { + i1_seed = i1_seed * 171 % c0; + i_seed[0] = i_seed[0] * 172 % c1; + i_seed[1] = i_seed[1] * 170 % c2; + double value = + (double)i1_seed / c0 + + (double)i_seed[0] / c1 + + (double)i_seed[1] / c2; + return value - (int) value; // ensure in range [0,1) + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/SignRank.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/SignRank.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/SignRank.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/SignRank.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,278 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class SignRank + { + + + public static final double SIGNRANK_NMAX = 50; + + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 R Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double n) + * + * DESCRIPTION + * + * The density of the Wilcoxon Signed Rank distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + static private double w[][]; + + static private double csignrank(int k, int n) { + int c, u, i; + + u = n * (n + 1) / 2; + c = (int) (u / 2); + + if ((k < 0) || (k > u)) + return(0); + if (k > c) + k = u - k; + if (w[n] == null) { + w[n] = new double[c + 1]; + for (i = 0; i <= c; i++) + w[n][i] = -1; + } + if (w[n][k] < 0) { + if (n == 0) + w[n][k] = (k == 0)?1.0:0.0; + else + w[n][k] = csignrank(k - n, n - 1) + csignrank(k, n - 1); + } + return(w[n][k]); + } + + public static double density(double x, double n) { + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + if (Double.isNaN(x) || Double.isNaN(n)) return x + n; + /*!* #endif /*4!*/ +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } else if (n >= SIGNRANK_NMAX) { + System.out.println("n should be less than %d\n"+ SIGNRANK_NMAX); + return Double.NaN; + } +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if ((x < 0) || (x > (n * (n + 1) / 2))) + return 0; +/*!* return(exp(log(csignrank(x, n)) - n * log(2))); *!*/ + return(java.lang.Math.exp( + java.lang.Math.log( + csignrank((int) x, (int) n)) - n * java.lang.Math.log(2))); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 R Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double n) + * + * DESCRIPTION + * + * The distribution function of the Wilcoxon Signed Rank distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double n) { + int i; + double p = 0.0; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n)) + return x + n; + if (Double.isInfinite(n)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } else if (n >= SIGNRANK_NMAX) { + System.out.println("n should be less than %d\n"+ SIGNRANK_NMAX); + return Double.NaN; + } +/*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if (x < 0.0) + return 0; + if (x >= n * (n + 1) / 2) + return 1; + for (i = 0; i <= x; i++) + p += density(i, n); + return(p); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 R Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double n); + * + * DESCRIPTION + * + * The quantile function of the Wilcoxon Signed Rank distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double n) + { + double p, q; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n)) + return x + n; + if(Double.isInfinite(x) || Double.isInfinite(n)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (x < 0 || x > 1 || n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } else if (n >= SIGNRANK_NMAX) { + System.out.println("n should be less than %d\n"+ SIGNRANK_NMAX); + return Double.NaN; + } + + if (x == 0) return(0.0); + if (x == 1) return(n * (n + 1) / 2); + p = 0.0; + q = 0.0; + for (;;) { + /* Don't call cumulative() for efficiency */ + p += density(q, n); + if (p >= x) + return(q); + q++; + } + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 R Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double random(double n) + * + * DESCRIPTION + * + * Random variates from the Wilcoxon Signed Rank distribution. + * + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double n) + { + int i, k; + double r; + + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + if (Double.isNaN(n)) return(n); + /*!* #endif /*4!*/ +/*!* n = floor(n + 0.5); *!*/ + n = java.lang.Math.floor(n + 0.5); + if (n < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (n == 0) + return(0); + r = 0.0; + k = (int) n; + for (i = 0; i < k; ) { +/*!* r += (++i) * floor(sunif() + 0.5); *!*/ + r += (++i) * java.lang.Math.floor(Uniform.random() + 0.5); + } + return(r); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/StdUniformRng.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/StdUniformRng.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/StdUniformRng.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/StdUniformRng.java 2010-01-27 09:33:28.000000000 +0000 @@ -0,0 +1,11 @@ +/** + * Interface for standard uniform random number generator in this package. + * + * Created on Apr 16, 2007 + */ +package org.mathpiper.builtin.library.statdistlib; + +public interface StdUniformRng { + public void fixupSeeds(); + public double random(); +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/t.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/t.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/t.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/t.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,269 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class t + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double n); + * + * DESCRIPTION + * + * The density of the "Student" t distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double n) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n)) + return x + n; + /*!* #endif /*4!*/ + if (n <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(x)) + return 0; + if(Double.isInfinite(n)) + return Normal.density(x, 0.0, 1.0); + /*!* #endif /*4!*/ +/*!* return pow(1.0 + x * x / n, -0.5 * (n + 1.0)) *!*/ + return java.lang.Math.pow(1.0 + x * x / n, -0.5 * (n + 1.0)) +/*!* / (sqrt(n) * Beta(0.5, 0.5 * n)); *!*/ + / (java.lang.Math.sqrt(n) * Misc.beta(0.5, 0.5 * n)); + } + /* + * R : A Computer Langage for Statistical Data Analysis + * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double n) + { + double val; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(n)) + return x + n; + /*!* #endif /*4!*/ + if (n <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #ifdef IEEE_754 /*4!*/ + if(Double.isInfinite(x)) + return (x < 0) ? 0 : 1; + if(Double.isInfinite(n)) + return Normal.cumulative(x, 0.0, 1.0); + /*!* #endif /*4!*/ + val = 0.5 * Beta.cumulative(n / (n + x * x), n / 2.0, 0.5); + return (x > 0.0) ? 1 - val : val; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double p, double ndf); + * + * DESCRIPTION + * + * The "Student" t distribution quantile function. + * + * NOTES + * + * This is a C translation of the Fortran routine given in: + * Algorithm 396: Student's t-quantiles by G.W. Hill + * CACM 13(10), 619-620, October 1970 + */ + + /*!* #include "DistLib.h" /*4!*/ + + static private double eps = 1.e-12; + + public static double quantile(double p, double ndf) + { + double a, b, c, d, prob, P, q, x, y; + boolean neg; + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(p) || Double.isNaN(ndf)) + return p + ndf; + if(ndf < 1 || p > 1 || p < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (p == 0) return Double.NEGATIVE_INFINITY; + if (p == 1) return Double.POSITIVE_INFINITY; + /*!* #else /*4!*/ + if (ndf < 1 || p > 1 || p < 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + if (ndf > 1e20) return Normal.quantile(p, 0.0, 1.0); + + if(p > 0.5) { + neg = false; P = 2 * (1 - p); + } else { + neg = true; P = 2 * p; + } + +/*!* if (fabs(ndf - 2) < eps) { *!*/ + if (java.lang.Math.abs(ndf - 2) < eps) { + /* df ~= 2 */ +/*!* q = sqrt(2 / (P * (2 - P)) - 2); *!*/ + q = java.lang.Math.sqrt(2 / (P * (2 - P)) - 2); + } + else if (ndf < 1 + eps) { + /* df ~= 1 */ + prob = P * Constants.M_PI_half; +/*!* q = cos(prob) / sin(prob); *!*/ + q = java.lang.Math.cos(prob) / java.lang.Math.sin(prob); + } + else { + /*-- usual case; including, e.g., df = 1.1 */ + a = 1 / (ndf - 0.5); + b = 48 / (a * a); + c = ((20700 * a / b - 98) * a - 16) * a + 96.36; +/*!* d = ((94.5 / (b + c) - 3) / b + 1) * sqrt(a * Constants.M_PI_half) * ndf; *!*/ + d = ((94.5 / (b + c) - 3) / b + 1) * java.lang.Math.sqrt(a * Constants.M_PI_half) * ndf; +/*!* y = pow(d * P, 2 / ndf); *!*/ + y = java.lang.Math.pow(d * P, 2 / ndf); + + if (y > 0.05 + a) { + /* Asymptotic inverse expansion about Normal */ + x = Normal.quantile(0.5 * P, 0.0, 1.0); + y = x * x; + if (ndf < 5) + c = c + 0.3 * (ndf - 4.5) * (x + 0.6); + c = (((0.05 * d * x - 5) * x - 7) * x - 2) * x + b + c; + y = (((((0.4 * y + 6.3) * y + 36) * y + 94.5) / c - y - 3) / b + 1) * x; + y = a * y * y; + if (y > 0.002) +/*!* y = exp(y) - 1; *!*/ + y = java.lang.Math.exp(y) - 1; + else { + /* Taylor of e^y -1 : */ + y = 0.5 * y * y + y; + } + } else { + y = ((1 / (((ndf + 6) / (ndf * y) - 0.089 * d - 0.822) + * (ndf + 2) * 3) + 0.5 / (ndf + 4)) + * y - 1) * (ndf + 1) / (ndf + 2) + 1 / y; + } +/*!* q = sqrt(ndf * y); *!*/ + q = java.lang.Math.sqrt(ndf * y); + } + if(neg) q = -q; + return q; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "mathlib.h" + * double random(double df); + * + * DESCRIPTION + * + * Pseudo-random variates from an F distribution. + * + * NOTES + * + * This function calls rchisq and rnorm to do the real work. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double df, Uniform uniformDistribution) + { + if ( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isNaN(df) || + /*!* #endif /*4!*/ + df <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if(Double.isInfinite(df)) + return Normal.random(uniformDistribution); + else +/*!* return Normal.random!!!COMMENT!!!() / sqrt(rchisq(df) / df); *!*/ + return Normal.random(uniformDistribution) / java.lang.Math.sqrt(Chisquare.random(df, uniformDistribution) / df); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Tukey.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Tukey.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Tukey.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Tukey.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,558 @@ +/* DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * data translated from C using perl script translate.pl + * script version 0.00 + */ +package org.mathpiper.builtin.library.statdistlib; + +//import org.apache.commons.math.MathException; +//import org.apache.commons.math.special.Erf; + +import org.mathpiper.builtin.library.cern.Probability; + +/** + * Distribution of the maximum of rr studentized + * ranges, each based on cc means and with df degrees of freedom + * for the standard error, is less than q. + *

+ * The algorithm is based on: + * Copenhaver, Margaret Diponzio & Holland, Burt S. + * Multiple comparisons of simple effects in + * the two-way analysis of variance with fixed effects. + * Journal of Statistical Computation and Simulation, + * Vol.30, pp.1-15, 1988. + */ + +public class Tukey { + + /* + * This function calculates probability integral of Hartley's + * form of the range. + * + * w = value of range + * rr = no. of rows or groups + * cc = no. of columns or treatments + * ir = error flag = 1 if wprob probability > 1 + * wprob = returned probability integral from (0, w) + * + * program will not terminate if ir is raised. + * + * bb = upper limit of legendre integration + * eps = maximum acceptable value of integral + * nleg = order of legendre quadrature + * ihalf = int ((nleg + 1) / 2) + * wlar = value of range above which wincr1 intervals are used to + * calculate second part of integral, + * else wincr2 intervals are used. + * eps1, eps2, eps3 = values which are used as cutoffs for terminating + * or modifying a calculation. + * + * M_1_SQRT_2PI = 1 / sqrt(2 * pi); from abramowitz & stegun, p. 3. + * M_SQRT_2 = sqrt(2) + * xleg = legendre 12-point nodes + * aleg = legendre 12-point coefficients + */ + + static final double nleg = 12; + static final double ihalf = 6; + + static double wprob(double w, double rr, double cc) throws ArithmeticException { //MathException { + final double eps = 1.0; + final double eps1 = -30.0; + final double eps2 = -50.0; + final double eps3 = 60.0; + final double bb = 8.0; + final double wlar = 3.0; + final double wincr1 = 2.0; + final double wincr2 = 3.0; + final double xleg[] = { + 0.981560634246719250690549090149e0, + 0.904117256370474856678465866119e0, + 0.769902674194304687036893833213e0, + 0.587317954286617447296702418941e0, + 0.367831498998180193752691536644e0, + 0.125233408511468915472441369464e0 + }; + final double aleg[] = { + 0.047175336386511827194615961485, + 0.106939325995318430960254718194, + 0.160078328543346226334652529543, + 0.203167426723065921749064455810, + 0.233492536538354808760849898925, + 0.249147045813402785000562436043 + }; + double a, ac, ans, b, binc, blb, bub, c, cc1, einsum, elsum, + pminus, pplus, qexpo, qsqz, rinsum, wi, wincr, xx; + int j, jj; + + qsqz = w * 0.5; + + /* if w >= 16 then the integral lower bound (occurs for c=20) */ + /* is 0.99999999999995 so return a value of 1. */ + + ans = 1.0; + if (qsqz >= bb) return 1.0; + + /* find (f(w/2) - 1) ** cc */ + /* (first term in integral of hartley's form). */ + + /* if ans ** cc < 2e-22 then set ans = 0 */ + + ans = Probability.errorFunction(qsqz / Constants.M_SQRT_2); + if (ans >= Math.exp(eps2 / cc)) ans = Math.pow(ans, cc); + else ans = 0.0; + + /* if w is large then the second component of the */ + /* integral is small, so fewer intervals are needed. */ + + if (w > wlar) wincr = wincr1; + else wincr = wincr2; + + /* find the integral of second term of hartley's form */ + /* for the integral of the range for equal-length */ + /* intervals using legendre quadrature. limits of */ + /* integration are from (w/2, 8). two or three */ + /* equal-length intervals are used. */ + + /* blb and bub are lower and upper limits of integration. */ + + blb = qsqz; + binc = (bb - qsqz) / wincr; + bub = blb + binc; + einsum = 0.0; + + /* integrate over each interval */ + + cc1 = cc - 1.0; + for (wi = 1; wi <= wincr; wi++) { + elsum = 0.0; + a = 0.5 * (bub + blb); + + /* legendre quadrature with order = nleg */ + + b = 0.5 * (bub - blb); + + for (jj = 1; jj <= nleg; jj++) { + if (ihalf < jj) { + j = (int) (nleg - jj) + 1; + xx = xleg[j-1]; + } else { + j = jj; + xx = -xleg[j-1]; + } + c = b * xx; + ac = a + c; + + /* if exp(-qexpo/2) < 9e-14, */ + /* then doesn't contribute to integral */ + + qexpo = ac * ac; + + if (qexpo > eps3) break; + if (ac > 0.0) + pplus = 1.0 + Probability.errorFunction(ac / Constants.M_SQRT_2); + else + pplus = 1.0 - Probability.errorFunction(-(ac / Constants.M_SQRT_2)); + + if (ac > w) + pminus = 1.0 + Probability.errorFunction((ac / Constants.M_SQRT_2) - (w / Constants.M_SQRT_2)); + else + pminus = 1.0 - Probability.errorFunction((w / Constants.M_SQRT_2) - (ac / Constants.M_SQRT_2)); + + /* if rinsum ** (cc-1) < 9e-14, */ + /* then doesn't contribute to integral */ + + rinsum = (pplus * 0.5) - (pminus * 0.5); + if (rinsum >= java.lang.Math.exp(eps1 / cc1)) { + rinsum = (aleg[j-1] * Math.exp(-(0.5 * qexpo))) + * Math.pow(rinsum, cc1); + elsum = elsum + rinsum; + } + } + elsum = (((2.0 * b) * cc) * Constants.M_1_SQRT_2PI) * elsum; + einsum = einsum + elsum; + blb = bub; + bub = bub + binc; + } + + // if ans ** rr < 9e-14, then return 0.0 + ans = einsum + ans; + if (ans <= Math.exp(eps1 / rr)) return 0.0; + + ans = Math.pow(ans, rr); + if (ans >= eps) ans = 1.0; + return ans; + } + + /** + * function qprob + * + * q = value of studentized range + * rr = no. of rows or groups + * cc = no. of columns or treatments + * df = degrees of freedom of error term + * ir[0] = error flag = 1 if wprob probability > 1 + * ir[1] = error flag = 1 if qprob probability > 1 + * + * qprob = returned probability integral over [0, q] + * + * The program will not terminate if ir[0] or ir[1] are raised. + * + * All references in wprob to Abramowitz and Stegun + * are from the following reference: + * + * Abramowitz, Milton and Stegun, Irene A. + * Handbook of Mathematical Functions. + * New York: Dover publications, Inc. (1970). + * + * All constants taken from this text are + * given to 25 significant digits. + * + * nlegq = order of legendre quadrature + * ihalfq = int ((nlegq + 1) / 2) + * eps = max. allowable value of integral + * eps1 & eps2 = values below which there is + * no contribution to integral. + * + * d.f. <= dhaf: integral is divided into ulen1 length intervals. else + * d.f. <= dquar: integral is divided into ulen2 length intervals. else + * d.f. <= deigh: integral is divided into ulen3 length intervals. else + * d.f. <= dlarg: integral is divided into ulen4 length intervals. + * + * d.f. > dlarg: the range is used to calculate integral. + * + * M_LN_2 = log(2) + * + * xlegq = legendre 16-point nodes + * + * alegq = legendre 16-point coefficients + * + * The coefficients and nodes for the legendre quadrature used in + * qprob and wprob were calculated using the algorithms found in: + * + * Stroud, A. H. and Secrest, D. + * Gaussian Quadrature Formulas. + * Englewood Cliffs, + * New Jersey: Prentice-Hall, Inc, 1966. + * + * All values matched the tables (provided in same reference) + * to 30 significant digits. + * + * f(x) = .5 + erf(x / sqrt(2)) / 2 for x > 0 + * + * f(x) = erfc( -x / sqrt(2)) / 2 for x < 0 + * + * where f(x) is standard normal c. d. f. + * + * if degrees of freedom large, approximate integral + * with range distribution. + */ + + static final double nlegq = 16; + static final double ihalfq = 8; + + public static double cumulative(double q, double rr, double cc, double df) { + final double eps = 1.0e0; + final double eps1 = -30.0e0; + final double eps2 = 1.0e-14; + final double dhaf = 100.0e0; + final double dquar = 800.0e0; + final double deigh = 5000.0e0; + final double dlarg = 25000.0e0; + final double ulen1 = 1.0e0; + final double ulen2 = 0.5e0; + final double ulen3 = 0.25e0; + final double ulen4 = 0.125e0; + final double xlegq[] = { + 0.989400934991649932596154173450e+00, + 0.944575023073232576077988415535e+00, + 0.865631202387831743880467897712e+00, + 0.755404408355003033895101194847e+00, + 0.617876244402643748446671764049e+00, + 0.458016777657227386342419442984e+00, + 0.281603550779258913230460501460e+00, + 0.950125098376374401853193354250e-01 + }; + final double alegq[] = { + 0.271524594117540948517805724560e-01, + 0.622535239386478928628438369944e-01, + 0.951585116824927848099251076022e-01, + 0.124628971255533872052476282192e+00, + 0.149595988816576732081501730547e+00, + 0.169156519395002538189312079030e+00, + 0.182603415044923588866763667969e+00, + 0.189450610455068496285396723208e+00 + }; + double ans, f2, f21, f2lf, ff4, otsum, qsqz, rotsum, + t1, twa1, ulen, wprb; + int i, j, jj; + + if (Double.isNaN(q) || Double.isNaN(rr) || Double.isNaN(cc) || Double.isNaN(df)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (q <= 0) return 0; + + /* df must be > 1 */ + /* there must be at least two values */ + + if (df < 2 || rr < 1 || cc < 2) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + if (Double.isInfinite(q)) return 1; + + if (df > dlarg) { + try { + ans = wprob(q, rr, cc); + } catch (ArithmeticException me) { //Catch MathException. + throw new ArithmeticException("Doesn't converge."); + } + return ans; + } + + /* calculate leading constant */ + /* lgamma is the log gamma function. */ + + f2 = df * 0.5; + f2lf = ((f2 * Math.log(df)) - (df * Constants.M_LN_2)) - Misc.lgammafn(f2); + f21 = f2 - 1.0; + + /* integral is divided into unit, half-unit, quarter-unit, or */ + /* eighth-unit length intervals depending on the value of the */ + /* degrees of freedom. */ + + ff4 = df * 0.25; + if (df <= dhaf) { + ulen = ulen1; + } else if (df <= dquar) { + ulen = ulen2; + } else if (df <= deigh) { + ulen = ulen3; + } else { + ulen = ulen4; + } + + f2lf = f2lf + Math.log(ulen); + + // integrate over each subinterval + ans = 0.0; + + L400: { + for (i = 1; i <= 50; i++) { + otsum = 0.0; + + /* legendre quadrature with order = nlegq */ + /* nodes (stored in xlegq) are symmetric around zero. */ + + twa1 = ((2.0 * i) - 1.0) * ulen; + + for (jj = 1; jj <= nlegq; jj++) { + if (ihalfq < jj) { + j = (int) (jj - ihalfq - 1); + t1 = (f2lf + (f21 * java.lang.Math.log(twa1 + (xlegq[j] * ulen)))) + - (((xlegq[j] * ulen) + twa1) * ff4); + } else { + j = jj - 1; + t1 = (f2lf + (f21 * java.lang.Math.log(twa1 - (xlegq[j] * ulen)))) + + (((xlegq[j] * ulen) - twa1) * ff4); + + } + + /* if exp(t1) < 9e-14, then doesn't */ + /* contribute to integral */ + + if (t1 >= eps1) { + if (ihalfq < jj) { + qsqz = q * java.lang.Math.sqrt(((xlegq[j] * ulen) + twa1) * 0.5); + } else { + qsqz = q * java.lang.Math.sqrt(((-(xlegq[j] * ulen)) + twa1) * 0.5); + } + + /* call wprob to find integral */ + /* of range portion */ + + try { + wprb = wprob(qsqz, rr, cc); + } catch (ArithmeticException e) { //Catch ArithmeticException. + throw new ArithmeticException("Doesn't converge"); + } + rotsum = (wprb * alegq[j]) * Math.exp(t1); + otsum = rotsum + otsum; + } + /* end legendre integral for interval i */ + /* L200: */ + } + + /* if integral for interval i < 1e-14, */ + /* then stop. however, in order to avoid */ + /* small area under left tail, at least */ + /* 1 / ulen intervals are calculated. */ + + if (i * ulen >= 1.0 && otsum <= eps2) + break L400; + + /* end of interval i */ + /* L330: */ + + ans = ans + otsum; + } + } //L400: + + if (ans > eps) ans = 1.0; + return ans; + } + + /** + * this function finds percentage point of the studentized range + * which is used as initial estimate for the secant method. + * function is adapted from portion of algorithm as 70 + * from applied statistics (1974) ,vol. 23, no. 1 + * by odeh, r. e. and evans, j. o. + * + * @param p percentage point + * @param c no. of columns or treatments + * @param v degrees of freedom + * @return initial estimate + */ + + static double qinv(double p, double c, double v) { + final double p0 = 0.322232421088; + final double q0 = 0.993484626060e-01; + final double p1 = -1.0; + final double q1 = 0.588581570495; + final double p2 = -0.342242088547; + final double q2 = 0.531103462366; + final double p3 = -0.204231210125; + final double q3 = 0.103537752850; + final double p4 = -0.453642210148e-04; + final double q4 = 0.38560700634e-02; + final double c1 = 0.8832; + final double c2 = 0.2368; + final double c3 = 1.214; + final double c4 = 1.208; + final double c5 = 1.4142; + final double vmax = 120.0; // cutoff above which degrees of freedom are treated as infinite + double ps, q, t, yi; + + ps = 0.5 - 0.5 * p; + yi = Math.sqrt (Math.log (1.0 / (ps * ps))); + t = yi + (((( yi * p4 + p3) * yi + p2) * yi + p1) * yi + p0) + / (((( yi * q4 + q3) * yi + q2) * yi + q1) * yi + q0); + if (v < vmax) t += (t * t * t + t) / v / 4.0; + q = c1 - c2 * t; + if (v < vmax) q += -c3 / v + c4 * t / v; + return t * (q * Math.log (c - 1.0) + c5); + } + + /** + * Computes the quantiles of the maximum of rr studentized + * ranges, each based on cc means and with df degrees of freedom + * for the standard error, is less than q. + * + * The algorithm is based on: + * Copenhaver, Margaret Diponzio & Holland, Burt S. + * Multiple comparisons of simple effects in + * the two-way analysis of variance with fixed effects. + * Journal of Statistical Computation and Simulation, + * Vol.30, pp.1-15, 1988. + * + * Uses the secant method to find critical values. + * If the difference between successive iterates is less than eps, + * the search is terminated and an exception thrown. + * + * @param p confidence level (1 - alpha) + * @param rr no. of rows or groups + * @param cc no. of columns or treatments + * @param df degrees of freedom of error term + * + * @return critical value + */ + public static double quantile(double p, double rr, double cc, double df) { + final double eps = 0.0001; + final int maxiter = 50; + double ans, valx0, valx1, x0, x1, xabs; + int iter; + + if (Double.isNaN(p) || Double.isNaN(rr) || Double.isNaN(cc) || Double.isNaN(df)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (p < 0 || p > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (p < 0 || p >= 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + /* df must be > 1 */ + /* there must be at least two values */ + + if (df < 2 || rr < 1 || cc < 2) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + + if (p <= 0) return 0; + + /* Initial value */ + + x0 = qinv(p, cc, df); + + /* Find prob(value < x0) */ + + valx0 = cumulative(x0, rr, cc, df) - p; + + /* Find the second iterate and prob(value < x1). */ + /* If the first iterate has probability value */ + /* exceeding p then second iterate is 1 less than */ + /* first iterate; otherwise it is 1 greater. */ + + if (valx0 > 0.0) x1 = Math.max(0.0, x0 - 1.0); + else x1 = x0 + 1.0; + valx1 = cumulative(x1, rr, cc, df) - p; + + /* Find new iterate */ + + for (iter=1 ; iter < maxiter ; iter++) { + ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0)); + valx0 = valx1; + + /* New iterate must be >= 0 */ + + x0 = x1; + if (ans < 0.0) { + ans = 0.0; + valx1 = -p; + } + /* Find prob(value < new iterate) */ + + valx1 = cumulative(ans, rr, cc, df) - p; + x1 = ans; + + /* If the difference between two successive */ + /* iterates is less than eps, stop */ + + /*!* xabs = fabs(x1 - x0); *!*/ + xabs = java.lang.Math.abs(x1 - x0); + if (xabs < eps) + return ans; + } + + /* The process did not converge in 'maxiter' iterations */ + throw new java.lang.ArithmeticException("No convergence."); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Uniform.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Uniform.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Uniform.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Uniform.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,98 @@ +/* DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * data translated from C using perl script translate.pl + * script version 0.00 + */ +package org.mathpiper.builtin.library.statdistlib; + +import org.mathpiper.builtin.library.statdistlib.rng.WichmannHill; + +/** + * Uniform distribution over an interval. + */ + +public class Uniform { + + /** + * density of the Uniform distribution. + */ + public static double density(double x, double a, double b) { + if (Double.isNaN(x) || Double.isNaN(a) || Double.isNaN(b)) + return x + a + b; + if (b <= a) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (a <= x && x <= b) + return 1.0 / (b - a); + return 0.0; + } + + /** + * distribution function of the Uniform distribution. + */ + public static double cumulative(double x, double a, double b) { + if (Double.isNaN(x) || Double.isNaN(a) || Double.isNaN(b)) + return x + a + b; + if (b <= a) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (x <= a) + return 0.0; + if (x >= b) + return 1.0; + return (x - a) / (b - a); + } + + /** + * quantile function of the Uniform distribution. + */ + public static double quantile(double x, double a, double b) { + if (Double.isNaN(x) || Double.isNaN(a) || Double.isNaN(b)) + return x + a + b; + if (b <= a || x < 0 || x > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + return a + x * (b - a); + } + + /** + * Random variates from the Uniform distribution. + */ + public static double random(double a, double b) { + if (Double.isInfinite(a) || Double.isInfinite(b) || b < a) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + } + if (a == b) + return a; + else + return a + (b - a) * random(); + } + + /** + * Generator used during random() call. Can be set. + */ + public static StdUniformRng uniRng = new WichmannHill(); + + /** + * generate standard Uniform random variate + */ + public static double random() { + return uniRng.random(); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Weibull.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Weibull.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Weibull.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Weibull.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,198 @@ +package org.mathpiper.builtin.library.statdistlib; + +/* data translated from C using perl script translate.pl */ +/* script version 0.00 */ + + +import java.lang.*; +import java.lang.Math; +import java.lang.Double; + +public class Weibull + { + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double shape, double scale); + * + * DESCRIPTION + * + * The density function of the Weibull distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double density(double x, double shape, double scale) + { + double tmp1, tmp2; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(shape) || Double.isNaN(scale)) + return x + shape + scale; + /*!* #endif /*4!*/ + if (shape <= 0 || scale <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x <= 0) return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isInfinite(x)) return 0; + /*!* #endif /*4!*/ +/*!* tmp1 = pow(x / scale, shape - 1); *!*/ + tmp1 = java.lang.Math.pow(x / scale, shape - 1); + tmp2 = tmp1 * (x / scale); +/*!* return shape * tmp1 * exp(-tmp2) / scale; *!*/ + return shape * tmp1 * java.lang.Math.exp(-tmp2) / scale; + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double cumulative(double x, double shape, double scale); + * + * DESCRIPTION + * + * The distribution function of the Weibull distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double cumulative(double x, double shape, double scale) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(shape) || Double.isNaN(scale)) + return x + shape + scale; + /*!* #endif /*4!*/ + if(shape <= 0 || scale <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x <= 0) return 0; +/*!* return 1.0 - exp(-pow(x / scale, shape)); *!*/ + return 1.0 - java.lang.Math.exp(-java.lang.Math.pow(x / scale, shape)); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double quantile(double x, double shape, double scale); + * + * DESCRIPTION + * + * The quantile function of the Weibull distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double quantile(double x, double shape, double scale) + { + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(shape) || Double.isNaN(scale)) + return x + shape + scale; + /*!* #endif /*4!*/ + if (shape <= 0 || scale <= 0 || x < 0 || x > 1) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (x == 0) return 0; + /*!* #ifdef IEEE_754 /*4!*/ + if (x == 1) return Double.POSITIVE_INFINITY; + /*!* #endif /*4!*/ +/*!* return scale * pow(-log(1.0 - x), 1.0 / shape); *!*/ + return scale * java.lang.Math.pow(-java.lang.Math.log(1.0 - x), 1.0 / shape); + } + /* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 Ross Ihaka + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * SYNOPSIS + * + * #include "DistLib.h" + * double density(double x, double shape, double scale); + * + * DESCRIPTION + * + * Random variates from the Weibull distribution. + */ + + /*!* #include "DistLib.h" /*4!*/ + + public static double random(double shape, double scale, Uniform uniformDistribution) + { + if ( + /*!* #ifdef IEEE_754 /*4!*/ + Double.isInfinite(shape) || Double.isInfinite(scale) || + /*!* #endif /*4!*/ + shape <= 0.0 || scale <= 0.0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } +/*!* return scale * pow(-log(sunif()), 1.0 / shape); *!*/ + return scale * java.lang.Math.pow(-java.lang.Math.log(uniformDistribution.random()), 1.0 / shape); + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Wilcox.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Wilcox.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/library/statdistlib/Wilcox.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/library/statdistlib/Wilcox.java 2010-05-24 05:44:51.000000000 +0000 @@ -0,0 +1,214 @@ +/* + * DistLib : A C Library of Special Functions + * Copyright (C) 1998 R Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * data translated from C using perl script translate.pl + * script version 0.00 + */ + +package org.mathpiper.builtin.library.statdistlib; + +//import org.apache.commons.logging.Log; +//import org.apache.commons.logging.LogFactory; + +/** + * Wrapper of functions for Wilcoxon distribution. + *

+ * This actually the Mann-Whitney Ux statistic. + */ + +public class Wilcox { + //private static Log log = LogFactory.getLog(Wilcox.class); + + public static final int WILCOX_MMAX = 50; + public static final int WILCOX_NMAX = 50; + + /** + * check values for too large and log complaint + */ + private static boolean checkSizesLarge(final double m, final double n) { + if (m >= WILCOX_MMAX) { + //log.info("m should be less than %d\n"+ WILCOX_MMAX); + return false; + } + if (n >= WILCOX_NMAX) { + //log.info("n should be less than %d\n"+ WILCOX_NMAX); + return false; + } + return true; + } + + /** + * round sizes to integer + */ + private static void roundSizes(double m, double n) { + m = Math.floor(m + 0.5); + n = Math.floor(n + 0.5); + } + + // table of exact cumulative probabilities + static private double w[][][] = new double[WILCOX_MMAX][WILCOX_NMAX][]; + + /** + * The density of the Wilcoxon distribution. + */ + static private double cwilcox(int k, int m, int n) { + int u = m * n; + int c = (int)(u / 2); + + if ((k < 0) || (k > u)) return(0); + if (k > c) k = u - k; + int i = m; + int j = n; + if (m >= n) { + i = n; + j = m; + } + if (w[i][j] == null) { + w[i][j] = new double[c + 1]; + for (int l = 0; l <= c; l++) + w[i][j][l] = -1; + } + if (w[i][j][k] < 0) { + if ((i == 0) || (j == 0)) + w[i][j][k] = (k == 0)?1.0:0.0; + else + w[i][j][k] = cwilcox(k - n, m - 1, n) + cwilcox(k, m, n - 1); + } + return(w[i][j][k]); + } + + /** + * density function + * @param x + * @param m + * @param n + * @return density + */ + public static double density(double x, double m, double n) { + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + if (Double.isNaN(x) || Double.isNaN(m) || Double.isNaN(n)) return x + m + n; + /*!* #endif /*4!*/ + roundSizes(m,n); + if (m <= 0 || n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (!checkSizesLarge(m,n)) return Double.NaN; + + /*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if ((x < 0) || (x > m * n)) + return 0; + /*!* return(cwilcox(x, m, n) / choose(m + n, n)); *!*/ + return(cwilcox((int) x, (int) m, (int) n) / Misc.choose(m + n, n)); + } + + /** + * Cumulative distribution function of the Wilcoxon distribution. + */ + public static double cumulative(double x, double m, double n) { + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(m) || Double.isNaN(n)) + return x + m + n; + if (Double.isInfinite(m) || Double.isInfinite(n)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + roundSizes(m,n); + if (m <= 0 || n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if (!checkSizesLarge(m,n)) return Double.NaN; + /*!* x = floor(x + 0.5); *!*/ + x = java.lang.Math.floor(x + 0.5); + if (x < 0.0) return 0; + if (x >= m * n) return 1; + double p = 0.0; + for (int i = 0; i <= x; i++) + p += density(i, m, n); + return(p); + } + + /** + * The quantile function of the Wilcoxon distribution. + */ + public static double quantile(double x, double m, double n) { + + /*!* #ifdef IEEE_754 /*4!*/ + if (Double.isNaN(x) || Double.isNaN(m) || Double.isNaN(n)) + return x + m + n; + if(Double.isInfinite(x) || Double.isInfinite(m) || Double.isInfinite(n)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + /*!* #endif /*4!*/ + + roundSizes(m,n); + if (x < 0 || x > 1 || m <= 0 || n <= 0) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + }; + if (!checkSizesLarge(m,n)) return Double.NaN; + + if (x == 0) return(0.0); + if (x == 1) return(m * n); + double p = 0.0; + double q = 0.0; + for (;;) { + /* Don't call cumulative() for efficiency */ + p += density(q, m, n); + if (p >= x) + return(q); + q++; + } + } + + /** + * Random variates from the Wilcoxon distribution. + */ + public static double random(double m, double n) { + + /*!* #ifdef IEEE_754 /*4!*/ + /* NaNs propagated correctly */ + if (Double.isNaN(m) || Double.isNaN(n)) return(m + n); + /*!* #endif /*4!*/ + roundSizes(m,n); + if ((m < 0) || (n < 0)) { + throw new java.lang.ArithmeticException("Math Error: DOMAIN"); + // return Double.NaN; + } + if ((m == 0) || (n == 0)) + return(0); + double r = 0.0; + int k = (int) (m + n); + int[] x = new int[k]; + for (int i = 0; i < k; i++) + x[i] = i; + for (int i = 0; i < n; i++) { + /*!* j = floor(k * sunif()); *!*/ + int j = (int) java.lang.Math.floor(k * Uniform.random()); + r += x[j]; + x[j] = x[--k]; + } + return(r - n * (n - 1) / 2); + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/builtin/PatternContainer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/PatternContainer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/builtin/PatternContainer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/builtin/PatternContainer.java 2010-07-18 20:33:50.000000000 +0000 @@ -13,72 +13,58 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.builtin; //import org.mathpiper.parametermatchers.PatternContainer; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.LispError; import org.mathpiper.lisp.Environment; -import org.mathpiper.builtin.ArgumentList; -import org.mathpiper.lisp.parametermatchers.Pattern; - +import org.mathpiper.lisp.parametermatchers.ParametersPatternMatcher; /** - * Allows a org.mathpiper.parametermatchers.Pattern to be placed into a org.mathpiper.lisp.BuiltinObject. + * Allows a org.mathpiper.parametermatchers.ParametersPatternMatcher to be placed into a org.mathpiper.lisp.BuiltinObject. * */ -public class PatternContainer extends BuiltinContainer -{ - protected org.mathpiper.lisp.parametermatchers.Pattern iPatternMatcher; - - public PatternContainer(org.mathpiper.lisp.parametermatchers.Pattern aPatternMatcher) - { - iPatternMatcher = aPatternMatcher; - } +public class PatternContainer extends BuiltinContainer { + + protected ParametersPatternMatcher iPatternMatcher; + - public Pattern getPattern() - { + public PatternContainer(org.mathpiper.lisp.parametermatchers.ParametersPatternMatcher aPatternMatcher) { + iPatternMatcher = aPatternMatcher; + } + + + public ParametersPatternMatcher getPattern() { return iPatternMatcher; } - public boolean matches(Environment aEnvironment, ConsPointer aArguments) throws Exception - { - LispError.lispAssert(iPatternMatcher != null); - boolean result; - result = iPatternMatcher.matches(aEnvironment, aArguments); - return result; - } - - public boolean matches(Environment aEnvironment, ConsPointer[] aArguments) throws Exception - { - LispError.lispAssert(iPatternMatcher != null); - boolean result; - result = iPatternMatcher.matches(aEnvironment, aArguments); - return result; - } - - //From BuiltinContainer - public String send(ArgumentList aArgList) - { - return null; - } - - public JavaObject execute(String methodName, Object[] arguemnts) throws Exception - { - return null; - } - - public String typeName() - { - return "\"Pattern\""; - } - - public Object getObject() - { - return null; + + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer aArguments) throws Exception { + LispError.lispAssert(iPatternMatcher != null, aEnvironment, aStackTop); + boolean result; + result = iPatternMatcher.matches(aEnvironment, aStackTop, aArguments); + return result; + } + + + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer[] aArguments) throws Exception { + LispError.lispAssert(iPatternMatcher != null, aEnvironment, aStackTop); + boolean result; + result = iPatternMatcher.matches(aEnvironment, aStackTop, aArguments); + return result; + } + + //From BuiltinContainer + + public String typeName() { + return "\"Pattern\""; + } + + + public Object getObject() { + return this; } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/exceptions/BreakException.java mathpiper-0.81f+dfsg1/src/org/mathpiper/exceptions/BreakException.java --- mathpiper-0.0.svn2556/src/org/mathpiper/exceptions/BreakException.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/exceptions/BreakException.java 2009-11-01 02:04:48.000000000 +0000 @@ -1,7 +1,4 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ + package org.mathpiper.exceptions; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/exceptions/EvaluationException.java mathpiper-0.81f+dfsg1/src/org/mathpiper/exceptions/EvaluationException.java --- mathpiper-0.0.svn2556/src/org/mathpiper/exceptions/EvaluationException.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/exceptions/EvaluationException.java 2010-12-16 01:32:55.000000000 +0000 @@ -13,25 +13,55 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.exceptions; + public class EvaluationException extends Exception //Note:tk: made this class public so that clients can use this exception. { - private int lineNumber = -1; + private int lineNumber = -1; + private String fileName = null; + private String functionName = null; + private String type = null; + + + public EvaluationException(String message, String fileName, int lineNumber, String functionName) { + this("Unspecified", message, fileName, lineNumber, functionName); + } + + + + public EvaluationException(String type, String message, String fileName, int lineNumber, String functionName) { + super(message); + this.type = type; + this.fileName = fileName; + this.lineNumber = lineNumber; + this.functionName = functionName; + } + + public EvaluationException(String message, String fileName, int lineNumber) { + this( message, fileName, lineNumber, null); + } - public EvaluationException(String message,int lineNumber) - { - super(message); - this.lineNumber = lineNumber; - } - - public int getLineNumber() - { + + public int getLineNumber() { return lineNumber; } - + + + public String getFileName() { + return fileName; + } + + + public String getFunctionName() { + return functionName; + } + + public String getType() { + return type; + } + + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/exceptions/ReturnException.java mathpiper-0.81f+dfsg1/src/org/mathpiper/exceptions/ReturnException.java --- mathpiper-0.0.svn2556/src/org/mathpiper/exceptions/ReturnException.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/exceptions/ReturnException.java 2009-11-01 02:04:48.000000000 +0000 @@ -0,0 +1,8 @@ + + +package org.mathpiper.exceptions; + + +public class ReturnException extends Exception{ + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/AsynchronousInterpreter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/AsynchronousInterpreter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/AsynchronousInterpreter.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/AsynchronousInterpreter.java 2010-03-26 02:13:27.000000000 +0000 @@ -24,6 +24,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.ConsPointer; /** * @@ -85,10 +86,14 @@ return EvaluationResponse.newInstance(); - }//end method. + public synchronized EvaluationResponse evaluate(ConsPointer inputExpressionPointer) { + return interpreter.evaluate(inputExpressionPointer); + } + + public void addResponseListener(ResponseListener listener) { interpreter.addResponseListener(listener); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/EvaluationResponse.java mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/EvaluationResponse.java --- mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/EvaluationResponse.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/EvaluationResponse.java 2010-12-29 04:07:15.000000000 +0000 @@ -5,13 +5,14 @@ package org.mathpiper.interpreters; +import org.mathpiper.lisp.cons.ConsPointer; + /** * This class is used by an {@link Interpreter} to send the results of an evaluation to * client code. */ public class EvaluationResponse { private String result = ""; - private String loadResult = ""; private String sideEffects = ""; private String exceptionMessage = ""; private boolean exceptionThrown = false; @@ -19,6 +20,7 @@ private int lineNumber; private String sourceFileName = ""; private Object object = null; + private ConsPointer resultList = null; private EvaluationResponse() { @@ -111,7 +113,7 @@ */ public void setSideEffects(String sideEffects) { - this.sideEffects = sideEffects.trim(); + this.sideEffects = sideEffects; } /** @@ -168,6 +170,18 @@ return exceptionThrown; } + + /** + * Allows the user to obtain a Java object from a function. + * + * @return a Java object if one is available to return to the user. + */ + public Object getObject() + { + return object; + } + + /** * Sets a Java object to be returned to the user.. * @@ -178,14 +192,27 @@ this.object = object; } + + /** - * Allows the user to obtain a Java object from a function. + * Allows the user to obtain the result list. * * @return a Java object if one is available to return to the user. */ - public Object getObject() - { - return object; + public ConsPointer getResultList() { + return resultList; + } + + + /** + * Sets the result list to be returned to the user.. + * + * @param exception the exception object + */ + public void setResultList(ConsPointer resultList) { + this.resultList = resultList; } + + }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/Interpreter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/Interpreter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/Interpreter.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/Interpreter.java 2010-03-26 02:13:27.000000000 +0000 @@ -17,6 +17,7 @@ package org.mathpiper.interpreters; import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.ConsPointer; /** * Interpreter is implemented by all MathPiper interpreters and it allows client code to evaluate @@ -45,6 +46,15 @@ public EvaluationResponse evaluate(String expression, boolean notifyListeners); /** + * Evaluates a MathPiper expression. The results of the evaluation are returned + * in a {@link EvaluationResponse} object. + * + * @param expressionPointer the list form of a MathPiper expression to be evaluated + * @return an EvaluationResponse object + */ + public EvaluationResponse evaluate(ConsPointer expressionPointer); + + /** * Halts the current evaluation. */ public void haltEvaluation(); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/SynchronousInterpreter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/SynchronousInterpreter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/interpreters/SynchronousInterpreter.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/interpreters/SynchronousInterpreter.java 2011-04-24 07:45:56.000000000 +0000 @@ -34,22 +34,28 @@ import org.mathpiper.io.CachedStandardFileInputStream; import java.io.*; import java.util.ArrayList; +import java.util.List; +import org.mathpiper.builtin.BuiltinContainer; +import org.mathpiper.builtin.BuiltinFunction; import org.mathpiper.builtin.JavaObject; import org.mathpiper.io.StringOutput; import org.mathpiper.lisp.Evaluator; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.SublistCons; /** - * - * + * + * */ class SynchronousInterpreter implements Interpreter { + private ArrayList removeListeners; private ArrayList responseListeners; - - private Environment environment = null; + private Environment iEnvironment = null; MathPiperTokenizer tokenizer = null; LispPrinter printer = null; - //private String iError = null; + //private String iException = null; String defaultDirectory = null; String archive = ""; String detect = ""; @@ -57,20 +63,35 @@ boolean inZipFile = false; MathPiperOutputStream sideEffectsStream; private static SynchronousInterpreter singletonInstance; + private Thread evaluationThread; + private SynchronousInterpreter(String docBase) { - responseListeners = new ArrayList(); + responseListeners = new ArrayList(); removeListeners = new ArrayList(); - + sideEffectsStream = new StringOutput(); + Utility.scriptsPath = "/org/mathpiper/assembledscripts/"; + try { - environment = new Environment(sideEffectsStream); + iEnvironment = new Environment(sideEffectsStream); + + BuiltinFunction.addCoreFunctions(iEnvironment); + + if (!Utility.scriptsPath.contains("geogebra")) { + List failList = BuiltinFunction.addOptionalFunctions(iEnvironment, "org/mathpiper/builtin/functions/optional/"); + } + + iEnvironment.pushLocalFrame(true, ""); + + + tokenizer = new MathPiperTokenizer(); - printer = new MathPiperPrinter(environment.iPrefixOperators, environment.iInfixOperators, environment.iPostfixOperators, environment.iBodiedOperators); + printer = new MathPiperPrinter(iEnvironment.iPrefixOperators, iEnvironment.iInfixOperators, iEnvironment.iPostfixOperators, iEnvironment.iBodiedOperators); - environment.iCurrentInput = new CachedStandardFileInputStream(environment.iInputStatus); + iEnvironment.iCurrentInput = new CachedStandardFileInputStream(iEnvironment.iInputStatus); if (docBase != null) { @@ -107,9 +128,10 @@ //eg docBase = "jar:http://www.geogebra.org/webstart/alpha/geogebra_cas.jar!/"; evaluate("DefaultDirectory(\"" + docBase + "\");"); - } + }//end if. + + }//end if. - } /* java.net.URL detectURL = java.lang.ClassLoader.getSystemResource("initialization.rep/mathpiperinit.mpi"); @@ -147,13 +169,20 @@ }*/ - EvaluationResponse evaluationResponse = evaluate("Load(\"org/mathpiper/assembledscripts/initialization.rep/mathpiperinit.mpi\");"); + EvaluationResponse initializationEvaluationResponse = evaluate("LoadScript(\"initialization.rep/mathpiperinit.mpi\");"); + + if (initializationEvaluationResponse.isExceptionThrown()) { + throw new Exception("Error during system script initialization."); + } + + initializationEvaluationResponse = evaluate("LoadScript(\"/mathpiper_user_initialization.mpi\");"); - if (evaluationResponse.isExceptionThrown()) { - System.out.println(evaluationResponse.getExceptionMessage() + " Source file name: " + evaluationResponse.getSourceFileName() + " Near line number: " + evaluationResponse.getLineNumber()); + if (!initializationEvaluationResponse.isExceptionThrown()) { + System.out.println("The initialization file mathpiper_user_initialization.mpi was evaluated."); } + } catch (Exception e) //Note:tk:need to handle exceptions better here. should return exception to user in an EvaluationResponse. { e.printStackTrace(); @@ -161,18 +190,22 @@ } }//end constructor. + private SynchronousInterpreter() { this(null); } + static SynchronousInterpreter newInstance() { return new SynchronousInterpreter(); } + static SynchronousInterpreter newInstance(String docBase) { return new SynchronousInterpreter(docBase); } + static SynchronousInterpreter getInstance() { if (singletonInstance == null) { singletonInstance = new SynchronousInterpreter(); @@ -180,6 +213,7 @@ return singletonInstance; } + static SynchronousInterpreter getInstance(String docBase) { if (singletonInstance == null) { singletonInstance = new SynchronousInterpreter(docBase); @@ -187,11 +221,23 @@ return singletonInstance; } + public synchronized EvaluationResponse evaluate(String inputExpression) { - return this.evaluate(inputExpression, false); + return this.evaluate(inputExpression, false); }//end method. - + + + /** + Evaluate an input expression which is a string. + + @param inputExpression + @param notifyEvaluationListeners + @return + */ public synchronized EvaluationResponse evaluate(String inputExpression, boolean notifyEvaluationListeners) { + + evaluationThread = Thread.currentThread(); + EvaluationResponse evaluationResponse = EvaluationResponse.newInstance(); if (inputExpression.length() == 0) { //return (String) ""; @@ -200,29 +246,29 @@ } String resultString = ""; try { - environment.iEvalDepth = 0; - - //todo:tk:this was causing problems with GeoGebraPoint() on Windows. + iEnvironment.iEvalDepth = 0; + + //todo:tk:this was causing problems with GeoGebraPoint() on Windows. //environment.resetArgumentStack(); - //iError = null; + //iException = null; ConsPointer inputExpressionPointer = new ConsPointer(); - if (environment.iPrettyReader != null) { + if (iEnvironment.iPrettyReaderName != null) { InputStatus someStatus = new InputStatus(); - StringBuffer inp = new StringBuffer(); + StringBuilder inp = new StringBuilder(); inp.append(inputExpression); - InputStatus oldstatus = environment.iInputStatus; - environment.iInputStatus.setTo("String"); - StringInputStream newInput = new StringInputStream(new StringBuffer(inputExpression), environment.iInputStatus); + InputStatus oldstatus = iEnvironment.iInputStatus; + iEnvironment.iInputStatus.setTo("String"); + StringInputStream newInput = new StringInputStream(new StringBuffer(inputExpression), iEnvironment.iInputStatus); - MathPiperInputStream previous = environment.iCurrentInput; - environment.iCurrentInput = newInput; + MathPiperInputStream previous = iEnvironment.iCurrentInput; + iEnvironment.iCurrentInput = newInput; try { ConsPointer args = new ConsPointer(); - Utility.applyString(environment, inputExpressionPointer, - environment.iPrettyReader, + Utility.applyString(iEnvironment, -1, inputExpressionPointer, + iEnvironment.iPrettyReaderName, args); } catch (Exception exception) { if (exception instanceof EvaluationException) { @@ -234,8 +280,8 @@ evaluationResponse.setExceptionMessage(exception.getMessage()); } finally { - environment.iCurrentInput = previous; - environment.iInputStatus.restoreFrom(oldstatus); + iEnvironment.iCurrentInput = previous; + iEnvironment.iInputStatus.restoreFrom(oldstatus); } } else //Else not PrettyPrinter. { @@ -247,58 +293,106 @@ inp.append(";"); StringInputStream inputExpressionBuffer = new StringInputStream(inp, someStatus); - Parser infixParser = new MathPiperParser(tokenizer, inputExpressionBuffer, environment, environment.iPrefixOperators, environment.iInfixOperators, environment.iPostfixOperators, environment.iBodiedOperators); - infixParser.parse(environment, inputExpressionPointer); + Parser infixParser = new MathPiperParser(tokenizer, inputExpressionBuffer, iEnvironment, iEnvironment.iPrefixOperators, iEnvironment.iInfixOperators, iEnvironment.iPostfixOperators, iEnvironment.iBodiedOperators); + infixParser.parse(-1, inputExpressionPointer); } - ConsPointer result = new ConsPointer(); - environment.iLispExpressionEvaluator.evaluate(environment, result, inputExpressionPointer); //*** The main valuation happens here. + return evaluate(inputExpressionPointer, notifyEvaluationListeners); + + } catch (Exception exception) { + this.handleException(exception, evaluationResponse); + } + + if (notifyEvaluationListeners) { + notifyListeners(evaluationResponse); + }//end if. + + return evaluationResponse; + + }//end method. + + + public synchronized EvaluationResponse evaluate(ConsPointer inputExpressionPointer) { + return evaluate(inputExpressionPointer, false); + } - if (result.type() == Utility.OBJECT) { - JavaObject javaObject = (JavaObject) result.car(); - evaluationResponse.setObject(javaObject.getObject()); + + /** + Evaluate an input expression which is a Lisp list. + + @param inputExpressionPointer + @param notifyEvaluationListeners + @return + */ + public synchronized EvaluationResponse evaluate(ConsPointer inputExpressionPointer, boolean notifyEvaluationListeners) { + + evaluationThread = Thread.currentThread(); + + //return this.evaluate(inputExpression, false); + EvaluationResponse evaluationResponse = EvaluationResponse.newInstance(); + + String resultString = "Exception"; + + try { + ConsPointer resultPointer = new ConsPointer(); + iEnvironment.iLispExpressionEvaluator.evaluate(iEnvironment, -1, resultPointer, inputExpressionPointer); //*** The main evaluation happens here. + + evaluationResponse.setResultList(resultPointer); + + if (resultPointer.type() == Utility.OBJECT) { + + Object object = resultPointer.car(); + + if (object instanceof BuiltinContainer) { + BuiltinContainer builtinContainer = (BuiltinContainer) object; + evaluationResponse.setObject(builtinContainer.getObject()); + } else { + evaluationResponse.setObject(object); + } }//end if. - String percent = (String) environment.getTokenHash().lookUp("%"); - environment.setGlobalVariable(percent, result, true); + //Set the % symbol to the result of the current evaluation. + String percent = (String) iEnvironment.getTokenHash().lookUp("%"); + iEnvironment.setGlobalVariable(-1, percent, resultPointer, true); + + StringBuffer outputBuffer = new StringBuffer(); + MathPiperOutputStream outputStream = new StringOutputStream(outputBuffer); - StringBuffer string_out = new StringBuffer(); - MathPiperOutputStream output = new StringOutputStream(string_out); + if (iEnvironment.iPrettyPrinterName != null) { + //Pretty printer. + + ConsPointer applyResultPointer = new ConsPointer(); + + if (iEnvironment.iPrettyPrinterName.equals("\"RForm\"")) { + Cons holdAtom = AtomCons.getInstance(iEnvironment, -1, "Hold"); + + holdAtom.cdr().setCons(resultPointer.getCons()); + + Cons subListCons = SublistCons.getInstance(iEnvironment, holdAtom); + + ConsPointer resultPointerWithHold = new ConsPointer(subListCons); + + Utility.applyString(iEnvironment, -1, applyResultPointer, iEnvironment.iPrettyPrinterName, resultPointerWithHold); + } else { + Utility.applyString(iEnvironment, -1, applyResultPointer, iEnvironment.iPrettyPrinterName, resultPointer); + } + + printer.rememberLastChar(' '); + printer.print(-1, applyResultPointer, outputStream, iEnvironment); + resultString = outputBuffer.toString(); - if (environment.iPrettyPrinter != null) { - ConsPointer nonresult = new ConsPointer(); - Utility.applyString(environment, nonresult, environment.iPrettyPrinter, result); - resultString = string_out.toString(); } else { + //Default printer. printer.rememberLastChar(' '); - printer.print(result, output, environment); - resultString = string_out.toString(); + printer.print(-1, resultPointer, outputStream, iEnvironment); + resultString = outputBuffer.toString(); } - } catch (Exception exception) { - //Uncomment this for debugging(); - //exception.printStackTrace(); - Evaluator.DEBUG = false; - Evaluator.VERBOSE_DEBUG = false; - Evaluator.TRACE_TO_STANDARD_OUT = false; - Evaluator.iTraced = false; - - if (exception instanceof EvaluationException) { - EvaluationException mpe = (EvaluationException) exception; - int errorLineNumber = mpe.getLineNumber(); - if (errorLineNumber == -1) { - errorLineNumber = environment.iInputStatus.lineNumber(); - if (errorLineNumber == -1) { - errorLineNumber = 1; //Code was probably a single line submitted from the command line or from a single line evaluation request. - } - } - evaluationResponse.setLineNumber(errorLineNumber); - evaluationResponse.setSourceFileName(environment.iInputStatus.fileName()); - } - evaluationResponse.setException(exception); - evaluationResponse.setExceptionMessage(exception.getMessage()); - } + + } catch (Exception exception) { + this.handleException(exception, evaluationResponse); + }//end catch. evaluationResponse.setResult(resultString); @@ -309,50 +403,108 @@ evaluationResponse.setSideEffects(sideEffects); } + /*try{ + org.mathpiper.builtin.functions.optional.ViewList.evaluate(iEnvironment, -1, inputExpressionPointer); + }catch(Exception e) + { + e.printStackTrace(); + }*/ + try { - if (inputExpression.trim().startsWith("Load")) { - ConsPointer loadResult = new ConsPointer(); - environment.getGlobalVariable("LoadResult", loadResult); - StringBuffer string_out = new StringBuffer(); - MathPiperOutputStream output = new StringOutputStream(string_out); - printer.rememberLastChar(' '); - printer.print(loadResult, output, environment); - String loadResultString = string_out.toString(); - //GlobalVariable loadResultVariable = (GlobalVariable) environment.iGlobalState.lookUp("LoadResult"); - evaluationResponse.setResult(loadResultString); - //environment.iGlobalState.release("LoadResult"); - if (loadResult.type() == Utility.OBJECT) { - JavaObject javaObject = (JavaObject) loadResult.car(); - evaluationResponse.setObject(javaObject.getObject()); - }//end if. - } + if (inputExpressionPointer.getCons() instanceof SublistCons) { + + Object object = ((ConsPointer) inputExpressionPointer.getCons().car()).car(); + + if (object instanceof String && ((String) object).startsWith("Load")) { + ConsPointer loadResult = new ConsPointer(); + iEnvironment.getGlobalVariable(-1, "$LoadResult", loadResult); + StringBuffer string_out = new StringBuffer(); + MathPiperOutputStream output = new StringOutputStream(string_out); + printer.rememberLastChar(' '); + printer.print(-1, loadResult, output, iEnvironment); + String loadResultString = string_out.toString(); + evaluationResponse.setResult(loadResultString); + if (loadResult.type() == Utility.OBJECT) { + JavaObject javaObject = (JavaObject) loadResult.car(); + evaluationResponse.setObject(javaObject.getObject()); + }//end if. + }//if. + }//end if } catch (Exception e) { evaluationResponse.setExceptionMessage(e.getMessage()); evaluationResponse.setException(e); } - - if(notifyEvaluationListeners) - { - notifyListeners(evaluationResponse); - }//end if. + + if (notifyEvaluationListeners) { + notifyListeners(evaluationResponse); + }//end if. return evaluationResponse; } + + private void handleException(Exception exception, EvaluationResponse evaluationResponse) { + //exception.printStackTrace(); //todo:tk:uncomment for debugging. + + Evaluator.DEBUG = false; + Evaluator.VERBOSE_DEBUG = false; + Evaluator.TRACE_TO_STANDARD_OUT = false; + Evaluator.iTraced = false; + + try { + iEnvironment.iArgumentStack.reset(-1, iEnvironment); + } catch (Exception e) { + e.printStackTrace(); + } + + if (exception instanceof EvaluationException) { + EvaluationException mpe = (EvaluationException) exception; + int errorLineNumber = mpe.getLineNumber(); + if (errorLineNumber == -1) { + errorLineNumber = iEnvironment.iInputStatus.lineNumber(); + if (errorLineNumber == -1) { + errorLineNumber = 1; //Code was probably a single line submitted from the command line or from a single line evaluation request. + } + evaluationResponse.setLineNumber(errorLineNumber); + evaluationResponse.setSourceFileName(iEnvironment.iInputStatus.fileName()); + } else { + evaluationResponse.setLineNumber(mpe.getLineNumber()); + evaluationResponse.setSourceFileName(mpe.getFileName()); + } + + + } else { + int errorLineNumber = iEnvironment.iInputStatus.lineNumber(); + if (errorLineNumber == -1) { + errorLineNumber = 1; //Code was probably a single line submitted from the command line or from a single line evaluation request. + } + evaluationResponse.setLineNumber(errorLineNumber); + evaluationResponse.setSourceFileName(iEnvironment.iInputStatus.fileName()); + } + + evaluationResponse.setException(exception); + evaluationResponse.setExceptionMessage(exception.getMessage()); + } + + public void haltEvaluation() { - synchronized (environment) { - environment.iEvalDepth = environment.iMaxEvalDepth + 100; + synchronized (iEnvironment) { + //iEnvironment.iEvalDepth = iEnvironment.iMaxEvalDepth + 100; //Deprecated. + + evaluationThread.interrupt(); } } + public Environment getEnvironment() { - return environment; + return iEnvironment; } /*public java.util.zip.ZipFile getScriptsZip() { return Utility.zipFile; }//end method.*/ + public void addScriptsDirectory(String directory) { String toEvaluate = "DefaultDirectory(\"" + directory + File.separator + "\");"; @@ -360,35 +512,32 @@ }//addScriptsDirectory. + public void addResponseListener(ResponseListener listener) { - responseListeners.add(listener); + responseListeners.add(listener); } + public void removeResponseListener(ResponseListener listener) { - responseListeners.remove(listener); + responseListeners.remove(listener); } - - - protected void notifyListeners(EvaluationResponse response) - { + + + protected void notifyListeners(EvaluationResponse response) { //notify listeners. - for (ResponseListener listener : responseListeners) - { + for (ResponseListener listener : responseListeners) { listener.response(response); - if (listener.remove()) - { + if (listener.remove()) { removeListeners.add(listener); }//end if. }//end for. //Remove certain listeners. - for (ResponseListener listener : removeListeners) - { + for (ResponseListener listener : removeListeners) { - if (listener.remove()) - { + if (listener.remove()) { responseListeners.remove(listener); }//end if. }//end for. @@ -396,6 +545,5 @@ removeListeners.clear(); }//end method. - }// end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/io/CachedStandardFileInputStream.java mathpiper-0.81f+dfsg1/src/org/mathpiper/io/CachedStandardFileInputStream.java --- mathpiper-0.0.svn2556/src/org/mathpiper/io/CachedStandardFileInputStream.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/io/CachedStandardFileInputStream.java 2010-12-29 04:07:15.000000000 +0000 @@ -18,11 +18,6 @@ package org.mathpiper.io; - - -import org.mathpiper.io.MathPiperInputStream; -import java.io.*; - /** CachedStandardFileInputStream : input from stdin */ public class CachedStandardFileInputStream extends MathPiperInputStream { diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/io/JarFileInputStream.java mathpiper-0.81f+dfsg1/src/org/mathpiper/io/JarFileInputStream.java --- mathpiper-0.0.svn2556/src/org/mathpiper/io/JarFileInputStream.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/io/JarFileInputStream.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,32 +13,28 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.io; - import java.io.InputStreamReader; -import org.mathpiper.io.StringInputStream; import java.net.*; -public class JarFileInputStream extends StringInputStream -{ - public JarFileInputStream(String aFileName, InputStatus aStatus) throws Exception - { - super(new StringBuffer(),aStatus); - URL url = new URL(aFileName); - JarURLConnection con = (JarURLConnection) url.openConnection(); - InputStreamReader stream = new InputStreamReader(con.getInputStream()); - int c; - while (true) - { - c = stream.read(); - if (c == -1) - break; - iString.append((char)c); - } - } +public class JarFileInputStream extends StringInputStream { + + public JarFileInputStream(String aFileName, InputStatus aStatus) throws Exception { + super(new StringBuffer(), aStatus); + URL url = new URL(aFileName); + JarURLConnection con = (JarURLConnection) url.openConnection(); + InputStreamReader stream = new InputStreamReader(con.getInputStream()); + int c; + while (true) { + c = stream.read(); + if (c == -1) { + break; + } + iString.append((char) c); + } + } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/io/StandardFileInputStream.java mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StandardFileInputStream.java --- mathpiper-0.0.svn2556/src/org/mathpiper/io/StandardFileInputStream.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StandardFileInputStream.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,61 +13,55 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - //}}} // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.io; import java.io.InputStreamReader; +public class StandardFileInputStream + extends StringInputStream { + // private static String path; + //static void setPath(String aPath) + //{ + // path = aPath; + //} + + public StandardFileInputStream(String aFileName, InputStatus aStatus) + throws Exception { + super(new StringBuffer(), aStatus); + //System.out.println("YYYYYY " + aFileName);//Note:tk: remove. + InputStreamReader stream = new InputStreamReader(new java.io.FileInputStream(aFileName)); + int c; + + while (true) { + c = stream.read(); + + if (c == -1) { + break; + } + + iString.append((char) c); + } + } + + + public StandardFileInputStream(java.io.InputStreamReader aStream, InputStatus aStatus) + throws Exception { + super(new StringBuffer(), aStatus); + + int c; + + while (true) { + c = aStream.read(); + + if (c == -1) { + break; + } + + iString.append((char) c); + } + } -public class StandardFileInputStream - extends StringInputStream -{ - // private static String path; - //static void setPath(String aPath) - //{ - // path = aPath; - //} - - public StandardFileInputStream(String aFileName, InputStatus aStatus) - throws Exception - { - super(new StringBuffer(), aStatus); - - //System.out.println("YYYYYY " + aFileName);//Note:tk: remove. - InputStreamReader stream = new InputStreamReader(new java.io.FileInputStream(aFileName)); - int c; - - while (true) - { - c = stream.read(); - - if (c == -1) - - break; - - iString.append((char)c); - } - } - - public StandardFileInputStream(java.io.InputStreamReader aStream, InputStatus aStatus) - throws Exception - { - super(new StringBuffer(), aStatus); - - int c; - - while (true) - { - c = aStream.read(); - - if (c == -1) - - break; - - iString.append((char)c); - } - } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/io/StringInputStream.java mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StringInputStream.java --- mathpiper-0.0.svn2556/src/org/mathpiper/io/StringInputStream.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StringInputStream.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,77 +13,74 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - //}}} // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.io; +public class StringInputStream + extends MathPiperInputStream { + + int iCurrent; + StringBuffer iString; -import org.mathpiper.io.MathPiperInputStream; -public class StringInputStream - extends MathPiperInputStream -{ + public StringInputStream(StringBuffer aString, InputStatus aStatus) { + super(aStatus); + iString = aString; + iCurrent = 0; + } + + + public char next() + throws Exception { + + if (iCurrent == iString.length()) { + return '\0'; + } - int iCurrent; - StringBuffer iString; + iCurrent++; - public StringInputStream(StringBuffer aString, InputStatus aStatus) - { - super(aStatus); - iString = aString; - iCurrent = 0; - } + char c = iString.charAt(iCurrent - 1); - public char next() - throws Exception - { + if (c == '\n') { + iStatus.nextLine(); + } - if (iCurrent == iString.length()) + return c; + } - return '\0'; - iCurrent++; + public char peek() + throws Exception { - char c = iString.charAt(iCurrent - 1); + if (iCurrent == iString.length()) { + return '\0'; + } - if (c == '\n') - iStatus.nextLine(); + return iString.charAt(iCurrent); + } - return c; - } - public char peek() - throws Exception - { + public boolean endOfStream() { - if (iCurrent == iString.length()) + return (iCurrent == iString.length()); + } - return '\0'; - return iString.charAt(iCurrent); - } + public StringBuffer startPtr() { - public boolean endOfStream() - { + return iString; + } - return (iCurrent == iString.length()); - } - public StringBuffer startPtr() - { + public int position() { - return iString; - } + return iCurrent; + } - public int position() - { - return iCurrent; - } + public void setPosition(int aPosition) { + iCurrent = aPosition; + } - public void setPosition(int aPosition) - { - iCurrent = aPosition; - } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/io/StringOutput.java mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StringOutput.java --- mathpiper-0.0.svn2556/src/org/mathpiper/io/StringOutput.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StringOutput.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,52 +13,46 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - //}}} // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.io; -public class StringOutput implements MathPiperOutputStream -{ - StringBuffer stringBuffer; - - public StringOutput() - { - this.stringBuffer = new java.lang.StringBuffer(); - } - - public void putChar(char aChar) - { - this.stringBuffer.append(aChar); - } - - - /*public void setStringBuffer(StringBuffer stringBuffer) - { - this.stringBuffer = stringBuffer; - }//end method.*/ - - - public String toString() - { - if(this.stringBuffer.length() != 0) - { - String outputMessage = this.stringBuffer.toString(); - this.clear(); - return outputMessage; - } - else - { - return null; - }//end else. - - - }//end method. - - public void clear() - { - this.stringBuffer.delete(0, this.stringBuffer.length()); - } +public class StringOutput implements MathPiperOutputStream { + + StringBuffer stringBuffer; + + + public StringOutput() { + this.stringBuffer = new java.lang.StringBuffer(); + } + + + public void putChar(char aChar) { + this.stringBuffer.append(aChar); + } + + + /*public void setStringBuffer(StringBuffer stringBuffer) + { + this.stringBuffer = stringBuffer; + }//end method.*/ + public String toString() { + if (this.stringBuffer.length() != 0) { + String outputMessage = this.stringBuffer.toString(); + this.clear(); + return outputMessage; + } else { + return null; + }//end else. + + + }//end method. + + + public void clear() { + this.stringBuffer.delete(0, this.stringBuffer.length()); + } + public void write(String aString) throws Exception { int i; @@ -66,5 +60,5 @@ putChar(aString.charAt(i)); } } - -}//end class. \ No newline at end of file + +}//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/io/StringOutputStream.java mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StringOutputStream.java --- mathpiper-0.0.svn2556/src/org/mathpiper/io/StringOutputStream.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/io/StringOutputStream.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,27 +13,24 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - //}}} // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.io; -import org.mathpiper.io.MathPiperOutputStream; +public class StringOutputStream implements MathPiperOutputStream { + + StringBuffer iString; -public class StringOutputStream implements MathPiperOutputStream -{ - StringBuffer iString; + public StringOutputStream(StringBuffer aString) { + iString = aString; + } + + + public void putChar(char aChar) { + iString.append(aChar); + } - public StringOutputStream(StringBuffer aString) - { - iString = aString; - } - - public void putChar(char aChar) - { - iString.append(aChar); - } public void write(String aString) throws Exception { int i; @@ -41,4 +38,5 @@ putChar(aString.charAt(i)); } } + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/license.txt mathpiper-0.81f+dfsg1/src/org/mathpiper/license.txt --- mathpiper-0.0.svn2556/src/org/mathpiper/license.txt 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/license.txt 2011-03-24 18:52:52.000000000 +0000 @@ -0,0 +1,4 @@ +MathPiper 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. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/behaviours/BackQuoteSubstitute.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/behaviours/BackQuoteSubstitute.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/behaviours/BackQuoteSubstitute.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/behaviours/BackQuoteSubstitute.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,9 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.behaviours; import org.mathpiper.lisp.cons.Cons; @@ -32,60 +30,65 @@ * head of function if a is a function. For instance, if * a is f(x) and f is g, then f(x) gets replaced by g(x) */ -public class BackQuoteSubstitute implements Substitute -{ - Environment iEnvironment; - - public BackQuoteSubstitute(Environment aEnvironment) - { - iEnvironment = aEnvironment; - } - public boolean matches(Environment aEnvironment,ConsPointer aResult, ConsPointer aElement) throws Exception - { - if (! (aElement.car() instanceof ConsPointer)) return false; - - Cons ptr = ((ConsPointer) aElement.car()).getCons(); - if (ptr == null) return false; - - if (!( ptr.car() instanceof String)) return false; - - if (ptr.car().equals("`")) - { - aResult.setCons(aElement.getCons()); - return true; - } - - if (!ptr.car().equals("@")) - return false; - - ptr = ptr.cdr().getCons(); - - if (ptr == null) - return false; - - if (ptr.car() instanceof String) - { - ConsPointer cur = new ConsPointer(); - cur.setCons(ptr); - iEnvironment.iLispExpressionEvaluator.evaluate(iEnvironment, aResult, cur); - return true; - } - else - { - ptr = ((ConsPointer) ptr.car()).getCons(); - ConsPointer cur = new ConsPointer(); - cur.setCons(ptr); - ConsPointer args = new ConsPointer(); - args.setCons(ptr.cdr().getCons()); - ConsPointer result = new ConsPointer(); - iEnvironment.iLispExpressionEvaluator.evaluate(iEnvironment, result, cur); - result.cdr().setCons(args.getCons()); - ConsPointer result2 = new ConsPointer(); - result2.setCons(SublistCons.getInstance(aEnvironment,result.getCons())); - Utility.substitute(aEnvironment, aResult,result2, this); - return true; - } - // return false; - } +public class BackQuoteSubstitute implements Substitute { + + Environment iEnvironment; + + + public BackQuoteSubstitute(Environment aEnvironment) { + iEnvironment = aEnvironment; + } + + + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aElement) throws Exception { + if (!(aElement.car() instanceof ConsPointer)) { + return false; + } + + Cons ptr = ((ConsPointer) aElement.car()).getCons(); + if (ptr == null) { + return false; + } + + if (!(ptr.car() instanceof String)) { + return false; + } + + if (ptr.car().equals("`")) { + aResult.setCons(aElement.getCons()); + return true; + } + + if (!ptr.car().equals("@")) { + return false; + } + + ptr = ptr.cdr().getCons(); + + if (ptr == null) { + return false; + } + + if (ptr.car() instanceof String) { + ConsPointer cur = new ConsPointer(); + cur.setCons(ptr); + iEnvironment.iLispExpressionEvaluator.evaluate(iEnvironment, aStackTop, aResult, cur); + return true; + } else { + ptr = ((ConsPointer) ptr.car()).getCons(); + ConsPointer cur = new ConsPointer(); + cur.setCons(ptr); + ConsPointer args = new ConsPointer(); + args.setCons(ptr.cdr().getCons()); + ConsPointer result = new ConsPointer(); + iEnvironment.iLispExpressionEvaluator.evaluate(iEnvironment, aStackTop, result, cur); + result.cdr().setCons(args.getCons()); + ConsPointer result2 = new ConsPointer(); + result2.setCons(SublistCons.getInstance(aEnvironment, result.getCons())); + Utility.substitute(aEnvironment, aStackTop, aResult, result2, this); + return true; + } + // return false; + } }; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/behaviours/ExpressionSubstitute.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/behaviours/ExpressionSubstitute.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/behaviours/ExpressionSubstitute.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/behaviours/ExpressionSubstitute.java 2010-12-29 04:07:15.000000000 +0000 @@ -4,36 +4,34 @@ import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.Environment; - /** Substing one expression for another. The simplest form * of substitution */ public class ExpressionSubstitute - implements Substitute -{ + implements Substitute { + + Environment iEnvironment; + ConsPointer iToMatch; + ConsPointer iToReplaceWith; + + + public ExpressionSubstitute(Environment aEnvironment, ConsPointer aToMatch, ConsPointer aToReplaceWith) { + iEnvironment = aEnvironment; + iToMatch = aToMatch; + iToReplaceWith = aToReplaceWith; + } + + + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aElement) + throws Exception { + + if (Utility.equals(iEnvironment, aStackTop, aElement, iToMatch)) { + aResult.setCons(iToReplaceWith.getCons().copy(aEnvironment, false)); - Environment iEnvironment; - ConsPointer iToMatch; - ConsPointer iToReplaceWith; - - public ExpressionSubstitute(Environment aEnvironment, ConsPointer aToMatch, ConsPointer aToReplaceWith) - { - iEnvironment = aEnvironment; - iToMatch = aToMatch; - iToReplaceWith = aToReplaceWith; - } - - public boolean matches(Environment aEnvironment,ConsPointer aResult, ConsPointer aElement) - throws Exception - { - - if (Utility.equals(iEnvironment, aElement, iToMatch)) - { - aResult.setCons(iToReplaceWith.getCons().copy( aEnvironment, false)); + return true; + } - return true; - } + return false; + } - return false; - } }; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/behaviours/LocalSymbolSubstitute.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/behaviours/LocalSymbolSubstitute.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/behaviours/LocalSymbolSubstitute.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/behaviours/LocalSymbolSubstitute.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,9 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.behaviours; import org.mathpiper.lisp.cons.ConsPointer; @@ -25,42 +23,40 @@ /** Substitute behaviour for changing the local variables to have unique * names. */ -public class LocalSymbolSubstitute implements Substitute -{ - Environment iEnvironment; - String[] iOriginalNames; - String[] iNewNames; - int iNumberOfNames; - - public LocalSymbolSubstitute(Environment aEnvironment, - String[] aOriginalNames, - String[] aNewNames, int aNrNames) - { - iEnvironment = aEnvironment; - iOriginalNames = aOriginalNames; - iNewNames = aNewNames; - iNumberOfNames = aNrNames; - } - public boolean matches(Environment aEnvironment,ConsPointer aResult, ConsPointer aElement) throws Exception - { - - if (!(aElement.car() instanceof String)) - { - return false; +public class LocalSymbolSubstitute implements Substitute { + + Environment iEnvironment; + String[] iOriginalNames; + String[] iNewNames; + int iNumberOfNames; + + + public LocalSymbolSubstitute(Environment aEnvironment, + String[] aOriginalNames, + String[] aNewNames, int aNrNames) { + iEnvironment = aEnvironment; + iOriginalNames = aOriginalNames; + iNewNames = aNewNames; + iNumberOfNames = aNrNames; + } + + + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aElement) throws Exception { + + if (!(aElement.car() instanceof String)) { + return false; }//end if. String name = (String) aElement.car(); - int i; - for (i=0;i +public class DefFileMap extends MathPiperMap // { public DefFile getFile(String aFileName) { diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/Map.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/Map.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/Map.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/Map.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.lisp.collections; - -import java.util.Collections; - -/** Map allows you to associate arbitrary - * information with a string in the above hash table. You can - * specify what type of information to link to the string, and - * this class then stores that information for a string. It is - * in a sense a way to extend the string object without modifying - * the string class itself. This class does not own the strings it - * points to, but instead relies on the fact that the strings - * are maintained in a hash table (like LispHashTable above). - */ -public class Map -{ - //java.util.Hashtable iMap = new java.util.Hashtable(); - java.util.Map iMap = Collections.synchronizedMap(new java.util.HashMap()); - - /** - * Find the data associated to \a aString. - * If \a aString is not stored in the hash table, this function - * returns #NULL. - * - * @param aString - * @return the object which is associated with the key or null if there is - * no object associated with the key. - */ - public Object lookUp(String aString) - { - //if (iMap.containsKey(aString)) - // return iMap.get(aString); - //return null; - return iMap.get(aString); - } - - /** - * Add an association to the hash table. - * If aString is already stored in the hash table, its - * association is changed to aData. Otherwise, a new - * association is added. - * - * @param aData - * @param aString - */ - public void setAssociation(Object aData, String aString) - { - //if (iMap.containsKey(aString)) - // iMap.remove(aString); - - iMap.put(aString, aData); - } - - - /** - * Delete an association from the hash table. - * - * @param aString - */ - public void release(String aString) - { - //if (iMap.containsKey(aString)) - //iMap.remove(aString); - iMap.remove(aString); - } - - public Object getMap() - { - return iMap; - } -} - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/MathPiperMap.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/MathPiperMap.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/MathPiperMap.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/MathPiperMap.java 2010-01-31 23:00:37.000000000 +0000 @@ -0,0 +1,89 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.collections; + +import java.util.Collections; + +/** MathPiperMap allows you to associate arbitrary + * information with a string in the above hash table. You can + * specify what type of information to link to the string, and + * this class then stores that information for a string. It is + * in a sense a way to extend the string object without modifying + * the string class itself. This class does not own the strings it + * points to, but instead relies on the fact that the strings + * are maintained in a hash table (like LispHashTable above). + */ +public class MathPiperMap +{ + //java.util.Hashtable iMap = new java.util.Hashtable(); + java.util.Map iMap = Collections.synchronizedMap(new java.util.HashMap()); + + /** + * Find the data associated to \a aString. + * If \a aString is not stored in the hash table, this function + * returns #NULL. + * + * @param aString + * @return the object which is associated with the key or null if there is + * no object associated with the key. + */ + public Object lookUp(String aString) + { + //if (iMap.containsKey(aString)) + // return iMap.get(aString); + //return null; + return iMap.get(aString); + } + + /** + * Add an association to the hash table. + * If aString is already stored in the hash table, its + * association is changed to aData. Otherwise, a new + * association is added. + * + * @param aData + * @param aString + */ + public void setAssociation(Object aData, String aString) + { + //if (iMap.containsKey(aString)) + // iMap.remove(aString); + + iMap.put(aString, aData); + } + + + /** + * Delete an association from the hash table. + * + * @param aString + */ + public void release(String aString) + { + //if (iMap.containsKey(aString)) + //iMap.remove(aString); + iMap.remove(aString); + } + + + public java.util.Map getMap() + { + return iMap; + } +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/OperatorMap.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/OperatorMap.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/OperatorMap.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/OperatorMap.java 2010-02-05 10:28:57.000000000 +0000 @@ -21,33 +21,39 @@ import org.mathpiper.lisp.*; -public class OperatorMap extends Map // +public class OperatorMap extends MathPiperMap // { - + Environment iEnvironment; + + public OperatorMap(Environment aEnvironment) + { + iEnvironment = aEnvironment; + } + public void setOperator(int aPrecedence,String aString) { - InfixOperator op = new InfixOperator(aPrecedence); + Operator op = new Operator(aPrecedence); setAssociation(op, aString); } - public void setRightAssociative(String aString) throws Exception + public void setRightAssociative(int aStackTop, String aString) throws Exception { - InfixOperator op = (InfixOperator)lookUp(aString); - LispError.check(op != null,LispError.NOT_AN_INFIX_OPERATOR); + Operator op = (Operator)lookUp(aString); + LispError.check(iEnvironment, aStackTop, op != null,LispError.NOT_AN_INFIX_OPERATOR, "INTERNAL"); op.setRightAssociative(); } - public void setLeftPrecedence(String aString,int aPrecedence) throws Exception + public void setLeftPrecedence(int aStackTop, String aString,int aPrecedence) throws Exception { - InfixOperator op = (InfixOperator)lookUp(aString); - LispError.check(op != null,LispError.NOT_AN_INFIX_OPERATOR); + Operator op = (Operator)lookUp(aString); + LispError.check(iEnvironment, aStackTop, op != null,LispError.NOT_AN_INFIX_OPERATOR, "INTERNAL"); op.setLeftPrecedence(aPrecedence); } - public void setRightPrecedence(String aString,int aPrecedence) throws Exception + public void setRightPrecedence(int aStackTop, String aString,int aPrecedence) throws Exception { - InfixOperator op = (InfixOperator)lookUp(aString); - LispError.check(op != null,LispError.NOT_AN_INFIX_OPERATOR); + Operator op = (Operator)lookUp(aString); + LispError.check(iEnvironment, aStackTop, op != null,LispError.NOT_AN_INFIX_OPERATOR, "INTERNAL"); op.setRightPrecedence(aPrecedence); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/TokenMap.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/TokenMap.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/collections/TokenMap.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/collections/TokenMap.java 2010-01-31 23:00:37.000000000 +0000 @@ -17,7 +17,7 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp.collections; -public class TokenMap extends Map +public class TokenMap extends MathPiperMap { // java.util.Hashtable iMap = new java.util.Hashtable(); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/AtomCons.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/AtomCons.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/AtomCons.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/AtomCons.java 2010-12-29 05:45:51.000000000 +0000 @@ -18,35 +18,36 @@ package org.mathpiper.lisp.cons; import org.mathpiper.lisp.*; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.Cons; public class AtomCons extends Cons { private String iCar; - ConsPointer iCdr = new ConsPointer(); + ConsPointer iCdr; - private AtomCons(Environment aEnvironment,String aString) throws Exception + public AtomCons(String aString) throws Exception { - super(aEnvironment); + //Make sure to use aEnvironment.getTokenHash().lookUp(aString) with aString before calling this constructor. + + super(); iCar = aString; + iCdr = new ConsPointer(); } - public static Cons getInstance(Environment aEnvironment, String aString) throws Exception + public static Cons getInstance(Environment aEnvironment, int aStackTop, String aString) throws Exception { Cons self = null; if (Utility.isNumber(aString, true)) // check if aString is a number (int or float) { /// construct a number from a decimal string representation (also create a number object) - self = new NumberCons(aEnvironment, aString, aEnvironment.getPrecision()); + self = new NumberCons(aString, aEnvironment.getPrecision()); } else { - self = new AtomCons(aEnvironment,(String)aEnvironment.getTokenHash().lookUp(aString)); + self = new AtomCons((String)aEnvironment.getTokenHash().lookUp(aString)); } - LispError.check(self != null, LispError.NOT_ENOUGH_MEMORY); + LispError.check(aEnvironment, aStackTop, self != null, LispError.NOT_ENOUGH_MEMORY, "INTERNAL"); return self; } @@ -62,9 +63,9 @@ return car(); }*/ - public Cons copy( Environment aEnvironment, boolean aRecursed) throws Exception + public Cons copy( Environment aEnvironment, boolean aRecursed) throws Exception { - Cons atomCons = new AtomCons(aEnvironment, iCar); + Cons atomCons = new AtomCons(iCar); atomCons.setMetadataMap(this.getMetadataMap()); @@ -77,6 +78,7 @@ return iCdr; } + @Override public String toString() { return iCar; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/BuiltinObjectCons.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/BuiltinObjectCons.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/BuiltinObjectCons.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/BuiltinObjectCons.java 2010-12-29 04:07:15.000000000 +0000 @@ -18,21 +18,25 @@ import org.mathpiper.lisp.*; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.Cons; import org.mathpiper.builtin.BuiltinContainer; public class BuiltinObjectCons extends Cons { BuiltinContainer iCarBuiltin; - ConsPointer iCdr = new ConsPointer(); + ConsPointer iCdr; - public static BuiltinObjectCons getInstance(Environment aEnvironment,BuiltinContainer aClass) throws Exception { - LispError.lispAssert(aClass != null); + private BuiltinObjectCons(Environment aEnvironment, BuiltinContainer aClass) throws Exception { + super(); + iCarBuiltin = aClass; + iCdr = new ConsPointer(); + } + + public static BuiltinObjectCons getInstance(Environment aEnvironment, int aStackTop, BuiltinContainer aClass) throws Exception { + LispError.lispAssert(aClass != null, aEnvironment, aStackTop); BuiltinObjectCons self = new BuiltinObjectCons(aEnvironment, aClass); - LispError.check(self != null, LispError.NOT_ENOUGH_MEMORY); + LispError.check(aEnvironment, aStackTop, self != null, LispError.NOT_ENOUGH_MEMORY, "INTERNAL"); return self; } @@ -53,11 +57,6 @@ } - BuiltinObjectCons(Environment aEnvironment, BuiltinContainer aClass) throws Exception { - super(aEnvironment); - iCarBuiltin = aClass; - } - public ConsPointer cdr() { return iCdr; @@ -67,4 +66,12 @@ public int type() { return Utility.OBJECT; }//end method. + + + @Override + public String toString() + { + return "JavaObject: " + this.iCarBuiltin.getObject().toString(); + }//end method. + }; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/Cons.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/Cons.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/Cons.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/Cons.java 2010-02-06 21:01:49.000000000 +0000 @@ -35,14 +35,12 @@ protected Map metadataMap; - - public Cons(Environment aEnvironment) throws Exception + public Cons() throws Exception { metadataMap = null; //aEnvironment.iEmptyAtom; }//end constructor. - public abstract ConsPointer cdr(); public abstract Object car() throws Exception; @@ -54,7 +52,7 @@ /** * If this is a number, return a BigNumber representation of it. */ - public Object getNumber(int aPrecision) throws Exception { + public Object getNumber(int aPrecision, Environment aEnvironment) throws Exception { return null; } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/ConsPointerArray.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/ConsPointerArray.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/ConsPointerArray.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/ConsPointerArray.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,67 +13,58 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.cons; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.Cons; - +import org.mathpiper.lisp.Environment; /** * Similar to ConsPointer, but implements an array of pointers to CONS. * */ -public class ConsPointerArray -{ - int iSize; - ConsPointer iArray[]; - - public ConsPointerArray(int aSize,Cons aInitialItem) - { - iArray = new ConsPointer[aSize]; - iSize = aSize; - int i; - for(i=0;i0 && last > 0 && first < iSize-1 && last < iSize-1) - { - ConsPointer[] arguments = new ConsPointer[last-first]; +public class ConsPointerArray { + + int iSize; + ConsPointer iArray[]; + + + public ConsPointerArray(Environment aEnvironment, int aSize, Cons aInitialItem) { + iArray = new ConsPointer[aSize]; + iSize = aSize; + int i; + for (i = 0; i < aSize; i++) { + iArray[i] = new ConsPointer(); + iArray[i].setCons(aInitialItem); + } + } + + + public int size() { + return iSize; + } + + + public ConsPointer getElement(int aItem) { + return iArray[aItem]; + } + + + public ConsPointer[] getElements(int first, int last) throws IndexOutOfBoundsException { + if (first < last && first > 0 && last > 0 && first < iSize - 1 && last < iSize - 1) { + ConsPointer[] arguments = new ConsPointer[last - first]; int i = 0; - for(int x = first; x < last; x++) - { + for (int x = first; x < last; x++) { arguments[i++] = iArray[x]; } return arguments; - } - else - { + } else { throw new IndexOutOfBoundsException("Stack index is out of bounds."); } } - - public void setElement(int aItem,Cons aCons) - { - iArray[aItem].setCons(aCons); - } + + + public void setElement(int aItem, Cons aCons) { + iArray[aItem].setCons(aCons); + } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/ConsPointer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/ConsPointer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/ConsPointer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/ConsPointer.java 2010-12-29 04:07:15.000000000 +0000 @@ -18,8 +18,8 @@ package org.mathpiper.lisp.cons; import org.mathpiper.io.StringOutput; +import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.Cons; import org.mathpiper.lisp.printers.LispPrinter; /** @@ -34,6 +34,7 @@ Cons iCons; + public Object car() throws Exception { return iCons.car(); } @@ -42,11 +43,14 @@ return iCons.cdr(); } - public ConsPointer() { - iCons = null; + public ConsPointer() + { + super(); } - public ConsPointer(Cons aCons) { + + public ConsPointer( Cons aCons) { + super(); iCons = aCons; } @@ -65,22 +69,23 @@ //iPointer = (iPointer.cdr()); - public void goNext() throws Exception { - LispError.check(iCons != null, LispError.NOT_LONG_ENOUGH); + public void goNext(int aStackTop , Environment aEnvironment) throws Exception { + LispError.check(aEnvironment, aStackTop, iCons != null, LispError.NOT_LONG_ENOUGH, "INTERNAL"); iCons = iCons.cdr().iCons; } - public void goSub() throws Exception { - LispError.check(iCons != null, LispError.INVALID_ARGUMENT); - LispError.check(iCons.car() instanceof ConsPointer, LispError.NOT_A_LIST); + public void goSub(int aStackTop , Environment aEnvironment) throws Exception { + LispError.check(aEnvironment, aStackTop, iCons != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, iCons.car() instanceof ConsPointer, LispError.NOT_A_LIST, "INTERNAL"); iCons = ((ConsPointer)iCons.car()).getCons(); } + @Override public String toString() { StringOutput out = new StringOutput(); LispPrinter printer = new LispPrinter(); try { - printer.print(this, out, null); + printer.print(-1, this, out, null); } catch (Exception e) { e.printStackTrace(); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/ConsTraverser.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/ConsTraverser.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/ConsTraverser.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/ConsTraverser.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,14 +13,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.cons; import org.mathpiper.lisp.*; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.Cons; /** * Works almost like ConsPointer, but doesn't enforce @@ -28,47 +24,53 @@ * should be used instead of ConsPointer if you are going to traverse * a lisp expression in a non-destructive way. */ -public class ConsTraverser -{ - ConsPointer iPointer; - - public ConsTraverser(ConsPointer aPtr) - { - iPointer = aPtr; - } +public class ConsTraverser { - public Object car() throws Exception - { + ConsPointer iPointer; + ConsPointer iHeadPointer; + + private Environment iEnvironment; + + public ConsTraverser(Environment aEnvironment, ConsPointer aPtr) { + iEnvironment = aEnvironment; + iPointer = aPtr; + iHeadPointer = aPtr; + } + + public Object car() throws Exception { return iPointer.car(); } - public ConsPointer cdr() - { + public ConsPointer cdr() { return iPointer.cdr(); } - - public Cons getCons() - { - return iPointer.getCons(); - } - - public ConsPointer getPointer() - { - return iPointer; - } - - public void goNext() throws Exception - { - LispError.check(iPointer.getCons() != null,LispError.NOT_LONG_ENOUGH); - iPointer = (iPointer.cdr()); - } - - public void goSub() throws Exception - { - LispError.check(iPointer.getCons() != null,LispError.INVALID_ARGUMENT); - LispError.check(iPointer.car() instanceof ConsPointer,LispError.NOT_A_LIST); - iPointer = (ConsPointer) iPointer.car(); - } + public Cons getCons() { + return iPointer.getCons(); + } + + public void setCons(Cons aCons) { + iPointer.setCons(aCons); + } + + public ConsPointer getPointer() { + return iPointer; + } + + public ConsPointer getHeadPointer() + { + return iHeadPointer; + } + + public void goNext(int aStackTop) throws Exception { + LispError.check(iEnvironment, aStackTop, iPointer.getCons() != null, LispError.NOT_LONG_ENOUGH, "INTERNAL"); + iPointer = (iPointer.cdr()); + } + + public void goSub(int aStackTop) throws Exception { + LispError.check(iEnvironment, aStackTop, iPointer.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(iEnvironment, aStackTop, iPointer.car() instanceof ConsPointer, LispError.NOT_A_LIST, "INTERNAL"); + iPointer = (ConsPointer) iPointer.car(); + } }; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/NumberCons.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/NumberCons.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/NumberCons.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/NumberCons.java 2010-12-29 04:07:15.000000000 +0000 @@ -18,9 +18,8 @@ package org.mathpiper.lisp.cons; import org.mathpiper.lisp.*; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.Cons; import org.mathpiper.builtin.BigNumber; +import org.mathpiper.exceptions.EvaluationException; /** @@ -35,7 +34,7 @@ private BigNumber iCarBigNumber; /// string representation in decimal; NULL if not yet converted from BigNumber private String iCarStringNumber; - private ConsPointer iCdr = new ConsPointer(); + private ConsPointer iCdr; /** * Construct a number from either a BigNumber or a String. @@ -43,20 +42,22 @@ * @param aNumber * @param aString */ - public NumberCons(Environment aEnvironment,BigNumber aNumber, String aString) throws Exception { - super(aEnvironment); + public NumberCons(BigNumber aNumber, String aString) throws Exception { + super(); iCarStringNumber = aString; iCarBigNumber = aNumber; + iCdr = new ConsPointer(); } /** * Construct a number from a BigNumber. * @param aNumber */ - public NumberCons(Environment aEnvironment,BigNumber aNumber) throws Exception { - super(aEnvironment); + public NumberCons(BigNumber aNumber) throws Exception { + super(); iCarStringNumber = null; iCarBigNumber = aNumber; + iCdr = new ConsPointer(); } /** @@ -65,11 +66,12 @@ * @param aString a number in decimal format * @param aBasePrecision the number of decimal digits for the number */ - public NumberCons(Environment aEnvironment,String aString, int aBasePrecision) throws Exception { - super(aEnvironment); + public NumberCons(String aString, int aBasePrecision) throws Exception { + super(); //(also create a number object). iCarStringNumber = aString; iCarBigNumber = null; // purge whatever it was. + iCdr = new ConsPointer(); // create a new BigNumber object out of iString, set its precision in digits //TODO FIXME enable this in the end NumberCons(aBasePrecision); @@ -77,7 +79,7 @@ public Cons copy( Environment aEnvironment, boolean aRecursed) throws Exception { - NumberCons numberCons = new NumberCons(aEnvironment, iCarBigNumber, iCarStringNumber); + NumberCons numberCons = new NumberCons(iCarBigNumber, iCarStringNumber); numberCons.setMetadataMap(this.getMetadataMap()); @@ -100,7 +102,9 @@ */ public Object car() throws Exception { if (iCarStringNumber == null) { - LispError.lispAssert(iCarBigNumber != null); // either the string is null or the number but not both. + //LispError.lispAssert(iCarBigNumber != null, aEnvironment, aStackTop); // either the string is null or the number but not both. + + if(iCarBigNumber == null) throw new EvaluationException("Internal error in NumberCons.","",-1); iCarStringNumber = iCarBigNumber.numToString(0/*TODO FIXME*/, 10); // export the current number to string and store it as NumberCons::iString @@ -108,6 +112,7 @@ return iCarStringNumber; } + @Override public String toString() { String stringRepresentation = null; try { @@ -128,10 +133,15 @@ * @return * @throws java.lang.Exception */ - public Object getNumber(int aPrecision) throws Exception { + @Override + public Object getNumber(int aPrecision, Environment aEnvironment) throws Exception { /// If necessary, will create a BigNumber object out of the stored string, at given precision (in decimal?) if (iCarBigNumber == null) { // create and store a BigNumber out of the string representation. - LispError.lispAssert(iCarStringNumber != null); + + //LispError.lispAssert(iCarStringNumber != null, aEnvironment, aStackTop); + + if(iCarStringNumber == null) throw new EvaluationException("Internal error in NumberCons.","",-1); + String str; str = iCarStringNumber; // aBasePrecision is in digits, not in bits, ok diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/SublistCons.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/SublistCons.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/cons/SublistCons.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/cons/SublistCons.java 2010-12-29 04:07:15.000000000 +0000 @@ -17,6 +17,7 @@ package org.mathpiper.lisp.cons; +import org.mathpiper.exceptions.EvaluationException; import org.mathpiper.io.StringOutput; import org.mathpiper.lisp.*; import org.mathpiper.lisp.printers.LispPrinter; @@ -24,10 +25,17 @@ public class SublistCons extends Cons { - ConsPointer iCar = new ConsPointer(); - ConsPointer iCdr = new ConsPointer(); + ConsPointer iCar; + ConsPointer iCdr; + private SublistCons(Environment aEnvironment, Cons aSubList) throws Exception { + super(); + iCar = new ConsPointer(); + iCar.setCons(aSubList); + iCdr = new ConsPointer(); + } + public static SublistCons getInstance(Environment aEnvironment, Cons aSubList) throws Exception { return new SublistCons(aEnvironment, aSubList); } @@ -45,7 +53,9 @@ }*/ public Cons copy(Environment aEnvironment, boolean aRecursed) throws Exception { //TODO recursed copy needs to be implemented still - LispError.lispAssert(aRecursed == false); + //LispError.lispAssert(aRecursed == false, aEnvironment, aStackTop); + + if(aRecursed != false) throw new EvaluationException("Internal error in SublistCons.","",-1); Cons copied = new SublistCons(aEnvironment, iCar.getCons()); @@ -55,22 +65,18 @@ } - SublistCons(Environment aEnvironment, Cons aSubList) throws Exception { - super(aEnvironment); - iCar.setCons(aSubList); - } - public ConsPointer cdr() { return iCdr; }//end method. + @Override public String toString() { StringOutput out = new StringOutput(); LispPrinter printer = new LispPrinter(); try { - printer.print(new ConsPointer(this), out, null); + printer.print(-1, new ConsPointer(this), out, null); } catch (Exception e) { e.printStackTrace(); } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/DefFile.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/DefFile.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/DefFile.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/DefFile.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,39 +13,41 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp; /** DefFile represents one file that can be loaded just-in-time. */ -public class DefFile -{ - public String iFileName; - public boolean iIsLoaded; - - public DefFile(String aFile) - { - iFileName = aFile; - iIsLoaded = false; - } - public DefFile(DefFile aOther) - { - iFileName = aOther.iFileName; - iIsLoaded = aOther.iIsLoaded; - } - public void setLoaded() - { - iIsLoaded = true; - } - public boolean isLoaded() - { - return iIsLoaded; - } - public String fileName() - { - return iFileName; - } +public class DefFile { + + public String iFileName; + public boolean iIsLoaded; + + + public DefFile(String aFile) { + iFileName = aFile; + iIsLoaded = false; + } + + + public DefFile(DefFile aOther) { + iFileName = aOther.iFileName; + iIsLoaded = aOther.iIsLoaded; + } + + + public void setLoaded() { + iIsLoaded = true; + } + + + public boolean isLoaded() { + return iIsLoaded; + } + + + public String fileName() { + return iFileName; + } }; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Environment.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Environment.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Environment.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Environment.java 2011-04-24 07:45:56.000000000 +0000 @@ -17,10 +17,12 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.mathpiper.lisp.stacks.ArgumentStack; import org.mathpiper.lisp.collections.DefFileMap; -import org.mathpiper.lisp.collections.Map; +import org.mathpiper.lisp.collections.MathPiperMap; import org.mathpiper.lisp.collections.TokenMap; import org.mathpiper.lisp.collections.OperatorMap; import org.mathpiper.lisp.cons.AtomCons; @@ -35,26 +37,25 @@ import org.mathpiper.io.InputDirectories; import org.mathpiper.lisp.cons.Cons; -import org.mathpiper.lisp.cons.SublistCons; import org.mathpiper.lisp.tokenizers.MathPiperTokenizer; -import org.mathpiper.lisp.userfunctions.MultipleArityUserFunction; +import org.mathpiper.lisp.rulebases.MultipleArityRulebase; -import org.mathpiper.lisp.userfunctions.MacroUserFunction; +import org.mathpiper.lisp.rulebases.MacroRulebase; -import org.mathpiper.lisp.userfunctions.ListedBranchingUserFunction; +import org.mathpiper.lisp.rulebases.ListedRulebase; -import org.mathpiper.lisp.userfunctions.SingleArityBranchingUserFunction; +import org.mathpiper.lisp.rulebases.SingleArityRulebase; -import org.mathpiper.lisp.userfunctions.ListedMacroUserFunction; +import org.mathpiper.lisp.rulebases.ListedMacroRulebase; import org.mathpiper.lisp.printers.MathPiperPrinter; import org.mathpiper.lisp.localvariables.LocalVariable; import org.mathpiper.lisp.localvariables.LocalVariableFrame; -public class Environment { +public final class Environment { public Evaluator iLispExpressionEvaluator = new LispExpressionEvaluator(); private int iPrecision = 10; @@ -68,17 +69,19 @@ public Cons iProgOpenAtom; public Cons iProgCloseAtom; public Cons iNthAtom; + public Cons iComplexAtom; public Cons iBracketOpenAtom; public Cons iBracketCloseAtom; public Cons iListOpenAtom; public Cons iListCloseAtom; public Cons iCommaAtom; public Cons iListAtom; + public Cons iSetAtom; public Cons iProgAtom; - public OperatorMap iPrefixOperators = new OperatorMap(); - public OperatorMap iInfixOperators = new OperatorMap(); - public OperatorMap iPostfixOperators = new OperatorMap(); - public OperatorMap iBodiedOperators = new OperatorMap(); + public OperatorMap iPrefixOperators = new OperatorMap(this); + public OperatorMap iInfixOperators = new OperatorMap(this); + public OperatorMap iPostfixOperators = new OperatorMap(this); + public OperatorMap iBodiedOperators = new OperatorMap(this); public volatile int iEvalDepth = 0; public int iMaxEvalDepth = 10000; //TODO FIXME @@ -94,14 +97,14 @@ public MathPiperTokenizer iCurrentTokenizer; public MathPiperTokenizer iDefaultTokenizer = new MathPiperTokenizer(); public MathPiperTokenizer iXmlTokenizer = new XmlTokenizer(); - public Map iGlobalState = new Map(); - public Map iUserFunctions = new Map(); - Map iBuiltinFunctions = new Map(); - public String iError = null; + public MathPiperMap iGlobalState = new MathPiperMap(); + public MathPiperMap iUserRules = new MathPiperMap(); + MathPiperMap iBuiltinFunctions = new MathPiperMap(); + public Throwable iException = null; public DefFileMap iDefFiles = new DefFileMap(); public InputDirectories iInputDirectories = new InputDirectories(); - public String iPrettyReader = null; - public String iPrettyPrinter = null; + public String iPrettyReaderName = null; + public String iPrettyPrinterName = null; public Environment(MathPiperOutputStream aCurrentOutput/*TODO FIXME*/) throws Exception { iCurrentTokenizer = iDefaultTokenizer; @@ -109,48 +112,46 @@ iCurrentOutput = aCurrentOutput; iCurrentPrinter = new MathPiperPrinter(iPrefixOperators, iInfixOperators, iPostfixOperators, iBodiedOperators); - iTrueAtom = AtomCons.getInstance(this, "True"); + iTrueAtom = new AtomCons((String)getTokenHash().lookUp("True")); iTrueString = (String) iTrueAtom.car(); - iFalseAtom = AtomCons.getInstance(this, "False"); + iFalseAtom = new AtomCons((String)getTokenHash().lookUp("False")); iFalseString = (String) iFalseAtom.car(); - iEndOfFileAtom = AtomCons.getInstance(this, "EndOfFile"); - iEndStatementAtom = AtomCons.getInstance(this, ";"); - iProgOpenAtom = AtomCons.getInstance(this, "["); - iProgCloseAtom = AtomCons.getInstance(this, "]"); - iNthAtom = AtomCons.getInstance(this, "Nth"); - iBracketOpenAtom = AtomCons.getInstance(this, "("); - iBracketCloseAtom = AtomCons.getInstance(this, ")"); - iListOpenAtom = AtomCons.getInstance(this, "{"); - iListCloseAtom = AtomCons.getInstance(this, "}"); - iCommaAtom = AtomCons.getInstance(this, ","); - iListAtom = AtomCons.getInstance(this, "List"); - iProgAtom = AtomCons.getInstance(this, "Prog"); + iEndOfFileAtom = new AtomCons((String)getTokenHash().lookUp("EndOfFile")); + iEndStatementAtom = new AtomCons((String)getTokenHash().lookUp(";")); + iProgOpenAtom = new AtomCons((String)getTokenHash().lookUp("[")); + iProgCloseAtom = new AtomCons((String)getTokenHash().lookUp("]")); + iNthAtom = new AtomCons((String)getTokenHash().lookUp("Nth")); + iComplexAtom = new AtomCons((String)getTokenHash().lookUp("Complex")); + iBracketOpenAtom = new AtomCons((String)getTokenHash().lookUp("(")); + iBracketCloseAtom = new AtomCons((String)getTokenHash().lookUp(")")); + iListOpenAtom = new AtomCons((String)getTokenHash().lookUp("{")); + iListCloseAtom = new AtomCons((String)getTokenHash().lookUp("}")); + iCommaAtom = new AtomCons((String)getTokenHash().lookUp(",")); + iListAtom = new AtomCons((String)getTokenHash().lookUp("List")); + iSetAtom = new AtomCons((String)getTokenHash().lookUp("Set")); + iProgAtom = new AtomCons((String)getTokenHash().lookUp("Prog")); - iArgumentStack = new ArgumentStack(50000 /*TODO FIXME*/); + iArgumentStack = new ArgumentStack(this, 50000 /*TODO FIXME*/); //org.mathpiper.builtin.Functions mc = new org.mathpiper.builtin.Functions(); //mc.addCoreFunctions(this); //System.out.println("Classpath: " + System.getProperty("java.class.path")); - BuiltinFunction.addCoreFunctions(this); - List failList = BuiltinFunction.addOptionalFunctions(this, "org/mathpiper/builtin/functions/optional/"); - - pushLocalFrame(true, ""); } public TokenMap getTokenHash() { return iTokenHash; } - public Map getGlobalState() { + public MathPiperMap getGlobalState() { return iGlobalState; } - public Map getUserFunctions() { - return iUserFunctions; + public MathPiperMap getUserFunctions() { + return iUserRules; } - public Map getBuiltinFunctions() { + public MathPiperMap getBuiltinFunctions() { return iBuiltinFunctions; } @@ -162,22 +163,22 @@ iPrecision = aPrecision; // getPrecision in decimal digits } - public void setGlobalVariable(String aVariable, ConsPointer aValue, boolean aGlobalLazyVariable) throws Exception { - ConsPointer localVariable = getLocalVariable(aVariable); + public void setGlobalVariable(int aStackTop, String aVariable, ConsPointer aValue, boolean aGlobalLazyVariable) throws Exception { + ConsPointer localVariable = getLocalVariable(aStackTop, aVariable); if (localVariable != null) { localVariable.setCons(aValue.getCons()); return; } - GlobalVariable globalVariable = new GlobalVariable(aValue); + GlobalVariable globalVariable = new GlobalVariable(this,aValue); iGlobalState.setAssociation(globalVariable, aVariable); if (aGlobalLazyVariable) { globalVariable.setEvalBeforeReturn(true); } } - public void getGlobalVariable(String aVariable, ConsPointer aResult) throws Exception { + public void getGlobalVariable(int aStackTop, String aVariable, ConsPointer aResult) throws Exception { aResult.setCons(null); - ConsPointer localVariable = getLocalVariable(aVariable); + ConsPointer localVariable = getLocalVariable(aStackTop, aVariable); if (localVariable != null) { aResult.setCons(localVariable.getCons()); return; @@ -185,7 +186,7 @@ GlobalVariable globalVariable = (GlobalVariable) iGlobalState.lookUp(aVariable); if (globalVariable != null) { if (globalVariable.iEvalBeforeReturn) { - iLispExpressionEvaluator.evaluate(this, aResult, globalVariable.iValue); + iLispExpressionEvaluator.evaluate(this, aStackTop, aResult, globalVariable.iValue); globalVariable.iValue.setCons(aResult.getCons()); globalVariable.iEvalBeforeReturn = false; return; @@ -197,21 +198,37 @@ } - public ConsPointer getLocalVariable(String aVariable) throws Exception { - LispError.check(iLocalVariablesFrame != null, LispError.INVALID_STACK); + public ConsPointer getLocalVariable(int aStackTop, String aVariable) throws Exception { + LispError.check(this, aStackTop, iLocalVariablesFrame != null, LispError.INVALID_STACK, "INTERNAL"); // check(iLocalsList.iFirst != null,INVALID_STACK); LocalVariable localVariable = iLocalVariablesFrame.iFirst; while (localVariable != null) { - if (localVariable.iVariable == aVariable) { + if (localVariable.iVariable.equals(aVariable)) { return localVariable.iValue; } localVariable = localVariable.iNext; } return null; }//end method. - public String getLocalVariables() throws Exception { - LispError.check(iLocalVariablesFrame != null, LispError.INVALID_STACK); + + + + public void unbindAllLocalVariables(int aStackTop) throws Exception{ + LispError.check(this, aStackTop, iLocalVariablesFrame != null, LispError.INVALID_STACK, "INTERNAL"); + + LocalVariable localVariable = iLocalVariablesFrame.iFirst; + + while (localVariable != null) { + localVariable.iValue.setCons(null); + localVariable = localVariable.iNext; + } + + }//end method. + + + public String getLocalVariables(int aStackTop) throws Exception { + LispError.check(this, aStackTop, iLocalVariablesFrame != null, LispError.INVALID_STACK, "INTERNAL"); // check(iLocalsList.iFirst != null,INVALID_STACK); LocalVariable localVariable = iLocalVariablesFrame.iFirst; @@ -244,19 +261,185 @@ }//end method. - public void unbindVariable(String aVariableName) throws Exception { - ConsPointer localVariable = getLocalVariable(aVariableName); - if (localVariable != null) { - localVariable.setCons(null); - return; + + public String dumpLocalVariablesFrame(int aStackTop) throws Exception { + + LispError.check(this, aStackTop, iLocalVariablesFrame != null, LispError.INVALID_STACK, "INTERNAL"); + + LocalVariableFrame localVariableFramePointer = iLocalVariablesFrame; + + StringBuilder stringBuilder = new StringBuilder(); + + + + int functionPositionIndex = 0; + + //int functionBaseIndex = 0; + + while (localVariableFramePointer != null) { + + String functionName = localVariableFramePointer.getFunctionName(); + + + if(functionPositionIndex == 0) + { + stringBuilder.append("\n\n========================================= Start Of User Function Stack Trace\n"); + } + else + { + stringBuilder.append("-----------------------------------------\n"); + } + + + stringBuilder.append(functionPositionIndex++ + ": "); + stringBuilder.append(functionName); + stringBuilder.append("\n"); + + LocalVariable localVariable = localVariableFramePointer.iFirst; + + + //stringBuilder.append("Local variables: "); + + + while (localVariable != null) { + + + stringBuilder.append(" " + functionPositionIndex++ + ": -> "); + + stringBuilder.append(localVariable.iVariable); + + stringBuilder.append(" = "); + + ConsPointer valuePointer = localVariable.iValue; + + String valueString = Utility.printMathPiperExpression(aStackTop, valuePointer, this, -1); + + stringBuilder.append(valueString); + + stringBuilder.append("\n"); + + + + + /*if(value != null) + { + localVariablesStringBuilder.append(value.trim().replace(" ","").replace("\n", "") ); + } + else + { + localVariablesStringBuilder.append("unbound"); + }//end else. + + + localVariablesStringBuilder.append(", ");*/ + + localVariable = localVariable.iNext; + }//end while. + + localVariableFramePointer = localVariableFramePointer.iNext; + + }//end while + + stringBuilder.append("========================================= End Of User Function Stack Trace\n\n"); + + return stringBuilder.toString(); + + + + + /*StringBuilder stringBuilder = new StringBuilder(); + + int functionBaseIndex = 0; + + int functionPositionIndex = 0; + + + while (functionBaseIndex <= aStackTop) { + + if(functionBaseIndex == 0) + { + stringBuilder.append("\n\n========================================= Start Of Stack Trace\n"); + } + else + { + stringBuilder.append("-----------------------------------------\n"); + } + + ConsPointer consPointer = getElement(functionBaseIndex, aStackTop, aEnvironment); + + int argumentCount = Utility.listLength(aEnvironment, aStackTop, consPointer); + + ConsPointer argumentPointer = new ConsPointer(); + + Object car = consPointer.getCons().car(); + + ConsPointer consTraverser = new ConsPointer( consPointer.getCons()); + + stringBuilder.append(functionPositionIndex++ + ": "); + stringBuilder.append(Utility.printMathPiperExpression(aStackTop, consTraverser, aEnvironment, -1)); + stringBuilder.append("\n"); + + consTraverser.goNext(aStackTop, aEnvironment); + + while(consTraverser.getCons() != null) + { + stringBuilder.append(" " + functionPositionIndex++ + ": "); + stringBuilder.append("-> " + Utility.printMathPiperExpression(aStackTop, consTraverser, aEnvironment, -1)); + stringBuilder.append("\n"); + + consTraverser.goNext(aStackTop, aEnvironment); + } + + + functionBaseIndex = functionBaseIndex + argumentCount; + + }//end while. + + stringBuilder.append("========================================= End Of User Function Stack Trace\n\n"); + + return stringBuilder.toString();*/ + + }//end method. + + public void unbindVariable(int aStackTop, String aVariableName) throws Exception { + + if(aVariableName.equals("*")) + { + this.unbindAllLocalVariables(aStackTop); + + + //Unbind global variables + Set keySet = new HashSet(iGlobalState.getMap().keySet()); + + for(String key : keySet) + { + if(!key.startsWith("$") + && !key.equals("I") + && !key.equals("%") + && !key.equals("geogebra")) + { + //Do not unbind private variables (which are those which start with a $) or the other listed variables. + iGlobalState.release(key); + } + } } - iGlobalState.release(aVariableName); + else + { + //Unbind local variable. + ConsPointer localVariable = getLocalVariable(aStackTop, aVariableName); + if (localVariable != null) { + localVariable.setCons(null); + return; + } + + iGlobalState.release(aVariableName); + }//end else. } - public void newLocalVariable(String aVariable, Cons aValue) throws Exception { - LispError.lispAssert(iLocalVariablesFrame != null); - iLocalVariablesFrame.add(new LocalVariable(aVariable, aValue)); + public void newLocalVariable(String aVariable, Cons aValue, int aStackTop) throws Exception { + LispError.lispAssert(iLocalVariablesFrame != null, this, aStackTop); + iLocalVariablesFrame.add(new LocalVariable(this, aVariable, aValue)); } public void pushLocalFrame(boolean aFenced, String functionName) { @@ -269,8 +452,8 @@ } } - public void popLocalFrame() throws Exception { - LispError.lispAssert(iLocalVariablesFrame != null); + public void popLocalFrame(int aStackTop) throws Exception { + LispError.lispAssert(iLocalVariablesFrame != null, this, aStackTop); LocalVariableFrame nextLocalVariableFrame = iLocalVariablesFrame.iNext; iLocalVariablesFrame.delete(); iLocalVariablesFrame = nextLocalVariableFrame; @@ -280,117 +463,115 @@ return iLastUniqueId++; } - public void holdArgument(String aOperator, String aVariable) throws Exception { - MultipleArityUserFunction multipleArityUserFunc = (MultipleArityUserFunction) iUserFunctions.lookUp(aOperator); - LispError.check(multipleArityUserFunc != null, LispError.INVALID_ARGUMENT); - multipleArityUserFunc.holdArgument(aVariable); + public void holdArgument(int aStackTop, String aOperator, String aVariable, Environment aEnvironment) throws Exception { + MultipleArityRulebase multipleArityUserFunc = (MultipleArityRulebase) iUserRules.lookUp(aOperator); + LispError.check(this, aStackTop, multipleArityUserFunc != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + multipleArityUserFunc.holdArgument(aVariable, aStackTop, aEnvironment); } - public void retractFunction(String aOperator, int aArity) throws Exception { - MultipleArityUserFunction multipleArityUserFunc = (MultipleArityUserFunction) iUserFunctions.lookUp(aOperator); + public void retractRule(String aOperator, int aArity, int aStackTop, Environment aEnvironment) throws Exception { + MultipleArityRulebase multipleArityUserFunc = (MultipleArityRulebase) iUserRules.lookUp(aOperator); if (multipleArityUserFunc != null) { - multipleArityUserFunc.deleteRulebaseEntry(aArity); + multipleArityUserFunc.deleteRulebaseEntry(aArity, aStackTop, aEnvironment); } } - public SingleArityBranchingUserFunction getUserFunction(ConsPointer aArguments) throws Exception { - MultipleArityUserFunction multipleArityUserFunc = (MultipleArityUserFunction) iUserFunctions.lookUp( (String) aArguments.car()); + public SingleArityRulebase getRulebase(int aStackTop, ConsPointer aArguments) throws Exception { + MultipleArityRulebase multipleArityUserFunc = (MultipleArityRulebase) iUserRules.lookUp( (String) aArguments.car()); if (multipleArityUserFunc != null) { - int arity = Utility.listLength(aArguments) - 1; - return multipleArityUserFunc.getUserFunction(arity); + int arity = Utility.listLength(this, aStackTop, aArguments) - 1; + return multipleArityUserFunc.getUserFunction(arity, aStackTop, this); } return null; } - public SingleArityBranchingUserFunction getUserFunction(String aName, int aArity) throws Exception { - MultipleArityUserFunction multipleArityUserFunc = (MultipleArityUserFunction) iUserFunctions.lookUp(aName); + public SingleArityRulebase getRulebase(String aName, int aArity, int aStackTop) throws Exception { + MultipleArityRulebase multipleArityUserFunc = (MultipleArityRulebase) iUserRules.lookUp(aName); if (multipleArityUserFunc != null) { - return multipleArityUserFunc.getUserFunction(aArity); + return multipleArityUserFunc.getUserFunction(aArity, aStackTop, this); } return null; } - public void unFenceRule(String aOperator, int aArity) throws Exception { - MultipleArityUserFunction multiUserFunc = (MultipleArityUserFunction) iUserFunctions.lookUp(aOperator); + public void unfenceRule(int aStackTop, String aOperator, int aArity) throws Exception { + MultipleArityRulebase multiUserFunc = (MultipleArityRulebase) iUserRules.lookUp(aOperator); - LispError.check(multiUserFunc != null, LispError.INVALID_ARGUMENT); - SingleArityBranchingUserFunction userFunc = multiUserFunc.getUserFunction(aArity); - LispError.check(userFunc != null, LispError.INVALID_ARGUMENT); + LispError.check(this, aStackTop, multiUserFunc != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + SingleArityRulebase userFunc = multiUserFunc.getUserFunction(aArity, aStackTop, this); + LispError.check(this, aStackTop, userFunc != null, LispError.INVALID_ARGUMENT, "INTERNAL"); userFunc.unFence(); } - public MultipleArityUserFunction getMultipleArityUserFunction(String aOperator, boolean create) throws Exception { + public MultipleArityRulebase getMultipleArityRulebase(int aStackTop, String aOperator, boolean create) throws Exception { // Find existing multiuser func. Todo:tk:a user function name is added to the list even if a non-existing function // is being executed or looked for by FindFunction(); - MultipleArityUserFunction multipleArityUserFunction = (MultipleArityUserFunction) iUserFunctions.lookUp(aOperator); + MultipleArityRulebase multipleArityUserFunction = (MultipleArityRulebase) iUserRules.lookUp(aOperator); // If none exists, add one to the user functions list if (multipleArityUserFunction == null && create == true) { - MultipleArityUserFunction newMultipleArityUserFunction = new MultipleArityUserFunction(); - iUserFunctions.setAssociation(newMultipleArityUserFunction, aOperator); - multipleArityUserFunction = (MultipleArityUserFunction) iUserFunctions.lookUp(aOperator); - LispError.check(multipleArityUserFunction != null, LispError.CREATING_USER_FUNCTION); + MultipleArityRulebase newMultipleArityUserFunction = new MultipleArityRulebase(); + iUserRules.setAssociation(newMultipleArityUserFunction, aOperator); + multipleArityUserFunction = (MultipleArityRulebase) iUserRules.lookUp(aOperator); + LispError.check(this, aStackTop, multipleArityUserFunction != null, LispError.CREATING_USER_FUNCTION, "INTERNAL"); } return multipleArityUserFunction; } - public void declareRulebase(String aOperator, ConsPointer aParametersPointer, boolean aListed) throws Exception { - MultipleArityUserFunction multipleArityUserFunction = getMultipleArityUserFunction(aOperator, true); + public void defineRulebase(int aStackTop, String aOperator, ConsPointer aParametersPointer, boolean aListed) throws Exception { + MultipleArityRulebase multipleArityUserFunction = getMultipleArityRulebase(aStackTop, aOperator, true); // add an operator with this arity to the multiuserfunc. - SingleArityBranchingUserFunction newBranchingUserFunction; + SingleArityRulebase newBranchingRulebase; if (aListed) { - newBranchingUserFunction = new ListedBranchingUserFunction(aParametersPointer, aOperator); + newBranchingRulebase = new ListedRulebase(this, aStackTop, aParametersPointer, aOperator); } else { - newBranchingUserFunction = new SingleArityBranchingUserFunction(aParametersPointer, aOperator); + newBranchingRulebase = new SingleArityRulebase(this, aStackTop, aParametersPointer, aOperator); } - multipleArityUserFunction.addRulebaseEntry(newBranchingUserFunction); + multipleArityUserFunction.addRulebaseEntry(this, aStackTop, newBranchingRulebase); } - public void defineRule(String aOperator, int aArity, - int aPrecedence, ConsPointer aPredicate, - ConsPointer aBody) throws Exception { - // Find existing multiuser func. - MultipleArityUserFunction multipleArityUserFunction = (MultipleArityUserFunction) iUserFunctions.lookUp(aOperator); - LispError.check(multipleArityUserFunction != null, LispError.CREATING_RULE); + public void defineRule(int aStackTop, String aOperator, int aArity, int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { + // Find existing multiuser rule. + MultipleArityRulebase multipleArityRulebase = (MultipleArityRulebase) iUserRules.lookUp(aOperator); + LispError.check(this, aStackTop, multipleArityRulebase != null, LispError.CREATING_RULE, "INTERNAL"); // Get the specific user function with the right arity - SingleArityBranchingUserFunction userFunction = (SingleArityBranchingUserFunction) multipleArityUserFunction.getUserFunction(aArity); - LispError.check(userFunction != null, LispError.CREATING_RULE); + SingleArityRulebase rulebase = (SingleArityRulebase) multipleArityRulebase.getUserFunction(aArity, aStackTop, this); + LispError.check(this, aStackTop, rulebase != null, LispError.CREATING_RULE, "INTERNAL"); // Declare a new evaluation rule - if (Utility.isTrue(this, aPredicate)) { + if (Utility.isTrue(this, aPredicate, aStackTop)) { // printf("FastPredicate on %s\n",aOperator->String()); - userFunction.declareRule(aPrecedence, aBody); + rulebase.defineAlwaysTrueRule(aStackTop, aPrecedence, aBody); } else { - userFunction.declareRule(aPrecedence, aPredicate, aBody); + rulebase.defineSometimesTrueRule(aStackTop, aPrecedence, aPredicate, aBody); } } - public void declareMacroRulebase(String aFunctionName, ConsPointer aParameters, boolean aListed) throws Exception { - MultipleArityUserFunction multipleArityUserFunc = getMultipleArityUserFunction(aFunctionName, true); + public void defineMacroRulebase(int aStackTop, String aFunctionName, ConsPointer aParameters, boolean aListed) throws Exception { + MultipleArityRulebase multipleArityRulebase = getMultipleArityRulebase(aStackTop, aFunctionName, true); - MacroUserFunction newMacroUserFunction; + MacroRulebase newMacroRulebase; if (aListed) { - newMacroUserFunction = new ListedMacroUserFunction(aParameters, aFunctionName); + newMacroRulebase = new ListedMacroRulebase(this, aStackTop, aParameters, aFunctionName); } else { - newMacroUserFunction = new MacroUserFunction(aParameters, aFunctionName); + newMacroRulebase = new MacroRulebase(this, aStackTop, aParameters, aFunctionName); } - multipleArityUserFunc.addRulebaseEntry(newMacroUserFunction); + multipleArityRulebase.addRulebaseEntry(this, aStackTop, newMacroRulebase); } - public void defineRulePattern(String aOperator, int aArity, int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { - // Find existing multiuser func. - MultipleArityUserFunction multipleArityUserFunc = (MultipleArityUserFunction) iUserFunctions.lookUp(aOperator); - LispError.check(multipleArityUserFunc != null, LispError.CREATING_RULE); + public void defineRulePattern(int aStackTop, String aOperator, int aArity, int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { + // Find existing multiuser rulebase. + MultipleArityRulebase multipleArityRulebase = (MultipleArityRulebase) iUserRules.lookUp(aOperator); + LispError.check(this, aStackTop, multipleArityRulebase != null, LispError.CREATING_RULE, "INTERNAL"); // Get the specific user function with the right arity - SingleArityBranchingUserFunction userFunction = multipleArityUserFunc.getUserFunction(aArity); - LispError.check(userFunction != null, LispError.CREATING_RULE); + SingleArityRulebase rulebase = multipleArityRulebase.getUserFunction(aArity, aStackTop, this); + LispError.check(this, aStackTop, rulebase != null, LispError.CREATING_RULE, "INTERNAL"); // Declare a new evaluation rule - userFunction.declarePattern(aPrecedence, aPredicate, aBody); + rulebase.definePattern(aStackTop, aPrecedence, aPredicate, aBody); } /** @@ -404,9 +585,9 @@ - public void resetArgumentStack() throws Exception + public void resetArgumentStack(int aStackTop) throws Exception { - this.iArgumentStack.reset(); + this.iArgumentStack.reset(aStackTop, this); }//end method. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Evaluator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Evaluator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Evaluator.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Evaluator.java 2010-12-29 04:07:15.000000000 +0000 @@ -24,7 +24,6 @@ import org.mathpiper.io.MathPiperOutputStream; import org.mathpiper.io.StringOutputStream; import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.localvariables.LocalVariableFrame; import org.mathpiper.lisp.printers.MathPiperPrinter; import org.mathpiper.lisp.stacks.UserStackInformation; @@ -39,6 +38,7 @@ public static boolean iTraced = false; private static List traceFunctionList = null; private static List traceExceptFunctionList = null; + public static boolean iStackTraced = false; UserStackInformation iBasicInfo = new UserStackInformation(); public static void showExpression(StringBuffer outString, Environment aEnvironment, ConsPointer aExpression) throws Exception { @@ -46,7 +46,7 @@ // Print out the current expression //StringOutput stream(outString); MathPiperOutputStream stream = new StringOutputStream(outString); - infixprinter.print(aExpression, stream, aEnvironment); + infixprinter.print(-1, aExpression, stream, aEnvironment); // Escape quotes. for (int i = outString.length() - 1; i >= 0; --i) { char c = outString.charAt(i); @@ -264,7 +264,19 @@ iTraced = true; } - public abstract void evaluate(Environment aEnvironment, ConsPointer aResult, ConsPointer aArgumentsOrExpression) throws Exception; + public static boolean isStackTraced() { + return iStackTraced; + } + + public static void stackTraceOff() { + iStackTraced = false; + } + + public static void stackTraceOn() { + iStackTraced = true; + } + + public abstract void evaluate(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aArgumentsOrExpression) throws Exception; public UserStackInformation stackInformation() { diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/GlobalVariable.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/GlobalVariable.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/GlobalVariable.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/GlobalVariable.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,57 +13,60 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp; import org.mathpiper.lisp.cons.ConsPointer; - - - /** * Value of a Lisp global variable. -* The only special feature of this class is the attribute -* iEvalBeforeReturn, which defaults to LispFalse. If this -* attribute is set to LispTrue, the value in iValue needs to be -* evaluated to get the value of the Lisp variable. -* See: LispEnvironment::GetVariable() + * The only special feature of this class is the attribute + * iEvalBeforeReturn, which defaults to LispFalse. If this + * attribute is set to LispTrue, the value in iValue needs to be + * evaluated to get the value of the Lisp variable. + * See: LispEnvironment::GetVariable() */ -public class GlobalVariable -{ - ConsPointer iValue = new ConsPointer(); - boolean iEvalBeforeReturn; - - public GlobalVariable(GlobalVariable aOther) - { - iValue = aOther.iValue; - iEvalBeforeReturn = aOther.iEvalBeforeReturn; - } - public GlobalVariable(ConsPointer aValue) - { - iValue.setCons(aValue.getCons()); - iEvalBeforeReturn = false; - } - public void setEvalBeforeReturn(boolean aEval) - { - iEvalBeforeReturn = aEval; - } - - public String toString() - { - return (String) iValue.getCons().toString(); - } +public class GlobalVariable { + + ConsPointer iValue; + boolean iEvalBeforeReturn; + private Environment iEnvironment; + + + public GlobalVariable(Environment aEnvironment, GlobalVariable aOther) { + iEnvironment = aEnvironment; + iValue = new ConsPointer(); + iValue = aOther.iValue; + iEvalBeforeReturn = aOther.iEvalBeforeReturn; + } + + + public GlobalVariable(Environment aEnvironment, ConsPointer aValue) { + iEnvironment = aEnvironment; + iValue = new ConsPointer(); + iValue.setCons(aValue.getCons()); + iEvalBeforeReturn = false; + } + + + public void setEvalBeforeReturn(boolean aEval) { + iEvalBeforeReturn = aEval; + } + + + @Override + public String toString() { + return (String) iValue.getCons().toString(); + } + public boolean isIEvalBeforeReturn() { return iEvalBeforeReturn; } + public ConsPointer getValue() { return iValue; } - - } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/InfixOperator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/InfixOperator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/InfixOperator.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/InfixOperator.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp; - - -public class InfixOperator -{ - public int iPrecedence; - public int iLeftPrecedence; - public int iRightPrecedence; - public int iRightAssociative; - - public InfixOperator(int aPrecedence) - { - iPrecedence = aPrecedence; - iLeftPrecedence = aPrecedence; - iRightPrecedence = aPrecedence; - iRightAssociative = 0; - } - - public void setRightAssociative() - { - iRightAssociative = 1; - } - - public void setLeftPrecedence(int aPrecedence) - { - iLeftPrecedence = aPrecedence; - } - - public void setRightPrecedence(int aPrecedence) - { - iRightPrecedence = aPrecedence; - } - -} - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/LispError.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/LispError.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/LispError.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/LispError.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,7 +13,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp; @@ -21,9 +20,9 @@ import org.mathpiper.exceptions.EvaluationException; import org.mathpiper.builtin.BuiltinFunction; +public class LispError { -public class LispError -{ + public static final int TODO = -1; public static final int NONE = 0; public static final int INVALID_ARGUMENT = 1; public static final int WRONG_NUMBER_OF_ARGUMENTS = 2; @@ -55,288 +54,302 @@ public static final int NON_BOOLEAN_PREDICATE_IN_PATTERN = 28; public static final int GENERIC_FORMAT = 29; public static final int LIST_LENGTHS_MUST_BE_EQUAL = 30; - public static final int MAXIMUM_NUMBER_OF_ERRORS = 31; - - public static String errorString(int aError) throws Exception - { - lispAssert(aError >= 0 && aError < MAXIMUM_NUMBER_OF_ERRORS); + public static String errorString(int aError) throws Exception { + //lispAssert(aError >= 0 && aError < MAXIMUM_NUMBER_OF_ERRORS, aEnvironment, aStackTop); + + if (aError < 0 || aError >= MAXIMUM_NUMBER_OF_ERRORS) { + throw new EvaluationException("Maximum number of errors exceeded.", "", -1); + } + + // switch (aError) { - if (aError == NONE) - { + if (aError == NONE) { return "No error."; } - if (aError == INVALID_ARGUMENT) - { + if (aError == INVALID_ARGUMENT) { return "Invalid argument."; } - if (aError == WRONG_NUMBER_OF_ARGUMENTS) - { + if (aError == WRONG_NUMBER_OF_ARGUMENTS) { return "Wrong number of arguments."; } - if (aError == NOT_A_LIST) - { + if (aError == NOT_A_LIST) { return "Argument is not a list."; } - if (aError == NOT_LONG_ENOUGH) - { + if (aError == NOT_LONG_ENOUGH) { return "List not long enough."; } - if (aError == INVALID_STACK) - { + if (aError == INVALID_STACK) { return "Invalid stack."; } - if (aError == QUITTING) - { + if (aError == QUITTING) { return "Quitting..."; } - if (aError == NOT_ENOUGH_MEMORY) - { + if (aError == NOT_ENOUGH_MEMORY) { return "Not enough memory."; } - if (aError == INVALID_TOKEN) - { + if (aError == INVALID_TOKEN) { return "Empty token during parsing."; } - if (aError == INVALID_EXPRESSION) - { + if (aError == INVALID_EXPRESSION) { return "Error parsing expression."; } - if (aError == UNPRINTABLE_TOKEN) - { + if (aError == UNPRINTABLE_TOKEN) { return "Unprintable atom."; } - if (aError == FILE_NOT_FOUND) - { + if (aError == FILE_NOT_FOUND) { return "File not found."; } - if (aError == READING_FILE) - { + if (aError == READING_FILE) { return "Error reading file."; } - if (aError == CREATING_USER_FUNCTION) - { + if (aError == CREATING_USER_FUNCTION) { return "Could not create user function."; } - if (aError == CREATING_RULE) - { + if (aError == CREATING_RULE) { return "Could not create rule."; } - if (aError == ARITY_ALREADY_DEFINED) - { + if (aError == ARITY_ALREADY_DEFINED) { return "Rule base with this arity already defined."; } - if (aError == COMMENT_TO_END_OF_FILE) - { + if (aError == COMMENT_TO_END_OF_FILE) { return "Reaching end of file within a comment block."; } - if (aError == NOT_A_STRING) - { + if (aError == NOT_A_STRING) { return "Argument is not a string."; } - if (aError == NOT_AN_INTEGER) - { + if (aError == NOT_AN_INTEGER) { return "Argument is not an integer."; } - if (aError == PARSING_INPUT) - { + if (aError == PARSING_INPUT) { return "Error while parsing input."; } - if (aError == MAXIMUM_RECURSE_DEPTH_REACHED) - { + if (aError == MAXIMUM_RECURSE_DEPTH_REACHED) { return "Max evaluation stack depth reached.\nPlease use MaxEvalDepth to increase the stack size as needed."; } - if (aError == DEF_FILE_ALREADY_CHOSEN) - { + if (aError == DEF_FILE_ALREADY_CHOSEN) { return "DefFile already chosen for function."; } - if (aError == DIVIDE_BY_ZERO) - { + if (aError == DIVIDE_BY_ZERO) { return "Divide by zero."; } - if (aError == NOT_AN_INFIX_OPERATOR) - { + if (aError == NOT_AN_INFIX_OPERATOR) { return "Trying to make a non-infix operator right-associative."; } - if (aError == IS_NOT_INFIX) - { + if (aError == IS_NOT_INFIX) { return "Trying to get precedence of non-infix operator."; } - if (aError == SECURITY_BREACH) - { + if (aError == SECURITY_BREACH) { return "Trying to perform an insecure action."; } - if (aError == LIBRARY_NOT_FOUND) - { + if (aError == LIBRARY_NOT_FOUND) { return "Could not find library."; } - if (aError == USER_INTERRUPT) - { + if (aError == USER_INTERRUPT) { return "User halted calculation."; } - if (aError == NON_BOOLEAN_PREDICATE_IN_PATTERN) - { + if (aError == NON_BOOLEAN_PREDICATE_IN_PATTERN) { return "Predicate doesn't evaluate to a boolean in pattern."; } - if (aError == GENERIC_FORMAT) - { + if (aError == GENERIC_FORMAT) { return "Generic format."; } - if (aError == LIST_LENGTHS_MUST_BE_EQUAL) - { + if (aError == LIST_LENGTHS_MUST_BE_EQUAL) { return "List lengths must be equal."; } } return "Unspecified Error."; } - public static void check(boolean hastobetrue, int aError) throws Exception - { - if (!hastobetrue) - { - String errorMessage = errorString(aError);//"LispError number "+aError+" (//TODO FIXME still need to port over the string table)"; - throw new EvaluationException(errorMessage,-1); + + public static void check(Environment aEnvironment, int aStackTop, boolean hastobetrue, int aError, String functionName) throws Exception { + if (!hastobetrue) { + String errorMessage = errorString(aError);// + " In function " + functionName + ". "; + + check(hastobetrue, errorMessage, functionName, aStackTop, aEnvironment); + } }//end method. - public static void check(boolean hastobetrue, String aErrorMessage) throws Exception - { - if (!hastobetrue) - { - throw new EvaluationException(aErrorMessage,-1); + public static void check(boolean predicate, String aErrorMessage, String functionName, int aStackTop, Environment aEnvironment) throws Exception { + if (!predicate) { + String stackTrace = ""; + + if (Evaluator.isStackTraced() && aStackTop >= 0) { + stackTrace = aEnvironment.iArgumentStack.dump(aStackTop, aEnvironment); + + stackTrace = stackTrace + aEnvironment.dumpLocalVariablesFrame(aStackTop); + } + + + if (aStackTop == -1) { + throw new EvaluationException("Error encountered during initialization or parsing: " + aErrorMessage + stackTrace, "none", -1); + } else if (aStackTop == -2) { + throw new EvaluationException("Error: " + aErrorMessage + stackTrace, "none", -1); + } else { + ConsPointer arguments = BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 0); + if (arguments.getCons() == null) { + throw new EvaluationException("Error in compiled code." + stackTrace, "none", -1); + } else { + //TODO FIXME ShowStack(aEnvironment); + aErrorMessage = aErrorMessage + " " + showFunctionError(arguments, aEnvironment) + "internal."; + } + + + throw new EvaluationException(aErrorMessage /*+ " In function " + functionName + ". " */ + stackTrace, "none", -1); + + } } }//end method. - - public static void raiseError(String str) throws Exception - { - throw new EvaluationException(str,-1); + + public static void raiseError(String errorMessage, String functionName, int aStackTop, Environment aEnvironment) throws Exception { + check(false, errorMessage, functionName, aStackTop, aEnvironment); + //throw new EvaluationException(errorMessage + " In function " + functionName + ". ","none",-1); } - public static void checkNumberOfArguments(int n, ConsPointer aArguments, Environment aEnvironment) throws Exception - { - int nrArguments = Utility.listLength(aArguments); - if (nrArguments != n) - { - errorNumberOfArguments(n - 1, nrArguments - 1, aArguments, aEnvironment); + + public static void checkNumberOfArguments(int aStackTop, int n, ConsPointer aArguments, Environment aEnvironment, String functionName) throws Exception { + int nrArguments = Utility.listLength(aEnvironment, aStackTop, aArguments); + if (nrArguments != n) { + errorNumberOfArguments(n - 1, nrArguments - 1, aArguments, aEnvironment, functionName, aStackTop); } } - public static void errorNumberOfArguments(int needed, int passed, ConsPointer aArguments, Environment aEnvironment) throws Exception - { - if (aArguments.getCons() == null) - { - throw new EvaluationException("Error in compiled code.",-1); - } else - { + + public static void errorNumberOfArguments(int needed, int passed, ConsPointer aArguments, Environment aEnvironment, String functionName, int aStackTop) throws Exception { + String stackTrace = ""; + + if (Evaluator.isStackTraced() && aStackTop >= 0) { + stackTrace = aEnvironment.iArgumentStack.dump(aStackTop, aEnvironment); + + stackTrace = stackTrace + aEnvironment.dumpLocalVariablesFrame(aStackTop); + } + + if (aArguments.getCons() == null) { + throw new EvaluationException("Error in compiled code." + stackTrace, "none", -1); + } else { //TODO FIXME ShowStack(aEnvironment); - String error = showFunctionError(aArguments, aEnvironment) + "expected " + needed + " arguments, got " + passed; - throw new EvaluationException(error,-1); + String error = showFunctionError(aArguments, aEnvironment) + "expected " + needed + " arguments, got " + passed + /*" in function " + functionName +*/ ". "; + throw new EvaluationException(error + stackTrace, "none", -1); - /*TODO FIXME - LispChar str[20]; - aEnvironment.iErrorOutput.Write("expected "); - InternalIntToAscii(str,needed); - aEnvironment.iErrorOutput.Write(str); - aEnvironment.iErrorOutput.Write(" arguments, got "); - InternalIntToAscii(str,passed); - aEnvironment.iErrorOutput.Write(str); - aEnvironment.iErrorOutput.Write("\n"); - LispError.check(passed == needed,LispError.WRONG_NUMBER_OF_ARGUMENTS); - */ + /*TODO FIXME + LispChar str[20]; + aEnvironment.iErrorOutput.Write("expected "); + InternalIntToAscii(str,needed); + aEnvironment.iErrorOutput.Write(str); + aEnvironment.iErrorOutput.Write(" arguments, got "); + InternalIntToAscii(str,passed); + aEnvironment.iErrorOutput.Write(str); + aEnvironment.iErrorOutput.Write("\n"); + LispError.check(passed == needed,LispError.WRONG_NUMBER_OF_ARGUMENTS); + */ } } - public static String showFunctionError(ConsPointer aArguments, Environment aEnvironment) throws Exception - { - if (aArguments.getCons() == null) - { + + public static String showFunctionError(ConsPointer aArguments, Environment aEnvironment) throws Exception { + if (aArguments.getCons() == null) { return "Error in compiled code. "; - } else - { + } else { String string = (String) aArguments.car(); - if (string != null) - { + if (string != null) { return "In function \"" + string + "\" : "; } } return "[Atom]"; } - public static void check(Environment aEnvironment, int aStackTop, boolean aPredicate, int errNo) throws Exception - { - if (!aPredicate) - { - ConsPointer arguments = BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 0); - if (arguments.getCons() == null) - { - throw new EvaluationException("Error in compiled code\n",-1); - } else - { - String error = ""; - //TODO FIXME ShowStack(aEnvironment); - error = error + showFunctionError(arguments, aEnvironment) + "generic error."; - throw new EvaluationException(error,-1); + + public static void check(Environment aEnvironment, int aStackTop, boolean aPredicate, int errNo) throws Exception { + if (!aPredicate) { + + String stackTrace = ""; + + if (Evaluator.isStackTraced() && aStackTop >= 0) { + stackTrace = aEnvironment.iArgumentStack.dump(aStackTop, aEnvironment); + + stackTrace = stackTrace + aEnvironment.dumpLocalVariablesFrame(aStackTop); + } + + if (aStackTop == -1) { + throw new EvaluationException("Error encountered during initialization: " + errorString(errNo) + stackTrace, "none", -1); + } else if (aStackTop == -2) { + throw new EvaluationException("Error: " + errorString(errNo) + stackTrace, "none", -1); + } else { + ConsPointer arguments = BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 0); + if (arguments.getCons() == null) { + throw new EvaluationException("Error in compiled code." + stackTrace, "none", -1); + } else { + String error = ""; + error = error + showFunctionError(arguments, aEnvironment) + "internal."; + throw new EvaluationException(error + stackTrace, "none", -1); + } } } } - public static void lispAssert(boolean aPredicate) throws Exception - { - if (!aPredicate) - { - throw new EvaluationException("Assertion failed.",-1); + + public static void lispAssert(boolean aPredicate, Environment aEnvironment, int aStackTop) throws Exception { + if (!aPredicate) { + //throw new EvaluationException("Assertion failed.","none",-1); + check(aPredicate, "Assertion error.", "", aStackTop, aEnvironment); } } - public static void checkArgument(Environment aEnvironment, int aStackTop, boolean aPredicate, int aArgNr) throws Exception - { - checkArgumentTypeWithError(aEnvironment, aStackTop, aPredicate, aArgNr, ""); + + public static void checkArgument(Environment aEnvironment, int aStackTop, boolean aPredicate, int aArgNr, String functionName) throws Exception { + checkArgumentTypeWithError(aEnvironment, aStackTop, aPredicate, aArgNr, "", functionName); } - public static void checkIsList(Environment aEnvironment, int aStackTop, ConsPointer evaluated, int aArgNr) throws Exception - { - checkArgumentTypeWithError(aEnvironment, aStackTop, Utility.isSublist(evaluated), aArgNr, "argument is not a list."); + + public static void checkIsList(Environment aEnvironment, int aStackTop, ConsPointer evaluated, int aArgNr, String functionName) throws Exception { + checkArgumentTypeWithError(aEnvironment, aStackTop, Utility.isSublist(evaluated), aArgNr, "argument is not a list.", functionName); } - public static void checkIsString(Environment aEnvironment, int aStackTop, ConsPointer evaluated, int aArgNr) throws Exception - { - checkArgumentTypeWithError(aEnvironment, aStackTop, Utility.isString( evaluated.car()), aArgNr, "argument is not a string."); + + public static void checkIsString(Environment aEnvironment, int aStackTop, ConsPointer evaluated, int aArgNr, String functionName) throws Exception { + checkArgumentTypeWithError(aEnvironment, aStackTop, Utility.isString(evaluated.car()), aArgNr, "argument is not a string.", functionName); } - public static void checkArgumentTypeWithError(Environment aEnvironment, int aStackTop, boolean aPredicate, int aArgNr, String aErrorDescription) throws Exception - { - if (!aPredicate) - { + + public static void checkArgumentTypeWithError(Environment aEnvironment, int aStackTop, boolean aPredicate, int aArgNr, String aErrorDescription, String functionName) throws Exception { + if (!aPredicate) { + String stackTrace = ""; + + if (Evaluator.isStackTraced() && aStackTop >= 0) { + stackTrace = aEnvironment.iArgumentStack.dump(aStackTop, aEnvironment); + + stackTrace = stackTrace + aEnvironment.dumpLocalVariablesFrame(aStackTop); + } + ConsPointer arguments = BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 0); - if (arguments.getCons() == null) - { - throw new EvaluationException("Error in compiled code\n",-1); - } else - { + if (arguments.getCons() == null) { + throw new EvaluationException("Error in compiled code." + stackTrace, "none", -1); + } else { String error = ""; - //TODO FIXME ShowStack(aEnvironment); error = error + showFunctionError(arguments, aEnvironment) + "\nbad argument number " + aArgNr + "(counting from 1) : \n" + aErrorDescription + "\n"; - ConsPointer arg = BuiltinFunction.getArgumentPointer(arguments, aArgNr); + ConsPointer arg = BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, arguments, aArgNr); String strout; error = error + "The offending argument "; - strout = Utility.printExpression(arg, aEnvironment, 60); + strout = Utility.printMathPiperExpression(aStackTop, arg, aEnvironment, 60); error = error + strout; ConsPointer eval = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, eval, arg); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, eval, arg); error = error + " evaluated to "; - strout = Utility.printExpression(eval, aEnvironment, 60); + strout = Utility.printMathPiperExpression(aStackTop, eval, aEnvironment, 60); error = error + strout; error = error + "\n"; - throw new EvaluationException(error,-1); + throw new EvaluationException(error + stackTrace, "none", -1); }//end else. } } -} \ No newline at end of file + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/LispExpressionEvaluator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/LispExpressionEvaluator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/LispExpressionEvaluator.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/LispExpressionEvaluator.java 2011-02-05 04:04:44.000000000 +0000 @@ -13,22 +13,15 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp; -import org.mathpiper.lisp.*; -import org.mathpiper.lisp.DefFile; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.cons.Cons; -import org.mathpiper.io.MathPiperOutputStream; -import org.mathpiper.io.StringOutputStream; import org.mathpiper.builtin.BuiltinFunctionEvaluator; -import org.mathpiper.lisp.userfunctions.MultipleArityUserFunction; +import org.mathpiper.lisp.rulebases.MultipleArityRulebase; -import org.mathpiper.lisp.userfunctions.SingleArityBranchingUserFunction; -import org.mathpiper.lisp.printers.MathPiperPrinter; -import org.mathpiper.lisp.Evaluator; +import org.mathpiper.lisp.rulebases.SingleArityRulebase; /** * The basic evaluator for Lisp expressions. @@ -52,11 +45,11 @@ * *

  • * If aExpression is a list, the head of the list is - * examined. If the head is not a string. InternalApplyPure() + * examined. If the head is not a string. ApplyFast() * is called. If the head is a string, it is checked against * the core commands (if there is a check, the corresponding * evaluator is called). Then it is checked agaist the list of - * user function with getUserFunction(). Again, the + * user function with getRulebase(). Again, the * corresponding evaluator is called if there is a check. If * all fails, ReturnUnEvaluated() is called.

    *
  • @@ -73,97 +66,127 @@ * @param aExpression the expression to evaluate * @throws java.lang.Exception */ - public void evaluate(Environment aEnvironment, ConsPointer aResult, ConsPointer aExpression) throws Exception { - LispError.lispAssert(aExpression.getCons() != null); + public void evaluate(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aExpression) throws Exception { + + LispError.lispAssert(aExpression.getCons() != null, aEnvironment, aStackTop); synchronized (aEnvironment) { aEnvironment.iEvalDepth++; if (aEnvironment.iEvalDepth >= aEnvironment.iMaxEvalDepth) { - if (aEnvironment.iEvalDepth > aEnvironment.iMaxEvalDepth + 20) { - LispError.check(aEnvironment.iEvalDepth < aEnvironment.iMaxEvalDepth, LispError.USER_INTERRUPT); - } else { - LispError.check(aEnvironment.iEvalDepth < aEnvironment.iMaxEvalDepth, LispError.MAXIMUM_RECURSE_DEPTH_REACHED); - } + /* if (aEnvironment.iEvalDepth > aEnvironment.iMaxEvalDepth + 20) { + LispError.check(aEnvironment, aStackTop, aEnvironment.iEvalDepth < aEnvironment.iMaxEvalDepth, LispError.USER_INTERRUPT, "INTERNAL"); + } else {*/ + LispError.check(aEnvironment, aStackTop, aEnvironment.iEvalDepth < aEnvironment.iMaxEvalDepth, LispError.MAXIMUM_RECURSE_DEPTH_REACHED, "INTERNAL"); + // } + } + + if (Thread.interrupted()) { + LispError.raiseError("User halted calculation.", "", aStackTop, aEnvironment); } } // evaluate an atom: find the bound value (treat it as a variable) - if ( aExpression.car() instanceof String) { + if (aExpression.car() instanceof String) { String str = (String) aExpression.car(); if (str.charAt(0) == '\"') { - aResult.setCons(aExpression.getCons().copy( aEnvironment, false)); + aResult.setCons(aExpression.getCons().copy(aEnvironment, false)); aEnvironment.iEvalDepth--; return; } ConsPointer val = new ConsPointer(); - aEnvironment.getGlobalVariable(str, val); + aEnvironment.getGlobalVariable(aStackTop, str, val); if (val.getCons() != null) { - aResult.setCons(val.getCons().copy( aEnvironment, false)); + aResult.setCons(val.getCons().copy(aEnvironment, false)); aEnvironment.iEvalDepth--; return; } - aResult.setCons(aExpression.getCons().copy( aEnvironment, false)); + aResult.setCons(aExpression.getCons().copy(aEnvironment, false)); aEnvironment.iEvalDepth--; return; } { - if ( aExpression.car() instanceof ConsPointer) { + if (aExpression.car() instanceof ConsPointer) { ConsPointer subList = (ConsPointer) aExpression.car(); Cons head = subList.getCons(); if (head != null) { + + String functionName; + if (head.car() instanceof String) { - { - BuiltinFunctionEvaluator evaluator = (BuiltinFunctionEvaluator) aEnvironment.getBuiltinFunctions().lookUp( (String) head.car()); - // Try to find a built-in command - if (evaluator != null) { - evaluator.evaluate(aEnvironment, aResult, subList); - aEnvironment.iEvalDepth--; - return; - } + + functionName = (String) head.car(); + + //Built-in function handler. + BuiltinFunctionEvaluator builtinInFunctionEvaluator = (BuiltinFunctionEvaluator) aEnvironment.getBuiltinFunctions().lookUp(functionName); + if (builtinInFunctionEvaluator != null) { + builtinInFunctionEvaluator.evaluate(aEnvironment, aStackTop, aResult, subList); + aEnvironment.iEvalDepth--; + return; } - { - SingleArityBranchingUserFunction userFunc; - userFunc = getUserFunction(aEnvironment, subList); - if (userFunc != null) { - userFunc.evaluate(aEnvironment, aResult, subList); - aEnvironment.iEvalDepth--; - return; - } + + //User function handler. + SingleArityRulebase userFunction; + userFunction = getUserFunction(aEnvironment, aStackTop, subList); + if (userFunction != null) { + userFunction.evaluate(aEnvironment, aStackTop, aResult, subList); + aEnvironment.iEvalDepth--; + return; } + + } else { - //printf("ApplyPure!\n"); - ConsPointer oper = new ConsPointer(); + //Pure function handler. + ConsPointer operator = new ConsPointer(); ConsPointer args2 = new ConsPointer(); - oper.setCons(subList.getCons()); + operator.setCons(subList.getCons()); args2.setCons(subList.cdr().getCons()); - Utility.applyPure(oper, args2, aResult, aEnvironment); + Utility.applyPure(aStackTop, operator, args2, aResult, aEnvironment); aEnvironment.iEvalDepth--; return; } //printf("**** Undef: %s\n",head.String().String()); - Utility.returnUnEvaluated(aResult, subList, aEnvironment); + + + /* todo:tk: This code is for experimenting with having non-existent functions throw an exception when they are called. + if (functionName.equals("_")) { + Utility.returnUnEvaluated(aStackTop, aResult, subList, aEnvironment); + aEnvironment.iEvalDepth--; + return; + } else { + LispError.raiseError("The function " + functionName + " is not defined.\n", null, aStackTop, aEnvironment ); + }*/ + + + Utility.returnUnEvaluated(aStackTop, aResult, subList, aEnvironment); + aEnvironment.iEvalDepth--; + return; + + + + } } - aResult.setCons(aExpression.getCons().copy( aEnvironment, false)); + aResult.setCons(aExpression.getCons().copy(aEnvironment, false)); } aEnvironment.iEvalDepth--; } - SingleArityBranchingUserFunction getUserFunction(Environment aEnvironment, ConsPointer subList) throws Exception { + + SingleArityRulebase getUserFunction(Environment aEnvironment, int aStackTop, ConsPointer subList) throws Exception { Cons head = subList.getCons(); - SingleArityBranchingUserFunction userFunc = null; + SingleArityRulebase userFunc = null; - userFunc = (SingleArityBranchingUserFunction) aEnvironment.getUserFunction(subList); + userFunc = (SingleArityRulebase) aEnvironment.getRulebase(aStackTop, subList); if (userFunc != null) { return userFunc; } else if (head.car() instanceof String) { - MultipleArityUserFunction multiUserFunc = aEnvironment.getMultipleArityUserFunction( (String) head.car(), true); + MultipleArityRulebase multiUserFunc = aEnvironment.getMultipleArityRulebase(aStackTop, (String) head.car(), true); if (multiUserFunc.iFileToOpen != null) { DefFile def = multiUserFunc.iFileToOpen; @@ -191,7 +214,7 @@ multiUserFunc.iFileToOpen = null; - Utility.use(aEnvironment, def.iFileName); + Utility.loadScriptOnce(aEnvironment, aStackTop, def.iFileName); if (DEBUG) { //extern int VERBOSE_DEBUG; @@ -213,7 +236,7 @@ } } } - userFunc = aEnvironment.getUserFunction(subList); + userFunc = aEnvironment.getRulebase(aStackTop, subList); } return userFunc; }//end method. @@ -438,9 +461,11 @@ { LispLocalEvaluator local(aEnvironment,NEW BasicEvaluator); LispPtr result; - defaultEval.Eval(aEnvironment, result, iError); + defaultEval.Eval(aEnvironment, result, iException); } */ -}//end class. \ No newline at end of file + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/localvariables/LocalVariableFrame.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/localvariables/LocalVariableFrame.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/localvariables/LocalVariableFrame.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/localvariables/LocalVariableFrame.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,47 +13,44 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.localvariables; - public class LocalVariableFrame - { - public LocalVariableFrame iNext; - public LocalVariable iFirst; - LocalVariable iLast; - private String functionName; - - public LocalVariableFrame(LocalVariableFrame aNext, LocalVariable aFirst, String functionName) - { - iNext = aNext; - iFirst = aFirst; - iLast = aFirst; - this.functionName = functionName; - } +public class LocalVariableFrame { + + public LocalVariableFrame iNext; + public LocalVariable iFirst; + LocalVariable iLast; + private String functionName; + + + public LocalVariableFrame(LocalVariableFrame aNext, LocalVariable aFirst, String functionName) { + iNext = aNext; + iFirst = aFirst; + iLast = aFirst; + this.functionName = functionName; + } + + + public void add(LocalVariable aNew) { + aNew.iNext = iFirst; + iFirst = aNew; + } + - public void add(LocalVariable aNew) - { - aNew.iNext = iFirst; - iFirst = aNew; + public void delete() { + LocalVariable t = iFirst; + LocalVariable next; + while (t != iLast) { + next = t.iNext; + t = next; } + }//end method. - public void delete() - { - LocalVariable t = iFirst; - LocalVariable next; - while (t != iLast) - { - next = t.iNext; - t = next; - } - }//end method. public String getFunctionName() { return functionName; } - +}//end class - }//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/localvariables/LocalVariable.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/localvariables/LocalVariable.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/localvariables/LocalVariable.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/localvariables/LocalVariable.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,27 +13,27 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.localvariables; +import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.cons.Cons; import org.mathpiper.lisp.cons.ConsPointer; - public class LocalVariable - { +public class LocalVariable { + + public LocalVariable iNext; + public String iVariable; + public ConsPointer iValue; - public LocalVariable iNext; - public String iVariable; - public ConsPointer iValue = new ConsPointer(); - - public LocalVariable(String aVariable, Cons aValue) - { - iNext = null; - iVariable = aVariable; - iValue.setCons(aValue); - } + public LocalVariable(Environment aEnvironment, String aVariable, Cons aValue) { + iNext = null; + iVariable = aVariable; + iValue = new ConsPointer(); + iValue.setCons(aValue); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Operator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Operator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Operator.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Operator.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,49 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp; + +public class Operator { + + public int iPrecedence; + public int iLeftPrecedence; + public int iRightPrecedence; + public int iRightAssociative; + + + public Operator(int aPrecedence) { + iPrecedence = aPrecedence; + iLeftPrecedence = aPrecedence; + iRightPrecedence = aPrecedence; + iRightAssociative = 0; + } + + + public void setRightAssociative() { + iRightAssociative = 1; + } + + + public void setLeftPrecedence(int aPrecedence) { + iLeftPrecedence = aPrecedence; + } + + + public void setRightPrecedence(int aPrecedence) { + iRightPrecedence = aPrecedence; + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Atom.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Atom.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Atom.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Atom.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp.parametermatchers; - -import org.mathpiper.builtin.BigNumber; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.cons.NumberCons; - - -/// Class for matching an expression to a given atom. -public class Atom extends PatternParameter -{ - protected String iString; - - public Atom(String aString) - { - iString = aString; - } - - public boolean argumentMatches(Environment aEnvironment, - ConsPointer aExpression, - ConsPointer[] arguments) throws Exception - { - // If it is a floating point, don't even bother comparing - if (aExpression.getCons() != null) - if (aExpression.getCons().getNumber(aEnvironment.getPrecision()) != null) - if (! ((BigNumber) ((NumberCons) aExpression.getCons()).getNumber(aEnvironment.getPrecision())).isInteger()) - return false; - - return (iString == aExpression.car()); - } - - public String getType() - { - return "Atom"; - } - -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/AtomPatternParameterMatcher.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/AtomPatternParameterMatcher.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/AtomPatternParameterMatcher.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/AtomPatternParameterMatcher.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,64 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.parametermatchers; + +import org.mathpiper.builtin.BigNumber; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.NumberCons; + +//Class for matching an expression to a given atom. +public class AtomPatternParameterMatcher extends PatternParameterMatcher { + + protected String iString; + + + public AtomPatternParameterMatcher(String aString) { + iString = aString; + } + + + public boolean argumentMatches(Environment aEnvironment, int aStackTop, ConsPointer aExpression, ConsPointer[] arguments) throws Exception { + + // If it is a floating point, don't even bother comparing + if (aExpression.getCons() != null) { + try { + if (aExpression.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment) != null) { + if (!((BigNumber) ((NumberCons) aExpression.getCons()).getNumber(aEnvironment.getPrecision(), aEnvironment)).isInteger()) { + return false; + } + } + } catch (NumberFormatException e) { + return false; + } + } + + return (iString == aExpression.car()); + } + + + public String getType() { + return "Atom"; + } + + @Override + public String toString() + { + return iString; + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Number.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Number.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Number.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Number.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp.parametermatchers; - -import org.mathpiper.builtin.BigNumber; - -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.LispError; - - -/// Class for matching an expression to a given number. -public class Number extends PatternParameter -{ - protected BigNumber iNumber; - - public Number(BigNumber aNumber) - { - iNumber = aNumber; - } - - public boolean argumentMatches(Environment aEnvironment, - ConsPointer aExpression, - ConsPointer[] arguments) throws Exception - { -// LispError.check(aExpression.type().equals("Number"), LispError.KLispErrInvalidArg); - BigNumber bigNumber = (BigNumber) aExpression.getCons().getNumber(aEnvironment.getPrecision()); - if (bigNumber != null) - return iNumber.equals(bigNumber); - return false; - } - - public String getType() - { - return "Number"; - } - -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/NumberPatternParameterMatcher.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/NumberPatternParameterMatcher.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/NumberPatternParameterMatcher.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/NumberPatternParameterMatcher.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,58 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.parametermatchers; + +import org.mathpiper.builtin.BigNumber; + +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Environment; + +/// Class for matching an expression to a given number. +public class NumberPatternParameterMatcher extends PatternParameterMatcher { + + protected BigNumber iNumber; + + + public NumberPatternParameterMatcher(BigNumber aNumber) { + iNumber = aNumber; + } + + + public boolean argumentMatches(Environment aEnvironment, int aStackTop, ConsPointer aExpression, ConsPointer[] arguments) throws Exception { + + BigNumber bigNumber = (BigNumber) aExpression.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + + if (bigNumber != null) { + return iNumber.equals(bigNumber); + } + + return false; + } + + + public String getType() { + return "Number"; + } + + + @Override + public String toString() + { + return this.iNumber.toString(); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/ParametersPatternMatcher.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/ParametersPatternMatcher.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/ParametersPatternMatcher.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/ParametersPatternMatcher.java 2010-07-19 00:43:47.000000000 +0000 @@ -0,0 +1,404 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.parametermatchers; + +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsTraverser; +//import org.mathpiper.lisp.AtomCons; +import org.mathpiper.lisp.Environment; +//import org.mathpiper.lisp.SublistCons; +import java.util.*; +import org.mathpiper.builtin.BigNumber; + +/** + *ParametersPatternMatcher matching code. + * + *General idea: have a class that can match function parameters + *to a pattern, check for predicates on the arguments, and return + *whether there was a match. + * + *First the pattern is mapped onto the arguments. Then local variables + *are set. Then the predicates are called. If they all return true, + *Then the pattern matches, and the locals can stay (the body is expected + *to use these variables). + * + *Class that matches function arguments to a pattern. + *This class (specifically, the matches() member function) can match + *function parameters to a pattern, check for predicates on the + *arguments, and return whether there was a match. + */ +public class ParametersPatternMatcher { + //List of parameter matchers, one for every parameter. + protected List iParamMatchers = new ArrayList(); + + // List of variables appearing in the pattern. + protected List iVariables = new ArrayList(); + + // List of predicates which need to be true for a match. + protected List iPredicates = new ArrayList(); + + + /** + *Constructor. + *@param aEnvironment the underlying Lisp environment + *@param aPattern Lisp expression containing the pattern + *@param aPostPredicate Lisp expression containing the postpredicate + * + *The function makeParameterMatcher() is called for every argument + *in aPattern, and the resulting pattern matchers are + *collected in iParamMatchers. Additionally, aPostPredicate + *is copied, and the copy is added to iPredicates. + */ + public ParametersPatternMatcher(Environment aEnvironment, int aStackTop, ConsPointer aPattern, ConsPointer aPostPredicate) throws Exception { + + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, aPattern); + + while (consTraverser.getCons() != null) { + + PatternParameterMatcher matcher = makeParameterMatcher(aEnvironment, aStackTop, consTraverser.getCons()); + + LispError.lispAssert(matcher != null, aEnvironment, aStackTop); + + iParamMatchers.add(matcher); + + consTraverser.goNext(aStackTop); + }//end while. + + ConsPointer postPredicatesPointer = new ConsPointer(); + + postPredicatesPointer.setCons(aPostPredicate.getCons()); + + iPredicates.add(postPredicatesPointer); + + + }//end method. + + + /* + Try to match the pattern against aArguments. + First, every argument in aArguments is matched against the + corresponding PatternParameterMatcher in iParamMatches. If any + match fails, matches() returns false. Otherwise, a temporary + LispLocalFrame is constructed, then setPatternVariables() and + checkPredicates() are called, and then the LispLocalFrame is + immediately deleted. If checkPredicates() returns false, this + function also returns false. Otherwise, setPatternVariables() + is called again, but now in the current LispLocalFrame, and + this function returns true. + */ + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer aArguments) throws Exception { + int i; + + ConsPointer[] argumentsPointer = null; + if (iVariables.size() > 0) { + argumentsPointer = new ConsPointer[iVariables.size()]; + for (i = 0; i < iVariables.size(); i++) { + argumentsPointer[i] = new ConsPointer(); + } + + } + ConsTraverser argumentsTraverser = new ConsTraverser(aEnvironment, aArguments); + + for (i = 0; i < iParamMatchers.size(); i++) { + if (argumentsTraverser.getCons() == null) { + return false; + } + ConsPointer argumentsPointer2 = argumentsTraverser.getPointer(); + if (argumentsPointer2 == null) { + return false; + } + if (!((PatternParameterMatcher) iParamMatchers.get(i)).argumentMatches(aEnvironment, aStackTop, argumentsPointer2, argumentsPointer)) { + return false; + } + argumentsTraverser.goNext(aStackTop); + } + if (argumentsTraverser.getCons() != null) { + return false; + } + + { + //Set the local variables. + aEnvironment.pushLocalFrame(false, "Pattern"); + try { + setPatternVariables(aEnvironment, argumentsPointer, aStackTop); + + //Do the predicates + if (!checkPredicates(aEnvironment, aStackTop)) { + return false; + } + } catch (Exception e) { + throw e; + } finally { + aEnvironment.popLocalFrame(aStackTop); + } + } + + // setCons the local variables for sure now + setPatternVariables(aEnvironment, argumentsPointer, aStackTop); + + return true; + } + + + /** + *Try to match the pattern against aArguments. + *This function does the same as matches(Environment, ConsPointer), + *but differs in the type of the arguments. + */ + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer[] aArguments) throws Exception { + int i; + + ConsPointer[] arguments = null; + if (iVariables.size() > 0) { + arguments = new ConsPointer[iVariables.size()]; + } + for (i = 0; i < iVariables.size(); i++) { + arguments[i] = new ConsPointer(); + } + + + + for (i = 0; i < iParamMatchers.size(); i++) { + LispError.check(i < aArguments.length, "Listed function definitions need at least two parameters.", "INTERNAL", aStackTop, aEnvironment); + PatternParameterMatcher patternParameter = (PatternParameterMatcher) iParamMatchers.get(i); + ConsPointer argument = aArguments[i]; + if (!patternParameter.argumentMatches(aEnvironment, aStackTop, argument, arguments)) { + return false; + } + } + + { + //Set the local variables. + aEnvironment.pushLocalFrame(false, "Pattern"); + try { + setPatternVariables(aEnvironment, arguments, aStackTop); + + //Check the predicates. + if (!checkPredicates(aEnvironment, aStackTop)) { + return false; + } + } catch (Exception e) { + throw e; + } finally { + aEnvironment.popLocalFrame(aStackTop); + } + } + + // Set the local variables for sure now. + setPatternVariables(aEnvironment, arguments, aStackTop); + + return true; + } + + + /* + Construct a pattern matcher out of a Lisp expression. + The result of this function depends on the value of aPattern: + - If aPattern is a number, the corresponding NumberPatternParameterMatcher is + constructed and returned. + - If aPattern is an atom, the corresponding AtomCons is + constructed and returned. + - If aPattern is a list of the form ( _var ), + where var is an atom, lookUp() is called on var. Then + the correspoding VariablePatternParameterMatcher is constructed and returned. + - If aPattern is a list of the form ( var_expr ), + where var is an atom, lookUp() is called on var. Then, + expr is appended to #iPredicates. Finally, the + correspoding VariablePatternParameterMatcher is constructed and returned. + - If aPattern is a list of another form, this function + calls itself on any of the entries in this list. The + resulting PatternParameterMatcher objects are collected in a + SublistCons, which is returned. + - Otherwise, this function returns #null. + */ + protected PatternParameterMatcher makeParameterMatcher(Environment aEnvironment, int aStackTop, Cons aPattern) throws Exception { + + if (aPattern == null) { + return null; + } + + + //Check for a number pattern. + if (aPattern.getNumber(aEnvironment.getPrecision(), aEnvironment) != null) { + return new NumberPatternParameterMatcher((BigNumber) aPattern.getNumber(aEnvironment.getPrecision(), aEnvironment)); + } + + + //Check for an atom pattern. + if (aPattern.car() instanceof String) { + return new AtomPatternParameterMatcher((String) aPattern.car()); + } + + + // Else, it must be a sublist pattern. + if (aPattern.car() instanceof ConsPointer) { + + // See if it is a variable template: + ConsPointer sublist = (ConsPointer) aPattern.car(); + //LispError.lispAssert(sublist != null); + + int num = Utility.listLength(aEnvironment, aStackTop, sublist); + + // variable matcher here... + if (num > 1) { + Cons head = sublist.getCons(); + + //Handle _ prefix or suffix on a pattern variables. + if (((String) head.car()) == aEnvironment.getTokenHash().lookUp("_")) { + Cons second = head.cdr().getCons(); + if (second.car() instanceof String) { + int index = lookUp((String) second.car()); + + + if (num > 2) { + //Handle a pattern variable which has a predicate (like var_PredicateFunction). + ConsPointer third = new ConsPointer(); + + Cons predicate = second.cdr().getCons(); + if ((predicate.car() instanceof ConsPointer)) { + Utility.flatCopy(aEnvironment, aStackTop, third, (ConsPointer) predicate.car()); + } else { + third.setCons(second.cdr().getCons().copy(aEnvironment, false)); + } + + String str = (String) second.car(); + Cons last = third.getCons(); + while (last.cdr().getCons() != null) { + last = last.cdr().getCons(); + } + + last.cdr().setCons(org.mathpiper.lisp.cons.AtomCons.getInstance(aEnvironment, aStackTop, str)); + + ConsPointer newPredicate = new ConsPointer(); + newPredicate.setCons(org.mathpiper.lisp.cons.SublistCons.getInstance(aEnvironment, third.getCons())); + + iPredicates.add(newPredicate); + }//end if. + + return new VariablePatternParameterMatcher(index); + } + } + } + + PatternParameterMatcher[] matchers = new PatternParameterMatcher[num]; + + int i; + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, sublist); + for (i = 0; i < num; i++) { + matchers[i] = makeParameterMatcher(aEnvironment, aStackTop, consTraverser.getCons()); + LispError.lispAssert(matchers[i] != null, aEnvironment, aStackTop); + consTraverser.goNext(aStackTop); + } + return new SublistPatternParameterMatcher(matchers, num); + } + + return null; + + }//end method. + + + /* + *Look up a variable name in iVariables. + *Returns index in iVariables array where aVariable + *appears. If aVariable is not in iVariables, it is added. + */ + protected int lookUp(String aVariable) { + int i; + for (i = 0; i < iVariables.size(); i++) { + if (iVariables.get(i) == aVariable) { + return i; + } + } + iVariables.add(aVariable); + return iVariables.size() - 1; + } + + + /** + *Set local variables corresponding to the pattern variables. + *This function goes through the #iVariables array. A local + *variable is made for every entry in the array, and the + *corresponding argument is assigned to it. + */ + protected void setPatternVariables(Environment aEnvironment, ConsPointer[] arguments, int aStackTop) throws Exception { + int i; + for (i = 0; i < iVariables.size(); i++) { + //Set the variable to the new value + aEnvironment.newLocalVariable((String) iVariables.get(i), arguments[i].getCons(), aStackTop); + } + } + + + /** + *Check whether all predicates are true. + *This function goes through all predicates in iPredicates and + *evaluates them. It returns false if at least one + *of these results IsFalse(). An error is raised if any result + *that is neither IsTrue() nor IsFalse(). + */ + protected boolean checkPredicates(Environment aEnvironment, int aStackTop) throws Exception { + int i; + for (i = 0; i < iPredicates.size(); i++) { + + ConsPointer resultPredicate = new ConsPointer(); + + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, resultPredicate, ((ConsPointer) iPredicates.get(i))); + + if (Utility.isFalse(aEnvironment, resultPredicate, aStackTop)) { + return false; + } + + + // If the result is not False, it should be True, else probably something is wrong (the expression returned unevaluated) + boolean isTrue = Utility.isTrue(aEnvironment, resultPredicate, aStackTop); + if (!isTrue) { + //TODO this is probably not the right way to generate an error, should we perhaps do a full throw new MathPiperException here? + String strout; + aEnvironment.write("The predicate\n\t"); + strout = Utility.printMathPiperExpression(aStackTop, ((ConsPointer) iPredicates.get(i)), aEnvironment, 60); + aEnvironment.write(strout); + aEnvironment.write("\nevaluated to\n\t"); + strout = Utility.printMathPiperExpression(aStackTop, resultPredicate, aEnvironment, 60); + aEnvironment.write(strout); + aEnvironment.write("\n"); + + LispError.check(aEnvironment, aStackTop, isTrue, LispError.NON_BOOLEAN_PREDICATE_IN_PATTERN, "INTERNAL"); + } + } + return true; + } + + + public List getParameterMatchers() { + return iParamMatchers; + } + + + public List getPredicates() { + return iPredicates; + } + + + public List getVariables() { + return iVariables; + } + +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Pattern.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Pattern.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Pattern.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Pattern.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,360 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.lisp.parametermatchers; - -import org.mathpiper.lisp.cons.Cons; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsTraverser; -//import org.mathpiper.lisp.AtomCons; -import org.mathpiper.lisp.Environment; -//import org.mathpiper.lisp.SublistCons; -import java.util.*; -import org.mathpiper.builtin.BigNumber; - -/** - *Pattern matching code. - * - *General idea: have a class that can match function parameters - *to a pattern, check for predicates on the arguments, and return - *whether there was a match. - * - *First the pattern is mapped onto the arguments. Then local variables - *are set. Then the predicates are called. If they all return true, - *Then the pattern matches, and the locals can stay (the body is expected - *to use these variables). - * - *Class that matches function arguments to a pattern. - *This class (specifically, the matches() member function) can match - *function parameters to a pattern, check for predicates on the - *arguments, and return whether there was a match. - */ -public class Pattern { - /// List of parameter matches, one for every parameter. - protected List iParamMatchers = new ArrayList(); //CDeletingArrayGrower iParamMatchers; - - /// List of variables appearing in the pattern. - protected List iVariables = new ArrayList(); //CArrayGrower - - /// List of predicates which need to be true for a match. - protected List iPredicates = new ArrayList(); //CDeletingArrayGrower - - /// Constructor. - /// \param aEnvironment the underlying Lisp environment - /// \param aPattern Lisp expression containing the pattern - /// \param aPostPredicate Lisp expression containing the - /// postpredicate - /// - /// The function MakePatternMatcher() is called for every argument - /// in \a aPattern, and the resulting pattern matchers are - /// collected in #iParamMatchers. Additionally, \a aPostPredicate - /// is copied, and the copy is added to #iPredicates. - public Pattern(Environment aEnvironment, - ConsPointer aPattern, - ConsPointer aPostPredicate) throws Exception { - ConsTraverser consTraverser = new ConsTraverser(aPattern); - - while (consTraverser.getCons() != null) { - PatternParameter matcher = makeParamMatcher(aEnvironment, consTraverser.getCons()); - LispError.lispAssert(matcher != null); - iParamMatchers.add(matcher); - consTraverser.goNext(); - } - ConsPointer post = new ConsPointer(); - post.setCons(aPostPredicate.getCons()); - iPredicates.add(post); - } - - - /// Try to match the pattern against \a aArguments. - /// First, every argument in \a aArguments is matched against the - /// corresponding PatternParameter in #iParamMatches. If any - /// match fails, matches() returns false. Otherwise, a temporary - /// LispLocalFrame is constructed, then setPatternVariables() and - /// checkPredicates() are called, and then the LispLocalFrame is - /// immediately deleted. If checkPredicates() returns false, this - /// function also returns false. Otherwise, setPatternVariables() - /// is called again, but now in the current LispLocalFrame, and - /// this function returns true. - public boolean matches(Environment aEnvironment, ConsPointer aArguments) throws Exception { - int i; - - ConsPointer[] argumentsPointer = null; - if (iVariables.size() > 0) { - argumentsPointer = new ConsPointer[iVariables.size()]; - for (i = 0; i < iVariables.size(); i++) { - argumentsPointer[i] = new ConsPointer(); - } - - } - ConsTraverser argumentsTraverser = new ConsTraverser(aArguments); - - for (i = 0; i < iParamMatchers.size(); i++) { - if (argumentsTraverser.getCons() == null) { - return false; - } - ConsPointer argumentsPointer2 = argumentsTraverser.getPointer(); - if (argumentsPointer2 == null) { - return false; - } - if (!((PatternParameter) iParamMatchers.get(i)).argumentMatches(aEnvironment, argumentsPointer2, argumentsPointer)) { - return false; - } - argumentsTraverser.goNext(); - } - if (argumentsTraverser.getCons() != null) { - return false; - } - - { - // setCons the local variables. - aEnvironment.pushLocalFrame(false, "Pattern"); - try { - setPatternVariables(aEnvironment, argumentsPointer); - - // do the predicates - if (!checkPredicates(aEnvironment)) { - return false; - } - } catch (Exception e) { - throw e; - } finally { - aEnvironment.popLocalFrame(); - } - } - - // setCons the local variables for sure now - setPatternVariables(aEnvironment, argumentsPointer); - - return true; - } - - /// Try to match the pattern against \a aArguments. - /// This function does the same as matches(Environment ,ConsPointer ), - /// but differs in the type of the arguments. - public boolean matches(Environment aEnvironment, ConsPointer[] aArguments) throws Exception { - int i; - - ConsPointer[] arguments = null; - if (iVariables.size() > 0) { - arguments = new ConsPointer[iVariables.size()]; - } - for (i = 0; i < iVariables.size(); i++) { - arguments[i] = new ConsPointer(); - } - - - - for (i = 0; i < iParamMatchers.size(); i++) { - LispError.check(i < aArguments.length, "Listed function definitions need at least two parameters."); - PatternParameter patternParameter = (PatternParameter) iParamMatchers.get(i); - ConsPointer argument = aArguments[i]; - if (! patternParameter.argumentMatches(aEnvironment, argument, arguments)) { - return false; - } - } - - { - // setCons the local variables. - aEnvironment.pushLocalFrame(false, "Pattern"); - try { - setPatternVariables(aEnvironment, arguments); - - // do the predicates - if (!checkPredicates(aEnvironment)) { - return false; - } - } catch (Exception e) { - throw e; - } finally { - aEnvironment.popLocalFrame(); - } - } - - // setCons the local variables for sure now - setPatternVariables(aEnvironment, arguments); - return true; - } - - /// Construct a pattern matcher out of a Lisp expression. - /// The result of this function depends on the value of \a aPattern: - /// - If \a aPattern is a number, the corresponding Number is - /// constructed and returned. - /// - If \a aPattern is an atom, the corresponding AtomCons is - /// constructed and returned. - /// - If \a aPattern is a list of the form ( _ var ), - /// where \c var is an atom, lookUp() is called on \c var. Then - /// the correspoding Variable is constructed and returned. - /// - If \a aPattern is a list of the form ( _ var expr ), - /// where \c var is an atom, lookUp() is called on \c var. Then, - /// \a expr is appended to #iPredicates. Finally, the - /// correspoding Variable is constructed and returned. - /// - If \a aPattern is a list of another form, this function - /// calls itself on any of the entries in this list. The - /// resulting PatternParameter objects are collected in a - /// SublistCons, which is returned. - /// - Otherwise, this function returns #null. - protected PatternParameter makeParamMatcher(Environment aEnvironment, Cons aPattern) throws Exception { - if (aPattern == null) { - return null; - } - //LispError.check(aPattern.type().equals("Number"), LispError.INVALID_ARGUMENT); - if (aPattern.getNumber(aEnvironment.getPrecision()) != null) { - return new Number((BigNumber) aPattern.getNumber(aEnvironment.getPrecision())); - } - // Deal with atoms - if (aPattern.car() instanceof String) { - return new Atom( (String) aPattern.car()); - } - - // Else it must be a sublist - if (aPattern.car() instanceof ConsPointer) { - // See if it is a variable template: - ConsPointer sublist = (ConsPointer) aPattern.car(); - //LispError.lispAssert(sublist != null); - - int num = Utility.listLength(sublist); - - // variable matcher here... - if (num > 1) { - Cons head = sublist.getCons(); - if (((String) head.car()) == aEnvironment.getTokenHash().lookUp("_")) { - Cons second = head.cdr().getCons(); - if (second.car() instanceof String) { - int index = lookUp( (String) second.car()); - - // Make a predicate for the type, if needed - if (num > 2) { - ConsPointer third = new ConsPointer(); - - Cons predicate = second.cdr().getCons(); - if ( (predicate.car() instanceof ConsPointer)) { - Utility.flatCopy(aEnvironment, third, (ConsPointer) predicate.car()); - } else { - third.setCons(second.cdr().getCons().copy( aEnvironment, false)); - } - - String str = (String) second.car(); - Cons last = third.getCons(); - while (last.cdr().getCons() != null) { - last = last.cdr().getCons(); - } - - last.cdr().setCons(org.mathpiper.lisp.cons.AtomCons.getInstance(aEnvironment, str)); - - ConsPointer pred = new ConsPointer(); - pred.setCons(org.mathpiper.lisp.cons.SublistCons.getInstance(aEnvironment,third.getCons())); - - iPredicates.add(pred); - } - return new Variable(index); - } - } - } - - PatternParameter[] matchers = new PatternParameter[num]; - - int i; - ConsTraverser consTraverser = new ConsTraverser(sublist); - for (i = 0; i < num; i++) { - matchers[i] = makeParamMatcher(aEnvironment, consTraverser.getCons()); - LispError.lispAssert(matchers[i] != null); - consTraverser.goNext(); - } - return new Sublist(matchers, num); - } - - return null; - } - - /// Look up a variable name in #iVariables - /// \returns index in #iVariables array where \a aVariable - /// appears. - /// - /// If \a aVariable is not in #iVariables, it is added. - protected int lookUp(String aVariable) { - int i; - for (i = 0; i < iVariables.size(); i++) { - if (iVariables.get(i) == aVariable) { - return i; - } - } - iVariables.add(aVariable); - return iVariables.size() - 1; - } - - /// Set local variables corresponding to the pattern variables. - /// This function goes through the #iVariables array. A local - /// variable is made for every entry in the array, and the - /// corresponding argument is assigned to it. - protected void setPatternVariables(Environment aEnvironment, ConsPointer[] arguments) throws Exception { - int i; - for (i = 0; i < iVariables.size(); i++) { - // setCons the variable to the new value - aEnvironment.newLocalVariable((String) iVariables.get(i), arguments[i].getCons()); - } - } - - /// check whether all predicates are true. - /// This function goes through all predicates in #iPredicates, and - /// evaluates them. It returns #false if at least one - /// of these results IsFalse(). An error is raised if any result - /// neither IsTrue() nor IsFalse(). - protected boolean checkPredicates(Environment aEnvironment) throws Exception { - int i; - for (i = 0; i < iPredicates.size(); i++) { - ConsPointer pred = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, pred, ((ConsPointer) iPredicates.get(i))); - if (Utility.isFalse(aEnvironment, pred)) { - return false; - } - - - // If the result is not False, it should be True, else probably something is wrong (the expression returned unevaluated) - boolean isTrue = Utility.isTrue(aEnvironment, pred); - if (!isTrue) { - //TODO this is probably not the right way to generate an error, should we perhaps do a full throw new MathPiperException here? - String strout; - aEnvironment.write("The predicate\n\t"); - strout = Utility.printExpression(((ConsPointer) iPredicates.get(i)), aEnvironment, 60); - aEnvironment.write(strout); - aEnvironment.write("\nevaluated to\n\t"); - strout = Utility.printExpression(pred, aEnvironment, 60); - aEnvironment.write(strout); - aEnvironment.write("\n"); - - LispError.check(isTrue, LispError.NON_BOOLEAN_PREDICATE_IN_PATTERN); - } - } - return true; - } - - public List getParameterMatchers() { - return iParamMatchers; - } - - public List getPredicates() { - return iPredicates; - } - - public List getVariables() { - return iVariables; - } -} - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/PatternParameter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/PatternParameter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/PatternParameter.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/PatternParameter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp.parametermatchers; - -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Environment; - - -/// Abstract class for matching one argument to a pattern. -public abstract class PatternParameter -{ - /// Check whether some expression matches to the pattern. - /// \param aEnvironment the underlying Lisp environment. - /// \param aExpression the expression to test. - /// \param arguments (input/output) actual values of the pattern - /// variables for \a aExpression. - public abstract boolean argumentMatches(Environment aEnvironment, - ConsPointer aExpression, - ConsPointer[] arguments) throws Exception; - - public abstract String getType(); -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/PatternParameterMatcher.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/PatternParameterMatcher.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/PatternParameterMatcher.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/PatternParameterMatcher.java 2010-07-18 20:33:50.000000000 +0000 @@ -0,0 +1,36 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.parametermatchers; + +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Environment; + +//Abstract class for matching one argument to a pattern. +public abstract class PatternParameterMatcher { + + /** + *Check whether some expression matches to the pattern. + *@aEnvironment the underlying Lisp environment. + *@aExpression the expression to test. + *@arguments (input/output) actual values of the pattern variables for aExpression. + */ + public abstract boolean argumentMatches(Environment aEnvironment, int aStackTop, ConsPointer aExpression, ConsPointer[] arguments) throws Exception; + + + public abstract String getType(); + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Sublist.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Sublist.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parametermatchers/Sublist.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parametermatchers/Sublist.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp.parametermatchers; - -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.cons.ConsTraverser; -import org.mathpiper.lisp.Environment; - - -/// Class for matching against a list of PatternParameter objects. -public class Sublist extends PatternParameter -{ - protected PatternParameter[] iMatchers; - protected int iNrMatchers; - - public Sublist(PatternParameter[] aMatchers, int aNrMatchers) - { - iMatchers = aMatchers; - iNrMatchers = aNrMatchers; - } - - public boolean argumentMatches(Environment aEnvironment, - ConsPointer aExpression, - ConsPointer[] arguments) throws Exception - { - if (!(aExpression.car() instanceof ConsPointer)) - return false; - int i; - - ConsTraverser consTraverser = new ConsTraverser(aExpression); - consTraverser.goSub(); - - for (i=0;i 0 && iLookAhead != iEnvironment.iEndStatementAtom.car()) { - readToken(); + readToken(aStackTop); } } @@ -96,13 +99,13 @@ { iSExpressionResult.setCons(null); } - LispError.check(!iError, LispError.INVALID_EXPRESSION); + LispError.check(iEnvironment, aStackTop, !iError, LispError.INVALID_EXPRESSION, "INTERNAL"); } - void readToken() throws Exception + void readToken(int aStackTop) throws Exception { // Get token. - iLookAhead = iTokenizer.nextToken(iInput, + iLookAhead = iTokenizer.nextToken(iEnvironment, aStackTop, iInput, iEnvironment.getTokenHash()); if (iLookAhead.length() == 0) { @@ -110,18 +113,18 @@ } } - void matchToken(String aToken) throws Exception + void matchToken(int aStackTop, String aToken) throws Exception { - if (aToken != iLookAhead) + if (!aToken.equals(iLookAhead)) { - fail(); + fail(aStackTop); } - readToken(); + readToken(aStackTop); } - void readExpression(Environment aEnvironment,int depth) throws Exception + void readExpression(Environment aEnvironment,int aStackTop, int depth) throws Exception { - readAtom(aEnvironment); + readAtom(aEnvironment, aStackTop); for (;;) { @@ -129,30 +132,30 @@ if (iLookAhead == iEnvironment.iProgOpenAtom.car()) { // Match opening bracket - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); // Read "index" argument - readExpression(aEnvironment,MathPiperPrinter.KMaxPrecedence); + readExpression(aEnvironment, aStackTop, MathPiperPrinter.KMaxPrecedence); // Match closing bracket if (iLookAhead != iEnvironment.iProgCloseAtom.car()) { - LispError.raiseError("Expecting a ] close bracket for program block, but got " + iLookAhead + " instead."); + LispError.raiseError("Expecting a ] close bracket for program block, but got " + iLookAhead + " instead.", "[INTERNAL]", aStackTop, aEnvironment); return; } - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); // Build into Ntn(...) String theOperator = (String) iEnvironment.iNthAtom.car(); - insertAtom(theOperator); - combine(aEnvironment,2); + insertAtom(aStackTop, theOperator); + combine(aEnvironment,aStackTop, 2); } else { - InfixOperator op = (InfixOperator) iInfixOperators.lookUp(iLookAhead); + Operator op = (Operator) iInfixOperators.lookUp(iLookAhead); if (op == null) { //printf("op [%s]\n",iLookAhead.String()); if(iLookAhead.equals("")) { - LispError.raiseError("Expression must end with a semi-colon (;)"); + LispError.raiseError("Expression must end with a semi-colon (;)", "[INTERNAL]", aStackTop, aEnvironment); return; } if (MathPiperTokenizer.isSymbolic(iLookAhead.charAt(0))) @@ -168,7 +171,7 @@ (String) iEnvironment.getTokenHash().lookUp(iLookAhead.substring(0, len)); //printf("trunc %s\n",lookUp.String()); - op = (InfixOperator) iInfixOperators.lookUp(lookUp); + op = (Operator) iInfixOperators.lookUp(lookUp); //if (op) printf("FOUND\n"); if (op != null) { @@ -216,183 +219,183 @@ { upper--; } - getOtherSide(aEnvironment,2, upper); + getOtherSide(aEnvironment,aStackTop, 2, upper); } } } - void readAtom(Environment aEnvironment) throws Exception + void readAtom(Environment aEnvironment, int aStackTop) throws Exception { - InfixOperator op; + Operator op; // parse prefix operators - op = (InfixOperator) iPrefixOperators.lookUp(iLookAhead); + op = (Operator) iPrefixOperators.lookUp(iLookAhead); if (op != null) { String theOperator = iLookAhead; - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); { - readExpression(aEnvironment,op.iPrecedence); - insertAtom(theOperator); - combine(aEnvironment,1); + readExpression(aEnvironment,aStackTop, op.iPrecedence); + insertAtom(aStackTop, theOperator); + combine(aEnvironment,aStackTop, 1); } } // Else parse brackets else if (iLookAhead == iEnvironment.iBracketOpenAtom.car()) { - matchToken(iLookAhead); - readExpression(aEnvironment,MathPiperPrinter.KMaxPrecedence); // least precedence - matchToken( (String) iEnvironment.iBracketCloseAtom.car()); + matchToken(aStackTop, iLookAhead); + readExpression(aEnvironment,aStackTop, MathPiperPrinter.KMaxPrecedence); // least precedence + matchToken( aStackTop, (String) iEnvironment.iBracketCloseAtom.car()); } //parse lists else if (iLookAhead == iEnvironment.iListOpenAtom.car()) { int nrargs = 0; - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); while (iLookAhead != iEnvironment.iListCloseAtom.car()) { - readExpression(aEnvironment,MathPiperPrinter.KMaxPrecedence); // least precedence + readExpression(aEnvironment,aStackTop, MathPiperPrinter.KMaxPrecedence); // least precedence nrargs++; if (iLookAhead == iEnvironment.iCommaAtom.car()) { - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); } else if (iLookAhead != iEnvironment.iListCloseAtom.car()) { - LispError.raiseError("Expecting a } close bracket for a list, but got " + iLookAhead + " instead."); + LispError.raiseError("Expecting a } close bracket for a list, but got " + iLookAhead + " instead.", "[INTERNAL]", aStackTop, aEnvironment); return; } } - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); String theOperator = (String) iEnvironment.iListAtom.car(); - insertAtom(theOperator); - combine(aEnvironment, nrargs); + insertAtom(aStackTop, theOperator); + combine(aEnvironment, aStackTop, nrargs); } // parse prog bodies else if (iLookAhead == iEnvironment.iProgOpenAtom.car()) { int nrargs = 0; - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); while (iLookAhead != iEnvironment.iProgCloseAtom.car()) { - readExpression(aEnvironment,MathPiperPrinter.KMaxPrecedence); // least precedence + readExpression(aEnvironment,aStackTop, MathPiperPrinter.KMaxPrecedence); // least precedence nrargs++; if (iLookAhead == iEnvironment.iEndStatementAtom.car()) { - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); } else { - LispError.raiseError("Expecting ; end of statement in program block, but got " + iLookAhead + " instead."); + LispError.raiseError("Expecting ; end of statement in program block, but got " + iLookAhead + " instead.", "[INTERNAL]", aStackTop, aEnvironment); return; } } - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); String theOperator = (String) iEnvironment.iProgAtom.car(); - insertAtom(theOperator); + insertAtom(aStackTop, theOperator); - combine(aEnvironment, nrargs); + combine(aEnvironment, aStackTop, nrargs); } // Else we have an atom. else { String theOperator = iLookAhead; - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); int nrargs = -1; if (iLookAhead == iEnvironment.iBracketOpenAtom.car()) { nrargs = 0; - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); while (iLookAhead != iEnvironment.iBracketCloseAtom.car()) { - readExpression(aEnvironment,MathPiperPrinter.KMaxPrecedence); // least precedence + readExpression(aEnvironment,aStackTop, MathPiperPrinter.KMaxPrecedence); // least precedence nrargs++; if (iLookAhead == iEnvironment.iCommaAtom.car()) { - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); } else if (iLookAhead != iEnvironment.iBracketCloseAtom.car()) { - LispError.raiseError("Expecting ) closing bracket for sub-expression, but got " + iLookAhead + " instead."); + LispError.raiseError("Expecting ) closing bracket for sub-expression, but got " + iLookAhead + " instead.", "[INTERNAL]", aStackTop, aEnvironment); return; } } - matchToken(iLookAhead); + matchToken(aStackTop, iLookAhead); - op = (InfixOperator) iBodiedOperators.lookUp(theOperator); + op = (Operator) iBodiedOperators.lookUp(theOperator); if (op != null) { - readExpression(aEnvironment,op.iPrecedence); // MathPiperPrinter.KMaxPrecedence + readExpression(aEnvironment,aStackTop, op.iPrecedence); // MathPiperPrinter.KMaxPrecedence nrargs++; } } - insertAtom(theOperator); + insertAtom(aStackTop, theOperator); if (nrargs >= 0) { - combine(aEnvironment, nrargs); + combine(aEnvironment, aStackTop, nrargs); } } // parse postfix operators - while ((op = (InfixOperator) iPostfixOperators.lookUp(iLookAhead)) != null) + while ((op = (Operator) iPostfixOperators.lookUp(iLookAhead)) != null) { - insertAtom(iLookAhead); - matchToken(iLookAhead); - combine(aEnvironment,1); + insertAtom(aStackTop, iLookAhead); + matchToken(aStackTop, iLookAhead); + combine(aEnvironment,aStackTop, 1); } } - void getOtherSide(Environment aEnvironment,int aNrArgsToCombine, int depth) throws Exception + void getOtherSide(Environment aEnvironment, int aStackTop, int aNrArgsToCombine, int depth) throws Exception { String theOperator = iLookAhead; - matchToken(iLookAhead); - readExpression(aEnvironment, depth); - insertAtom(theOperator); - combine(aEnvironment, aNrArgsToCombine); + matchToken(aStackTop, iLookAhead); + readExpression(aEnvironment, aStackTop, depth); + insertAtom(aStackTop, theOperator); + combine(aEnvironment, aStackTop, aNrArgsToCombine); } - void combine(Environment aEnvironment,int aNrArgsToCombine) throws Exception + void combine(Environment aEnvironment, int aStackTop, int aNrArgsToCombine) throws Exception { ConsPointer subList = new ConsPointer(); subList.setCons(SublistCons.getInstance(aEnvironment,iSExpressionResult.getCons())); - ConsTraverser consTraverser = new ConsTraverser(iSExpressionResult); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, iSExpressionResult); int i; for (i = 0; i < aNrArgsToCombine; i++) { if (consTraverser.getCons() == null) { - fail(); + fail(aStackTop); return; } - consTraverser.goNext(); + consTraverser.goNext(aStackTop); } if (consTraverser.getCons() == null) { - fail(); + fail(aStackTop); return; } subList.cdr().setCons(consTraverser.cdr().getCons()); consTraverser.cdr().setCons(null); - Utility.reverseList(((ConsPointer) subList.car()).cdr(), + Utility.reverseList(aEnvironment, ((ConsPointer) subList.car()).cdr(), ((ConsPointer) subList.car()).cdr()); iSExpressionResult.setCons(subList.getCons()); } - void insertAtom(String aString) throws Exception + void insertAtom(int aStackTop, String aString) throws Exception { ConsPointer ptr = new ConsPointer(); - ptr.setCons(AtomCons.getInstance(iEnvironment, aString)); + ptr.setCons(AtomCons.getInstance(iEnvironment, aStackTop, aString)); ptr.cdr().setCons(iSExpressionResult.getCons()); iSExpressionResult.setCons(ptr.getCons()); } - void fail() throws Exception // called when parsing fails, raising an exception + void fail(int aStackTop) throws Exception // called when parsing fails, raising an exception { iError = true; if (iLookAhead != null) { - LispError.raiseError("Error parsing expression, near token " + iLookAhead + "."); + LispError.raiseError("Error parsing expression, near token " + iLookAhead + ".", "[INTERNAL]", aStackTop, iEnvironment); } - LispError.raiseError("Error parsing expression."); + LispError.raiseError("Error parsing expression.", "[INTERNAL]", aStackTop, iEnvironment); } }; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parsers/Parser.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parsers/Parser.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/parsers/Parser.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/parsers/Parser.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,9 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.parsers; import org.mathpiper.lisp.cons.SublistCons; @@ -25,84 +23,80 @@ import org.mathpiper.io.MathPiperInputStream; import org.mathpiper.lisp.*; +public class Parser { -public class Parser -{ - public MathPiperTokenizer iTokenizer; - public MathPiperInputStream iInput; - public Environment iEnvironment; - public boolean iListed; - - public Parser(MathPiperTokenizer aTokenizer, MathPiperInputStream aInput, - Environment aEnvironment) - { - iTokenizer = aTokenizer; - iInput = aInput; - iEnvironment = aEnvironment; - iListed = false; - } - - public void parse(Environment aEnvironment,ConsPointer aResult ) throws Exception - { - aResult.setCons(null); - - String token; - // Get token. - token = iTokenizer.nextToken(iInput,iEnvironment.getTokenHash()); - if (token.length() == 0) //TODO FIXME either token == null or token.length() == 0? - { - aResult.setCons(AtomCons.getInstance(iEnvironment,"EndOfFile")); - return; - } - parseAtom(aEnvironment,aResult, token); - } - - void parseList(Environment aEnvironment,ConsPointer aResult) throws Exception - { - String token; - - ConsPointer iter = aResult; - if (iListed) - { - aResult.setCons(AtomCons.getInstance(iEnvironment,"List")); - iter = (aResult.cdr()); //TODO FIXME - } - for (;;) - { - //Get token. - token = iTokenizer.nextToken(iInput,iEnvironment.getTokenHash()); - // if token is empty string, error! - LispError.check(token.length() > 0,LispError.INVALID_TOKEN); //TODO FIXME - // if token is ")" return result. - if (token == iEnvironment.getTokenHash().lookUp(")")) - { - return; - } - // else parse simple atom with parse, and append it to the - // results list. - - parseAtom(aEnvironment,iter, token); - iter = (iter.cdr()); //TODO FIXME - } - } - - void parseAtom(Environment aEnvironment,ConsPointer aResult,String aToken) throws Exception - { - // if token is empty string, return null pointer (no expression) - if (aToken.length() == 0) //TODO FIXME either token == null or token.length() == 0? - return; - // else if token is "(" read in a whole array of objects until ")", - // and make a sublist - if (aToken == iEnvironment.getTokenHash().lookUp("(")) - { - ConsPointer subList = new ConsPointer(); - parseList(aEnvironment, subList); - aResult.setCons(SublistCons.getInstance(aEnvironment,subList.getCons())); - return; - } - // else make a simple atom, and return it. - aResult.setCons(AtomCons.getInstance(iEnvironment,aToken)); - } - -} + public MathPiperTokenizer iTokenizer; + public MathPiperInputStream iInput; + public Environment iEnvironment; + public boolean iListed; + + + public Parser(MathPiperTokenizer aTokenizer, MathPiperInputStream aInput, + Environment aEnvironment) { + iTokenizer = aTokenizer; + iInput = aInput; + iEnvironment = aEnvironment; + iListed = false; + } + + + public void parse(int aStackTop, ConsPointer aResult) throws Exception { + aResult.setCons(null); + + String token; + // Get token. + token = iTokenizer.nextToken(iEnvironment, aStackTop, iInput, iEnvironment.getTokenHash()); + if (token.length() == 0) //TODO FIXME either token == null or token.length() == 0? + { + aResult.setCons(AtomCons.getInstance(iEnvironment, aStackTop, "EndOfFile")); + return; + } + parseAtom(iEnvironment, aStackTop, aResult, token); + } + + + void parseList(Environment aEnvironment, int aStackTop, ConsPointer aResult) throws Exception { + String token; + + ConsPointer iter = aResult; + if (iListed) { + aResult.setCons(AtomCons.getInstance(iEnvironment, aStackTop, "List")); + iter = (aResult.cdr()); //TODO FIXME + } + for (;;) { + //Get token. + token = iTokenizer.nextToken(iEnvironment, aStackTop, iInput, iEnvironment.getTokenHash()); + // if token is empty string, error! + LispError.check(iEnvironment, aStackTop, token.length() > 0, LispError.INVALID_TOKEN, "INTERNAL"); //TODO FIXME + // if token is ")" return result. + if (token == iEnvironment.getTokenHash().lookUp(")")) { + return; + } + // else parse simple atom with parse, and append it to the + // results list. + + parseAtom(aEnvironment, aStackTop, iter, token); + iter = (iter.cdr()); //TODO FIXME + } + } + + + void parseAtom(Environment aEnvironment, int aStackTop, ConsPointer aResult, String aToken) throws Exception { + // if token is empty string, return null pointer (no expression) + if (aToken.length() == 0) //TODO FIXME either token == null or token.length() == 0? + { + return; + } + // else if token is "(" read in a whole array of objects until ")", + // and make a sublist + if (aToken == iEnvironment.getTokenHash().lookUp("(")) { + ConsPointer subList = new ConsPointer(); + parseList(aEnvironment, aStackTop, subList); + aResult.setCons(SublistCons.getInstance(aEnvironment, subList.getCons())); + return; + } + // else make a simple atom, and return it. + aResult.setCons(AtomCons.getInstance(iEnvironment, aStackTop, aToken)); + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/printers/LispPrinter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/printers/LispPrinter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/printers/LispPrinter.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/printers/LispPrinter.java 2010-12-29 04:07:15.000000000 +0000 @@ -16,21 +16,14 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp.printers; - -import java.util.ArrayList; -import java.util.List; import org.mathpiper.lisp.cons.ConsPointer; import org.mathpiper.lisp.*; import org.mathpiper.io.MathPiperOutputStream; -import org.mathpiper.lisp.cons.Cons; - public class LispPrinter { //private List visitedLists = new ArrayList(); - - - public void print(ConsPointer aExpression, MathPiperOutputStream aOutput, Environment aEnvironment) throws Exception { + public void print(int aStackTop, ConsPointer aExpression, MathPiperOutputStream aOutput, Environment aEnvironment) throws Exception { printExpression(aExpression, aOutput, aEnvironment, 0); //visitedLists.clear(); @@ -61,18 +54,18 @@ /* Cons atomCons = (Cons) consWalker.getCons(); if (visitedLists.contains(atomCons)) { - aOutput.write("(CYCLE_LIST)"); + aOutput.write("(CYCLE_LIST)"); } else { - visitedLists.add(atomCons);*/ + visitedLists.add(atomCons);*/ - if (item != 0) { - indent(aOutput, aDepth + 1); - } - aOutput.write("("); - printExpression(((ConsPointer) consWalker.car()), aOutput, aEnvironment, aDepth + 1); - aOutput.write(")"); - item = 0; + if (item != 0) { + indent(aOutput, aDepth + 1); + } + aOutput.write("("); + printExpression(((ConsPointer) consWalker.car()), aOutput, aEnvironment, aDepth + 1); + aOutput.write(")"); + item = 0; //} @@ -94,7 +87,4 @@ } } - }; - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/printers/MathPiperPrinter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/printers/MathPiperPrinter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/printers/MathPiperPrinter.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/printers/MathPiperPrinter.java 2010-12-29 04:07:15.000000000 +0000 @@ -16,9 +16,6 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp.printers; - -import java.util.ArrayList; -import java.util.List; import org.mathpiper.builtin.BuiltinContainer; import org.mathpiper.io.MathPiperOutputStream; import org.mathpiper.lisp.Utility; @@ -27,10 +24,8 @@ import org.mathpiper.lisp.cons.ConsTraverser; import org.mathpiper.lisp.Environment; import org.mathpiper.lisp.tokenizers.MathPiperTokenizer; -import org.mathpiper.lisp.InfixOperator; +import org.mathpiper.lisp.Operator; import org.mathpiper.lisp.collections.OperatorMap; -import org.mathpiper.lisp.cons.Cons; - public class MathPiperPrinter extends LispPrinter { @@ -44,8 +39,6 @@ Environment iCurrentEnvironment; //private List visitedLists = new ArrayList(); - - public MathPiperPrinter(OperatorMap aPrefixOperators, OperatorMap aInfixOperators, OperatorMap aPostfixOperators, @@ -57,41 +50,39 @@ iPrevLastChar = 0; } - - - - public void print(ConsPointer aExpression, MathPiperOutputStream aOutput, Environment aEnvironment) throws Exception { + @Override + public void print(int aStackTop, ConsPointer aExpression, MathPiperOutputStream aOutput, Environment aEnvironment) throws Exception { iCurrentEnvironment = aEnvironment; - Print(aExpression, aOutput, KMaxPrecedence); + Print(aEnvironment, aStackTop, aExpression, aOutput, KMaxPrecedence); //visitedLists.clear(); } - + @Override public void rememberLastChar(char aChar) { iPrevLastChar = aChar; } + void Print(Environment aEnvironment, int aStackTop, ConsPointer aExpression, MathPiperOutputStream aOutput, int iPrecedence) throws Exception { - void Print(ConsPointer aExpression, MathPiperOutputStream aOutput, int iPrecedence) throws Exception { - - LispError.lispAssert(aExpression.getCons() != null); + LispError.lispAssert(aExpression.getCons() != null, aEnvironment, aStackTop); - String string; + String functionOrOperatorName; if (aExpression.car() instanceof String) { - string = (String) aExpression.car(); + functionOrOperatorName = (String) aExpression.car(); boolean bracket = false; if (iPrecedence < KMaxPrecedence && - string.charAt(0) == '-' && - (MathPiperTokenizer.isDigit(string.charAt(1)) || string.charAt(1) == '.')) { + functionOrOperatorName.charAt(0) == '-' && + (MathPiperTokenizer.isDigit(functionOrOperatorName.charAt(1)) || functionOrOperatorName.charAt(1) == '.')) { + //Code for (-1)/2 . bracket = true; } if (bracket) { WriteToken(aOutput, "("); } - WriteToken(aOutput, string); + WriteToken(aOutput, functionOrOperatorName); if (bracket) { WriteToken(aOutput, ")"); } @@ -100,24 +91,24 @@ if (aExpression.car() instanceof BuiltinContainer) { //TODO display genericclass - WriteToken(aOutput, ((BuiltinContainer) aExpression.car()).typeName()); + WriteToken(aOutput, ((BuiltinContainer) aExpression.car()).getObject().getClass().toString()); return; } ConsPointer subList = (ConsPointer) aExpression.car(); - LispError.check(subList != null, LispError.UNPRINTABLE_TOKEN); + LispError.check(aEnvironment, aStackTop, subList != null, LispError.UNPRINTABLE_TOKEN, "INTERNAL"); if (subList.getCons() == null) { WriteToken(aOutput, "( )"); } else { - int length = Utility.listLength(subList); - string = (String) subList.car(); - InfixOperator prefix = (InfixOperator) iPrefixOperators.lookUp(string); - InfixOperator infix = (InfixOperator) iInfixOperators.lookUp(string); - InfixOperator postfix = (InfixOperator) iPostfixOperators.lookUp(string); - InfixOperator bodied = (InfixOperator) iBodiedOperators.lookUp(string); - InfixOperator op = null; + int length = Utility.listLength(aEnvironment, aStackTop, subList); + functionOrOperatorName = (String) subList.car(); + Operator prefix = (Operator) iPrefixOperators.lookUp(functionOrOperatorName); + Operator infix = (Operator) iInfixOperators.lookUp(functionOrOperatorName); + Operator postfix = (Operator) iPostfixOperators.lookUp(functionOrOperatorName); + Operator bodied = (Operator) iBodiedOperators.lookUp(functionOrOperatorName); + Operator operator = null; if (length != 2) { prefix = null; @@ -127,16 +118,16 @@ infix = null; } if (prefix != null) { - op = prefix; + operator = prefix; } if (postfix != null) { - op = postfix; + operator = postfix; } if (infix != null) { - op = infix; + operator = infix; } - if (op != null) { + if (operator != null) { ConsPointer left = null; ConsPointer right = null; @@ -149,49 +140,114 @@ left = subList.cdr(); } - if (iPrecedence < op.iPrecedence) { + if (iPrecedence < operator.iPrecedence) { WriteToken(aOutput, "("); } else { //Vladimir? aOutput.write(" "); } + if (left != null) { - Print(left, aOutput, op.iLeftPrecedence); + + if (functionOrOperatorName.equals("/") && Utility.functionType(left).equals("/")) { + //Code for In> Hold((3/2)/(1/2)) Result> (3/2)/(1/2) . + WriteToken(aOutput, "("); + }//end if. + + Print(aEnvironment, aStackTop, left, aOutput, operator.iLeftPrecedence); + + if (functionOrOperatorName.equals("/") && Utility.functionType(left).equals("/")) { + //Code for In> Hold((3/2)/(1/2)) Result> (3/2)/(1/2) . + WriteToken(aOutput, ")"); + }//end if. + } + + boolean addSpaceAroundInfixOperator = false; //Todo:tk:perhaps a more general way should be found to place a space after a prefix operator. + if(functionOrOperatorName.equals("And")) + { + addSpaceAroundInfixOperator = true; } - WriteToken(aOutput, string); + + if (addSpaceAroundInfixOperator == true) { + WriteToken(aOutput, " "); + }//end if. + + WriteToken(aOutput, functionOrOperatorName); + + if (addSpaceAroundInfixOperator == true) { + WriteToken(aOutput, " "); + }//end if. + if (right != null) { - Print(right, aOutput, op.iRightPrecedence); + + if (functionOrOperatorName.equals("/") && Utility.functionType(right).equals("/")) { + //Code for In> Hold((3/2)/(1/2)) Result> (3/2)/(1/2) . + WriteToken(aOutput, "("); + }//end if. + + if (functionOrOperatorName.equals("Not")) {//Todo:tk:perhaps a more general way should be found to place a space after a prefix operator. + WriteToken(aOutput, " "); + }//end if. + + Print(aEnvironment, aStackTop, right, aOutput, operator.iRightPrecedence); + + if (functionOrOperatorName.equals("/") && Utility.functionType(right).equals("/")) { + //Code for In> Hold((3/2)/(1/2)) Result> (3/2)/(1/2) . + WriteToken(aOutput, ")"); + }//end if. } - if (iPrecedence < op.iPrecedence) { + + if (iPrecedence < operator.iPrecedence) { WriteToken(aOutput, ")"); } + } else { - ConsTraverser consTraverser = new ConsTraverser(subList.cdr()); - if (string == iCurrentEnvironment.iListAtom.car()) { + + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, subList.cdr()); + + /* + Removing complex number output notation formatting until the problem with Solve(x^3 - 2*x - 7 == 0,x) is resolved. + + if (functionOrOperatorName == iCurrentEnvironment.iComplexAtom.car()) { + + Print(consTraverser.getPointer(), aOutput, KMaxPrecedence); + + consTraverser.goNext(); //Point to second argument. + + if (!consTraverser.car().toString().startsWith("-")) { + WriteToken(aOutput, "+"); + } + + Print(consTraverser.getPointer(), aOutput, KMaxPrecedence); + + WriteToken(aOutput, "*I"); + + } else */ + if (functionOrOperatorName == iCurrentEnvironment.iListAtom.car()) { /* Cons atomCons = (Cons) subList.getCons(); if (visitedLists.contains(atomCons)) { - WriteToken(aOutput, "{CYCLE_LIST}"); - return; + WriteToken(aOutput, "{CYCLE_LIST}"); + return; } else { - visitedLists.add(atomCons);*/ + visitedLists.add(atomCons);*/ - WriteToken(aOutput, "{"); + WriteToken(aOutput, "{"); - while (consTraverser.getCons() != null) { - Print(consTraverser.getPointer(), aOutput, KMaxPrecedence); - consTraverser.goNext(); - if (consTraverser.getCons() != null) { - WriteToken(aOutput, ","); - } - }//end while. + while (consTraverser.getCons() != null) { + Print(aEnvironment, aStackTop, consTraverser.getPointer(), aOutput, KMaxPrecedence); + consTraverser.goNext(aStackTop); + if (consTraverser.getCons() != null) { + WriteToken(aOutput, ","); + } + }//end while. - WriteToken(aOutput, "}"); + WriteToken(aOutput, "}"); - // }//end else. - } else if (string == iCurrentEnvironment.iProgAtom.car()) // Program block brackets. + // }//end else. + } else if (functionOrOperatorName == iCurrentEnvironment.iProgAtom.car()) // Program block brackets. { WriteToken(aOutput, "["); aOutput.write("\n"); @@ -199,8 +255,8 @@ while (consTraverser.getCons() != null) { aOutput.write(spaces.toString()); - Print(consTraverser.getPointer(), aOutput, KMaxPrecedence); - consTraverser.goNext(); + Print(aEnvironment, aStackTop, consTraverser.getPointer(), aOutput, KMaxPrecedence); + consTraverser.goNext(aStackTop); WriteToken(aOutput, ";"); aOutput.write("\n"); } @@ -208,11 +264,11 @@ WriteToken(aOutput, "]"); aOutput.write("\n"); spaces.delete(0, 4); - } else if (string == iCurrentEnvironment.iNthAtom.car()) { - Print(consTraverser.getPointer(), aOutput, 0); - consTraverser.goNext(); + } else if (functionOrOperatorName == iCurrentEnvironment.iNthAtom.car()) { + Print(aEnvironment, aStackTop, consTraverser.getPointer(), aOutput, 0); + consTraverser.goNext(aStackTop); WriteToken(aOutput, "["); - Print(consTraverser.getPointer(), aOutput, KMaxPrecedence); + Print(aEnvironment, aStackTop, consTraverser.getPointer(), aOutput, KMaxPrecedence); WriteToken(aOutput, "]"); } else { boolean bracket = false; @@ -225,18 +281,18 @@ if (bracket) { WriteToken(aOutput, "("); } - if (string != null) { - WriteToken(aOutput, string); + if (functionOrOperatorName != null) { + WriteToken(aOutput, functionOrOperatorName); //Print function name. } else { - Print(subList, aOutput, 0); + Print(aEnvironment, aStackTop, subList, aOutput, 0); } - WriteToken(aOutput, "("); + WriteToken(aOutput, "("); //Print the opening parenthese of the function argument list. - ConsTraverser counter = new ConsTraverser(consTraverser.getPointer()); + ConsTraverser counter = new ConsTraverser(aEnvironment, consTraverser.getPointer()); int nr = 0; - while (counter.getCons() != null) { - counter.goNext(); + while (counter.getCons() != null) { //Count arguments. + counter.goNext(aStackTop); nr++; } @@ -244,27 +300,29 @@ nr--; } while (nr-- != 0) { - Print(consTraverser.getPointer(), aOutput, KMaxPrecedence); + Print(aEnvironment, aStackTop, consTraverser.getPointer(), aOutput, KMaxPrecedence); //Print argument. + + consTraverser.goNext(aStackTop); - consTraverser.goNext(); if (nr != 0) { - WriteToken(aOutput, ","); + WriteToken(aOutput, ","); //Print the comma which is between arguments. } - } + }//end while. + WriteToken(aOutput, ")"); + if (consTraverser.getCons() != null) { - Print(consTraverser.getPointer(), aOutput, bodied.iPrecedence); + Print(aEnvironment, aStackTop, consTraverser.getPointer(), aOutput, bodied.iPrecedence); } if (bracket) { - WriteToken(aOutput, ")"); + WriteToken(aOutput, ")"); //Print the closing parenthese of the function argument list. } } } }//end sublist if. } - void WriteToken(MathPiperOutputStream aOutput, String aString) throws Exception { /*if (MathPiperTokenizer.isAlNum(iPrevLastChar) && (MathPiperTokenizer.isAlNum(aString.charAt(0)) || aString.charAt(0)=='_')) { @@ -277,6 +335,4 @@ aOutput.write(aString); rememberLastChar(aString.charAt(aString.length() - 1)); } - - } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/ListedMacroRulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/ListedMacroRulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/ListedMacroRulebase.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/ListedMacroRulebase.java 2011-01-29 01:58:56.000000000 +0000 @@ -0,0 +1,66 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsTraverser; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.SublistCons; + +public class ListedMacroRulebase extends MacroRulebase { + + public ListedMacroRulebase(Environment aEnvironment, int aStackTop, ConsPointer aParameters, String functionName) throws Exception { + super(aEnvironment, aStackTop, aParameters, functionName); + } + + + @Override + public boolean isArity(int aArity) { + return (arity() <= aArity); + } + + + @Override + public void evaluate(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aArguments) throws Exception { + ConsPointer newArgs = new ConsPointer(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, aArguments); + ConsPointer ptr = newArgs; + int arity = arity(); + int i = 0; + while (i < arity && consTraverser.getCons() != null) { + ptr.setCons(consTraverser.getCons().copy(aEnvironment, false)); + ptr = (ptr.cdr()); + i++; + consTraverser.goNext(aStackTop); + } + if (consTraverser.cdr().getCons() == null) { + ptr.setCons(consTraverser.getCons().copy(aEnvironment, false)); + ptr = (ptr.cdr()); + i++; + consTraverser.goNext(aStackTop); + LispError.lispAssert(consTraverser.getCons() == null, aEnvironment, aStackTop); + } else { + ConsPointer head = new ConsPointer(); + head.setCons(aEnvironment.iListAtom.copy(aEnvironment, false)); + head.cdr().setCons(consTraverser.getCons()); + ptr.setCons(SublistCons.getInstance(aEnvironment, head.getCons())); + } + super.evaluate(aEnvironment, aStackTop, aResult, newArgs); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/ListedRulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/ListedRulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/ListedRulebase.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/ListedRulebase.java 2011-01-29 01:58:56.000000000 +0000 @@ -0,0 +1,66 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsTraverser; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.SublistCons; + +public class ListedRulebase extends SingleArityRulebase { + + public ListedRulebase(Environment aEnvironment, int aStackTop, ConsPointer aParameters, String functionName) throws Exception { + super(aEnvironment, aStackTop, aParameters, functionName); + } + + + @Override + public boolean isArity(int aArity) { + return (arity() <= aArity); + } + + + @Override + public void evaluate(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aArguments) throws Exception { + ConsPointer newArgs = new ConsPointer(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, aArguments); + ConsPointer ptr = newArgs; + int arity = arity(); + int i = 0; + while (i < arity && consTraverser.getCons() != null) { + ptr.setCons(consTraverser.getCons().copy(aEnvironment, false)); + ptr = (ptr.cdr()); + i++; + consTraverser.goNext(aStackTop); + } + if (consTraverser.cdr().getCons() == null) { + ptr.setCons(consTraverser.getCons().copy(aEnvironment, false)); + ptr = (ptr.cdr()); + i++; + consTraverser.goNext(aStackTop); + LispError.lispAssert(consTraverser.getCons() == null, aEnvironment, aStackTop); + } else { + ConsPointer head = new ConsPointer(); + head.setCons(aEnvironment.iListAtom.copy(aEnvironment, false)); + head.cdr().setCons(consTraverser.getCons()); + ptr.setCons(SublistCons.getInstance(aEnvironment, head.getCons())); + } + super.evaluate(aEnvironment, aStackTop, aResult, newArgs); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/MacroRulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/MacroRulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/MacroRulebase.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/MacroRulebase.java 2011-02-02 08:39:53.000000000 +0000 @@ -0,0 +1,162 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.exceptions.EvaluationException; +import org.mathpiper.lisp.stacks.UserStackInformation; +import org.mathpiper.lisp.behaviours.BackQuoteSubstitute; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.cons.ConsTraverser; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Evaluator; +import org.mathpiper.lisp.LispExpressionEvaluator; +import org.mathpiper.lisp.cons.SublistCons; + +public class MacroRulebase extends SingleArityRulebase { + + public MacroRulebase(Environment aEnvironment, int aStackTop, ConsPointer aParameters, String functionName) throws Exception { + super(aEnvironment, aStackTop, aParameters, functionName); + ConsTraverser parameterTraverser = new ConsTraverser(aEnvironment, aParameters); + int i = 0; + while (parameterTraverser.getCons() != null) { + + //LispError.check(parameterTraverser.car() != null, LispError.CREATING_USER_FUNCTION); + try { + LispError.check(aEnvironment, aStackTop, parameterTraverser.car() instanceof String, LispError.CREATING_USER_FUNCTION, "INTERNAL"); + } catch (EvaluationException ex) { + if (ex.getFunctionName() == null) { + throw new EvaluationException(ex.getMessage() + " In function: " + this.functionName + ", ", "none", -1, this.functionName); + } else { + throw ex; + } + }//end catch. + + + ((ParameterName) iParameters.get(i)).iHold = true; + parameterTraverser.goNext(aStackTop); + i++; + } + //Macros are all unfenced. + unFence(); + + this.functionType = "macro"; + } + + + @Override + public void evaluate(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aArgumentsPointer) throws Exception { + int arity = arity(); + ConsPointer[] argumentsResultPointerArray = evaluateArguments(aEnvironment, aStackTop, aArgumentsPointer); + + + + ConsPointer substitutedBodyPointer = new ConsPointer(); + + //Create a new local variable frame that is unfenced (false = unfenced). + aEnvironment.pushLocalFrame(false, this.functionName); + + try { + // define the local variables. + for (int parameterIndex = 0; parameterIndex < arity; parameterIndex++) { + String variable = ((ParameterName) iParameters.get(parameterIndex)).iName; + + // set the variable to the new value + aEnvironment.newLocalVariable(variable, argumentsResultPointerArray[parameterIndex].getCons(), aStackTop); + } + + // walk the rules database, returning the evaluated result if the + // predicate is true. + int numberOfRules = iBranchRules.size(); + UserStackInformation userStackInformation = aEnvironment.iLispExpressionEvaluator.stackInformation(); + for (int ruleIndex = 0; ruleIndex < numberOfRules; ruleIndex++) { + Rule thisRule = ((Rule) iBranchRules.get(ruleIndex)); + //TODO remove CHECKPTR(thisRule); + LispError.lispAssert(thisRule != null, aEnvironment, aStackTop); + + userStackInformation.iRulePrecedence = thisRule.getPrecedence(); + + boolean matches = thisRule.matches(aEnvironment, aStackTop, argumentsResultPointerArray); + + if (matches) { + /* Rule dump trace code. */ + if (isTraced() && showFlag) { + ConsPointer argumentsPointer = new ConsPointer(); + argumentsPointer.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + String ruleDump = org.mathpiper.lisp.Utility.dumpRule(aStackTop, thisRule, aEnvironment, this); + Evaluator.traceShowRule(aEnvironment, argumentsPointer, ruleDump); + } + userStackInformation.iSide = 1; + + BackQuoteSubstitute backQuoteSubstitute = new BackQuoteSubstitute(aEnvironment); + + ConsPointer originalBodyPointer = thisRule.getBodyPointer(); + Utility.substitute(aEnvironment, aStackTop, substitutedBodyPointer, originalBodyPointer, backQuoteSubstitute); + // aEnvironment.iLispExpressionEvaluator.Eval(aEnvironment, aResult, thisRule.body()); + break; + } + + // If rules got inserted, walk back + while (thisRule != ((Rule) iBranchRules.get(ruleIndex)) && ruleIndex > 0) { + ruleIndex--; + } + } + } catch (EvaluationException ex) { + if (ex.getFunctionName() == null) { + throw new EvaluationException(ex.getMessage() + " In function: " + this.functionName + ", ", "none", -1, this.functionName); + } else { + throw ex; + } + } finally { + aEnvironment.popLocalFrame(aStackTop); + } + + + + if (substitutedBodyPointer.getCons() != null) { + //Note:tk:substituted body must be evaluated after the local frame has been popped. + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, aResult, substitutedBodyPointer); + } else // No predicate was true: return a new expression with the evaluated + // arguments. + { + ConsPointer full = new ConsPointer(); + full.setCons(aArgumentsPointer.getCons().copy(aEnvironment, false)); + if (arity == 0) { + full.cdr().setCons(null); + } else { + full.cdr().setCons(argumentsResultPointerArray[0].getCons()); + for (int parameterIndex = 0; parameterIndex < arity - 1; parameterIndex++) { + argumentsResultPointerArray[parameterIndex].cdr().setCons(argumentsResultPointerArray[parameterIndex + 1].getCons()); + } + } + aResult.setCons(SublistCons.getInstance(aEnvironment, full.getCons())); + } + //FINISH: + + /*Leave trace code */ + if (isTraced() && showFlag) { + ConsPointer tr = new ConsPointer(); + tr.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + String localVariables = aEnvironment.getLocalVariables(aStackTop); + LispExpressionEvaluator.traceShowLeave(aEnvironment, aResult, tr, "macro", localVariables); + tr.setCons(null); + } + + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/MultipleArityRulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/MultipleArityRulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/MultipleArityRulebase.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/MultipleArityRulebase.java 2011-01-29 01:58:56.000000000 +0000 @@ -0,0 +1,120 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.lisp.*; +import java.util.*; + +/** + * Holds a set of {@link SingleArityRulebase} which are associated with one function name. + * A specific SingleArityRulebase can be selected by providing its name. The + * name of the file in which the function is defined can also be specified. + */ +public class MultipleArityRulebase { + + /// Set of SingleArityRulebase's provided by this MultipleArityRulebase. + List iFunctions = new ArrayList();// + /// File to read for the definition of this function. + public DefFile iFileToOpen; + public String iFileLocation; + + + public MultipleArityRulebase() { + iFileToOpen = null; + } + + + /** + *Return user function with given arity. + */ + public SingleArityRulebase getUserFunction(int aArity, int aStackTop, Environment aEnvironment) throws Exception { + int ruleIndex; + //Find function body with the right arity + int numberOfRules = iFunctions.size(); + for (ruleIndex = 0; ruleIndex < numberOfRules; ruleIndex++) { + LispError.lispAssert(iFunctions.get(ruleIndex) != null, aEnvironment, aStackTop); + + if (((SingleArityRulebase) iFunctions.get(ruleIndex)).isArity(aArity)) { + return (SingleArityRulebase) iFunctions.get(ruleIndex); + } + } + + // If function not found, just unaccept! + // User-defined function not found! Returning null + return null; + + }//end method. + + + /** + * Specify that some argument should be held. + */ + public void holdArgument(String aVariable, int aStackTop, Environment aEnvironment) throws Exception { + int ruleIndex; + for (ruleIndex = 0; ruleIndex < iFunctions.size(); ruleIndex++) { + LispError.lispAssert(iFunctions.get(ruleIndex) != null, aEnvironment, aStackTop); + ((SingleArityRulebase) iFunctions.get(ruleIndex)).holdArgument(aVariable); + } + }//end method. + + + /** + *Add another SingleArityRulebase to #iFunctions. + */ + public void addRulebaseEntry(Environment aEnvironment, int aStackTop, SingleArityRulebase aNewFunction) throws Exception { + int ruleIndex; + //Find function body with the right arity + int numberOfRules = iFunctions.size(); + for (ruleIndex = 0; ruleIndex < numberOfRules; ruleIndex++) { + LispError.lispAssert(((SingleArityRulebase) iFunctions.get(ruleIndex)) != null, aEnvironment, aStackTop); + LispError.lispAssert(aNewFunction != null, aEnvironment, aStackTop); + LispError.check(aEnvironment, aStackTop, !((SingleArityRulebase) iFunctions.get(ruleIndex)).isArity(aNewFunction.arity()), LispError.ARITY_ALREADY_DEFINED, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, !aNewFunction.isArity(((SingleArityRulebase) iFunctions.get(ruleIndex)).arity()), LispError.ARITY_ALREADY_DEFINED, "INTERNAL"); + } + iFunctions.add(aNewFunction); + }//end method. + + + /** + *Delete user function with given arity. If arity is -1 then delete all functions regardless of arity. + */ + public void deleteRulebaseEntry(int aArity, int aStackTop, Environment aEnvironment) throws Exception { + if (aArity == -1) //Retract all functions regardless of arity. + { + iFunctions.clear(); + return; + }//end if. + + int ruleIndex; + //Find function body with the right arity + int numberOfRules = iFunctions.size(); + for (ruleIndex = 0; ruleIndex < numberOfRules; ruleIndex++) { + LispError.lispAssert(((SingleArityRulebase) iFunctions.get(ruleIndex)) != null, aEnvironment, aStackTop); + + if (((SingleArityRulebase) iFunctions.get(ruleIndex)).isArity(aArity)) { + iFunctions.remove(ruleIndex); + return; + } + } + }//end method. + + + public Iterator getFunctions() { + return this.iFunctions.iterator(); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/ParameterName.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/ParameterName.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/ParameterName.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/ParameterName.java 2010-07-18 16:36:18.000000000 +0000 @@ -0,0 +1,44 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +/** + * Contains the name of a parameter and if it is put on hold. + */ +public class ParameterName +{ + String iName; + boolean iHold; + + public ParameterName(String aParameter, boolean aHold /*=false*/) + { + iName = aParameter; + iHold = aHold; + } + + public String getName() + { + return iName; + } + + public boolean isHold() + { + return iHold; + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/PatternRule.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/PatternRule.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/PatternRule.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/PatternRule.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,80 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.builtin.BuiltinContainer; +import org.mathpiper.builtin.PatternContainer; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.parametermatchers.ParametersPatternMatcher; + +/** + * A rule which matches if the corresponding {@link PatternContainer} matches. + */ +public class PatternRule extends Rule { + + protected int iPrecedence; + protected ConsPointer iBody; + protected ConsPointer iPredicate; + protected PatternContainer iPattern; //The pattern that decides whether this rule matches or not. + + /** + * + * @param aPrecedence precedence of the rule + * @param aPredicate getObject object of type PatternContainer + * @param aBody body of the rule + */ + public PatternRule(Environment aEnvironment, int aStackTop, int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { + iBody = new ConsPointer(); + iPredicate = new ConsPointer(); + iPattern = null; + iPrecedence = aPrecedence; + iPredicate.setCons(aPredicate.getCons()); + + BuiltinContainer gen = (BuiltinContainer) aPredicate.car(); + LispError.check(aEnvironment, aStackTop, gen != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, gen.typeName().equals("\"Pattern\""), LispError.INVALID_ARGUMENT, "INTERNAL"); + + iPattern = (PatternContainer) gen; + iBody.setCons(aBody.getCons()); + } + + //Return true if the corresponding pattern matches. + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer[] aArguments) throws Exception { + return iPattern.matches(aEnvironment, aStackTop, aArguments); + } + + //Access iPrecedence. + public int getPrecedence() { + return iPrecedence; + } + + public ConsPointer getPredicatePointer() { + return this.iPredicate; + } + + public ParametersPatternMatcher getPattern() { + return iPattern.getPattern(); + } + + //Access iBody + public ConsPointer getBodyPointer() { + return iBody; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/PredicateRule.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/PredicateRule.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/PredicateRule.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/PredicateRule.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,86 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; + +/** + * A rule with a predicate (the rule matches if the predicate evaluates to True.) + */ +class PredicateRule extends Rule { + + protected int iPrecedence; + protected ConsPointer iBody; + protected ConsPointer iPredicate; + + + public PredicateRule(Environment aEnvironment, int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) { + iBody = new ConsPointer(); + iBody.setCons(aBody.getCons()); + iPredicate = new ConsPointer(); + iPrecedence = aPrecedence; + iPredicate.setCons(aPredicate.getCons()); + + } + + + protected PredicateRule(Environment aEnvironment) { + iBody = new ConsPointer(); + iPredicate = new ConsPointer(); + } + + + private PredicateRule() { + } + + + /** + * Return true if the rule matches. + * + * @param aEnvironment + * @param aArguments + * @return + * @throws java.lang.Exception + */ + // iPredicate is evaluated in \a Environment. If the result + /// IsTrue(), this function returns true + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer[] aArguments) throws Exception { + ConsPointer pred = new ConsPointer(); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, pred, iPredicate); + return Utility.isTrue(aEnvironment, pred, aStackTop); + } + + /// Access #iPrecedence. + + public int getPrecedence() { + return iPrecedence; + } + + /// Access #iBody. + + public ConsPointer getBodyPointer() { + return iBody; + } + + + public ConsPointer getPredicatePointer() { + return this.iPredicate; + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/Rule.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/Rule.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/Rule.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/Rule.java 2010-07-18 16:36:18.000000000 +0000 @@ -0,0 +1,36 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Environment; + +/** + * Base class for rules. + */ +public abstract class Rule +{ + + public abstract boolean matches(Environment aEnvironment, int aStackTop, ConsPointer[] aArguments) throws Exception; + + public abstract int getPrecedence(); + + public abstract ConsPointer getPredicatePointer(); + + public abstract ConsPointer getBodyPointer(); +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/SingleArityRulebase.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/SingleArityRulebase.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/SingleArityRulebase.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/SingleArityRulebase.java 2011-02-02 08:39:53.000000000 +0000 @@ -0,0 +1,496 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.lisp.stacks.UserStackInformation; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.LispError; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.SublistCons; +import java.util.*; +import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.exceptions.EvaluationException; +import org.mathpiper.exceptions.ReturnException; +import org.mathpiper.lisp.Evaluator; + +/** + * A function (usually mathematical) which is defined by one or more rules. + * This is the basic class which implements functions. Evaluation is done + * by consulting a set of rewritng rules. The body of the first rule that + * matches is evaluated and its result is returned as the function's result. + */ +public class SingleArityRulebase extends Evaluator { + // List of arguments, with corresponding iHold property. + protected List iParameters = new ArrayList(); //CArrayGrower + + // List of rules, sorted on precedence. + protected List iBranchRules = new ArrayList();//CDeletingArrayGrower + + // List of arguments + ConsPointer iParameterList; +/// Abstract class providing the basic user function API. +/// Instances of this class are associated to the name of the function +/// via an associated hash table. When obtained, they can be used to +/// evaluate the function with some arguments. + boolean iFenced = true; + boolean showFlag = false; + protected String functionType = "**** user rulebase"; + protected String functionName; + protected Environment iEnvironment; + + + /** + * Constructor. + * + * @param aParameters linked list constaining the names of the arguments + * @throws java.lang.Exception + */ + public SingleArityRulebase(Environment aEnvironment, int aStackTop, ConsPointer aParametersPointer, String functionName) throws Exception { + iEnvironment = aEnvironment; + this.functionName = functionName; + iParameterList = new ConsPointer(); + // iParameterList and #iParameters are set from \a aParameters. + iParameterList.setCons(aParametersPointer.getCons()); + + ConsPointer parameterPointer = new ConsPointer(aParametersPointer.getCons()); + + while (parameterPointer.getCons() != null) { + + try { + LispError.check(aEnvironment, aStackTop, parameterPointer.car() instanceof String, LispError.CREATING_USER_FUNCTION, "INTERNAL"); + } catch (EvaluationException ex) { + if (ex.getFunctionName() == null) { + throw new EvaluationException(ex.getMessage() + " In function: " + this.functionName + ", ", "none", -1, this.functionName); + } else { + throw ex; + } + }//end catch. + + ParameterName parameter = new ParameterName((String) parameterPointer.car(), false); + iParameters.add(parameter); + parameterPointer.goNext(aStackTop, aEnvironment); + } + } + + + /** + * Evaluate the function with the given arguments. + * First, all arguments are evaluated by the evaluator associated + * with aEnvironment, unless the iHold flag of the + * corresponding parameter is true. Then a new LocalFrame is + * constructed, in which the actual arguments are assigned to the + * names of the formal arguments, as stored in iName. Then + * all rules in iRules are tried one by one. The body of the + * first rule that matches is evaluated, and the result is put in + * aResult. If no rule matches, aResult will recieve a new + * expression with evaluated arguments. + * + * @param aResult (on output) the result of the evaluation + * @param aEnvironment the underlying Lisp environment + * @param aArguments the arguments to the function + * @throws java.lang.Exception + */ + public void evaluate(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aArgumentsPointer) throws Exception { + int arity = arity(); + ConsPointer[] argumentsResultPointerArray = evaluateArguments(aEnvironment, aStackTop, aArgumentsPointer); + + // Create a new local variables frame that has the same fenced state as this function. + aEnvironment.pushLocalFrame(fenced(), this.functionName); + + int beforeStackTop = -1; + int beforeEvaluationDepth = -1; + int originalStackTop = -1; + + try { + + // define the local variables. + for (int parameterIndex = 0; parameterIndex < arity; parameterIndex++) { + String variableName = ((ParameterName) iParameters.get(parameterIndex)).iName; + // set the variable to the new value + aEnvironment.newLocalVariable(variableName, argumentsResultPointerArray[parameterIndex].getCons(), aStackTop); + } + + // walk the rules database, returning the evaluated result if the + // predicate is true. + int numberOfRules = iBranchRules.size(); + + UserStackInformation userStackInformation = aEnvironment.iLispExpressionEvaluator.stackInformation(); + + for (int ruleIndex = 0; ruleIndex < numberOfRules; ruleIndex++) { + Rule thisRule = ((Rule) iBranchRules.get(ruleIndex)); + LispError.lispAssert(thisRule != null, aEnvironment, aStackTop); + + userStackInformation.iRulePrecedence = thisRule.getPrecedence(); + + boolean matches = thisRule.matches(aEnvironment, aStackTop, argumentsResultPointerArray); + + if (matches) { + + /* Rule dump trace code. */ + if (isTraced() && showFlag) { + ConsPointer argumentsPointer = new ConsPointer(); + argumentsPointer.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + String ruleDump = org.mathpiper.lisp.Utility.dumpRule(aStackTop, thisRule, aEnvironment, this); + Evaluator.traceShowRule(aEnvironment, argumentsPointer, ruleDump); + } + + userStackInformation.iSide = 1; + + try { + beforeStackTop = aEnvironment.iArgumentStack.getStackTopIndex(); + beforeEvaluationDepth = aEnvironment.iEvalDepth; + + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, aResult, thisRule.getBodyPointer()); //*** User function is called here. + + } catch (ReturnException re) { + //todo:tk:note that user functions currently return their results in aResult, not on the stack. + int stackTopIndex = aEnvironment.iArgumentStack.getStackTopIndex(); + ConsPointer resultPointer = BuiltinFunction.getTopOfStackPointer(aEnvironment, stackTopIndex - 1); + + aResult.setCons(resultPointer.getCons()); + + aEnvironment.iArgumentStack.popTo(beforeStackTop, aStackTop, aEnvironment); + aEnvironment.iEvalDepth = beforeEvaluationDepth; + + } + + /*Leave trace code */ + if (isTraced() && showFlag) { + ConsPointer argumentsPointer2 = new ConsPointer(); + argumentsPointer2.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + String localVariables = aEnvironment.getLocalVariables(aStackTop); + Evaluator.traceShowLeave(aEnvironment, aResult, argumentsPointer2, functionType, localVariables); + argumentsPointer2.setCons(null); + }//end if. + + return; + }//end if matches. + + // If rules got inserted, walk back. + while (thisRule != ((Rule) iBranchRules.get(ruleIndex)) && ruleIndex > 0) { + ruleIndex--; + } + }//end for. + + + // No predicate was true: return a new expression with the evaluated + // arguments. + ConsPointer full = new ConsPointer(); + full.setCons(aArgumentsPointer.getCons().copy(aEnvironment, false)); + if (arity == 0) { + full.cdr().setCons(null); + } else { + full.cdr().setCons(argumentsResultPointerArray[0].getCons()); + for (int parameterIndex = 0; parameterIndex < arity - 1; parameterIndex++) { + argumentsResultPointerArray[parameterIndex].cdr().setCons(argumentsResultPointerArray[parameterIndex + 1].getCons()); + } + } + aResult.setCons(SublistCons.getInstance(aEnvironment, full.getCons())); + + + /* Trace code */ + if (isTraced() && showFlag) { + ConsPointer argumentsPointer3 = new ConsPointer(); + argumentsPointer3.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + String localVariables = aEnvironment.getLocalVariables(aStackTop); + Evaluator.traceShowLeave(aEnvironment, aResult, argumentsPointer3, functionType, localVariables); + argumentsPointer3.setCons(null); + } + + } catch (EvaluationException ex) { + + //ex.printStackTrace();//todo:tk:uncomment for debugging. + + if (ex.getFunctionName() == null) { + throw new EvaluationException(ex.getMessage() + " In function: " + this.functionName + ", ", "none", -1, this.functionName); + } else { + throw ex; + } + } finally { + aEnvironment.popLocalFrame(aStackTop); + } + } + + + protected ConsPointer[] evaluateArguments(Environment aEnvironment, int aStackTop, ConsPointer aArgumentsPointer) throws Exception { + int arity = arity(); + int parameterIndex; + + /*Enter trace code*/ + if (isTraced()) { + ConsPointer argumentsPointer = new ConsPointer(); + argumentsPointer.setCons(SublistCons.getInstance(aEnvironment, aArgumentsPointer.getCons())); + String traceFunctionName = ""; + if (argumentsPointer.car() instanceof ConsPointer) { + ConsPointer sub = (ConsPointer) argumentsPointer.car(); + if (sub.car() instanceof String) { + traceFunctionName = (String) sub.car(); + } + }//end function. + if (Evaluator.isTraceFunction(traceFunctionName)) { + showFlag = true; + Evaluator.traceShowEnter(aEnvironment, argumentsPointer, functionType); + } else { + showFlag = false; + }// + argumentsPointer.setCons(null); + } + + ConsPointer argumentsTraverser = new ConsPointer(aArgumentsPointer.getCons()); + + //Strip the function name from the head of the list. + argumentsTraverser.goNext(aStackTop, aEnvironment); + + //Creat an array which holds pointers to each argument. + ConsPointer[] argumentsResultPointerArray; + if (arity == 0) { + argumentsResultPointerArray = null; + } else { + LispError.lispAssert(arity > 0, aEnvironment, aStackTop); + argumentsResultPointerArray = new ConsPointer[arity]; + } + + // Walk over all arguments, evaluating them as necessary ******************************************************** + for (parameterIndex = 0; parameterIndex < arity; parameterIndex++) { + + argumentsResultPointerArray[parameterIndex] = new ConsPointer(); + + LispError.check(aEnvironment, aStackTop, argumentsTraverser.getCons() != null, LispError.WRONG_NUMBER_OF_ARGUMENTS, "INTERNAL"); + + if (((ParameterName) iParameters.get(parameterIndex)).iHold) { + //If the parameter is on hold, don't evaluate it and place a copy of it in argumentsPointerArray. + argumentsResultPointerArray[parameterIndex].setCons(argumentsTraverser.getCons().copy(aEnvironment, false)); + } else { + //If the parameter is not on hold: + + //Verify that the pointer to the arguments is not null. + LispError.check(aEnvironment, aStackTop, argumentsTraverser != null, LispError.WRONG_NUMBER_OF_ARGUMENTS, "INTERNAL"); + + //Evaluate each argument and place the result into argumentsResultPointerArray[i]; + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, argumentsResultPointerArray[parameterIndex], argumentsTraverser); + } + argumentsTraverser.goNext(aStackTop, aEnvironment); + }//end for. + + /*Argument trace code */ + if (isTraced() && argumentsResultPointerArray != null && showFlag) { + //ConsTraverser consTraverser2 = new ConsTraverser(aArguments); + //ConsPointer traceArgumentPointer = new ConsPointer(aArgumentsPointer.getCons()); + + //ConsTransverser traceArgumentPointer new ConsTraverser(this.iParameterList); + ConsPointer traceParameterPointer = new ConsPointer(this.iParameterList.getCons()); + + //traceArgumentPointer.goNext(); + for (parameterIndex = 0; parameterIndex < argumentsResultPointerArray.length; parameterIndex++) { + Evaluator.traceShowArg(aEnvironment, traceParameterPointer, argumentsResultPointerArray[parameterIndex]); + + traceParameterPointer.goNext(aStackTop, aEnvironment); + }//end for. + }//end if. + + return argumentsResultPointerArray; + + }//end method. + + + /** + * Put an argument on hold. + * The \c iHold flag of the corresponding argument is setCons. This + * implies that this argument is not evaluated by evaluate(). + * + * @param aVariable name of argument to put un hold + */ + public void holdArgument(String aVariable) { + int i; + int nrc = iParameters.size(); + for (i = 0; i < nrc; i++) { + if (((ParameterName) iParameters.get(i)).iName.equals(aVariable)) { + ((ParameterName) iParameters.get(i)).iHold = true; + } + } + } + + + /** + * Return true if the arity of the function equals \a aArity. + * + * @param aArity + * @return true of the arities match. + */ + public boolean isArity(int aArity) { + return (arity() == aArity); + } + + + /** + * Return the arity (number of arguments) of the function. + * + * @return the arity of the function + */ + public int arity() { + return iParameters.size(); + } + + + /** + * Add a PredicateRule to the list of rules. + * See: insertRule() + * + * @param aPrecedence + * @param aPredicate + * @param aBody + * @throws java.lang.Exception + */ + public void defineSometimesTrueRule(int aStackTop, int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { + // New branching rule. + PredicateRule newRule = new PredicateRule(iEnvironment, aPrecedence, aPredicate, aBody); + LispError.check(iEnvironment, aStackTop, newRule != null, LispError.CREATING_RULE, "INTERNAL"); + + insertRule(aPrecedence, newRule); + } + + + /** + * Add a TrueRule to the list of rules. + * See: insertRule() + * + * @param aPrecedence + * @param aBody + * @throws java.lang.Exception + */ + public void defineAlwaysTrueRule(int aStackTop, int aPrecedence, ConsPointer aBody) throws Exception { + // New branching rule. + PredicateRule newRule = new TrueRule(iEnvironment, aPrecedence, aBody); + LispError.check(iEnvironment, aStackTop, newRule != null, LispError.CREATING_RULE, "INTERNAL"); + + insertRule(aPrecedence, newRule); + } + + + /** + * Add a PatternRule to the list of rules. + * See: insertRule() + * + * @param aPrecedence + * @param aPredicate + * @param aBody + * @throws java.lang.Exception + */ + public void definePattern(int aStackTop, int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { + // New branching rule. + PatternRule newRule = new PatternRule(iEnvironment, aStackTop, aPrecedence, aPredicate, aBody); + LispError.check(iEnvironment, aStackTop, newRule != null, LispError.CREATING_RULE, "INTERNAL"); + + insertRule(aPrecedence, newRule); + } + + + /** + * Insert any Rule object in the list of rules. + * This function does the real work for defineAlwaysTrueRule() and + * definePattern(): it inserts the rule in iRules, while + * keeping it sorted. The algorithm is O(log n), where + * n denotes the number of rules. + * + * @param aPrecedence + * @param newRule + */ + void insertRule(int aNewRulePrecedence, Rule aNewRule) { + // Find place to insert + int low, high, mid; + low = 0; + high = iBranchRules.size(); + + // Constant time: find out if the precedence is before any of the + // currently defined rules or past them. + if (high > 0) { + if (((Rule) iBranchRules.get(0)).getPrecedence() > aNewRulePrecedence) { + mid = 0; + // Insert it + iBranchRules.add(mid, aNewRule); + return; + } + if (((Rule) iBranchRules.get(high - 1)).getPrecedence() < aNewRulePrecedence) { + mid = high; + // Insert it + iBranchRules.add(mid, aNewRule); + return; + } + } + + // Otherwise, O(log n) search algorithm for place to insert + while(true) { + if (low >= high) { + //Insert it. + mid = low; + iBranchRules.add(mid, aNewRule); + return; + } + + + mid = (low + high) >> 1; + + Rule existingRule = (Rule) iBranchRules.get(mid); + + int existingRulePrecedence = existingRule.getPrecedence(); + + if (existingRulePrecedence > aNewRulePrecedence) { + high = mid; + } else if (existingRulePrecedence < aNewRulePrecedence) { + low = (++mid); + } else { + + //existingRule. + //Insert it. + iBranchRules.add(mid, aNewRule); + return; + } + } + } + + + /** + * Return the argument list, stored in #iParameterList. + * + * @return a ConsPointer + */ + public ConsPointer argList() { + return iParameterList; + } + + + public Iterator getRules() { + return iBranchRules.iterator(); + } + + + public Iterator getParameters() { + return iParameters.iterator(); + } + + + public void unFence() { + iFenced = false; + } + + + public boolean fenced() { + return iFenced; + } + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/TrueRule.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/TrueRule.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/rulebases/TrueRule.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/rulebases/TrueRule.java 2010-12-29 04:07:15.000000000 +0000 @@ -0,0 +1,41 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.lisp.rulebases; + +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.Environment; + +/** + * A rule that always matches. + */ +class TrueRule extends PredicateRule +{ + + public TrueRule(Environment aEnvironment, int aPrecedence, ConsPointer aBody) + { + super(aEnvironment); + iPrecedence = aPrecedence; + iBody.setCons(aBody.getCons()); + } + /// Return true, always. + @Override + public boolean matches(Environment aEnvironment, int aStackTop, ConsPointer[] aArguments) throws Exception + { + return true; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/stacks/ArgumentStack.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/stacks/ArgumentStack.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/stacks/ArgumentStack.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/stacks/ArgumentStack.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,9 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - package org.mathpiper.lisp.stacks; import org.mathpiper.lisp.*; @@ -27,97 +25,118 @@ * Implements a stack of pointers to CONS that can be used to pass * arguments to functions, and receive results back. */ -public class ArgumentStack -{ +public class ArgumentStack { ConsPointerArray iArgumentStack; int iStackTopIndex; //TODO appropriate constructor? - public ArgumentStack(int aStackSize) - { - iArgumentStack = new ConsPointerArray(aStackSize, null); + public ArgumentStack(Environment aEnvironment, int aStackSize) { + iArgumentStack = new ConsPointerArray(aEnvironment, aStackSize, null); iStackTopIndex = 0; - //printf("STACKSIZE %d\n",aStackSize); + //printf("STACKSIZE %d\n",aStackSize); } - public int getStackTopIndex() - { + public int getStackTopIndex() { return iStackTopIndex; } - public void raiseStackOverflowError() throws Exception - { - LispError.raiseError("Argument stack reached maximum. Please extend argument stack with --stack argument on the command line."); + public void raiseStackOverflowError(int aStackTop, Environment aEnvironment) throws Exception { + LispError.raiseError("Argument stack reached maximum. Please extend argument stack with --stack argument on the command line.", "[INTERNAL]", aStackTop, aEnvironment); } - public void pushArgumentOnStack(Cons aCons) throws Exception - { - if (iStackTopIndex >= iArgumentStack.size()) - { - raiseStackOverflowError(); + public void pushArgumentOnStack(Cons aCons, int aStackTop, Environment aEnvironment) throws Exception { + if (iStackTopIndex >= iArgumentStack.size()) { + raiseStackOverflowError(aStackTop, aEnvironment); } iArgumentStack.setElement(iStackTopIndex, aCons); iStackTopIndex++; } - public void pushNulls(int aNr) throws Exception - { - if (iStackTopIndex + aNr > iArgumentStack.size()) - { - raiseStackOverflowError(); + public void pushNulls(int aNr, int aStackTop, Environment aEnvironment) throws Exception { + if (iStackTopIndex + aNr > iArgumentStack.size()) { + raiseStackOverflowError(aStackTop, aEnvironment); } iStackTopIndex += aNr; } - public ConsPointer getElement(int aPos) throws Exception - { - LispError.lispAssert(aPos >= 0 && aPos < iStackTopIndex); + public ConsPointer getElement(int aPos, int aStackTop, Environment aEnvironment) throws Exception { + LispError.lispAssert(aPos >= 0 && aPos < iStackTopIndex, aEnvironment, aStackTop); return iArgumentStack.getElement(aPos); } - public void popTo(int aTop) throws Exception - { - LispError.lispAssert(aTop <= iStackTopIndex); - while (iStackTopIndex > aTop) - { + public void popTo(int aTop, int aStackTop, Environment aEnvironment) throws Exception { + LispError.lispAssert(aTop <= iStackTopIndex, aEnvironment, aStackTop); + while (iStackTopIndex > aTop) { iStackTopIndex--; iArgumentStack.setElement(iStackTopIndex, null); } } - - public void reset() throws Exception - { - this.popTo(0); - }//end method. - - public void dump() throws Exception - { - for(int x=0; x <= iStackTopIndex; x++) - { - //try - //{ - ConsPointer consPointer = getElement(x); - Cons cons = consPointer.getCons(); - //} - //catch(Exception e) - //{ - // e.printStackTrace(); - //} - - //System.out.println() - } + public void reset(int aStackTop, Environment aEnvironment) throws Exception { + this.popTo(0, aStackTop, aEnvironment); }//end method. + public String dump(int aStackTop, Environment aEnvironment) throws Exception { + + StringBuilder stringBuilder = new StringBuilder(); + + int functionBaseIndex = 0; + + int functionPositionIndex = 0; + + + while (functionBaseIndex <= aStackTop) { + + if(functionBaseIndex == 0) + { + stringBuilder.append("\n\n========================================= Start Of Built In Function Stack Trace\n"); + } + else + { + stringBuilder.append("-----------------------------------------\n"); + } + + ConsPointer consPointer = getElement(functionBaseIndex, aStackTop, aEnvironment); + + int argumentCount = Utility.listLength(aEnvironment, aStackTop, consPointer); - public ConsPointer[] getElements(int quantity) throws IndexOutOfBoundsException - { + ConsPointer argumentPointer = new ConsPointer(); + + Object car = consPointer.getCons().car(); + + ConsPointer consTraverser = new ConsPointer( consPointer.getCons()); + + stringBuilder.append(functionPositionIndex++ + ": "); + stringBuilder.append(Utility.printMathPiperExpression(aStackTop, consTraverser, aEnvironment, -1)); + stringBuilder.append("\n"); + + consTraverser.goNext(aStackTop, aEnvironment); + + while(consTraverser.getCons() != null) + { + stringBuilder.append(" " + functionPositionIndex++ + ": "); + stringBuilder.append("-> " + Utility.printMathPiperExpression(aStackTop, consTraverser, aEnvironment, -1)); + stringBuilder.append("\n"); + + consTraverser.goNext(aStackTop, aEnvironment); + } + + + functionBaseIndex = functionBaseIndex + argumentCount; + + }//end while. + + stringBuilder.append("========================================= End Of Built In Function Stack Trace\n\n"); + + return stringBuilder.toString(); + + }//end method. + + public ConsPointer[] getElements(int quantity) throws IndexOutOfBoundsException { int last = iStackTopIndex; int first = last - quantity; return iArgumentStack.getElements(first, last); }//end method. - - - }//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/stacks/UserStackInformation.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/stacks/UserStackInformation.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/stacks/UserStackInformation.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/stacks/UserStackInformation.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,24 +13,23 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - //}}} // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp.stacks; import org.mathpiper.lisp.cons.ConsPointer; -public class UserStackInformation -{ +public class UserStackInformation { + + public ConsPointer iExpression; + public ConsPointer iOperator; + public int iRulePrecedence; + public int iSide; // 0=pattern, 1=body + + + public UserStackInformation() { + iRulePrecedence = -1; + iSide = 0; + } - public ConsPointer iExpression; - public ConsPointer iOperator; - public int iRulePrecedence; - public int iSide; // 0=pattern, 1=body - - public UserStackInformation() - { - iRulePrecedence = -1; - iSide = 0; - } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/tokenizers/CommonLispTokenizer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/tokenizers/CommonLispTokenizer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/tokenizers/CommonLispTokenizer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/tokenizers/CommonLispTokenizer.java 2010-12-29 04:07:15.000000000 +0000 @@ -17,123 +17,6 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp.tokenizers; -import org.mathpiper.lisp.collections.TokenMap; -import org.mathpiper.io.MathPiperInputStream; - -/** - * - * - */ -/* -Running MathPiper from Eclipse IDE -From: Axel - 2005-08-14 09:56 - - - - -Hi - -I"ve a little project which is similar to the piper applet: -http://www.matheclipse.org -which uses a JavaScript interface and a Java servlet backend. - -So I would like to test the piper applet from sources inside the -http://www.eclipse.org IDE and checked out JavaMathPiper from CVS and get the -following compile errors: - -Severity Description Resource In Folder Location Creation Time -2 Syntax error on token "goto", throw -expected CommonLispTokenizer.java JavaMathPiper line 14 14. August 2005 -18:43:21 -2 Syntax error on token "goto", break -expected CommonLispTokenizer.java JavaMathPiper line 47 14. August 2005 -18:43:21 -2 Syntax error on token "goto", throw -expected CommonLispTokenizer.java JavaMathPiper line 49 14. August 2005 -18:43:21 -2 Syntax error on token "goto", break -expected CommonLispTokenizer.java JavaMathPiper line 54 14. August 2005 -18:43:21 -2 Syntax error on token "goto", throw -expected CommonLispTokenizer.java JavaMathPiper line 113 14. August 2005 -18:43:21 -2 Syntax error on token "&", delete this -token CommonLispTokenizer.java JavaMathPiper line 117 14. August 2005 -18:43:21 -2 CVersion cannot be resolved ConsoleApplet.java JavaMathPiper line -123 14. August 2005 18:43:21 -2 CVersion cannot be resolved MathCommands.java JavaMathPiper line -4194 14. August 2005 18:43:20 -2 CVersion cannot be resolved MathPiperConsole.java JavaMathPiper line 134 14. -August 2005 18:43:18 -2 The method AddLine(String) in the type HintWindow is not applicable -for the arguments (String, -MathPiperGraphicsContext) MathPiperNotebook.java JavaMathPiper line 36 14. August -2005 18:43:18 -2 The method AddLine(String) in the type HintWindow is not applicable -for the arguments (String, -MathPiperGraphicsContext) MathPiperNotebook.java JavaMathPiper line 37 14. August -2005 18:43:18 -2 The method AddDescription(String) in the type HintWindow is not -applicable for the arguments (String, -MathPiperGraphicsContext) MathPiperNotebook.java JavaMathPiper line 38 14. August -2005 18:43:18 -2 The method AddDescription(String) in the type HintWindow is not -applicable for the arguments (String, -MathPiperGraphicsContext) MathPiperNotebook.java JavaMathPiper line 39 14. August -2005 18:43:18 - -BTW: - * all *.java files don"t contain a package declaration, which is -really unusual in Java, by convention you can use something like: -"package net.sourceforge.piper;" - * also by convention in most projects java source files a stored below -a subfolder "/src". - * I attached the eclipse .project and .classpath I"ve used for the test. - --- -Axel Kramer - - - - - -Re: Running MathPiper from Eclipse IDE -From: Ayal Pinkus - 2005-08-14 11:32 - -Hi Axel, -matheclipse looks interesting! - -For now I think you can leave out compiling CommonLispTokenizer.java. - -CVersion.java is generated by the make file makefile.piper. The -contents are -currently: - -class CVersion { static String VERSION = "1.0.58"; } - -For now you can skip compiling MathPiperNotebook.java too. Regarding -package, -that is something some one else mentioned too. I am not a very -experienced -Java programmer, as you might be able to tell. - -I will fix these things as soon as possible. In the mean time, I"ll -forward an email I -got from some one who is trying to use it in a way that might be -similar to how you -want to use it. He made changes that made it work for him. That might -be of interest -to you. - -Ayal - - - -*/ - -import org.mathpiper.lisp.*; - class CommonLispTokenizer extends MathPiperTokenizer { /* diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/tokenizers/MathPiperTokenizer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/tokenizers/MathPiperTokenizer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/tokenizers/MathPiperTokenizer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/tokenizers/MathPiperTokenizer.java 2010-12-29 04:07:15.000000000 +0000 @@ -25,13 +25,13 @@ public class MathPiperTokenizer { - static String symbolics = new String("~`!@#$^&*-=+:<>?/\\|"); + static String symbolics = "~`!@#$^&*-=+:<>?/\\|"; //static String unicodeVariableChars = "αβγ"; String iToken; //Can be used as a token container. /// NextToken returns a string representing the next token, /// or an empty list. - public String nextToken(MathPiperInputStream aInput, TokenMap aTokenHashTable) throws Exception { + public String nextToken(Environment aEnvironment, int aStackTop, MathPiperInputStream aInput, TokenMap aTokenHashTable) throws Exception { char streamCharacter; int firstpos = aInput.position(); @@ -69,7 +69,7 @@ aInput.next(); //consume * while (true) { while (aInput.next() != '*' && !aInput.endOfStream()); - LispError.check(!aInput.endOfStream(), LispError.COMMENT_TO_END_OF_FILE); + LispError.check(aEnvironment, aStackTop, !aInput.endOfStream(), LispError.COMMENT_TO_END_OF_FILE, "INTERNAL"); if (aInput.peek() == '/') { aInput.next(); // consume / redo = true; @@ -93,11 +93,17 @@ while (aInput.peek() != '\"') { if (aInput.peek() == '\\') { aInput.next(); - LispError.check(!aInput.endOfStream(), LispError.PARSING_INPUT); + LispError.check(aEnvironment, aStackTop, !aInput.endOfStream(), LispError.PARSING_INPUT, "INTERNAL"); + + /*if(! (aInput.peek() == '\"')) + { + //Leave in backslash in front of all characters except a " character. + aResult = aResult + "\\"; + }*/ } //TODO FIXME is following append char correct? aResult = aResult + ((char) aInput.next()); - LispError.check(!aInput.endOfStream(), LispError.PARSING_INPUT); + LispError.check(aEnvironment, aStackTop, !aInput.endOfStream(), LispError.PARSING_INPUT, "INTERNAL"); } //TODO FIXME is following append char correct? aResult = aResult + ((char) aInput.next()); // consume the close quote @@ -159,7 +165,9 @@ return true; } else if (c == '\'') { return true; - } else if (c == 0x00b7) { // middle dot (for Catalan). + } else if (c == '?') { + return true; + }else if (c == 0x00b7) { // middle dot (for Catalan). return true; } else if (c == 0x00b0) { // degree symbol). return true; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/tokenizers/XmlTokenizer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/tokenizers/XmlTokenizer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/tokenizers/XmlTokenizer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/tokenizers/XmlTokenizer.java 2010-12-29 04:07:15.000000000 +0000 @@ -13,75 +13,69 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - //}}} // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp.tokenizers; import org.mathpiper.lisp.collections.TokenMap; import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.tokenizers.MathPiperTokenizer; import org.mathpiper.io.MathPiperInputStream; +import org.mathpiper.lisp.Environment; public class XmlTokenizer - extends MathPiperTokenizer -{ + extends MathPiperTokenizer { + + /// NextToken returns a string representing the next token, + /// or an empty list. + @Override + public String nextToken(Environment aEnvironment, int aStackTop, MathPiperInputStream aInput, TokenMap aHashTable) + throws Exception { + + char c; + int firstpos = 0; + + if (aInput.endOfStream()) { + return (String) aHashTable.lookUp(aInput.startPtr().substring(firstpos, aInput.position())); + } + + //skipping spaces + while (IsSpace(aInput.peek())) { + aInput.next(); + } + + firstpos = aInput.position(); + c = aInput.next(); + + if (c == '<') { + + while (c != '>') { + c = aInput.next(); + LispError.check(aEnvironment, aStackTop, !aInput.endOfStream(), LispError.COMMENT_TO_END_OF_FILE, "INTERNAL"); + } + } else { + + while (aInput.peek() != '<' && !aInput.endOfStream()) { + c = aInput.next(); + } + } + + return (String) aHashTable.lookUp(aInput.startPtr().substring(firstpos, aInput.position())); + } + + + private static boolean IsSpace(int c) { + + switch (c) { + + case 0x20: + case 0x0D: + case 0x0A: + case 0x09: + return true; + + default: + return false; + } + } - /// NextToken returns a string representing the next token, - /// or an empty list. - public String nextToken(MathPiperInputStream aInput, TokenMap aHashTable) - throws Exception - { - - char c; - int firstpos = 0; - - if (aInput.endOfStream()) - - return (String) aHashTable.lookUp(aInput.startPtr().substring(firstpos, aInput.position())); - - //skipping spaces - while (IsSpace(aInput.peek())) - aInput.next(); - - firstpos = aInput.position(); - c = aInput.next(); - - if (c == '<') - { - - while (c != '>') - { - c = aInput.next(); - LispError.check(!aInput.endOfStream(), LispError.COMMENT_TO_END_OF_FILE); - } - } - else - { - - while (aInput.peek() != '<' && !aInput.endOfStream()) - { - c = aInput.next(); - } - } - - return (String) aHashTable.lookUp(aInput.startPtr().substring(firstpos, aInput.position())); - } - - private static boolean IsSpace(int c) - { - - switch (c) - { - - case 0x20: - case 0x0D: - case 0x0A: - case 0x09: - return true; - - default: - return false; - } - } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/Branch.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/Branch.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/Branch.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/Branch.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.lisp.userfunctions; - -import java.util.Iterator; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Environment; - -/** - * Base class for rules. - */ -public abstract class Branch -{ - - public abstract boolean matches(Environment aEnvironment, ConsPointer[] aArguments) throws Exception; - - public abstract int getPrecedence(); - - public abstract ConsPointer getPredicatePointer(); - - public abstract ConsPointer getBodyPointer(); -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/FunctionParameter.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/FunctionParameter.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/FunctionParameter.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/FunctionParameter.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.lisp.userfunctions; - -/** - * Contains the name of a parameter and if it is put on hold. - */ -public class FunctionParameter -{ - String iParameter; - boolean iHold; - - public FunctionParameter(String aParameter, boolean aHold /*=false*/) - { - iParameter = aParameter; - iHold = aHold; - } - - public String getParameter() - { - return iParameter; - } - - public boolean isHold() - { - return iHold; - } - -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/ListedBranchingUserFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/ListedBranchingUserFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/ListedBranchingUserFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/ListedBranchingUserFunction.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp.userfunctions; - -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsTraverser; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.cons.SublistCons; - - -public class ListedBranchingUserFunction extends SingleArityBranchingUserFunction -{ - public ListedBranchingUserFunction(ConsPointer aParameters, String functionName) throws Exception - { - super(aParameters, functionName); - } - - public boolean isArity(int aArity) - { - return (arity() <= aArity); - } - - public void evaluate( Environment aEnvironment,ConsPointer aResult, ConsPointer aArguments) throws Exception - { - ConsPointer newArgs = new ConsPointer(); - ConsTraverser consTraverser = new ConsTraverser(aArguments); - ConsPointer ptr = newArgs; - int arity = arity(); - int i=0; - while (i < arity && consTraverser.getCons() != null) - { - ptr.setCons(consTraverser.getCons().copy( aEnvironment, false)); - ptr = (ptr.cdr()); - i++; - consTraverser.goNext(); - } - if (consTraverser.cdr().getCons() == null) - { - ptr.setCons(consTraverser.getCons().copy( aEnvironment, false)); - ptr = (ptr.cdr()); - i++; - consTraverser.goNext(); - LispError.lispAssert(consTraverser.getCons() == null); - } - else - { - ConsPointer head = new ConsPointer(); - head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); - head.cdr().setCons(consTraverser.getCons()); - ptr.setCons(SublistCons.getInstance(aEnvironment,head.getCons())); - } - super.evaluate(aEnvironment, aResult, newArgs); - } -} - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/ListedMacroUserFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/ListedMacroUserFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/ListedMacroUserFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/ListedMacroUserFunction.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp.userfunctions; - -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsTraverser; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.cons.SublistCons; - - -public class ListedMacroUserFunction extends MacroUserFunction -{ - - public ListedMacroUserFunction(ConsPointer aParameters, String functionName) throws Exception - { - super(aParameters, functionName); - } - - public boolean isArity(int aArity) - { - return (arity() <= aArity); - } - - public void evaluate( Environment aEnvironment,ConsPointer aResult, ConsPointer aArguments) throws Exception - { - ConsPointer newArgs = new ConsPointer(); - ConsTraverser consTraverser = new ConsTraverser(aArguments); - ConsPointer ptr = newArgs; - int arity = arity(); - int i=0; - while (i < arity && consTraverser.getCons() != null) - { - ptr.setCons(consTraverser.getCons().copy( aEnvironment, false)); - ptr = (ptr.cdr()); - i++; - consTraverser.goNext(); - } - if (consTraverser.cdr().getCons() == null) - { - ptr.setCons(consTraverser.getCons().copy( aEnvironment, false)); - ptr = (ptr.cdr()); - i++; - consTraverser.goNext(); - LispError.lispAssert(consTraverser.getCons() == null); - } - else - { - ConsPointer head = new ConsPointer(); - head.setCons(aEnvironment.iListAtom.copy( aEnvironment, false)); - head.cdr().setCons(consTraverser.getCons()); - ptr.setCons(SublistCons.getInstance(aEnvironment,head.getCons())); - } - super.evaluate(aEnvironment, aResult, newArgs); - } -} - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/MacroUserFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/MacroUserFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/MacroUserFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/MacroUserFunction.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,156 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.lisp.userfunctions; - -import org.mathpiper.exceptions.EvaluationException; -import org.mathpiper.lisp.stacks.UserStackInformation; -import org.mathpiper.lisp.behaviours.BackQuoteSubstitute; -import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.LispError; -import org.mathpiper.lisp.cons.ConsTraverser; -import org.mathpiper.lisp.Environment; -import org.mathpiper.lisp.Evaluator; -import org.mathpiper.lisp.LispExpressionEvaluator; -import org.mathpiper.lisp.cons.SublistCons; - -public class MacroUserFunction extends SingleArityBranchingUserFunction { - - public MacroUserFunction(ConsPointer aParameters, String functionName) throws Exception { - super(aParameters, functionName); - ConsTraverser parameterTraverser = new ConsTraverser(aParameters); - int i = 0; - while (parameterTraverser.getCons() != null) { - - //LispError.check(parameterTraverser.car() != null, LispError.CREATING_USER_FUNCTION); - try{ - LispError.check(parameterTraverser.car() instanceof String, LispError.CREATING_USER_FUNCTION); - }catch(EvaluationException ex) - { - throw new EvaluationException(ex.getMessage() + " Function: " + this.functionName + " ",-1) ; - }//end catch. - - - ((FunctionParameter) iParameters.get(i)).iHold = true; - parameterTraverser.goNext(); - i++; - } - //Macros are all unfenced. - unFence(); - - this.functionType = "macro"; - } - - public void evaluate(Environment aEnvironment, ConsPointer aResult, ConsPointer aArgumentsPointer) throws Exception { - int arity = arity(); - ConsPointer[] argumentsResultPointerArray = evaluateArguments(aEnvironment, aArgumentsPointer); - int parameterIndex; - - - - ConsPointer substitutedBodyPointer = new ConsPointer(); - - //Create a new local variable frame that is unfenced (false = unfenced). - aEnvironment.pushLocalFrame(false, this.functionName); - - try { - // define the local variables. - for (parameterIndex = 0; parameterIndex < arity; parameterIndex++) { - String variable = ((FunctionParameter) iParameters.get(parameterIndex)).iParameter; - - // setCons the variable to the new value - aEnvironment.newLocalVariable(variable, argumentsResultPointerArray[parameterIndex].getCons()); - } - - // walk the rules database, returning the evaluated result if the - // predicate is true. - int numberOfRules = iBranchRules.size(); - UserStackInformation userStackInformation = aEnvironment.iLispExpressionEvaluator.stackInformation(); - for (parameterIndex = 0; parameterIndex < numberOfRules; parameterIndex++) { - Branch thisRule = ((Branch) iBranchRules.get(parameterIndex)); - //TODO remove CHECKPTR(thisRule); - LispError.lispAssert(thisRule != null); - - userStackInformation.iRulePrecedence = thisRule.getPrecedence(); - - boolean matches = thisRule.matches(aEnvironment, argumentsResultPointerArray); - - if (matches) { - /* Rule dump trace code. */ - if (isTraced() && showFlag) { - ConsPointer argumentsPointer = new ConsPointer(); - argumentsPointer.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); - String ruleDump = org.mathpiper.lisp.Utility.dumpRule(thisRule, aEnvironment, this); - Evaluator.traceShowRule(aEnvironment, argumentsPointer, ruleDump); - } - userStackInformation.iSide = 1; - - BackQuoteSubstitute backQuoteSubstitute = new BackQuoteSubstitute(aEnvironment); - - ConsPointer originalBodyPointer = thisRule.getBodyPointer(); - Utility.substitute(aEnvironment,substitutedBodyPointer, originalBodyPointer, backQuoteSubstitute); - // aEnvironment.iLispExpressionEvaluator.Eval(aEnvironment, aResult, thisRule.body()); - break; - } - - // If rules got inserted, walk back - while (thisRule != ((Branch) iBranchRules.get(parameterIndex)) && parameterIndex > 0) { - parameterIndex--; - } - } - } catch (Exception e) { - throw e; - } finally { - aEnvironment.popLocalFrame(); - } - - - - if (substitutedBodyPointer.getCons() != null) { - //Note:tk:substituted body must be evaluated after the local frame has been popped. - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aResult, substitutedBodyPointer); - } else // No predicate was true: return a new expression with the evaluated - // arguments. - { - ConsPointer full = new ConsPointer(); - full.setCons(aArgumentsPointer.getCons().copy( aEnvironment, false)); - if (arity == 0) { - full.cdr().setCons(null); - } else { - full.cdr().setCons(argumentsResultPointerArray[0].getCons()); - for (parameterIndex = 0; parameterIndex < arity - 1; parameterIndex++) { - argumentsResultPointerArray[parameterIndex].cdr().setCons(argumentsResultPointerArray[parameterIndex + 1].getCons()); - } - } - aResult.setCons(SublistCons.getInstance(aEnvironment,full.getCons())); - } - //FINISH: - - /*Leave trace code */ - if (isTraced() && showFlag) { - ConsPointer tr = new ConsPointer(); - tr.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); - String localVariables = aEnvironment.getLocalVariables(); - LispExpressionEvaluator.traceShowLeave(aEnvironment, aResult, tr, "macro", localVariables); - tr.setCons(null); - } - - } -} - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/MultipleArityUserFunction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/MultipleArityUserFunction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/MultipleArityUserFunction.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/MultipleArityUserFunction.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.lisp.userfunctions; - - -import org.mathpiper.lisp.DefFile; -import org.mathpiper.lisp.*; -import java.util.*; - - - -/** - * Holds a set of {@link SingleArityBranchingUserFunction} which are associated with one function name. - * A specific SingleArityBranchingUserFunction can be selected by providing its name. The - * name of the file in which the function is defined can also be specified. - */ -public class MultipleArityUserFunction -{ - - /// Set of SingleArityBranchingUserFunction's provided by this MultipleArityUserFunction. - List iFunctions = new ArrayList();// - - /// File to read for the definition of this function. - public DefFile iFileToOpen; - - public String iFileLocation; - - /// Constructor. - public MultipleArityUserFunction() - { - iFileToOpen = null; - } - - /// Return user function with given arity. - public SingleArityBranchingUserFunction getUserFunction(int aArity) throws Exception - { - int ruleIndex; - //Find function body with the right arity - int numberOfRules=iFunctions.size(); - for (ruleIndex =0; ruleIndex iParameters = new ArrayList(); //CArrayGrower - - /// List of rules, sorted on precedence. - protected List iBranchRules = new ArrayList();//CDeletingArrayGrower - - /// List of arguments - ConsPointer iParameterList = new ConsPointer(); -/// Abstract class providing the basic user function API. -/// Instances of this class are associated to the name of the function -/// via an associated hash table. When obtained, they can be used to -/// evaluate the function with some arguments. - boolean iFenced = true; - boolean showFlag = false; - protected String functionType = "**** user rulebase"; - protected String functionName; - - /** - * Constructor. - * - * @param aParameters linked list constaining the names of the arguments - * @throws java.lang.Exception - */ - public SingleArityBranchingUserFunction(ConsPointer aParameters, String functionName) throws Exception { - this.functionName = functionName; - // iParameterList and #iParameters are set from \a aParameters. - iParameterList.setCons(aParameters.getCons()); - - ConsPointer parameterTraverser = new ConsPointer(aParameters.getCons()); - - while (parameterTraverser.getCons() != null) { - - try{ - LispError.check(parameterTraverser.car() instanceof String, LispError.CREATING_USER_FUNCTION); - }catch(EvaluationException ex) - { - throw new EvaluationException(ex.getMessage() + " Function: " + this.functionName + " ",-1) ; - }//end catch. - - FunctionParameter parameter = new FunctionParameter( (String) parameterTraverser.car(), false); - iParameters.add(parameter); - parameterTraverser.goNext(); - } - } - - /** - * Evaluate the function with the given arguments. - * First, all arguments are evaluated by the evaluator associated - * with aEnvironment, unless the iHold flag of the - * corresponding parameter is true. Then a new LocalFrame is - * constructed, in which the actual arguments are assigned to the - * names of the formal arguments, as stored in iParameter. Then - * all rules in iRules are tried one by one. The body of the - * getFirstPointer rule that matches is evaluated, and the result is put in - * aResult. If no rule matches, aResult will recieve a new - * expression with evaluated arguments. - * - * @param aResult (on output) the result of the evaluation - * @param aEnvironment the underlying Lisp environment - * @param aArguments the arguments to the function - * @throws java.lang.Exception - */ - public void evaluate(Environment aEnvironment, ConsPointer aResult, ConsPointer aArgumentsPointer) throws Exception { - int arity = arity(); - ConsPointer[] argumentsResultPointerArray = evaluateArguments(aEnvironment, aArgumentsPointer); - int parameterIndex; - - // Create a new local variables frame that has the same fenced state as this function. - aEnvironment.pushLocalFrame(fenced(), this.functionName); - - - - try { - // define the local variables. - for (parameterIndex = 0; parameterIndex < arity; parameterIndex++) { - String variableName = ((FunctionParameter) iParameters.get(parameterIndex)).iParameter; - // set the variable to the new value - aEnvironment.newLocalVariable(variableName, argumentsResultPointerArray[parameterIndex].getCons()); - } - - // walk the rules database, returning the evaluated result if the - // predicate is true. - int numberOfRules = iBranchRules.size(); - - UserStackInformation userStackInformation = aEnvironment.iLispExpressionEvaluator.stackInformation(); - - for (parameterIndex = 0; parameterIndex < numberOfRules; parameterIndex++) { - Branch thisRule = ((Branch) iBranchRules.get(parameterIndex)); - LispError.lispAssert(thisRule != null); - - userStackInformation.iRulePrecedence = thisRule.getPrecedence(); - - boolean matches = thisRule.matches(aEnvironment, argumentsResultPointerArray); - - if (matches) { - - /* Rule dump trace code. */ - if (isTraced() && showFlag) { - ConsPointer argumentsPointer = new ConsPointer(); - argumentsPointer.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); - String ruleDump = org.mathpiper.lisp.Utility.dumpRule(thisRule, aEnvironment, this); - Evaluator.traceShowRule(aEnvironment, argumentsPointer, ruleDump); - } - - userStackInformation.iSide = 1; - - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aResult, thisRule.getBodyPointer()); - - /*Leave trace code */ - if (isTraced() && showFlag) { - ConsPointer argumentsPointer2 = new ConsPointer(); - argumentsPointer2.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); - String localVariables = aEnvironment.getLocalVariables(); - Evaluator.traceShowLeave(aEnvironment, aResult, argumentsPointer2, functionType, localVariables); - argumentsPointer2.setCons(null); - }//end if. - - return; - }//end if matches. - - // If rules got inserted, walk back - while (thisRule != ((Branch) iBranchRules.get(parameterIndex)) && parameterIndex > 0) { - parameterIndex--; - } - }//end for. - - - // No predicate was true: return a new expression with the evaluated - // arguments. - ConsPointer full = new ConsPointer(); - full.setCons(aArgumentsPointer.getCons().copy( aEnvironment, false)); - if (arity == 0) { - full.cdr().setCons(null); - } else { - full.cdr().setCons(argumentsResultPointerArray[0].getCons()); - for (parameterIndex = 0; parameterIndex < arity - 1; parameterIndex++) { - argumentsResultPointerArray[parameterIndex].cdr().setCons(argumentsResultPointerArray[parameterIndex + 1].getCons()); - } - } - aResult.setCons(SublistCons.getInstance(aEnvironment,full.getCons())); - - - /* Trace code */ - if (isTraced() && showFlag) { - ConsPointer argumentsPointer3 = new ConsPointer(); - argumentsPointer3.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); - String localVariables = aEnvironment.getLocalVariables(); - Evaluator.traceShowLeave(aEnvironment, aResult, argumentsPointer3, functionType, localVariables); - argumentsPointer3.setCons(null); - } - - } catch (Exception e) { - throw e; - } finally { - aEnvironment.popLocalFrame(); - } - } - - protected ConsPointer[] evaluateArguments(Environment aEnvironment, ConsPointer aArgumentsPointer) throws Exception { - int arity = arity(); - int parameterIndex; - - /*Enter trace code*/ - if (isTraced()) { - ConsPointer argumentsPointer = new ConsPointer(); - argumentsPointer.setCons(SublistCons.getInstance(aEnvironment,aArgumentsPointer.getCons())); - String functionName = ""; - if (argumentsPointer.car() instanceof ConsPointer) { - ConsPointer sub = (ConsPointer) argumentsPointer.car(); - if (sub.car() instanceof String) { - functionName = (String) sub.car(); - } - }//end function. - if (Evaluator.isTraceFunction(functionName)) { - showFlag = true; - Evaluator.traceShowEnter(aEnvironment, argumentsPointer, functionType); - } else { - showFlag = false; - }// - argumentsPointer.setCons(null); - } - - ConsPointer argumentsTraverser = new ConsPointer(aArgumentsPointer.getCons()); - - //Strip the function name from the head of the list. - argumentsTraverser.goNext(); - - //Creat an array which holds pointers to each argument. - ConsPointer[] argumentsResultPointerArray; - if (arity == 0) { - argumentsResultPointerArray = null; - } else { - LispError.lispAssert(arity > 0); - argumentsResultPointerArray = new ConsPointer[arity]; - } - - // Walk over all arguments, evaluating them as necessary ******************************************************** - for (parameterIndex = 0; parameterIndex < arity; parameterIndex++) { - - argumentsResultPointerArray[parameterIndex] = new ConsPointer(); - - LispError.check(argumentsTraverser.getCons() != null, LispError.WRONG_NUMBER_OF_ARGUMENTS); - - if (((FunctionParameter) iParameters.get(parameterIndex)).iHold) { - //If the parameter is on hold, don't evaluate it and place a copy of it in argumentsPointerArray. - argumentsResultPointerArray[parameterIndex].setCons(argumentsTraverser.getCons().copy( aEnvironment, false)); - } else { - //If the parameter is not on hold: - - //Verify that the pointer to the arguments is not null. - LispError.check(argumentsTraverser != null, LispError.WRONG_NUMBER_OF_ARGUMENTS); - - //Evaluate each argument and place the result into argumentsResultPointerArray[i]; - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, argumentsResultPointerArray[parameterIndex], argumentsTraverser); - } - argumentsTraverser.goNext(); - }//end for. - - /*Argument trace code */ - if (isTraced() && argumentsResultPointerArray != null && showFlag) { - //ConsTraverser consTraverser2 = new ConsTraverser(aArguments); - //ConsPointer traceArgumentPointer = new ConsPointer(aArgumentsPointer.getCons()); - - //ConsTransverser traceArgumentPointer new ConsTraverser(this.iParameterList); - ConsPointer traceParameterPointer = new ConsPointer(this.iParameterList.getCons()); - - //traceArgumentPointer.goNext(); - for (parameterIndex = 0; parameterIndex < argumentsResultPointerArray.length; parameterIndex++) { - Evaluator.traceShowArg(aEnvironment, traceParameterPointer, argumentsResultPointerArray[parameterIndex]); - - traceParameterPointer.goNext(); - }//end for. - }//end if. - - return argumentsResultPointerArray; - - }//end method. - - /** - * Put an argument on hold. - * The \c iHold flag of the corresponding argument is setCons. This - * implies that this argument is not evaluated by evaluate(). - * - * @param aVariable name of argument to put un hold - */ - public void holdArgument(String aVariable) { - int i; - int nrc = iParameters.size(); - for (i = 0; i < nrc; i++) { - if (((FunctionParameter) iParameters.get(i)).iParameter == aVariable) { - ((FunctionParameter) iParameters.get(i)).iHold = true; - } - } - } - - /** - * Return true if the arity of the function equals \a aArity. - * - * @param aArity - * @return true of the arities match. - */ - public boolean isArity(int aArity) { - return (arity() == aArity); - } - - /** - * Return the arity (number of arguments) of the function. - * - * @return the arity of the function - */ - public int arity() { - return iParameters.size(); - } - - /** - * Add a RuleBranch to the list of rules. - * See: insertRule() - * - * @param aPrecedence - * @param aPredicate - * @param aBody - * @throws java.lang.Exception - */ - public void declareRule(int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { - // New branching rule. - RuleBranch newRule = new RuleBranch(aPrecedence, aPredicate, aBody); - LispError.check(newRule != null, LispError.CREATING_RULE); - - insertRule(aPrecedence, newRule); - } - - /** - * Add a TruePredicateRuleBranch to the list of rules. - * See: insertRule() - * - * @param aPrecedence - * @param aBody - * @throws java.lang.Exception - */ - public void declareRule(int aPrecedence, ConsPointer aBody) throws Exception { - // New branching rule. - RuleBranch newRule = new TruePredicateRuleBranch(aPrecedence, aBody); - LispError.check(newRule != null, LispError.CREATING_RULE); - - insertRule(aPrecedence, newRule); - } - - /** - * Add a PatternBranch to the list of rules. - * See: insertRule() - * - * @param aPrecedence - * @param aPredicate - * @param aBody - * @throws java.lang.Exception - */ - public void declarePattern(int aPrecedence, ConsPointer aPredicate, ConsPointer aBody) throws Exception { - // New branching rule. - PatternBranch newRule = new PatternBranch(aPrecedence, aPredicate, aBody); - LispError.check(newRule != null, LispError.CREATING_RULE); - - insertRule(aPrecedence, newRule); - } - - /** - * Insert any Branch object in the list of rules. - * This function does the real work for declareRule() and - * declarePattern(): it inserts the rule in iRules, while - * keeping it sorted. The algorithm is O(log n), where - * n denotes the number of rules. - * - * @param aPrecedence - * @param newRule - */ - void insertRule(int aPrecedence, Branch newRule) { - // Find place to insert - int low, high, mid; - low = 0; - high = iBranchRules.size(); - - // Constant time: find out if the precedence is before any of the - // currently defined rules or past them. - if (high > 0) { - if (((Branch) iBranchRules.get(0)).getPrecedence() > aPrecedence) { - mid = 0; - // Insert it - iBranchRules.add(mid, newRule); - return; - } - if (((Branch) iBranchRules.get(high - 1)).getPrecedence() < aPrecedence) { - mid = high; - // Insert it - iBranchRules.add(mid, newRule); - return; - } - } - - // Otherwise, O(log n) search algorithm for place to insert - for (;;) { - if (low >= high) { - mid = low; - // Insert it - iBranchRules.add(mid, newRule); - return; - } - mid = (low + high) >> 1; - - if (((Branch) iBranchRules.get(mid)).getPrecedence() > aPrecedence) { - high = mid; - } else if (((Branch) iBranchRules.get(mid)).getPrecedence() < aPrecedence) { - low = (++mid); - } else { - // Insert it - iBranchRules.add(mid, newRule); - return; - } - } - } - - /** - * Return the argument list, stored in #iParameterList. - * - * @return a ConsPointer - */ - public ConsPointer argList() { - return iParameterList; - } - - public Iterator getRules() { - return iBranchRules.iterator(); - } - - public Iterator getParameters() { - return iParameters.iterator(); - } - - public void unFence() { - iFenced = false; - } - - public boolean fenced() { - return iFenced; - } -}//end class. - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/TruePredicateRuleBranch.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/TruePredicateRuleBranch.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/userfunctions/TruePredicateRuleBranch.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/userfunctions/TruePredicateRuleBranch.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.lisp.userfunctions; - -import org.mathpiper.lisp.cons.ConsPointer; -import org.mathpiper.lisp.Environment; - -/** - * A rule that always matches. - */ -class TruePredicateRuleBranch extends RuleBranch -{ - - public TruePredicateRuleBranch(int aPrecedence, ConsPointer aBody) - { - iPrecedence = aPrecedence; - iBody.setCons(aBody.getCons()); - } - /// Return #true, always. - public boolean matches(Environment aEnvironment, ConsPointer[] aArguments) throws Exception - { - return true; - } -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Utility.java mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Utility.java --- mathpiper-0.0.svn2556/src/org/mathpiper/lisp/Utility.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/lisp/Utility.java 2011-04-24 07:45:56.000000000 +0000 @@ -16,7 +16,6 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.lisp; - import org.mathpiper.lisp.collections.OperatorMap; import org.mathpiper.lisp.cons.ConsTraverser; import org.mathpiper.lisp.cons.SublistCons; @@ -28,29 +27,35 @@ import java.util.Iterator; import java.util.Map; import org.mathpiper.io.MathPiperInputStream; +import org.mathpiper.io.MathPiperOutputStream; import org.mathpiper.exceptions.EvaluationException; import org.mathpiper.io.InputStatus; import org.mathpiper.builtin.BigNumber; import org.mathpiper.builtin.BuiltinFunction; +import org.mathpiper.builtin.JavaObject; import org.mathpiper.io.InputDirectories; import org.mathpiper.lisp.behaviours.Substitute; import org.mathpiper.lisp.tokenizers.MathPiperTokenizer; -import org.mathpiper.lisp.userfunctions.MultipleArityUserFunction; +import org.mathpiper.lisp.rulebases.MultipleArityRulebase; import org.mathpiper.lisp.printers.MathPiperPrinter; import org.mathpiper.lisp.parsers.MathPiperParser; import org.mathpiper.io.JarFileInputStream; import org.mathpiper.io.StandardFileInputStream; +import org.mathpiper.io.StringInputStream; +import org.mathpiper.io.StringOutput; import org.mathpiper.io.StringOutputStream; import org.mathpiper.lisp.behaviours.BackQuoteSubstitute; +import org.mathpiper.lisp.cons.BuiltinObjectCons; import org.mathpiper.lisp.cons.NumberCons; -import org.mathpiper.lisp.parametermatchers.Pattern; -import org.mathpiper.lisp.parametermatchers.PatternParameter; -import org.mathpiper.lisp.userfunctions.Branch; -import org.mathpiper.lisp.userfunctions.FunctionParameter; -import org.mathpiper.lisp.userfunctions.MacroUserFunction; -import org.mathpiper.lisp.userfunctions.PatternBranch; -import org.mathpiper.lisp.userfunctions.SingleArityBranchingUserFunction; - +import org.mathpiper.lisp.parametermatchers.ParametersPatternMatcher; +import org.mathpiper.lisp.parametermatchers.PatternParameterMatcher; +import org.mathpiper.lisp.parsers.Parser; +import org.mathpiper.lisp.printers.LispPrinter; +import org.mathpiper.lisp.rulebases.Rule; +import org.mathpiper.lisp.rulebases.ParameterName; +import org.mathpiper.lisp.rulebases.MacroRulebase; +import org.mathpiper.lisp.rulebases.PatternRule; +import org.mathpiper.lisp.rulebases.SingleArityRulebase; public class Utility { @@ -96,7 +101,7 @@ 5. }; public static java.util.zip.ZipFile zipFile = null; - + public static String scriptsPath = null; public static boolean isNumber(String ptr, boolean aAllowFloat) { @@ -166,19 +171,17 @@ return true; } - - public static int listLength(ConsPointer aOriginal) throws Exception { - ConsPointer consTraverser = new ConsPointer(aOriginal.getCons()); + public static int listLength(Environment aEnvironment, int aStackTop, ConsPointer aOriginal) throws Exception { + ConsPointer consTraverser = new ConsPointer( aOriginal.getCons()); int length = 0; while (consTraverser.getCons() != null) { - consTraverser.goNext(); + consTraverser.goNext(aStackTop, aEnvironment); length++; } return length; } - - public static void reverseList(ConsPointer aResult, ConsPointer aOriginal) { + public static void reverseList(Environment aEnvironment, ConsPointer aResult, ConsPointer aOriginal) { //ConsPointer iter = new ConsPointer(aOriginal); ConsPointer iter = new ConsPointer(); iter.setCons(aOriginal.getCons()); @@ -195,88 +198,81 @@ aResult.setCons(previous.getCons()); } - - public static void returnUnEvaluated(ConsPointer aResult, ConsPointer aArguments, Environment aEnvironment) throws Exception { + public static void returnUnEvaluated(int aStackTop, ConsPointer aResult, ConsPointer aArguments, Environment aEnvironment) throws Exception { ConsPointer full = new ConsPointer(); full.setCons(aArguments.getCons().copy(aEnvironment, false)); aResult.setCons(SublistCons.getInstance(aEnvironment, full.getCons())); - ConsTraverser consTraverser = new ConsTraverser(aArguments); - consTraverser.goNext(); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, aArguments); + consTraverser.goNext(aStackTop); while (consTraverser.getCons() != null) { ConsPointer next = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, next, consTraverser.getPointer()); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, next, consTraverser.getPointer()); full.cdr().setCons(next.getCons()); full.setCons(next.getCons()); - consTraverser.goNext(); + consTraverser.goNext(aStackTop); } full.cdr().setCons(null); } + //Evaluate a function which is in string form. + public static void applyString(Environment aEnvironment, int aStackTop, ConsPointer aResult, String aOperator, ConsPointer aArgs) throws Exception { + LispError.check(aEnvironment, aStackTop, isString(aOperator), LispError.NOT_A_STRING, "INTERNAL"); - public static void applyString(Environment aEnvironment, ConsPointer aResult, - String aOperator, ConsPointer aArgs) throws Exception { - LispError.check(isString(aOperator), LispError.NOT_A_STRING); - - Cons head = - AtomCons.getInstance(aEnvironment, getSymbolName(aEnvironment, aOperator)); + Cons head = AtomCons.getInstance(aEnvironment, aStackTop, getSymbolName(aEnvironment, aOperator)); head.cdr().setCons(aArgs.getCons()); ConsPointer body = new ConsPointer(); body.setCons(SublistCons.getInstance(aEnvironment, head)); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aResult, body); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, aResult, body); } - - public static void applyPure(ConsPointer oper, ConsPointer args2, ConsPointer aResult, Environment aEnvironment) throws Exception { - LispError.check(oper.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT); - LispError.check(((ConsPointer) oper.car()).getCons() != null, LispError.INVALID_ARGUMENT); + public static void applyPure(int aStackTop, ConsPointer oper, ConsPointer args2, ConsPointer aResult, Environment aEnvironment) throws Exception { + LispError.check(aEnvironment, aStackTop, oper.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, ((ConsPointer) oper.car()).getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); ConsPointer oper2 = new ConsPointer(); oper2.setCons(((ConsPointer) oper.car()).cdr().getCons()); - LispError.check(oper2.getCons() != null, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, oper2.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); ConsPointer body = new ConsPointer(); body.setCons(oper2.cdr().getCons()); - LispError.check(body.getCons() != null, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, body.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); - LispError.check(oper2.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT); - LispError.check(((ConsPointer) oper2.car()).getCons() != null, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, oper2.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, ((ConsPointer) oper2.car()).getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); oper2.setCons(((ConsPointer) oper2.car()).cdr().getCons()); aEnvironment.pushLocalFrame(false, "Pure"); try { while (oper2.getCons() != null) { - LispError.check(args2.getCons() != null, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, args2.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); String var = (String) oper2.car(); - LispError.check(var != null, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, var != null, LispError.INVALID_ARGUMENT, "INTERNAL"); ConsPointer newly = new ConsPointer(); newly.setCons(args2.getCons().copy(aEnvironment, false)); - aEnvironment.newLocalVariable(var, newly.getCons()); + aEnvironment.newLocalVariable(var, newly.getCons(), aStackTop); oper2.setCons(oper2.cdr().getCons()); args2.setCons(args2.cdr().getCons()); } - LispError.check(args2.getCons() == null, LispError.INVALID_ARGUMENT); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aResult, body); + LispError.check(aEnvironment, aStackTop, args2.getCons() == null, LispError.INVALID_ARGUMENT, "INTERNAL"); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, aResult, body); } catch (EvaluationException e) { throw e; } finally { - aEnvironment.popLocalFrame(); + aEnvironment.popLocalFrame(aStackTop); } } - public static void putTrueInPointer(Environment aEnvironment, ConsPointer aResult) throws Exception { aResult.setCons(aEnvironment.iTrueAtom.copy(aEnvironment, false)); } - public static void putFalseInPointer(Environment aEnvironment, ConsPointer aResult) throws Exception { aResult.setCons(aEnvironment.iFalseAtom.copy(aEnvironment, false)); } - public static void putBooleanInPointer(Environment aEnvironment, ConsPointer aResult, boolean aValue) throws Exception { if (aValue) { putTrueInPointer(aEnvironment, aResult); @@ -285,39 +281,37 @@ } } - - public static void nth(Environment aEnvironment, ConsPointer aResult, ConsPointer aArg, int n) throws Exception { - LispError.check(aArg.getCons() != null, LispError.INVALID_ARGUMENT); - LispError.check(aArg.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT); - LispError.check(n >= 0, LispError.INVALID_ARGUMENT); - ConsTraverser consTraverser = new ConsTraverser((ConsPointer) aArg.car()); + public static void nth(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aArg, int n) throws Exception { + LispError.check(aEnvironment, aStackTop, aArg.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, aArg.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, n >= 0, LispError.INVALID_ARGUMENT, "INTERNAL"); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, (ConsPointer) aArg.car()); while (n > 0) { - LispError.check(consTraverser.getCons() != null, LispError.INVALID_ARGUMENT); - consTraverser.goNext(); + LispError.check(aEnvironment, aStackTop, consTraverser.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + consTraverser.goNext(aStackTop); n--; } - LispError.check(consTraverser.getCons() != null, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, consTraverser.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); aResult.setCons(consTraverser.getCons().copy(aEnvironment, false)); } - - public static void tail(Environment aEnvironment, ConsPointer aResult, ConsPointer aArg) throws Exception { - LispError.check(aArg.getCons() != null, LispError.INVALID_ARGUMENT); - LispError.check(aArg.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT); + public static void tail(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aArg) throws Exception { + LispError.check(aEnvironment, aStackTop, aArg.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, aArg.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT, "INTERNAL"); ConsPointer iter = (ConsPointer) aArg.car(); - LispError.check(iter.getCons() != null, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, iter.getCons() != null, LispError.INVALID_ARGUMENT, "INTERNAL"); aResult.setCons(SublistCons.getInstance(aEnvironment, iter.cdr().getCons())); } - public static boolean isTrue(Environment aEnvironment, ConsPointer aExpression) throws Exception { - LispError.lispAssert(aExpression.getCons() != null); + public static boolean isTrue(Environment aEnvironment, ConsPointer aExpression, int aStackTop) throws Exception { + LispError.lispAssert(aExpression.getCons() != null, aEnvironment, aStackTop); //return aExpression.car() == aEnvironment.iTrueAtom.car(); - return aExpression.car() instanceof String && ((String) aExpression.car()) == aEnvironment.iTrueString; + return aExpression.car() instanceof String && ((String) aExpression.car()).equals(aEnvironment.iTrueString); /* Code which returns True for everything except False and {}; String expressionString = aExpression.car(); @@ -340,18 +334,15 @@ }*/ }//end method. - - - public static boolean isFalse(Environment aEnvironment, ConsPointer aExpression) throws Exception { - LispError.lispAssert(aExpression.getCons() != null); - return aExpression.car() instanceof String && ((String) aExpression.car()) == aEnvironment.iFalseString; + public static boolean isFalse(Environment aEnvironment, ConsPointer aExpression, int aStackTop) throws Exception { + LispError.lispAssert(aExpression.getCons() != null, aEnvironment, aStackTop); + return aExpression.car() instanceof String && ((String) aExpression.car()).equals(aEnvironment.iFalseString); /* Code which returns True for everything except False and {}; return aExpression.car() == aEnvironment.iFalseString || (isSublist(aExpression) && (listLength(aExpression.car()) == 1)); */ } - public static String getSymbolName(Environment aEnvironment, String aSymbol) { if (aSymbol.charAt(0) == '\"') { return aEnvironment.getTokenHash().lookUpUnStringify(aSymbol); @@ -360,7 +351,6 @@ } } - public static boolean isSublist(ConsPointer aPtr) throws Exception { /** * todo:tk: I am currently not sure why non nested lists are not supported in Yacas. @@ -382,7 +372,6 @@ }//end method. - public static boolean isList(ConsPointer aPtr) throws Exception { /** * todo:tk: I am currently not sure why non nested lists are not supported in Yacas. @@ -404,16 +393,15 @@ }//end method. + public static boolean isNestedList(Environment aEnvironment, int aStackTop, ConsPointer clientListPointer) throws Exception { - public static boolean isNestedList(ConsPointer clientListPointer) throws Exception { - - ConsPointer listPointer = new ConsPointer(clientListPointer.getCons()); + ConsPointer listPointer = new ConsPointer( clientListPointer.getCons()); - listPointer.goNext(); //Strip List tag. + listPointer.goNext(aStackTop, aEnvironment); //Strip List tag. while (listPointer.getCons() != null) { if (listPointer.car() instanceof ConsPointer && isList((ConsPointer) listPointer.car())) { - listPointer.goNext(); + listPointer.goNext(aStackTop, aEnvironment); } else { return false; } @@ -421,30 +409,29 @@ return true; }//end method. - - public static Map optionsListToJavaMap(ConsPointer argumentsPointer, Map defaultOptions) throws Exception { + public static Map optionsListToJavaMap(Environment aEnvironment, int aStackTop, ConsPointer argumentsPointer, Map defaultOptions) throws Exception { Map userOptions = (Map) ((HashMap) defaultOptions).clone(); while (argumentsPointer.getCons() != null) { //Obtain -> operator. ConsPointer optionPointer = (ConsPointer) argumentsPointer.car(); - LispError.check(optionPointer.type() == Utility.ATOM, LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, optionPointer.type() == Utility.ATOM, LispError.INVALID_ARGUMENT, "INTERNAL"); String operator = (String) optionPointer.car(); - LispError.check(operator.equals("->"), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, operator.equals("->"), LispError.INVALID_ARGUMENT, "INTERNAL"); //Obtain key. - optionPointer.goNext(); - LispError.check(optionPointer.type() == Utility.ATOM, LispError.INVALID_ARGUMENT); + optionPointer.goNext(aStackTop, aEnvironment); + LispError.check(aEnvironment, aStackTop, optionPointer.type() == Utility.ATOM, LispError.INVALID_ARGUMENT, "INTERNAL"); String key = (String) optionPointer.car(); - key = Utility.stripEndQuotes(key); + key = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, key); //Obtain value. - optionPointer.goNext(); - LispError.check(optionPointer.type() == Utility.ATOM || optionPointer.type() == Utility.NUMBER, LispError.INVALID_ARGUMENT); + optionPointer.goNext(aStackTop, aEnvironment); + LispError.check(aEnvironment, aStackTop, optionPointer.type() == Utility.ATOM || optionPointer.type() == Utility.NUMBER, LispError.INVALID_ARGUMENT, "INTERNAL"); if (optionPointer.type() == Utility.ATOM) { String value = (String) optionPointer.car(); - value = Utility.stripEndQuotes(value); + value = Utility.stripEndQuotesIfPresent(aEnvironment, aStackTop, value); if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { userOptions.put(key, Boolean.parseBoolean(value)); } else { @@ -453,21 +440,20 @@ } else //Number { NumberCons numberCons = (NumberCons) optionPointer.getCons(); - BigNumber bigNumber = (BigNumber) numberCons.getNumber(10); + BigNumber bigNumber = (BigNumber) numberCons.getNumber(10, aEnvironment); Double value = bigNumber.toDouble(); userOptions.put(key, value); }//end if/else. - argumentsPointer.goNext(); + argumentsPointer.goNext(aStackTop, aEnvironment); }//end while return userOptions; }//end method. - public static boolean isString(Object aOriginal) { if (!(aOriginal instanceof String)) { @@ -487,9 +473,10 @@ }//end method - public static String stripEndQuotes(String aOriginal) throws Exception { - //If there are not quotes on both ends of the string then return without any changes. - if (aOriginal.startsWith("\"") && aOriginal.endsWith("\"")) { + public static String stripEndDollarSigns(String aOriginal) throws Exception { + //If there are not dollar signs on both ends of the string then return without any changes. + aOriginal = aOriginal.trim(); + if (aOriginal.startsWith("$") && aOriginal.endsWith("$")) { aOriginal = aOriginal.substring(1, aOriginal.length()); aOriginal = aOriginal.substring(0, aOriginal.length() - 1); }//end if. @@ -497,38 +484,35 @@ return aOriginal; }//end method. - - public static void not(ConsPointer aResult, Environment aEnvironment, ConsPointer aExpression) throws Exception { - if (isTrue(aEnvironment, aExpression)) { + public static void not(int aStackTop, ConsPointer aResult, Environment aEnvironment, ConsPointer aExpression) throws Exception { + if (isTrue(aEnvironment, aExpression, aStackTop)) { putFalseInPointer(aEnvironment, aResult); } else { - LispError.check(isFalse(aEnvironment, aExpression), LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, isFalse(aEnvironment, aExpression, aStackTop), LispError.INVALID_ARGUMENT, "INTERNAL"); putTrueInPointer(aEnvironment, aResult); } } - - public static void flatCopy(Environment aEnvironment, ConsPointer aResult, ConsPointer aOriginal) throws Exception { - ConsTraverser orig = new ConsTraverser(aOriginal); - ConsTraverser res = new ConsTraverser(aResult); + public static void flatCopy(Environment aEnvironment, int aStackTop, ConsPointer aResult, ConsPointer aOriginal) throws Exception { + ConsTraverser orig = new ConsTraverser(aEnvironment, aOriginal); + ConsTraverser res = new ConsTraverser(aEnvironment, aResult); while (orig.getCons() != null) { res.getPointer().setCons(orig.getCons().copy(aEnvironment, false)); - orig.goNext(); - res.goNext(); + orig.goNext(aStackTop); + res.goNext(aStackTop); } } - - public static boolean equals(Environment aEnvironment, ConsPointer aExpression1, ConsPointer aExpression2) throws Exception { + public static boolean equals(Environment aEnvironment, int aStackTop, ConsPointer aExpression1, ConsPointer aExpression2) throws Exception { // Handle pointers to same, or null if (aExpression1.getCons() == aExpression2.getCons()) { return true; } //LispError.check(aExpression1.type().equals("Number"), LispError.INVALID_ARGUMENT); //LispError.check(aExpression2.type().equals("Number"), LispError.INVALID_ARGUMENT); - BigNumber n1 = (BigNumber) aExpression1.getCons().getNumber(aEnvironment.getPrecision()); - BigNumber n2 = (BigNumber) aExpression2.getCons().getNumber(aEnvironment.getPrecision()); + BigNumber n1 = (BigNumber) aExpression1.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + BigNumber n2 = (BigNumber) aExpression2.getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); if (!(n1 == null && n2 == null)) { if (n1 == n2) { return true; @@ -563,18 +547,18 @@ if (!(aExpression2.car() instanceof ConsPointer)) { return false; } - ConsTraverser consTraverser1 = new ConsTraverser((ConsPointer) aExpression1.car()); - ConsTraverser consTraverser2 = new ConsTraverser((ConsPointer) aExpression2.car()); + ConsTraverser consTraverser1 = new ConsTraverser(aEnvironment, (ConsPointer) aExpression1.car()); + ConsTraverser consTraverser2 = new ConsTraverser(aEnvironment, (ConsPointer) aExpression2.car()); while (consTraverser1.getCons() != null && consTraverser2.getCons() != null) { // compare two list elements - if (!equals(aEnvironment, consTraverser1.getPointer(), consTraverser2.getPointer())) { + if (!equals(aEnvironment, aStackTop, consTraverser1.getPointer(), consTraverser2.getPointer())) { return false; } // Step to rest - consTraverser1.goNext(); - consTraverser2.goNext(); + consTraverser1.goNext(aStackTop); + consTraverser2.goNext(aStackTop); } // Lists don't have the same length if (consTraverser1.getCons() != consTraverser2.getCons()) { @@ -587,11 +571,10 @@ return false; } - - public static void substitute(Environment aEnvironment, ConsPointer aTarget, ConsPointer aSource, Substitute aBehaviour) throws Exception { + public static void substitute(Environment aEnvironment, int aStackTop, ConsPointer aTarget, ConsPointer aSource, Substitute aBehaviour) throws Exception { Cons object = aSource.getCons(); - LispError.lispAssert(object != null); - if (!aBehaviour.matches(aEnvironment, aTarget, aSource)) { + LispError.lispAssert(object != null, aEnvironment, aStackTop); + if (!aBehaviour.matches(aEnvironment, aStackTop, aTarget, aSource)) { Object oldList = object.car(); ConsPointer oldListPointer = null; @@ -604,7 +587,7 @@ ConsPointer newList = new ConsPointer(); ConsPointer next = newList; while (oldListPointer.getCons() != null) { - substitute(aEnvironment, next, oldListPointer, aBehaviour); + substitute(aEnvironment, aStackTop, next, oldListPointer, aBehaviour); oldListPointer = oldListPointer.cdr(); next = next.cdr(); } @@ -616,16 +599,33 @@ } - public static String unstringify(String aOriginal) throws Exception { - LispError.check(aOriginal != null, LispError.INVALID_ARGUMENT); - LispError.check(aOriginal.charAt(0) == '\"', LispError.INVALID_ARGUMENT); + public static String stripEndQuotesIfPresent(Environment aEnvironment, int aStackTop, String aOriginal) throws Exception { + //If there are not quotes on both ends of the string then return without any changes. + if (aOriginal.startsWith("\"") && aOriginal.endsWith("\"")) { + aOriginal = aOriginal.substring(1, aOriginal.length()); + aOriginal = aOriginal.substring(0, aOriginal.length() - 1); + }//end if. + + return aOriginal; + }//end method. + + + + public static String toNormalString(Environment aEnvironment, int aStackTop, String aOriginal) throws Exception { + LispError.check(aEnvironment, aStackTop, aOriginal != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + LispError.check(aEnvironment, aStackTop, aOriginal.charAt(0) == '\"', LispError.INVALID_ARGUMENT, "INTERNAL"); int nrc = aOriginal.length() - 1; - LispError.check(aOriginal.charAt(nrc) == '\"', LispError.INVALID_ARGUMENT); + LispError.check(aEnvironment, aStackTop, aOriginal.charAt(nrc) == '\"', LispError.INVALID_ARGUMENT, "INTERNAL"); return aOriginal.substring(1, nrc); } + public static String toMathPiperString(Environment aEnvironment, int aStackTop, String aOriginal) throws Exception { + LispError.check(aEnvironment, aStackTop, aOriginal != null, LispError.INVALID_ARGUMENT, "INTERNAL"); + + return "\"" + aOriginal + "\""; + } - private static void doInternalLoad(Environment aEnvironment, MathPiperInputStream aInput) throws Exception { + private static void doInternalLoad(Environment aEnvironment, int aStackTop, MathPiperInputStream aInput) throws Exception { MathPiperInputStream previous = aEnvironment.iCurrentInput; try { aEnvironment.iCurrentInput = aInput; @@ -640,39 +640,40 @@ ConsPointer readIn = new ConsPointer(); while (!endoffile) { // Read expression - parser.parse(aEnvironment, readIn); + parser.parse(aStackTop, readIn); - LispError.check(readIn.getCons() != null, LispError.READING_FILE); + LispError.check(aEnvironment, aStackTop, readIn.getCons() != null, LispError.READING_FILE, "INTERNAL"); // check for end of file - if (readIn.car() instanceof String && ((String) readIn.car()) == eof) { + if (readIn.car() instanceof String && ((String) readIn.car()).equals(eof)) { endoffile = true; } // Else evaluate else { ConsPointer result = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result, readIn); - aEnvironment.setGlobalVariable("LoadResult", result, false);//Note:tk:added to make the result of executing Loaded code available. + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, result, readIn); + aEnvironment.setGlobalVariable(aStackTop, "$LoadResult", result, false);//Note:tk:added to make the result of executing Loaded code available. } }//end while. } catch (Exception e) { - EvaluationException ee = new EvaluationException(e.getMessage(), aEnvironment.iCurrentInput.iStatus.lineNumber()); + //e.printStackTrace(); //todo:tk:uncomment for debugging. + + EvaluationException ee = new EvaluationException(e.getMessage(), aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); throw ee; } finally { aEnvironment.iCurrentInput = previous; } } - /** * Searches for a file on the classpath then in the default directories. If the file is found, it is loaded. * @param aEnvironment * @param aFileName * @throws java.lang.Exception */ - public static void load(Environment aEnvironment, String aFileName) throws Exception { - String oper = unstringify(aFileName); + public static void loadScript(Environment aEnvironment, int aStackTop, String aFileName) throws Exception { + String oper = toNormalString(aEnvironment, aStackTop, aFileName); String hashedname = (String) aEnvironment.getTokenHash().lookUp(oper); @@ -681,27 +682,32 @@ MathPiperInputStream newInput = null; - /*java.io.MathPiperInputStream scriptStream = Scripts.getScriptStream(oper); - if (scriptStream != null) { - newInput = new StandardFileInputStream(scriptStream, aEnvironment.iInputStatus); - LispError.check(newInput != null, LispError.FILE_NOT_FOUND); - doInternalLoad(aEnvironment, newInput); - } else {*/ -//System.out.println("Loading: " + oper); - java.net.URL fileURL = java.lang.ClassLoader.getSystemResource(oper); - if (fileURL != null) //File is on the classpath. + String path = Utility.scriptsPath + oper; + + //Try to find script on classpath + scriptspath. + java.io.InputStream inputStream = Utility.class.getResourceAsStream(path); + + //Try to find script on classpath. + if(inputStream == null) + { + inputStream = Utility.class.getResourceAsStream(oper); + } + + + if (inputStream != null) //File is on the classpath. { - newInput = new StandardFileInputStream(new InputStreamReader(fileURL.openStream()), aEnvironment.iInputStatus); - LispError.check(newInput != null, LispError.FILE_NOT_FOUND); - doInternalLoad(aEnvironment, newInput); + newInput = new StandardFileInputStream(new InputStreamReader(inputStream), aEnvironment.iInputStatus); + LispError.check(aEnvironment, aStackTop, newInput != null, LispError.FILE_NOT_FOUND, "INTERNAL"); + doInternalLoad(aEnvironment, aStackTop, newInput); + } else { //File may be in the filesystem. try { // Open file newInput = // new StandardFileInputStream(hashedname, aEnvironment.iInputStatus); openInputFile(aEnvironment, aEnvironment.iInputDirectories, hashedname, aEnvironment.iInputStatus); - LispError.check(newInput != null, LispError.FILE_NOT_FOUND); - doInternalLoad(aEnvironment, newInput); + LispError.check(aEnvironment, aStackTop, newInput != null, LispError.FILE_NOT_FOUND, "INTERNAL"); + doInternalLoad(aEnvironment, aStackTop, newInput); } catch (Exception e) { throw e; } finally { @@ -715,26 +721,58 @@ } - - public static void use(Environment aEnvironment, String aFileName) throws Exception { + public static void loadScriptOnce(Environment aEnvironment, int aStackTop, String aFileName) throws Exception { DefFile def = aEnvironment.iDefFiles.getFile(aFileName); if (!def.isLoaded()) { def.setLoaded(); - load(aEnvironment, aFileName); + loadScript(aEnvironment, aStackTop, aFileName); + } + } + + public static void doPatchString(String unpatchedString, MathPiperOutputStream aOutput, Environment aEnvironment, int aStackTop) throws Exception + { + String[] tags = unpatchedString.split("\\?\\>"); + if (tags.length > 1) { + for (int x = 0; x < tags.length; x++) { + String[] tag = tags[x].split("\\<\\?"); + if (tag.length > 1) { + aOutput.write(tag[0]); + String scriptCode = tag[1].trim(); + StringBuffer scriptCodeBuffer = + new StringBuffer(scriptCode); + StringInputStream scriptStream = + new StringInputStream(scriptCodeBuffer, aEnvironment.iInputStatus); + MathPiperOutputStream previous = + aEnvironment.iCurrentOutput; + try { + aEnvironment.iCurrentOutput = aOutput; + Utility.doInternalLoad(aEnvironment, aStackTop, scriptStream); + } catch(Exception e) { + throw e; + } finally { + aEnvironment.iCurrentOutput = previous; + } + } + } // end for + aOutput.write(tags[tags.length - 1]); + } else { + aOutput.write(unpatchedString); } } + public static String printMathPiperExpression(int aStackTop, ConsPointer aExpression, Environment aEnvironment, int aMaxChars) throws Exception { + if(aExpression.getCons() == null) + { + return "NULL"; + } - public static String printExpression(ConsPointer aExpression, - Environment aEnvironment, - int aMaxChars) throws Exception { StringBuffer result = new StringBuffer(); StringOutputStream newOutput = new StringOutputStream(result); MathPiperPrinter infixprinter = new MathPiperPrinter(aEnvironment.iPrefixOperators, aEnvironment.iInfixOperators, aEnvironment.iPostfixOperators, aEnvironment.iBodiedOperators); - infixprinter.print(aExpression, newOutput, aEnvironment); + infixprinter.print(aStackTop, aExpression, newOutput, aEnvironment); if (aMaxChars > 0 && result.length() > aMaxChars) { result.delete(aMaxChars, result.length()); result.append((char) '.'); @@ -742,10 +780,28 @@ result.append((char) '.'); } return result.toString(); - } + }//end method. + + + public static String printLispExpression( int aStackTop, ConsPointer aExpression, Environment aEnvironment, int aMaxChars) throws Exception { + if(aExpression.getCons() == null) + { + return "NULL"; + } + + StringOutput out = new StringOutput(); + LispPrinter printer = new LispPrinter(); + + printer.print(aStackTop, aExpression, out, aEnvironment); + + //todo:tk:add the ability to truncate the result. + + return out.toString(); + } public static MathPiperInputStream openInputFile(String aFileName, InputStatus aInputStatus) throws Exception {//Note:tk:primary method for file opening. + try { if (zipFile != null) { java.util.zip.ZipEntry e = zipFile.getEntry(aFileName); @@ -768,7 +824,6 @@ //return new StandardFileInputStream(aFileName, aInputStatus); } - public static MathPiperInputStream openInputFile(Environment aEnvironment, InputDirectories aInputDirectories, String aFileName, InputStatus aInputStatus) throws Exception { @@ -783,7 +838,6 @@ return f; } - public static String findFile(String aFileName, InputDirectories aInputDirectories) throws Exception { InputStatus inputStatus = new InputStatus(); String othername = aFileName; @@ -803,8 +857,7 @@ return ""; } - - private static void doLoadDefFile(Environment aEnvironment, MathPiperInputStream aInput, DefFile def) throws Exception { + private static void doLoadDefFile(Environment aEnvironment, int aStackTop, MathPiperInputStream aInput, DefFile def) throws Exception { MathPiperInputStream previous = aEnvironment.iCurrentInput; try { aEnvironment.iCurrentInput = aInput; @@ -816,17 +869,17 @@ while (!endoffile) { // Read expression - String token = tok.nextToken(aEnvironment.iCurrentInput, aEnvironment.getTokenHash()); + String token = tok.nextToken(aEnvironment, aStackTop, aEnvironment.iCurrentInput, aEnvironment.getTokenHash()); // check for end of file - if (token == eof || token == end) { + if (token.equals(eof) || token.equals(end)) { endoffile = true; } // Else evaluate else { String str = token; - MultipleArityUserFunction multiUser = aEnvironment.getMultipleArityUserFunction(str, true); + MultipleArityRulebase multiUser = aEnvironment.getMultipleArityRulebase(aStackTop, str, true); if (multiUser.iFileToOpen != null) { - throw new EvaluationException("[" + str + "]" + "] : def file already chosen: " + multiUser.iFileToOpen.iFileName, -1); + throw new EvaluationException("[" + str + "]" + "] : def file already chosen: " + multiUser.iFileToOpen.iFileName, aEnvironment.iInputStatus.fileName(), aEnvironment.iCurrentInput.iStatus.lineNumber()); } multiUser.iFileToOpen = def; multiUser.iFileLocation = def.fileName(); @@ -839,11 +892,10 @@ } } + public static void loadDefFile(Environment aEnvironment, int aStackTop, String aFileName) throws Exception { + LispError.lispAssert(aFileName != null, aEnvironment, aStackTop); - public static void loadDefFile(Environment aEnvironment, String aFileName) throws Exception { - LispError.lispAssert(aFileName != null); - - String flatfile = unstringify(aFileName) + ".def"; + String flatfile = toNormalString(aEnvironment, aStackTop, aFileName) + ".def"; DefFile def = aEnvironment.iDefFiles.getFile(aFileName); String hashedname = (String) aEnvironment.getTokenHash().lookUp(flatfile); @@ -852,30 +904,25 @@ aEnvironment.iInputStatus.setTo(hashedname); - MathPiperInputStream newInput = null; + String path = Utility.scriptsPath + flatfile; - /* java.io.MathPiperInputStream scriptStream = Scripts.getScriptStream(flatfile); - if (scriptStream != null) { - newInput = new StandardFileInputStream(scriptStream, aEnvironment.iInputStatus); - LispError.check(newInput != null, LispError.FILE_NOT_FOUND); - doLoadDefFile(aEnvironment, newInput, def); - } else {*/ -//System.out.println("Loading: " + flatfile); - java.net.URL fileURL = java.lang.ClassLoader.getSystemResource(flatfile); - if (fileURL != null) //File is on the classpath. + java.io.InputStream inputStream = Utility.class.getResourceAsStream(path); + + + if (inputStream != null) //File is on the classpath. { - newInput = new StandardFileInputStream(new InputStreamReader(fileURL.openStream()), aEnvironment.iInputStatus); - LispError.check(newInput != null, LispError.FILE_NOT_FOUND); - doLoadDefFile(aEnvironment, newInput, def); + newInput = new StandardFileInputStream(new InputStreamReader(inputStream), aEnvironment.iInputStatus); + LispError.check(aEnvironment, aStackTop, newInput != null, LispError.FILE_NOT_FOUND, "INTERNAL"); + doLoadDefFile(aEnvironment, aStackTop, newInput, def); } else //File may be in the filesystem. { newInput = // new StandardFileInputStream(hashedname, aEnvironment.iInputStatus); openInputFile(aEnvironment, aEnvironment.iInputDirectories, hashedname, aEnvironment.iInputStatus); - LispError.check(newInput != null, LispError.FILE_NOT_FOUND); - doLoadDefFile(aEnvironment, newInput, def); + LispError.check(aEnvironment, aStackTop, newInput != null, LispError.FILE_NOT_FOUND, "INTERNAL"); + doLoadDefFile(aEnvironment, aStackTop, newInput, def); } aEnvironment.iInputStatus.restoreFrom(oldstatus); @@ -886,22 +933,19 @@ // lookup table for transforming the number of digits // report the table size - int log2TableRange() { return log2_table_size; } // table look-up of small integer logarithms, for converting the number of digits to binary and back - static double log2TableLookup(int n) throws Exception { if (n <= log2_table_size && n >= 2) { return log2_table[n - 1]; } else { - throw new EvaluationException("log2_table_lookup: error: invalid argument " + n, -1); + throw new EvaluationException("log2_table_lookup: error: invalid argument " + n, "none", -1); } } - /** * Convert the number of digits in given base to the number of bits. To make sure there is no hysteresis, the returned * value is rounded up. @@ -915,7 +959,6 @@ return (long) Math.ceil(((double) digits) * log2TableLookup(base)); } - /** * Convert the number of bits in a given base to the number of digits. To make sure there is no hysteresis, the returned * value is rounded down. @@ -930,7 +973,6 @@ } //************************* The following methods were taken from the Functions class. - /** * Construct a {@link BigNumber}. * @param aEnvironment the current {@link Environment}. @@ -941,53 +983,49 @@ */ public static BigNumber getNumber(Environment aEnvironment, int aStackTop, int aArgNr) throws Exception { //LispError.check(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, aArgNr).type().equals("Number"), LispError.INVALID_ARGUMENT); - BigNumber x = (BigNumber) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, aArgNr).getCons().getNumber(aEnvironment.getPrecision()); - LispError.checkArgument(aEnvironment, aStackTop, x != null, aArgNr); + BigNumber x = (BigNumber) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, aArgNr).getCons().getNumber(aEnvironment.getPrecision(), aEnvironment); + LispError.checkArgument(aEnvironment, aStackTop, x != null, aArgNr, "INTERNAL"); return x; } - public static void multiFix(Environment aEnvironment, int aStackTop, OperatorMap aOps) throws Exception { // Get operator - LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "INTERNAL"); String orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "INTERNAL"); ConsPointer precedence = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, precedence, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2)); - LispError.checkArgument(aEnvironment, aStackTop, precedence.car() instanceof String, 2); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, precedence, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2)); + LispError.checkArgument(aEnvironment, aStackTop, precedence.car() instanceof String, 2, "INTERNAL"); int prec = Integer.parseInt((String) precedence.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, prec <= MathPiperPrinter.KMaxPrecedence, 2); + LispError.checkArgument(aEnvironment, aStackTop, prec <= MathPiperPrinter.KMaxPrecedence, 2, "INTERNAL"); aOps.setOperator(prec, Utility.getSymbolName(aEnvironment, orig)); Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop)); } - public static void singleFix(int aPrecedence, Environment aEnvironment, int aStackTop, OperatorMap aOps) throws Exception { // Get operator - LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "INTERNAL"); String orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "INTERNAL"); aOps.setOperator(aPrecedence, Utility.getSymbolName(aEnvironment, orig)); Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop)); } - - public static InfixOperator operatorInfo(Environment aEnvironment, int aStackTop, OperatorMap aOperators) throws Exception { + public static Operator operatorInfo(Environment aEnvironment, int aStackTop, OperatorMap aOperators) throws Exception { // Get operator - LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "INTERNAL"); ConsPointer evaluated = new ConsPointer(); evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); String orig = (String) evaluated.car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "INTERNAL"); // - InfixOperator op = (InfixOperator) aOperators.lookUp(Utility.getSymbolName(aEnvironment, orig)); + Operator op = (Operator) aOperators.lookUp(Utility.getSymbolName(aEnvironment, orig)); return op; } - /** * Sets a variable in the current {@link Environment}. * @param aEnvironment holds the execution environment of the program. @@ -1000,43 +1038,42 @@ String variableString = null; if (aMacroMode) { ConsPointer result = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1)); + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, result, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1)); variableString = (String) result.car(); } else { variableString = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car(); } - LispError.checkArgument(aEnvironment, aStackTop, variableString != null, 1); - LispError.checkArgument(aEnvironment, aStackTop, !Utility.isNumber(variableString, true), 1); + LispError.checkArgument(aEnvironment, aStackTop, variableString != null, 1, "INTERNAL"); + LispError.checkArgument(aEnvironment, aStackTop, !Utility.isNumber(variableString, true), 1, "INTERNAL"); ConsPointer result = new ConsPointer(); - aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2)); - aEnvironment.setGlobalVariable(variableString, result, aGlobalLazyVariable); //Variable setting is deligated to Environment. + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, result, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2)); + aEnvironment.setGlobalVariable(aStackTop, variableString, result, aGlobalLazyVariable); //Variable setting is deligated to Environment. Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop)); } - public static void delete(Environment aEnvironment, int aStackTop, boolean aDestructive) throws Exception { ConsPointer evaluated = new ConsPointer(); evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkIsList(aEnvironment, aStackTop, evaluated, 1); + LispError.checkIsList(aEnvironment, aStackTop, evaluated, 1, "INTERNAL"); ConsPointer copied = new ConsPointer(); if (aDestructive) { copied.setCons(((ConsPointer) evaluated.car()).getCons()); } else { - Utility.flatCopy(aEnvironment, copied, (ConsPointer) evaluated.car()); + Utility.flatCopy(aEnvironment, aStackTop, copied, (ConsPointer) evaluated.car()); } ConsPointer index = new ConsPointer(); index.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2, "INTERNAL"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2, "INTERNAL"); int ind = Integer.parseInt((String) index.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2); + LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2, "INTERNAL"); - ConsTraverser consTraverser = new ConsTraverser(copied); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, copied); while (ind > 0) { - consTraverser.goNext(); + consTraverser.goNext(aStackTop); ind--; } LispError.check(aEnvironment, aStackTop, consTraverser.getCons() != null, LispError.NOT_LONG_ENOUGH); @@ -1046,29 +1083,28 @@ BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, copied.getCons())); } - public static void insert(Environment aEnvironment, int aStackTop, boolean aDestructive) throws Exception { ConsPointer evaluated = new ConsPointer(); evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); - LispError.checkIsList(aEnvironment, aStackTop, evaluated, 1); + LispError.checkIsList(aEnvironment, aStackTop, evaluated, 1, "INTERNAL"); ConsPointer copied = new ConsPointer(); if (aDestructive) { copied.setCons(((ConsPointer) evaluated.car()).getCons()); } else { - Utility.flatCopy(aEnvironment, copied, (ConsPointer) evaluated.car()); + Utility.flatCopy(aEnvironment, aStackTop, copied, (ConsPointer) evaluated.car()); } ConsPointer index = new ConsPointer(); index.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2, "INTERNAL"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2, "INTERNAL"); int ind = Integer.parseInt((String) index.car(), 10); - LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2); + LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2, "INTERNAL"); - ConsTraverser consTraverser = new ConsTraverser(copied); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, copied); while (ind > 0) { - consTraverser.goNext(); + consTraverser.goNext(aStackTop); ind--; } @@ -1079,130 +1115,134 @@ BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, copied.getCons())); } - public static void replace(Environment aEnvironment, int aStackTop, boolean aDestructive) throws Exception { ConsPointer evaluated = new ConsPointer(); evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons()); // Ok, so lets not check if it is a list, but it needs to be at least a 'function' - LispError.checkArgument(aEnvironment, aStackTop, evaluated.car() instanceof ConsPointer, 1); + LispError.checkArgument(aEnvironment, aStackTop, evaluated.car() instanceof ConsPointer, 1, "INTERNAL"); ConsPointer index = new ConsPointer(); index.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2); + LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2, "INTERNAL"); + LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2, "INTERNAL"); int ind = Integer.parseInt((String) index.car(), 10); ConsPointer copied = new ConsPointer(); if (aDestructive) { copied.setCons(((ConsPointer) evaluated.car()).getCons()); } else { - Utility.flatCopy(aEnvironment, copied, (ConsPointer) evaluated.car()); + Utility.flatCopy(aEnvironment, aStackTop, copied, (ConsPointer) evaluated.car()); } - LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2); + LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2, "INTERNAL"); - ConsTraverser consTraverser = new ConsTraverser(copied); + ConsTraverser consTraverser = new ConsTraverser(aEnvironment, copied); while (ind > 0) { - consTraverser.goNext(); + consTraverser.goNext(aStackTop); ind--; } ConsPointer toInsert = new ConsPointer(); toInsert.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); - LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getPointer() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getPointer().getCons() != null, 2); + LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getPointer() != null, 2, "INTERNAL"); + LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getPointer().getCons() != null, 2, "INTERNAL"); toInsert.cdr().setCons(consTraverser.getPointer().cdr().getCons()); consTraverser.getPointer().setCons(toInsert.getCons()); BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, copied.getCons())); } - /** - *Implements the MathPiper functions RuleBase and MacroRuleBase . - * The real work is done by Environment.declareRulebase(). + *Implements the MathPiper functions Rulebase and MacroRulebase . + * The real work is done by Environment.defineRulebase(). */ - public static void ruleDatabase(Environment aEnvironment, int aStackTop, boolean aListed) throws Exception { - //TESTARGS(3); + public static void rulebase(Environment aEnvironment, int aStackTop, boolean aListed) throws Exception { // Get operator ConsPointer argsPointer = new ConsPointer(); String functionName = null; - LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "INTERNAL"); functionName = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, functionName != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, functionName != null, 1, "INTERNAL"); argsPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); // Check the arguments. - LispError.checkIsList(aEnvironment, aStackTop, argsPointer, 2); + LispError.checkIsList(aEnvironment, aStackTop, argsPointer, 2, "INTERNAL"); // Finally define the rule database. - aEnvironment.declareRulebase(Utility.getSymbolName(aEnvironment, functionName), - ((ConsPointer) argsPointer.car()).cdr(), aListed); + aEnvironment.defineRulebase(aStackTop, Utility.getSymbolName(aEnvironment, functionName), ((ConsPointer) argsPointer.car()).cdr(), aListed); // Return true Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop)); } - - public static void newRule(Environment aEnvironment, int aStackTop) throws Exception { - //TESTARGS(6); + public static void newRule(Environment aEnvironment, int aStackTop, boolean aPattern) throws Exception { int arity; int precedence; - ConsPointer ar = new ConsPointer(); - ConsPointer pr = new ConsPointer(); + ConsPointer arityPointer = new ConsPointer(); + ConsPointer precidencePointer = new ConsPointer(); ConsPointer predicate = new ConsPointer(); - ConsPointer body = new ConsPointer(); + ConsPointer bodyPointer = new ConsPointer(); String orig = null; // Get operator - LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "INTERNAL"); orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - ar.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - pr.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "INTERNAL"); + arityPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); + precidencePointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); predicate.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 4).getCons()); - body.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 5).getCons()); + bodyPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 5).getCons()); // The arity - LispError.checkArgument(aEnvironment, aStackTop, ar.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, ar.car() instanceof String, 2); - arity = Integer.parseInt((String) ar.car(), 10); + LispError.checkArgument(aEnvironment, aStackTop, arityPointer.getCons() != null, 2, "INTERNAL"); + LispError.checkArgument(aEnvironment, aStackTop, arityPointer.car() instanceof String, 2, "INTERNAL"); + arity = Integer.parseInt((String) arityPointer.car(), 10); // The precedence - LispError.checkArgument(aEnvironment, aStackTop, pr.getCons() != null, 3); - LispError.checkArgument(aEnvironment, aStackTop, pr.car() instanceof String, 3); - precedence = Integer.parseInt((String) pr.car(), 10); + LispError.checkArgument(aEnvironment, aStackTop, precidencePointer.getCons() != null, 3, "INTERNAL"); + LispError.checkArgument(aEnvironment, aStackTop, precidencePointer.car() instanceof String, 3, "INTERNAL"); + precedence = Integer.parseInt((String) precidencePointer.car(), 10); // Finally define the rule base - aEnvironment.defineRule(Utility.getSymbolName(aEnvironment, orig), + if(aPattern == true) + { + aEnvironment.defineRulePattern(aStackTop, Utility.getSymbolName(aEnvironment, orig), + arity, + precedence, + predicate, + bodyPointer); + } + else + { + aEnvironment.defineRule(aStackTop, Utility.getSymbolName(aEnvironment, orig), arity, precedence, predicate, - body); + bodyPointer); + } // Return true Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop)); } - - public static void defMacroRuleBase(Environment aEnvironment, int aStackTop, boolean aListed) throws Exception { + public static void defMacroRulebase(Environment aEnvironment, int aStackTop, boolean aListed) throws Exception { // Get operator ConsPointer args = new ConsPointer(); ConsPointer body = new ConsPointer(); String orig = null; - LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1, "INTERNAL"); orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); + LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1, "INTERNAL"); // The arguments args.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - LispError.checkIsList(aEnvironment, aStackTop, args, 2); + LispError.checkIsList(aEnvironment, aStackTop, args, 2, "INTERNAL"); // Finally define the rule base - aEnvironment.declareMacroRulebase(Utility.getSymbolName(aEnvironment, orig), + aEnvironment.defineMacroRulebase(aStackTop, Utility.getSymbolName(aEnvironment, orig), ((ConsPointer) args.car()).cdr(), aListed); // Return true @@ -1210,64 +1250,26 @@ } - public static void newRulePattern(Environment aEnvironment, int aStackTop, boolean aMacroMode) throws Exception { - int arity; - int precedence; - - ConsPointer arityPointer = new ConsPointer(); - ConsPointer precedencePointer = new ConsPointer(); - ConsPointer predicatePointer = new ConsPointer(); - ConsPointer bodyPointer = new ConsPointer(); - String orig = null; - - // Get operator - LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1); - orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car(); - LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1); - arityPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons()); - precedencePointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons()); - predicatePointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 4).getCons()); - bodyPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 5).getCons()); - - // The arity - LispError.checkArgument(aEnvironment, aStackTop, arityPointer.getCons() != null, 2); - LispError.checkArgument(aEnvironment, aStackTop, arityPointer.car() instanceof String, 2); - arity = Integer.parseInt((String) arityPointer.car(), 10); - - // The precedence - LispError.checkArgument(aEnvironment, aStackTop, precedencePointer.getCons() != null, 3); - LispError.checkArgument(aEnvironment, aStackTop, precedencePointer.car() instanceof String, 3); - precedence = Integer.parseInt((String) precedencePointer.car(), 10); - // Finally define the rule base - aEnvironment.defineRulePattern(Utility.getSymbolName(aEnvironment, orig), - arity, - precedence, - predicatePointer, - bodyPointer); - - // Return true - Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop)); - } - - - public static String dumpRule(Branch branch, Environment aEnvironment, SingleArityBranchingUserFunction userFunction) { + public static String dumpRule(int aStackTop, Rule rule, Environment aEnvironment, SingleArityRulebase userFunction) { StringBuilder dumpResult = new StringBuilder(); try { - int precedence = branch.getPrecedence(); - ConsPointer predicatePointer1 = branch.getPredicatePointer(); + int precedence = rule.getPrecedence(); + + ConsPointer predicatePointer1 = rule.getPredicatePointer(); String predicate = ""; String predicatePointerString = predicatePointer1.toString(); + if (predicatePointerString == null || predicatePointerString.equalsIgnoreCase("Empty.")) { predicate = "None."; } else { - predicate = Utility.printExpression(predicatePointer1, aEnvironment, 0); + predicate = Utility.printMathPiperExpression(aStackTop, predicatePointer1, aEnvironment, 0); } - if (predicate.equalsIgnoreCase("\"Pattern\"")) { + if (rule instanceof PatternRule) { predicate = "(Pattern) "; - PatternBranch branchPattern = (PatternBranch) branch; - Pattern pattern = branchPattern.getPattern(); + PatternRule branchPattern = (PatternRule) rule; + ParametersPatternMatcher pattern = branchPattern.getPattern(); Iterator variablesIterator = pattern.getVariables().iterator(); String patternVariables = ""; @@ -1283,9 +1285,10 @@ Iterator parameterMatchersIterator = pattern.getParameterMatchers().iterator(); String parameterTypes = ""; while (parameterMatchersIterator.hasNext()) { - PatternParameter parameter = (PatternParameter) parameterMatchersIterator.next(); + PatternParameterMatcher parameter = (PatternParameterMatcher) parameterMatchersIterator.next(); String parameterType = (String) parameter.getType(); - parameterTypes += parameterType + ", "; + parameterTypes += parameterType + ": " + parameter.toString(); + parameterTypes += "; "; } if (parameterTypes.contains(",")) { parameterTypes = parameterTypes.substring(0, parameterTypes.lastIndexOf(",")); @@ -1296,7 +1299,7 @@ Iterator patternPredicatesIterator = pattern.getPredicates().iterator(); while (patternPredicatesIterator.hasNext()) { ConsPointer predicatePointer = (ConsPointer) patternPredicatesIterator.next(); - String patternPredicate = Utility.printExpression(predicatePointer, aEnvironment, 0); + String patternPredicate = Utility.printMathPiperExpression(aStackTop, predicatePointer, aEnvironment, 0); predicate += patternPredicate + ", "; } /*if (predicate.contains(",")) { @@ -1305,15 +1308,14 @@ predicate += "\n Variables: " + patternVariables + ", "; predicate += "\n Types: " + parameterTypes; - }//end if. Iterator paremetersIterator = userFunction.getParameters(); String parameters = ""; boolean isHold = false; while (paremetersIterator.hasNext()) { - FunctionParameter branchParameter = (FunctionParameter) paremetersIterator.next(); - String parameter = branchParameter.getParameter(); + ParameterName branchParameter = (ParameterName) paremetersIterator.next(); + String parameter = branchParameter.getName(); isHold = branchParameter.isHold(); parameters += parameter + ", "; } @@ -1321,24 +1323,26 @@ parameters = parameters.substring(0, parameters.lastIndexOf(",")); } - String body = Utility.printExpression(branch.getBodyPointer(), aEnvironment, 0); + String body = Utility.printMathPiperExpression(aStackTop, rule.getBodyPointer(), aEnvironment, 0); body = body.replace(",", ", "); //System.out.println(data); String substitutedMacroBody = ""; - if (userFunction instanceof MacroUserFunction) { + if (userFunction instanceof MacroRulebase) { BackQuoteSubstitute backQuoteSubstitute = new BackQuoteSubstitute(aEnvironment); ConsPointer substitutedBodyPointer = new ConsPointer(); - Utility.substitute(aEnvironment, substitutedBodyPointer, branch.getBodyPointer(), backQuoteSubstitute); - substitutedMacroBody = Utility.printExpression(substitutedBodyPointer, aEnvironment, 0); + Utility.substitute(aEnvironment, aStackTop, substitutedBodyPointer, rule.getBodyPointer(), backQuoteSubstitute); + substitutedMacroBody = Utility.printMathPiperExpression(aStackTop, substitutedBodyPointer, aEnvironment, 0); } dumpResult.append("Precedence: " + precedence + ", "); + dumpResult.append("\n" + "Rule Type: " + rule.getClass().getSimpleName() + ", "); + dumpResult.append("\n" + "Arity: " + userFunction.arity() + ", "); dumpResult.append("\n" + "Parameters: " + parameters + ", "); dumpResult.append("\n" + "Predicates: " + predicate + ", "); - if (userFunction instanceof MacroUserFunction) { + if (userFunction instanceof MacroRulebase) { dumpResult.append("\n" + "Body: \n" + body + ", "); dumpResult.append("\n" + "Substituted Macro Body: \n" + substitutedMacroBody + "\n"); } else { @@ -1354,8 +1358,7 @@ }//end method. - - public static Cons associativeListGet(Environment aEnvironment, ConsPointer key, Cons listCons) throws Exception { + public static Cons associativeListGet(Environment aEnvironment, int aStackTop, ConsPointer key, Cons listCons) throws Exception { while (listCons != null) { @@ -1365,7 +1368,7 @@ sub = sub.cdr().getCons(); ConsPointer temp = new ConsPointer(); temp.setCons(sub); - if (Utility.equals(aEnvironment, key, temp)) { + if (Utility.equals(aEnvironment, aStackTop, key, temp)) { return listCons; }//end if. @@ -1380,6 +1383,139 @@ return null; }//end method. + /** + * Returns the type of a. + * @param aEnvironment + * @param expressionPointer + * @throws java.lang.Exception + */ + public static String functionType(ConsPointer expressionPointer) throws Exception { + if (!(expressionPointer.car() instanceof ConsPointer)) { + return ""; + } + + ConsPointer subList = (ConsPointer) expressionPointer.car(); + Cons head = null; + head = subList.getCons(); + if (!(head.car() instanceof String)) { + return ""; + }//end if. + + return (String) head.car(); + + }//end method. + + /** + * Converts a =Java Iterable into a MathPiper List. + * + * @param aEnvironment + * @param iterable + * @return cons + * @throws java.lang.Exception + */ + public static Cons iterableToList(Environment aEnvironment, int aStackTop, java.lang.Iterable iterable) throws Exception { + + Cons head = aEnvironment.iListAtom.copy(aEnvironment, false); + + ConsPointer consPointer = new ConsPointer(); + + consPointer.setCons(head); + + Iterator iterator = iterable.iterator(); + + while (iterator.hasNext()) { + Object object = iterator.next(); + + if(object instanceof String) + { + String key = (String) object; + + Cons stringCons = AtomCons.getInstance(aEnvironment, aStackTop, key); + + consPointer.getCons().cdr().setCons(stringCons); + } + else + { + consPointer.getCons().cdr().setCons(BuiltinObjectCons.getInstance(aEnvironment, aStackTop, new JavaObject(object))); + } + + consPointer.goNext(aStackTop, aEnvironment); + + }//end while. + + return head; + + }//end method. + + + public static ConsPointer mathPiperParse(Environment aEnvironment, int aStackTop, String inputExpression) throws Exception { + MathPiperTokenizer tokenizer = new MathPiperTokenizer(); + InputStatus someStatus = new InputStatus(); + ConsPointer inputExpressionPointer = new ConsPointer(); + + StringBuffer inp = new StringBuffer(); + inp.append(inputExpression); + inp.append(";"); + StringInputStream inputExpressionBuffer = new StringInputStream(inp, someStatus); + + Parser infixParser = new MathPiperParser(tokenizer, inputExpressionBuffer, aEnvironment, aEnvironment.iPrefixOperators, aEnvironment.iInfixOperators, aEnvironment.iPostfixOperators, aEnvironment.iBodiedOperators); + infixParser.parse(aStackTop, inputExpressionPointer); + + return inputExpressionPointer; + }//end method. + + + + + public static ConsPointer lispEvaluate(Environment aEnvironment, int aStackTop, String inputExpression) throws Exception { + ConsPointer result = new ConsPointer(); + + ConsPointer inputExpressionPointer = mathPiperParse(aEnvironment, aStackTop, inputExpression); + + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, result, inputExpressionPointer); + + return result; + }//end method. + + + + + public static ConsPointer lispEvaluate(Environment aEnvironment, int aStackTop, ConsPointer inputExpressionPointer) throws Exception { + ConsPointer result = new ConsPointer(); + MathPiperTokenizer tokenizer = new MathPiperTokenizer(); + InputStatus someStatus = new InputStatus(); + + aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aStackTop, result, inputExpressionPointer); + + return result; + }//end method. + + + + public static void declareFunction(String functionName, String[] parameters, String body, Environment aEnvironment, int aStackTop) throws Exception + { + + ConsTraverser parameterTraverser = new ConsTraverser(aEnvironment, new ConsPointer()); + + for(String parameterName:parameters) + { + Cons atomCons = AtomCons.getInstance(aEnvironment, aStackTop, parameterName); + + parameterTraverser.setCons(atomCons); + + parameterTraverser.goNext(aStackTop); + }//end for. + + aEnvironment.defineRulebase(aStackTop, functionName, parameterTraverser.getHeadPointer(), false); + + ConsPointer truePointer = new ConsPointer(); + + Utility.putTrueInPointer(aEnvironment, truePointer); + + ConsPointer expressionPointer = Utility.mathPiperParse(aEnvironment, aStackTop, body); + + aEnvironment.defineRule(aStackTop, functionName, parameters.length, 100, truePointer, expressionPointer); + } }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/array/ArrayCreateFromList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/array/ArrayCreateFromList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/array/ArrayCreateFromList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/array/ArrayCreateFromList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ - -%mathpiper,def="ArrayCreateFromList" - -ArrayCreateFromList(list):= -[ - Local(result,i); - result:=ArrayCreate(Length(list),0); - i:=1; - While (list != {}) - [ - result[i]:=First(list); - i++; - list:=Rest(list); - ]; - result; -]; - -%/mathpiper - - - - - -%mathpiper_docs,name="ArrayCreateFromList",categories="Programmer Functions;Native Objects" -*CMD ArrayCreateFromList --- convert list to array -*CALL - ArrayCreateFromList(list) - -*DESC -Creates an array from the contents of the list passed in. - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/array/ArrayToList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/array/ArrayToList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/array/ArrayToList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/array/ArrayToList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="ArrayToList" - -ArrayToList(array):= (array[1 .. ArraySize(array) ]); - -%/mathpiper - - - - -%mathpiper_docs,name="ArrayToList",categories="Programmer Functions;Native Objects" -*CMD ArrayToList --- convert array to list -*CORE -*CALL - ArrayToList(array) - -*DESC -Creates a list from the contents of the array passed in. - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/assoc/AssocDelete.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/assoc/AssocDelete.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/assoc/AssocDelete.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/assoc/AssocDelete.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -%mathpiper,def="AssocDelete" - -/// Delete an element of an associative list. -LocalSymbols(hash, key, element, hash'expr) -[ - -/// AssocDelete(hash,{"key", value}) -10 # AssocDelete(hash_IsList, element_IsList) <-- -[ - Local(index); - index := Find(hash, element); - If( - index > 0, - DestructiveDelete(hash, index) - ); - index>0; // return False if nothing found - -]; - - -/// AssocDelete(hash, "key") -20 # AssocDelete(hash_IsList, key_IsString) <-- -[ - AssocDelete(hash, Builtin'Assoc(key, hash)); -]; - -30 # AssocDelete(hash_IsList, Empty) <-- False; - -//HoldArg("AssocDelete", hash); -//UnFence("AssocDelete", 1); -//UnFence("AssocDelete", 2); - -]; // LocalSymbols(hash, ...) - -%/mathpiper - - - -%mathpiper_docs,name="AssocDelete",categories="User Functions;Lists (Operations)" -*CMD AssocDelete --- delete an entry in an association list -*STD -*CALL - AssocDelete(alist, "key") - AssocDelete(alist, {key, value}) - -*PARMS - -{alist} -- association list - -{"key"} -- string, association key - -{value} -- value of the key to be deleted - -*DESC - -The key {"key"} in the association list {alist} is deleted. (The list itself is modified.) If the key was found and successfully deleted, returns {True}, otherwise if the given key was not found, the function returns {False}. - -The second, longer form of the function deletes the entry that has both the -specified key and the specified value. It can be used for two purposes: -* 1. to make sure that we are deleting the right value; -* 2. if several values are stored on the same key, to delete the specified entry (see the last example). - -At most one entry is deleted. - -*E.G. - - In> writer := {}; - Out> {}; - In> writer["Iliad"] := "Homer"; - Out> True; - In> writer["Henry IV"] := "Shakespeare"; - Out> True; - In> writer["Ulysses"] := "James Joyce"; - Out> True; - In> AssocDelete(writer, "Henry IV") - Out> True; - In> AssocDelete(writer, "Henry XII") - Out> False; - In> writer - Out> {{"Ulysses","James Joyce"}, - {"Iliad","Homer"}}; - In> DestructiveAppend(writer, - {"Ulysses", "Dublin"}); - Out> {{"Iliad","Homer"},{"Ulysses","James Joyce"}, - {"Ulysses","Dublin"}}; - In> writer["Ulysses"]; - Out> "James Joyce"; - In> AssocDelete(writer,{"Ulysses","James Joyce"}); - Out> True; - In> writer - Out> {{"Iliad","Homer"},{"Ulysses","Dublin"}}; - - -*SEE Assoc, AssocIndices -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/assoc/AssocIndices.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/assoc/AssocIndices.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/assoc/AssocIndices.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/assoc/AssocIndices.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="AssocIndices" - -AssocIndices(associndiceslist_IsList) <-- - DestructiveReverse(MapSingle("First",associndiceslist)); - -%/mathpiper - - - -%mathpiper_docs,name="AssocIndices",categories="User Functions;Lists (Operations)" -*CMD AssocIndices --- return the keys in an association list -*STD -*CALL - AssocIndices(alist) - -*PARMS - -{alist} -- association list to examine - -*DESC - -All the keys in the association list "alist" are assembled in a list -and this list is returned. - -*E.G. - - In> writer := {}; - Out> {}; - In> writer["Iliad"] := "Homer"; - Out> True; - In> writer["Henry IV"] := "Shakespeare"; - Out> True; - In> writer["Ulysses"] := "James Joyce"; - Out> True; - In> AssocIndices(writer); - Out> {"Iliad","Henry IV","Ulysses"}; - -*SEE Assoc, AssocDelete -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/assoc/Assoc.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/assoc/Assoc.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/assoc/Assoc.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/assoc/Assoc.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper,def="Assoc" - -/* Assoc : given an assoc list like for example l:={{a,2},{b,3}}, - Assoc(b,l) will return {b,3}. if the key is not in the list, - it will return the atom Empty. -*/ - -Function("Assoc",{key,list}) Builtin'Assoc(key,list); - -%/mathpiper - - - -%mathpiper_docs,name="Assoc",categories="User Functions;Lists (Operations)" -*CMD Assoc --- return element stored in association list -*STD -*CALL - Assoc(key, alist) - -*PARMS - -{key} -- string, key under which element is stored - -{alist} -- association list to examine - -*DESC - -The association list "alist" is searched for an entry stored with -index "key". If such an entry is found, it is returned. Otherwise -the atom {Empty} is returned. - -Association lists are represented as a list of two-entry lists. The -first element in the two-entry list is the key, the second element is -the value stored under this key. - -The call {Assoc(key, alist)} can (probably more -intuitively) be accessed as {alist[key]}. - -*E.G. - - In> writer := {}; - Out> {}; - In> writer["Iliad"] := "Homer"; - Out> True; - In> writer["Henry IV"] := "Shakespeare"; - Out> True; - In> writer["Ulysses"] := "James Joyce"; - Out> True; - In> Assoc("Henry IV", writer); - Out> {"Henry IV","Shakespeare"}; - In> Assoc("War and Peace", writer); - Out> Empty; - -*SEE AssocIndices, [], :=, AssocDelete -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/CosN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/CosN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/CosN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/CosN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="CosN" - -Defun("CosN",{x})Trigonometry(x,0.0,1.0,1.0); - -%/mathpiper - - - - - -%mathpiper_docs,name="CosN",categories="User Functions;Numeric" -*CMD CosN --- cosine (arbitrary-precision math function) -*CALL - CosN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/ExpN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/ExpN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/ExpN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/ExpN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="ExpN" - -/// ExpN(x). Algorithm: for x<0, divide 1 by ExpN(-x); for x>1, compute ExpN(x/2)^2 recursively; for 0must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathExpDoubling.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathExpDoubling.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathExpDoubling.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathExpDoubling.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="MathExpDoubling",scope="private" - -/// Identity transformation, compute Exp(x) from value=Exp(x/2^n) by squaring the value n times -Defun("MathExpDoubling", {value, n}) -[ - Local(shift, result); - Set(shift, n); - Set(result, value); - While (GreaterThan(shift,0)) // will lose 'shift' bits of precision here - [ - Set(result, MultiplyN(result, result)); - Set(shift, AddN(shift,MathNegate(1))); - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathExpTaylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathExpTaylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathExpTaylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathExpTaylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -%mathpiper,def="MathExpTaylor",scope="private" - -// simple Taylor expansion, use only for 0<=x<1 -Defun("MathExpTaylor0",{x}) -[ - Local(i,aResult,term,eps); - // Exp(x)=Sum(i=0 to Inf) x^(i) /(i)! - // Which incrementally becomes the algorithm: - // - // i <- 0 - Set(i,0); - // sum <- 1 - Set(aResult,1.0); - // term <- 1 - Set(term,1.0); - Set(eps,MathIntPower(10,MathNegate(BuiltinPrecisionGet()))); - // While (term>epsilon) - While(GreaterThan(AbsN(term),eps)) - [ - // i <- i+1 - Set(i,AddN(i,1)); - // term <- term*x/(i) - Set(term,DivideN(MultiplyN(term,x),i)); - // sum <- sum+term - Set(aResult,AddN(aResult,term)); - ]; - aResult; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathFloatPower.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathFloatPower.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathFloatPower.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathFloatPower.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="MathFloatPower",scope="private" - -// power function for non-integer argument y -- use ExpN and LogN -/* Serge, I disabled this one for now, until we get a compiled version of LogN that does not hang in - an infinite loop. The C++ version of LogN never terminates, so I mapped LogN to your Internal'LnNum - which of course does a much better job of it. Corollary is that this function can be defined when we also - have Internal'LnNum in this file. -Defun("MathFloatPower", {x,y}) - If(IsInteger(y), False, ExpN(MultiplyN(y,LogN(x)))); -*/ - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathIntPower.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathIntPower.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathIntPower.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathIntPower.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -%mathpiper,def="MathIntPower",scope="private" - -// power x^y only for integer y (perhaps negative) -Defun("MathIntPower", {x,y}) - If(Equals(x,0),0,If(Equals(x,1),1, - If(IsInteger(y),If(LessThan(y,0), // negative power, need to convert x to float to save time, since x^(-n) is never going to be integer anyway - DivideN(1, PositiveIntPower(AddN(x,0.),MathNegate(y))), - // now the positive integer y calculation - note that x might still be integer - PositiveIntPower(x,y) - ), // floating-point calculation is absent, return False - False) - )); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathMul2Exp.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathMul2Exp.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathMul2Exp.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathMul2Exp.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="MathMul2Exp" - -// MathMul2Exp: multiply x by 2^n quickly (for integer n) -// this should really be implemented in the core as a call to BigNumber::ShiftRight or ShiftLeft -Defun("MathMul2Exp", {x,n}) // avoid roundoff by not calculating 1/2^n separately - If(GreaterThan(n,0), MultiplyN(x, MathIntPower(2,n)), DivideN(x, MathIntPower(2,MathNegate(n)))); -// this doesn't work because ShiftLeft/Right don't yet work on floats -// If(GreaterThan(n,0), ShiftLeft(x,n), ShiftRight(x,n) -// ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathPi.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathPi.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/MathPi.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/MathPi.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="MathPi" - -Defun("MathPi",{}) -[ - // Newton's method for finding pi: - // x[0] := 3.1415926 - // x[n+1] := x[n] + Sin(x[n]) - Local(initialPrec,curPrec,result,aPrecision); - Set(aPrecision,BuiltinPrecisionGet()); - Set(initialPrec, aPrecision); // target precision of first iteration, will be computed below - Set(curPrec, 40); // precision of the initial guess - Set(result, 3.141592653589793238462643383279502884197169399); // initial guess - - // optimize precision sequence - While (GreaterThan(initialPrec, MultiplyN(curPrec,3))) - [ - Set(initialPrec, FloorN(DivideN(AddN(initialPrec,2),3))); - ]; - Set(curPrec, initialPrec); - While (Not(GreaterThan(curPrec, aPrecision))) - [ - // start of iteration code - // Get Sin(result) - BuiltinPrecisionSet(curPrec); - Set(result,AddN(result,SinN(result))); - // Calculate new result: result := result + Sin(result); - // end of iteration code - // decide whether we are at end of loop now - If (Equals(curPrec, aPrecision), // if we are exactly at full precision, it's the last iteration - [ - Set(curPrec, AddN(aPrecision,1)); // terminate loop - ], - [ - Set(curPrec, MultiplyN(curPrec,3)); // precision triples at each iteration - // need to guard against overshooting precision - If (GreaterThan(curPrec, aPrecision), - [ - Set(curPrec, aPrecision); // next will be the last iteration - ]); - ]); - ]; - BuiltinPrecisionSet(aPrecision); - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/PositiveIntPower.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/PositiveIntPower.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/PositiveIntPower.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/PositiveIntPower.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="PositiveIntPower",scope="private" - -// first define the binary exponentiation algorithm, MathIntPower. -// Later, the PowerN function will be defined through IntPower and MathLn/ExpN. Note that ExpN uses IntPower. - -// power x^n only for non-negative integer n -Defun("PositiveIntPower", {x,n}) -[ - Local(result,unit); - If(LessThan(n,0), False, - [ - Set(unit,1); // this is a constant, initial value of the power - Set(result, unit); - If(Equals(n,0),unit, - If(Equals(n,1),x, - [ - While(GreaterThan(n,0)) - [ - If( - Equals(BitAnd(n,1), 1), -// If( -// Equals(result,unit), // if result is already assigned -// Set(result, x), // avoid multiplication - Set(result, MultiplyN(result,x)) -// ) - ); - Set(x, MultiplyN(x,x)); - Set(n,ShiftRight(n,1)); - ]; - result; - ] - ) - ); - ]); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/PowerN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/PowerN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/PowerN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/PowerN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -%mathpiper,def="PowerN" - -// power function that works for all real x, y -/// FIXME: No precision tracking yet. - -/* Serge, as MathFloatPower cannot be defined yet, I made the "avoid PowerN(num,float) explicit :-) -*/ -Defun("PowerN", {x,y}) -// avoid PowerN(0,float) - If(Equals(x,0),0, If(Equals(x,1),1, - If(IsInteger(y), MathIntPower(x,y), False/*MathFloatPower(x,y)*/) - )); - -%/mathpiper - - - - - -%mathpiper_docs,name="PowerN",categories="User Functions;Numeric" -*CMD PowerN --- power x^y (arbitrary-precision math function) -*CALL - PowerN(x,y) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> BuiltinPrecisionSet(10) - Out> True - In> PowerN(2,3) - Out> 8 - In> PowerN(2,-3) - Out> 0.125 - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/SinN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/SinN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/SinN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/SinN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="SinN" - -Defun("SinN",{x})Trigonometry(x,1.0,x,x); - -%/mathpiper - - - - - -%mathpiper_docs,name="SinN",categories="User Functions;Numeric" -*CMD SinN --- sine (arbitrary-precision math function) -*CALL - SinN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/TanN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/TanN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/TanN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/TanN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="TanN" - -Defun("TanN",{x})DivideN(SinN(x),CosN(x)); - -%/mathpiper - - - - - -%mathpiper_docs,name="TanN",categories="User Functions;Numeric" -*CMD TanN --- tangent (arbitrary-precision math function) -*CALL - TanN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/Trigonometry.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/Trigonometry.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/base/Trigonometry.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/base/Trigonometry.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="Trigonometry",scope="private" - -Defun("Trigonometry",{x,i,sum,term}) -[ - Local(x2,orig,eps,previousPrec,newPrec); - Set(previousPrec,BuiltinPrecisionGet()); - Set(newPrec,AddN(BuiltinPrecisionGet(),2)); - Set(x2,MultiplyN(x,x)); - BuiltinPrecisionSet(newPrec); - Set(eps,MathIntPower(10,MathNegate(previousPrec))); - While(GreaterThan(AbsN(term),eps)) - [ - Set(term,MultiplyN(term,x2)); - Set(i,AddN(i,1.0)); - Set(term,DivideN(term,i)); - Set(i,AddN(i,1.0)); - Set(term,DivideN(MathNegate(term),i)); - BuiltinPrecisionSet(previousPrec); - Set(sum, AddN(sum, term)); - BuiltinPrecisionSet(newPrec); - ]; - BuiltinPrecisionSet(previousPrec); - sum; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/c_form/CForm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/c_form/CForm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/c_form/CForm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/c_form/CForm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,251 +0,0 @@ -%mathpiper,def="CForm" - -/* CForm: convert MathPiper objects to C/C++ code. */ - -/* version 0.3 */ - -/* Changelog - 0.1 CForm() derived from TeXForm() v0.4. Have basic functionality. Do not allow list manipulation, unevaluated derivatives, set operations, limits, integrals, Infinity, explicit matrices. Complex numbers and expressions are handled just like real ones. Indexed symbols are assumed to be arrays and handled literally. No declarations or prototypes are supplied. Function definitions are not handled. Sum() is left as is (can be defined as a C function). - 0.2 Fix for extra parens in Sin() and other functions; fixes for Exp(), Abs() and inverse trig functions - 0.3 Fix for indexed expressions: support a[2][3][4] - 0.3.1 Fix for CForm(integer): add a decimal point - 0.4 Support While()[]. Added IsCFormable. Use Concat() instead of Union() on lists. - 0.4.1 Support False, True - 0.4.2 Changed it so that integers are not coerced to floats any more automatically (one can coerce integers to floats manually nowadays by adding a decimal point to the string representation, eg. 1. instead of 1). -*/ - -/* To do: - 0. Find and fix bugs. - 1. Chop strings that are longer than 80 chars? - 2. Optimization of C code? -*/ - -RuleBase("CForm",{expression}); -RuleBase("CForm",{expression, precedence}); - -Function ("CFormBracketIf", {predicate, string}) -[ - Check(IsBoolean(predicate) And IsString(string), "CForm internal error: non-boolean and/or non-string argument of CFormBracketIf"); - If(predicate, ConcatStrings("( ", string, ") "), string); -]; - -/* Proceed just like TeXForm() -*/ - -// CFormMaxPrec should perhaps only be used from within this file, it is thus not in the .def file. -CFormMaxPrec() := 60000; /* This precedence will never be bracketed. It is equal to KMaxPrec */ - -100 # CForm(_x) <-- CForm(x, CFormMaxPrec()); - -/* Replace numbers and variables -- never bracketed except explicitly */ -110 # CForm(x_IsInteger, _p) <-- String(x); -111 # CForm(x_IsZero, _p) <-- "0."; -112 # CForm(x_IsNumber, _p) <-- String(x); -/* Variables are left as is, except some special ones */ -190 # CForm(False, _p) <-- "false"; -190 # CForm(True, _p) <-- "true"; -200 # CForm(x_IsAtom, _p) <-- String(x); - -/* Strings must be quoted but not bracketed */ -100 # CForm(x_IsString, _p) <-- ConcatStrings("\"", x, "\""); - -/* Replace operations */ - -/* arithmetic */ - -/* addition, subtraction, multiplication, all comparison and logical operations are "regular" */ - - -LocalSymbols(cformRegularOps) [ - cformRegularOps := { {"+"," + "}, {"-"," - "}, {"*"," * "}, - {"/"," / "}, {":="," = "}, {"=="," == "}, - {"="," == "}, {"!="," != "}, {"<="," <= "}, - {">="," >= "}, {"<"," < "}, {">"," > "}, - {"And"," && "}, {"Or"," || "}, {">>", " >> "}, - { "<<", " << " }, { "&", " & " }, { "|", " | " }, - { "%", " % " }, { "^", " ^ " }, - }; - - CFormRegularOps() := cformRegularOps; -]; // LocalSymbols(cformRegularOps) - - /* This is the template for "regular" binary infix operators: -100 # CForm(_x + _y, _p) <-- CFormBracketIf(p CForm(Sin(a1)+2*Cos(b1)); - Out> "sin(a1) + 2 * cos(b1)"; - -*SEE PrettyForm, TeXForm, IsCFormable -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/c_form/IsCFormable.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/c_form/IsCFormable.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/c_form/IsCFormable.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/c_form/IsCFormable.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -%mathpiper,def="IsCFormable" - -////////////////////////////////////////////////// -/// IsCFormable -////////////////////////////////////////////////// - -LocalSymbols(CFormAllFunctions) [ - - /// predicate to test whether an expression can be successfully exported to C code - - /// interface with empty extra function list - // need the backquote stuff b/c we have HoldArg now - IsCFormable(_expr) <-- `IsCFormable(@expr, {}); - - // need to check that expr contains only allowed functions - IsCFormable(_expr, funclist_IsList) <-- - [ - Local(bad'functions); - bad'functions := Difference(`FuncList(@expr), Concat(CFormAllFunctions, funclist)); - If(Length(bad'functions)=0, - True, - [ - If(InVerboseMode(), - Echo(Concat({"IsCFormable: Info: unexportable function(s): "}, bad'functions)) - ); - False; - ] - ); - ]; - HoldArgNr("IsCFormable", 1, 1); - HoldArgNr("IsCFormable", 2, 1); - - /// This is a list of all function atoms which CForm can safely handle - CFormAllFunctions := MapSingle(Atom, Concat(AssocIndices(CFormMathFunctions()), AssocIndices(CFormRegularOps()), - // list of "other" (non-math) functions supported by CForm: needs to be updated when CForm is extended to handle new functions - { - "For", - "While", - "Prog", - "Nth", - "Mod", - "Complex", - "if", - "else", - "++", - "--", - } - )); - - -]; // LocalSymbols(CFormAllFunctions) - -%/mathpiper - - - -%mathpiper_docs,name="IsCFormable",categories="User Functions;Input/Output;Predicates" -*CMD IsCFormable --- check possibility to export expression to C++ code -*STD -*CALL - IsCFormable(expr) - IsCFormable(expr, funclist) - -*PARMS - -{expr} -- expression to be exported (this argument is not evaluated) - -{funclist} -- list of "allowed" function atoms - -*DESC - -{IsCFormable} returns {True} if the MathPiper expression {expr} can be exported -into C++ code. This is a check whether the C++ exporter {CForm} can be safely -used on the expression. - -A MathPiper expression is considered exportable if it contains only functions that can be translated into C++ (e.g. {UnList} cannot be exported). All variables and constants are considered exportable. - -The verbose option prints names of functions that are not exportable. - -The second calling format of {IsCFormable} can be used to "allow" certain function names that will be available in the C++ code. - -*E.G. notest - - In> IsCFormable(Sin(a1)+2*Cos(b1)) - Out> True; - In> V(IsCFormable(1+func123(b1))) - IsCFormable: Info: unexportable function(s): - func123 - Out> False; -This returned {False} because the function {func123} is not available in C++. We can -explicitly allow this function and then the expression will be considered -exportable: - - In> IsCFormable(1+func123(b1), {func123}) - Out> True; - -*SEE CForm, V -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/combinatorics/Combinations.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/combinatorics/Combinations.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/combinatorics/Combinations.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/combinatorics/Combinations.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="Combinations;BinomialCoefficient" - -/* Binomials -- now using partial factorial for speed */ -// BinomialCoefficient(n,m) = BinomialCoefficient(n, n-m) -10 # BinomialCoefficient(0,0) <-- 1; -10 # BinomialCoefficient(n_IsPositiveInteger,m_IsNonNegativeInteger)_(2*m <= n) <-- ((n-m+1) *** n) / m!; -15 # BinomialCoefficient(n_IsPositiveInteger,m_IsNonNegativeInteger)_(2*m > n And m <= n) <-- BinomialCoefficient(n, n-m); -20 # BinomialCoefficient(n_IsInteger,m_IsInteger) <-- 0; - -Combinations(n,m) := BinomialCoefficient(n,m); - -%/mathpiper - - - -%mathpiper_docs,name="Combinations;BinomialCoefficient",categories="User Functions;Combinatorics" -*CMD Combinations/BinomialCoefficient --- combinations/ binomial coefficient -*STD -*CALL - Combinations(n, r) - BinomialCoefficient(n, r) - -*PARMS - -{n} -- integer - total number of objects -{r} -- integer - number of objects chosen - -*DESC - -These functions are actually two names for a single function. - -In combinatorics, the function is thought of as being the number of ways -to choose "r" objects out of a total of "n" objects if order is -not taken into account. - -In mathematics the function is called the binomial coefficient function -and it is thought of as the coefficient of the x^r term in the polynomial expansion -of the binomial power (1 + x)^n. - -The binomial coefficient is defined to be zero -if "r" is negative or greater than "n"; {BinomialCoefficient(0,0)}=1. - - -*E.G. - - In> Combinations(10, 4) - Out> 210; - - In> BinomialCoefficient(10, 4) - Out> 210; - - -*SEE CombinationsAll, Permutations, PermutationsAll, !, Eulerian -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/combinatorics/PermutationsList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/combinatorics/PermutationsList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/combinatorics/PermutationsList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/combinatorics/PermutationsList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -%mathpiper,def="PermutationsList" - -Function("PermutationsList",{result,list}) -[ - If (Length(list) = 0, - [ - result; - ], - [ - Local(head); - Local(newresult); - Local(i); - head:=list[1]; - newresult:={}; - ForEach(item,result) - [ - For(i:=Length(item)+1,i>0,i--) - [ - DestructiveInsert(newresult,1,Insert(item,i,head)); - ]; - ]; - newresult:=DestructiveReverse(newresult); - PermutationsList(newresult,Rest(list)); - ]); -]; - - -Function("PermutationsList",{list}) -[ - PermutationsList({{}},list); -]; - -%/mathpiper - - - -%mathpiper_docs,name="PermutationsList",categories="User Functions;Combinatorics" -*CMD PermutationsList --- get all permutations of a list -*STD -*CALL - PermutationsList(list) - -*PARMS - -{list} -- a list of elements - -*DESC - -PermutationsList returns a list with all the permutations of -the original list. - -*E.G. - - In> PermutationsList({a,b,c}) - Out> {{a,b,c},{a,c,b},{c,a,b},{b,a,c}, - {b,c,a},{c,b,a}}; - -*SEE Permutations, Combinations, CombinationsAll, LeviCivita -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Arg.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Arg.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Arg.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Arg.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="Arg" - -10 # Arg(Complex(Cos(_x),Sin(_x))) <-- x; -10 # Arg(x_IsZero) <-- Undefined; -15 # Arg(x_IsPositiveReal) <-- 0; -15 # Arg(x_IsNegativeReal) <-- Pi; -20 # Arg(Complex(r_IsZero,i_IsConstant)) <-- Sign(i)*Pi/2; -30 # Arg(Complex(r_IsPositiveReal,i_IsConstant)) <-- ArcTan(i/r); -40 # Arg(Complex(r_IsNegativeReal,i_IsPositiveReal)) <-- Pi+ArcTan(i/r); -50 # Arg(Complex(r_IsNegativeReal,i_IsNegativeReal)) <-- ArcTan(i/r)-Pi; - -%/mathpiper - - - -%mathpiper_docs,name="Arg",categories="User Functions;Numbers (Complex)" -*CMD Arg --- argument of a complex number -*STD -*CALL - Arg(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function returns the argument of "x". The argument is the angle -with the positive real axis in the Argand diagram, or the angle -"phi" in the polar representation $r * Exp(I*phi)$ of "x". The -result is in the range ($-Pi$, $Pi$], that is, excluding $-Pi$ but including $Pi$. The -argument of 0 is {Undefined}. - -*E.G. - - In> Arg(2) - Out> 0; - In> Arg(-1) - Out> Pi; - In> Arg(1+I) - Out> Pi/4; - -*SEE Abs, Sign -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Complex.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Complex.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Complex.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Complex.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,140 +0,0 @@ -%mathpiper,def="Complex" - -0 # Complex(_r,i_IsZero) <-- r; -2 # Complex(Complex(_r1,_i1),_i2) <-- Complex(r1,i1+i2); -2 # Complex(_r1,Complex(_r2,_i2)) <-- Complex(r1-i2,r2); - -6 # Complex(Undefined,_x) <-- Undefined; -6 # Complex(_x,Undefined) <-- Undefined; - - -/* Addition */ - -110 # Complex(_r1,_i1) + Complex(_r2,_i2) <-- Complex(r1+r2,i1+i2); -300 # Complex(_r,_i) + x_IsConstant <-- Complex(r+x,i); -300 # x_IsConstant + Complex(_r,_i) <-- Complex(r+x,i); - -110 # - Complex(_r,_i) <-- Complex(-r,-i); - -300 # Complex(_r,_i) - x_IsConstant <-- Complex(r-x,i); -300 # x_IsConstant - Complex(_r,_i) <-- Complex((-r)+x,-i); -111 # Complex(_r1,_i1) - Complex(_r2,_i2) <-- Complex(r1-r2,i1-i2); - -/* Multiplication */ -110 # Complex(_r1,_i1) * Complex(_r2,_i2) <-- Complex(r1*r2-i1*i2,r1*i2+r2*i1); -/* right now this is slower than above -110 # Complex(_r1,_i1) * Complex(_r2,_i2) <-- -[ // the Karatsuba trick - Local(A,B); - A:=r1*r2; - B:=i1*i2; - Complex(A-B,(r1+i1)*(r2+i2)-A-B); -]; -*/ - - -// Multiplication in combination with complex numbers in the light of infinity -250 # Complex(r_IsZero,_i) * x_IsInfinity <-- Complex(0,i*x); -250 # Complex(_r,i_IsZero) * x_IsInfinity <-- Complex(r*x,0); -251 # Complex(_r,_i) * x_IsInfinity <-- Complex(r*x,i*x); - -250 # x_IsInfinity * Complex(r_IsZero,_i) <-- Complex(0,i*x); -250 # x_IsInfinity * Complex(_r,i_IsZero) <-- Complex(r*x,0); -251 # x_IsInfinity * Complex(_r,_i) <-- Complex(r*x,i*x); - - -300 # Complex(_r,_i) * y_IsConstant <-- Complex(r*y,i*y); -300 # y_IsConstant * Complex(_r,_i) <-- Complex(r*y,i*y); - -330 # Complex(_r,_i) * (y_IsConstant / _z) <-- (Complex(r*y,i*y))/z; -330 # (y_IsConstant / _z) * Complex(_r,_i) <-- (Complex(r*y,i*y))/z; - - -110 # x_IsConstant / Complex(_r,_i) <-- (x*Conjugate(Complex(r,i)))/(r^2+i^2); - - -300 # Complex(_r,_i) / y_IsConstant <-- Complex(r/y,i/y); - -110 # (_x ^ Complex(_r,_i)) <-- Exp(Complex(r,i)*Ln(x)); - -110 # Sqrt(Complex(_r,_i)) <-- Exp(Ln(Complex(r,i))/2); -110 # (Complex(_r,_i) ^ x_IsRationalOrNumber)_(Not(IsInteger(x))) <-- Exp(x*Ln(Complex(r,i))); - -// This is commented out because it used PowerN so (2*I)^(-10) became a floating-point number. Now everything is handled by binary algorithm below -//120 # Complex(r_IsZero,_i) ^ n_IsInteger <-- {1,I,-1,-I}[1+Mod(n,4)] * i^n; - -123 # Complex(_r, _i) ^ n_IsNegativeInteger <-- 1/Complex(r, i)^(-n); - -124 # Complex(_r, _i) ^ (p_IsZero) <-- 1; // cannot have Complex(0,0) here - -125 # Complex(_r, _i) ^ n_IsPositiveInteger <-- -[ - // use binary method - Local(result, x); - x:=Complex(r,i); - result:=1; - While(n > 0) - [ - if ((n&1) = 1) - [ - result := result*x; - ]; - x := x*x; - n := n>>1; - ]; - result; -]; - - -/*[ // this method is disabled b/c it suffers from severe roundoff errors - Local(rr,ii,count,sign); - rr:=r^n; - ii:=0; - For(count:=1,count<=n,count:=count+2) [ - sign:=If(IsZero(Mod(count-1,4)),1,-1); - ii:=ii+sign*BinomialCoefficient(n,count)*i^count*r^(n-count); - If(count I - Out> Complex(0,1); - In> 3+4*I - Out> Complex(3,4); - In> Complex(-2,0) - Out> -2; - -*SEE Re, Im, I, Abs, Arg -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Conjugate.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Conjugate.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Conjugate.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Conjugate.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="Conjugate" - -LocalSymbols(a,x) -[ -Function("Conjugate",{a}) - Substitute(a,{{x},Type(x)="Complex"},{{x},Complex(x[1],-(x[2]))}); -]; // LocalSymbols(a,x) - -%/mathpiper - - - -%mathpiper_docs,name="Conjugate",categories="User Functions;Numbers (Complex)" -*CMD Conjugate --- complex conjugate -*STD -*CALL - Conjugate(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function returns the complex conjugate of "x". The complex -conjugate of $a + I*b$ is $a - I*b$. This function assumes that all -unbound variables are real. - -*E.G. - - In> Conjugate(2) - Out> 2; - In> Conjugate(Complex(a,b)) - Out> Complex(a,-b); - -*SEE Complex, Re, Im -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/II.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/II.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/II.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/II.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="II",scope="private" - -// -// II is the imaginary number Sqrt(-1), and remains that way. -// The difference is it isn't converted to the form Complex(x,y). -// - -10 # II^n_IsNegativeInteger <-- (-II)^(-n); -20 # (II^_n)_(IsEven(n) = True) <-- (-1)^(n>>1); -20 # (II^_n)_(IsOdd(n) = True) <-- II*(-1)^(n>>1); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/ImII.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/ImII.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/ImII.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/ImII.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="ImII",scope="private" - -ImII(_c) <-- NN(c)[2]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Im.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Im.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Im.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Im.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="Im" - -/* Imaginary parts */ -110 # Im(Complex(_r,_i)) <-- i; -120 # Im(Undefined) <-- Undefined; -300 # Im(_x) <-- 0; - -%/mathpiper - - - -%mathpiper_docs,name="Im",categories="User Functions;Numbers (Complex)" -*CMD Im --- imaginary part of a complex number -*STD -*CALL - Im(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function returns the imaginary part of the complex number "x". - -*E.G. - - In> Im(5) - Out> 0; - In> Im(I) - Out> 1; - In> Im(Complex(3,4)) - Out> 4; - -*SEE Complex, Re -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/IsComplexII.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/IsComplexII.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/IsComplexII.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/IsComplexII.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="IsComplexII",scope="private" - -IsComplexII(_c) <-- (ImII(c) != 0); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/IsComplex.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/IsComplex.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/IsComplex.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/IsComplex.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -%mathpiper,def="IsComplex" - -/* All things you can request a real and imaginary part for are complex */ -1 # IsComplex(x_IsRationalOrNumber) <-- True; -2 # IsComplex(Complex(_r,_i)) <-- True; -3 # IsComplex(_x) <-- False; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/IsNotComplex.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/IsNotComplex.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/IsNotComplex.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/IsNotComplex.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="IsNotComplex",scope="private" - -IsNotComplex(x) := Not(IsComplex(x)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Magnitude.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Magnitude.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Magnitude.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Magnitude.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Magnitude" - -Function("Magnitude",{x}) [ - Sqrt(Re(x)^2 + Im(x)^2); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/NN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/NN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/NN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/NN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -%mathpiper,def="NN",scope="private" - -LocalSymbols(complexReduce) [ - - Set(complexReduce, - Hold( - { - Exp(x_IsComplexII) <- Exp(ReII(x))*(Cos(ImII(x))+II*Sin(ImII(x))) - })); - - NN(_c) <-- - [ - Local(result); - c := (c /:: complexReduce); - result := Coef(Expand(c,II),II,{0,1}); - result; - ]; - -]; //LocalSymbols(complexReduce) - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -OMDef( "Complex" , "complex1","complex_cartesian" ); -OMDef( "Re" , "complex1","real" ); -OMDef( "Im" , "complex1","imaginary" ); -OMDef( "Conjugate", "complex1","conjugate" ); -OMDef( "Arg" , "complex1","argument" ); -OMDef( "IsComplex", mathpiper,"is_complex" ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/ReII.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/ReII.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/ReII.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/ReII.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="ReII",scope="private" - -ReII(_c) <-- NN(c)[1]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Re.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Re.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/complex/Re.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/complex/Re.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="Re" - -/*Real parts */ -110 # Re(Complex(_r,_i)) <-- r; -120 # Re(Undefined) <-- Undefined; -300 # Re(_x) <-- x; - -%/mathpiper - - - -%mathpiper_docs,name="Re",categories="User Functions;Numbers (Complex)" -*CMD Re --- real part of a complex number -*STD -*CALL - Re(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function returns the real part of the complex number "x". - -*E.G. - - In> Re(5) - Out> 5; - In> Re(I) - Out> 0; - In> Re(Complex(3,4)) - Out> 3; - -*SEE Complex, Im -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/constants/constants.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/constants/constants.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/constants/constants.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/constants/constants.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,362 +0,0 @@ -%mathpiper,def="I;CachedConstant;AssignCachedConstants;ClearCachedConstants" - -/* def file definitions. -I -CachedConstant -AssignCachedConstants -ClearCachedConstants -*/ - -/* Definition of constants. */ - -/* TODO: - * There is a problem with defining I this way: if I is used, but the - * file "complex" has not been loaded, the interpreter can not deal - * with "Complex". - */ - -SetGlobalLazyVariable(I,Complex(0,1)); - -////////////////////////////////////////////////// -/// Cached constants support and definition of Pi -////////////////////////////////////////////////// - -//TODO: here we wrap the entire file in LocalSymbols, this is inefficient in that it slows loading of this file. Needs optimization. -LocalSymbols(CacheOfConstantsN) [ - -/// declare a new cached constant C'atom and its associated function C'atom(). -/// C'atom() will call C'func() at current precision to evaluate C'atom if it has not yet been cached at that precision. (note: any arguments to C'func() must be included) -RuleBase("CachedConstant", {C'cache, C'atom, C'func}); -UnFence("CachedConstant", 3); // not sure if this is useful -HoldArg("CachedConstant", C'func); -HoldArg("CachedConstant", C'cache); // name of the cache -// check syntax: must be called on an atom and a function -Rule("CachedConstant", 3, 10, And(IsAtom(C'atom), IsFunction(C'func))) -[ - Local(C'name,C'functionName); - Set(C'name, String(C'atom)); // this is for later conveniences - Set(C'functionName,ConcatStrings("Internal'",C'name)); - - If( // create the cache it if it does not already exist - IsAtom(Eval(C'cache)), - MacroSet(Eval(C'cache), {}) - ); -// Write({"debug step 0: ", C'cache, Eval(C'cache), C'atom, C'func, C'name}); - // check that the constant is not already defined - If( - Equals(Builtin'Assoc(C'name, Eval(C'cache)), Empty), // the constant is not already defined, so need to define "C'atom" and the corresponding function "C'atom"() - [ // e.g. C'atom evaluates to Pi, C'cache to a name e.g. CacheOfConstantsN, which is bound to a hash - MacroClear(C'atom); -// Write({"debug step 1: ", Cache'name, C'cache, Eval(C'cache)}); - // add the new constant to the cache -// MacroSet(Cache'name, Insert(Eval(C'cache), 1, {C'name, 0, 0})); - DestructiveInsert(Eval(C'cache), 1, {C'name, 0, 0}); -// Write({"debug step 2: ", Cache'name, C'cache, Eval(C'cache)}); - // define the new function "C'atom"() - // note: this should not use N() because it may be called from inside N() itself - - MacroRuleBase(C'functionName, {}); - `( Rule(@C'functionName, 0, 1024, True) - [ - Local(new'prec, new'C, cached'C); - Set(new'prec, BuiltinPrecisionGet()); - // fetch the cache entry for this constant - // note that this procedure will store the name of the cache here in this statement as Eval(C'cache) - Set(cached'C, Builtin'Assoc(@C'name, @C'cache)); - If( - LessThan(MathNth(cached'C, 2), new'prec), - [ // need to recalculate at current precision - If(Equals(InVerboseMode(),True), Echo("CachedConstant: Info: constant ", @C'name, " is being recalculated at precision ", new'prec)); - Set(new'C, Eval(@C'func)); - DestructiveReplace(cached'C, 2, new'prec); - DestructiveReplace(cached'C, 3, new'C); - new'C; - ], - // return cached value of C'atom - MathNth(cached'C, 3) - ); - ]); - - // calculate C'atom at current precision for the first time -// Eval(UnList({C'atom})); // "C'name"(); - // we do not need this until the constant is used; it will just slow us down - ], - // the constant is defined - Echo("CachedConstant: Warning: constant ", C'atom, " already defined") - ); -]; - -Rule("CachedConstant", 3, 20, True) - Echo("CachedConstant: Error: ", C'atom, " must be an atom and ", C'func, " must be a function."); - -/// assign numerical values to all cached constants: using fixed cache "CacheOfConstantsN" -// this is called from N() -Function("AssignCachedConstantsN", {}) -[ - Local(var,fname); - ForEach(var, AssocIndices(CacheOfConstantsN)) - [ - MacroClear(Atom(var)); - Set(fname,ConcatStrings("Internal'",var)); - Set(var,Atom(var)); - // this way the routine Internal'Pi() will be actually called only when the variable 'Pi' is used, etcetera. - `SetGlobalLazyVariable((@var), UnList({Atom(fname)})); - ]; -]; -UnFence("AssignCachedConstantsN", 0); - -/// clear values from all cached constants: using fixed cache "CacheOfConstantsN" -// this is called from N() -Function("ClearCachedConstantsN", {}) -[ - Local(c'entry); - ForEach(c'entry, CacheOfConstantsN) - MacroClear(Atom(c'entry[1])); -]; -UnFence("ClearCachedConstantsN", 0); - -/// declare some constants now -CachedConstant(CacheOfConstantsN, Pi, -[// it seems necessary to precompute Pi to a few more digits -// so that Cos(0.5*Pi)=0 at precision 10 -// FIXME: find a better solution - Local(result,old'prec); - Set(old'prec,BuiltinPrecisionGet()); -If(Equals(InVerboseMode(),True), Echo("Recalculating Pi at precision ",old'prec+5)); - BuiltinPrecisionSet(BuiltinPrecisionGet()+5); - result := MathPi(); -If(Equals(InVerboseMode(),True),Echo("Switching back to precision ",old'prec)); - BuiltinPrecisionSet(old'prec); - result; -] -); -CachedConstant(CacheOfConstantsN, gamma, GammaConstNum()); -CachedConstant(CacheOfConstantsN, GoldenRatio, N( (1+Sqrt(5))/2 ) ); -CachedConstant(CacheOfConstantsN, Catalan, CatalanConstNum() ); - -]; // LocalSymbols(CacheOfConstantsN) - -%/mathpiper - - - - - -%mathpiper_docs,name="I",categories="User Functions;Constants (Mathematical);Numbers (Complex)" -*CMD I --- imaginary unit -*STD -*CALL - I - -*DESC - -This symbol represents the imaginary unit, which equals the square -root of -1. It evaluates to {Complex(0,1)}. - -*E.G. - - In> I - Out> Complex(0,1); - In> I = Sqrt(-1) - Out> True; - -*SEE Complex -%/mathpiper_docs - - - -%mathpiper_docs,name="Pi",categories="User Functions;Constants (Mathematical)" -*CMD Pi --- mathematical constant $pi$ - -*STD -*CALL - Pi - -*DESC - -Pi symbolically represents the exact value of $pi$. When the {N()} function is -used, {Pi} evaluates to a numerical value according to the current precision. -It is better to use {Pi} than {N(Pi)} except in numerical calculations, because exact -simplification will be possible. - -This is a "cached constant" which is recalculated only when precision is increased. - -*E.G. - - In> Sin(3*Pi/2) - Out> -1; - In> Pi+1 - Out> Pi+1; - In> N(Pi) - Out> 3.14159265358979323846; - -*SEE Sin, Cos, N, CachedConstant -%/mathpiper_docs - - - -%mathpiper_docs,name="GoldenRatio",categories="User Functions;Constants (Mathematical)" -*CMD GoldenRatio --- the Golden Ratio -*STD -*CALL - GoldenRatio - -*DESC - -These functions compute the "golden ratio" -$$phi <=> 1.6180339887 <=> (1+Sqrt(5))/2 $$. - -The ancient Greeks defined the "golden ratio" as follows: -If one divides a length 1 into two pieces $x$ and $1-x$, such that the ratio of 1 to $x$ is the same as the ratio of $x$ to $1-x$, then $1/x <=> 1.618$... is the "golden ratio". - - -The constant is available symbolically as {GoldenRatio} or numerically through {N(GoldenRatio)}. -This is a "cached constant" which is recalculated only when precision is increased. -The numerical value of the constant can also be obtained as {N(GoldenRatio)}. - - -*E.G. - - In> x:=GoldenRatio - 1 - Out> GoldenRatio-1; - In> N(x) - Out> 0.6180339887; - In> N(1/GoldenRatio) - Out> 0.6180339887; - In> V(N(GoldenRatio,20)); - - CachedConstant: Info: constant GoldenRatio is - being recalculated at precision 20 - Out> 1.6180339887498948482; - - -*SEE N, CachedConstant -%/mathpiper_docs - - - -%mathpiper_docs,name="Catalan",categories="User Functions;Constants (Mathematical)" -*CMD Catalan --- Catalan's Constant -*STD -*CALL - Catalan - -*DESC - -These functions compute Catalan's Constant $Catalan<=>0.9159655941$. - -The constant is available symbolically as {Catalan} or numerically through {N(Catalan)} with {N(...)} the usual operator used to try to coerce an expression in to a numeric approximation of that expression. -This is a "cached constant" which is recalculated only when precision is increased. -The numerical value of the constant can also be obtained as {N(Catalan)}. -The low-level numerical computations are performed by the routine {CatalanConstNum}. - - -*E.G. - - In> N(Catalan) - Out> 0.9159655941; - In> DirichletBeta(2) - Out> Catalan; - In> V(N(Catalan,20)) - - CachedConstant: Info: constant Catalan is - being recalculated at precision 20 - Out> 0.91596559417721901505; - - -*SEE N, CachedConstant -%/mathpiper_docs - - - -%mathpiper_docs,name="gamma",categories="User Functions;Constants (Mathematical)" -*CMD gamma --- Euler's constant $gamma$ -*STD -*CALL - gamma - -*DESC - -These functions compute Euler's constant $gamma<=>0.57722$... - -The constant is available symbolically as {gamma} or numerically through using the usual function {N(...)} to get a numeric result, {N(gamma)}. -This is a "cached constant" which is recalculated only when precision is increased. -The numerical value of the constant can also be obtained as {N(gamma)}. -The low-level numerical computations are performed by the routine {GammaConstNum}. - -Note that Euler's Gamma function $Gamma(x)$ is the capitalized {Gamma} in MathPiper. - -*E.G. - - In> gamma+Pi - Out> gamma+Pi; - In> N(gamma+Pi) - Out> 3.7188083184; - In> V(N(gamma,20)) - - CachedConstant: Info: constant gamma is being - recalculated at precision 20 - GammaConstNum: Info: used 56 iterations at - working precision 24 - Out> 0.57721566490153286061; - -*SEE Gamma, N, CachedConstant -%/mathpiper_docs - - - -%mathpiper_docs,name="CachedConstant",categories="User Functions;Constants (Mathematical)" -*CMD CachedConstant --- precompute multiple-precision constants -*STD -*CALL - CachedConstant(cache, Cname, Cfunc) - -*PARMS -{cache} -- atom, name of the cache - -{Cname} -- atom, name of the constant - -{Cfunc} -- expression that evaluates the constant - -*DESC - -This function is used to create precomputed multiple-precision values of -constants. Caching these values will save time if they are frequently used. - -The call to {CachedConstant} defines a new function named {Cname()} that -returns the value of the constant at given precision. If the precision is -increased, the value will be recalculated as necessary, otherwise calling {Cname()} will take very little time. - -The parameter {Cfunc} must be an expression that can be evaluated and returns -the value of the desired constant at the current precision. (Most arbitrary-precision mathematical functions do this by default.) - -The associative list {cache} contains elements of the form {{Cname, prec, value}}, as illustrated in the example. If this list does not exist, it will be created. - -This mechanism is currently used by {N()} to precompute the values of $Pi$ and $gamma$ (and the golden ratio through {GoldenRatio}, and {Catalan}). -The name of the cache for {N()} is {CacheOfConstantsN}. -The code in the function {N()} assigns unevaluated calls to {Internal'Pi()} and {Internal'gamma()} to the atoms {Pi} and {gamma} and declares them to be lazy global variables through {SetGlobalLazyVariable} (with equivalent functions assigned to other constants that are added to the list of cached constants). - -The result is that the constants will be recalculated only when they are used in the expression under {N()}. -In other words, the code in {N()} does the equivalent of - - SetGlobalLazyVariable(mypi,Hold(Internal'Pi())); - SetGlobalLazyVariable(mygamma,Hold(Internal'gamma())); - -After this, evaluating an expression such as {1/2+gamma} will call the function {Internal'gamma()} but not the function {Internal'Pi()}. - -*E.G. notest - - In> CachedConstant( my'cache, Ln2, Internal'LnNum(2) ) - Out> True; - In> Internal'Ln2() - Out> 0.6931471806; - In> V(N(Internal'Ln2(),20)) - CachedConstant: Info: constant Ln2 is being - recalculated at precision 20 - Out> 0.69314718055994530942; - In> my'cache - Out> {{"Ln2",20,0.69314718055994530942}}; - - -*SEE N, BuiltinPrecisionSet, Pi, GoldenRatio, Catalan, gamma -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/constants/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/constants/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/constants/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/constants/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="" - -//From code.mpi.def: -OMDef( "I", "nums1", "i" ); -OMDef( "CachedConstant", mathpiper, "CachedConstant" ); -OMDef( "AssignCachedConstants", mathpiper, "AssignCachedConstants" ); -OMDef( "ClearCachedConstants", mathpiper, "ClearCachedConstants" ); -OMDef( "Pi", "nums1", "pi" ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/Apply.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/Apply.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/Apply.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/Apply.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -%mathpiper,def="Apply" - -10 # Apply(_applyoper,_applyargs) _ (Or(IsString(applyoper), IsList(applyoper))) <-- ApplyPure(applyoper,applyargs); -20 # Apply(applyoper_IsAtom,_applyargs) <-- ApplyPure(String(applyoper),applyargs); - -30 # Apply(Lambda(_args,_body),_applyargs) <-- `ApplyPure(Hold({@args,@body}),applyargs); -UnFence("Apply",2); - -%/mathpiper - - - -%mathpiper_docs,name="Apply",categories="User Functions;Control Flow" -*CMD Apply --- apply a function to arguments -*STD -*CALL - Apply(fn, arglist) - -*PARMS - -{fn} -- function to apply - -{arglist} -- list of arguments - -*DESC - -This function applies the function "fn" to the arguments in -"arglist" and returns the result. The first parameter "fn" can -either be a string containing the name of a function or a pure -function. Pure functions, modeled after lambda-expressions, have the -form "{varlist,body}", where "varlist" is the list of formal -parameters. Upon application, the formal parameters are assigned the -values in "arglist" (the second parameter of {Apply}) and the "body" is evaluated. - -Another way to define a pure function is with the Lambda construct. -Here, instead of passing in "{varlist,body}", one can pass in -"Lambda(varlist,body)". Lambda has the advantage that its arguments -are not evaluated (using lists can have undesirable effects because -lists are evaluated). Lambda can be used everywhere a pure function -is expected, in principle, because the function Apply is the only function -dealing with pure functions. So all places where a pure function can -be passed in will also accept Lambda. - -An shorthand for {Apply} is provided by the {@} operator. - -*E.G. - - In> Apply("+", {5,9}); - Out> 14; - - In> Apply({{x,y}, x-y^2}, {Cos(a), Sin(a)}); - Out> Cos(a)-Sin(a)^2; - - In> Apply(Lambda({x,y}, x-y^2), {Cos(a), Sin(a)}); - Out> Cos(a)-Sin(a)^2 - - In> Lambda({x,y}, x-y^2) @ {Cos(a), Sin(a)} - Out> Cos(a)-Sin(a)^2 - -*SEE Map, MapSingle, @, Lambda -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/else.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/else.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/else.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/else.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="else" - -RuleBase("else",{ifthen,otherwise}); - -0 # (if (_predicate) _body else _otherwise)_(Eval(predicate) = True) <-- Eval(body); - -0 # (if (_predicate) _body else _otherwise)_(Eval(predicate) = False) <-- Eval(otherwise); - -1 # (if (_predicate) _body else _otherwise) <-- - UnList({Atom("else"), - UnList({Atom("if"), (Eval(predicate)), body}), - otherwise}); - -HoldArg("else",ifthen); - -HoldArg("else",otherwise); - -UnFence("else",2); - -%/mathpiper - - - - -%mathpiper_docs,name="else",categories="User Functions;Control Flow" -*CMD else --- branch point -*STD -*CALL - if(predicate) body else otherwise) - -*PARMS - -{predicate} -- predicate to test - -{body} -- expression to evaluate if the predicate is {True}. - -{otherwise} -- expression to evaluate if the predicate if {False}. - -*DESC - -(This description under in development.) - - -*SEE If, if -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/ForEachExperimental.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/ForEachExperimental.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/ForEachExperimental.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/ForEachExperimental.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -%mathpiper,def="",public="todo" - -/* - * TODO This was an experiment to try to get to using a new ForEach that works the - * same on lists and arrays. For some odd reason all sorts of places in the scripts - * break if we use this version of ForEach. We need to look into this still! I want - * a ForEach that works on lists as well as arrays. - -Macro()(ForEachRest(i,L,B)); - -LocalSymbols(foreachtail) -[ - 10 # ForEachRest(_i,L_IsFunction,_B) <-- - [ - Local(foreachtail); - Local(@i); - Set(foreachtail,@L); - While(Not(Equals(foreachtail,{}))) - [ - Set(@i,First(foreachtail)); - @B; - Set(foreachtail,Rest(foreachtail)); - ]; - ]; -]; - -LocalSymbols(index,nr) -[ - 20 # ForEachRest(_i,_A,_B)_( And( - Equals(IsGeneric(A),True), - Equals(GenericTypeName(A),"Array") - )) <-- - [ - Local(index,nr); - Local(@i); - Set(index,1); - Set(nr,Length(@A)); - While(index<=nr) - [ - Set(@i,(@A)[index]); - @B; - Set(index,AddN(index,1)); - ]; - ]; -]; - -Macro()(ForEach(i,L)(B)); - -LocalSymbols(itm,lst,bd) -[ - (ForEach(_i,_L)(_B)) <-- - [ - Local(itm,lst,bd); -//CurrentFile(),CurrentLine(),,Hold(@B) -//Echo(CurrentFile(),CurrentLine()); -// Echo("ForEach(",Hold(@i),", ",Hold(@L),", ) "); - itm:=Hold(@i); - lst:= (@L); - bd:=Hold(@B); -//Echo("1...",itm); - `ForEachRest(@itm,@lst,@bd); - ]; -]; -*/ - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/ForEachInArray.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/ForEachInArray.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/ForEachInArray.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/ForEachInArray.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="ForEachInArray",scope="private" - -LocalSymbols(i,nr) -[ - TemplateFunction("ForEachInArray",{item,list,body}) - [ - Local(i,nr); - MacroLocal(item); - Set(i,1); - Set(nr,Length(list)); - While(i<=nr) - [ - MacroSet(item,list[i]); - Eval(body); - Set(i,AddN(i,1)); - ]; - ]; -]; - -UnFence("ForEachInArray",3); -HoldArgNr("ForEachInArray",3,1); -HoldArgNr("ForEachInArray",3,3); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/ForEach.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/ForEach.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/ForEach.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/ForEach.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -%mathpiper,def="ForEach" - -Retract("ForEach" , *); - -/*TODO remove? Not yet. If the code above (ForEachExperimental) can be made to work we can do away with this version. */ -TemplateFunction("ForEach",{item,listOrString,body}) -[ - If(And(Equals(IsGeneric(listOrString),True), - Equals(GenericTypeName(listOrString),"Array") - ), - `ForEachInArray(@item,listOrString,@body), - [ - - MacroLocal(item); - - If(IsString(listOrString), - [ - - Local(index, stringLength); - - stringLength := Length(listOrString); - - index := 1; - While(index <= stringLength ) - [ - MacroSet(item,listOrString[index] ); - - Eval(body); - - index++; - ]; - - ], - [ - Local(foreachtail); - Set(foreachtail,listOrString); - While(Not(Equals(foreachtail,{}))) - [ - MacroSet(item,First(foreachtail)); - Eval(body); - Set(foreachtail,Rest(foreachtail)); - ]; - ]); - ]); -]; -UnFence("ForEach",3); -HoldArgNr("ForEach",3,1); -HoldArgNr("ForEach",3,3); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - -%mathpiper_docs,name="ForEach",categories="User Functions;Control Flow" -*CMD ForEach --- loop over all entries in a list or a string -*STD -*CALL - ForEach(var, list_or_string) body - -*PARMS - -{var} -- looping variable - -{list} -- list of values or string of characters to assign to "var" - -{body} -- expression to evaluate with different values of "var" - -*DESC - -The expression "body" is evaluated multiple times. The first time, -"var" has the value of the first element of "list" or the first -character in "string", then it gets -the value of the second element and so on. {ForEach} -returns {True}. - -*E.G. notest - - In> ForEach(i,{2,3,5,7,11}) Echo({i, i!}); - 2 2 - 3 6 - 5 120 - 7 5040 - 11 39916800 - Out> True; - - - In> ForEach(i,"Hello") Echo(i) - Result: True - Side Effects: - H - e - l - l - o - -*SEE For, While, Until, Break, Continue -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/For.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/For.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/For.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/For.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -%mathpiper,def="For" - -/* Defining a For function */ -TemplateFunction("For",{start,predicate,increment,body}) -[ - Eval(start); - While (Equals(Eval(predicate),True)) - [ - Eval(body); - Eval(increment); - ]; -]; -UnFence("For",4); -HoldArgNr("For",4,1); -HoldArgNr("For",4,2); -HoldArgNr("For",4,3); -HoldArgNr("For",4,4); - -%/mathpiper - - - -%mathpiper_docs,name="For",categories="User Functions;Control Flow" -*CMD For --- C-style {for} loop -*STD -*CALL - For(init, pred, incr) body - -*PARMS - -{init} -- expression for performing the initialization - -{pred} -- predicate deciding whether to continue the loop - -{incr} -- expression to increment the counter - -{body} -- expression to loop over - -*DESC - -This commands implements a C style {for} loop. First -of all, the expression "init" is evaluated. Then the predicate -"pred" is evaluated, which should return {True} or -{False}. Next the loop is executed as long as the -predicate yields {True}. One traversal of the loop -consists of the subsequent evaluations of "body", "incr", and -"pred". Finally, the value {True} is returned. - -This command is most often used in a form such as {For(i=1, i<=10, i++) body}, which evaluates {body} with -{i} subsequently set to 1, 2, 3, 4, 5, 6, 7, 8, 9, -and 10. - -The expression {For(init, pred, incr) body} is -equivalent to {init; While(pred) [body; incr;]}. - -*E.G. notest - - In> For (i:=1, i<=10, i++) Echo({i, i!}); - 1 1 - 2 2 - 3 6 - 4 24 - 5 120 - 6 720 - 7 5040 - 8 40320 - 9 362880 - 10 3628800 - Out> True; - -*SEE While, Until, ForEach, Break, Continue -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/if.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/if.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/if.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/if.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="if" - -RuleBase("if",{predicate,body}); - -(if(True) _body) <-- Eval(body); - -HoldArg("if",body); - -UnFence("if",2); - -%/mathpiper - - - - -%mathpiper_docs,name="if",categories="User Functions;Control Flow" -*CMD if --- branch point -*STD -*CALL - if(predicate)body - -*PARMS - -{predicate} -- predicate to test - -{body} -- expression to evaluate if the predicate is true - -*DESC - -(This description is in development.) - - -*SEE If, else -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/Lambda.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/Lambda.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/Lambda.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/Lambda.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="Lambda" - -/* Lambda was introduced as a form of pure function that can be passed on to the function Apply as a first argument. - * The original method, passing it in as a list, had the disadvantage that the list was evaluated, which caused the - * arguments to be evaluated too. This resulted in unwanted behaviour sometimes (expressions being prematurely evaluated - * in the body of the pure function). The arguments to Lambda are not evaluated. - */ -DefMacroRuleBase("Lambda",{args,body}); - -%/mathpiper - - - - -%mathpiper_docs,name="Lambda",categories="User Functions;Control Flow" -*CMD Lambda --- a form of pure function that can be passed to functions like Apply and Select -*STD -*CALL - Lambda(arglist, function body) - -*PARMS - -{arglist} -- list of arguments - -*DESC - -Lambda functions are unnamed pure functions which can be used in places where a small function -is needed and creating a normal function is either inconvenient or impossible. - -*E.G. -In> Apply(Lambda({x,y}, x-y^2), {Cos(a), Sin(a)}); -Out> Cos(a)-Sin(a)^2 - -In> Lambda({x,y}, x-y^2) @ {Cos(a), Sin(a)} -Out> Cos(a)-Sin(a)^2 - - -\%mathpiper - -list := {1,-3,2,-6,-4,3}; - -Select(Lambda({i}, i > 0 ),list); - -\%/mathpiper - - \%output,preserve="false" - Result: {1,2,3} -. \%/output - -*SEE Apply, @, Select -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/Until.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/Until.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/contolflow/Until.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/contolflow/Until.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -%mathpiper,def="Until" - -TemplateFunction("Until",{predicate,body}) -[ - Eval(body); - While (Equals(Eval(predicate),False)) - [ - Eval(body); - ]; - True; -]; -UnFence("Until",2); -HoldArgNr("Until",2,1); -HoldArgNr("Until",2,2); - -%/mathpiper - - - -%mathpiper_docs,name="Until",categories="User Functions;Control Flow" -*CMD Until --- loop until a condition is met -*STD -*CALL - Until(pred) body - -*PARMS - -{pred} -- predicate deciding whether to stop - -{body} -- expression to loop over - -*DESC - -Keep on evaluating "body" until "pred" becomes {True}. More precisely, {Until} first -evaluates the expression "body". Then the predicate "pred" is -evaluated, which should yield either {True} or {False}. In the latter case, the expressions "body" -and "pred" are again evaluated and this continues as long as -"pred" is {False}. As soon as "pred" yields {True}, the loop terminates and {Until} returns {True}. - -The main difference with {While} is that {Until} always evaluates the body at least once, but {While} may not evaluate the body at all. Besides, the -meaning of the predicate is reversed: {While} stops -if "pred" is {False} while {Until} stops if "pred" is {True}. -The command -{Until(pred) body;} is equivalent to {pred; While(Not pred) body;}. In fact, the -implementation of {Until} is based on the internal -command {While}. The {Until} -command can be compared to the {do ... while} -construct in the programming language C. - -*E.G. notest - - In> x := 0; - Out> 0; - In> Until (x! > 10^6) \ - [ Echo({x, x!}); x++; ]; - 0 1 - 1 1 - 2 2 - 3 6 - 4 24 - 5 120 - 6 720 - 7 5040 - 8 40320 - 9 362880 - Out> True; - -*SEE While, For, ForEach, Break, Continue -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/debug/debug.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/debug/debug.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/debug/debug.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/debug/debug.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,346 +0,0 @@ -%mathpiper,def="TraceExp;Debug;Profile;DebugRun;DebugStep;DebugStepOver;DebugBreakAt;DebugRemoveBreakAt;DebugStop;DebugVerbose;DebugAddBreakpoint;BreakpointsClear;DebugCallstack;DebugBreakIf;DebugLocals;EchoTime;DebugShowCode" - -/* def file definitions -TraceExp -Debug -Profile -DebugRun -DebugStep -DebugStepOver -DebugBreakAt -DebugRemoveBreakAt -DebugStop -DebugVerbose -DebugAddBreakpoint -BreakpointsClear -DebugCallstack -DebugBreakIf -DebugLocals -EchoTime -DebugShowCode -*/ - -LocalSymbols(TraceStart,TraceEnter,TraceLeave,DebugStart,DebugEnter, - DebugLeave,ProfileStart,ProfileEnter,result, - WriteLines,ClearScreenString,Debug'FileLoaded, Debug'FileLines, Debug'NrLines, - debugstepoverfile, debugstepoverline) [ - -TraceStart() := [indent := 0;]; -TraceEnter() := -[ - indent++; - Space(2*indent); - Echo("Enter ",CustomEval'Expression()); -]; -TraceLeave() := -[ - Space(2*indent); - Echo("Leave ",CustomEval'Result()); - indent--; -]; -Macro(TraceExp,{expression}) -[ - TraceStart(); - CustomEval(TraceEnter(),TraceLeave(),CustomEval'Stop(),@expression); -]; - - - -DebugStart():= -[ - debugging:=True; - debugstopdepth := -1; - breakpoints:={}; - filebreakpoints := {}; - debugstopped:=False; - debugverbose:=False; - debugcallstack:={}; - breakpredicate:=False; -]; -DebugRun():= [debugging:=False;True;]; -DebugStep():=[debugging:=False;nextdebugging:=True;]; - -DebugStepOver():= -[ - debugging:=False; - debugstepoverfile := DebugFile(CustomEval'Expression()); - debugstepoverline := DebugLine(CustomEval'Expression()); - debugstopdepth := Length(debugcallstack); -]; -DebugBreakAt(file,line):= -[ - Check(InDebugMode(),"DebugBreakAt only supported in the debug build of MathPiper"); - If(filebreakpoints[file] = Empty,filebreakpoints[file]:={}); - DestructiveAppend(filebreakpoints[file],line); -]; -DebugRemoveBreakAt(file,line):= -[ - Check(InDebugMode(),"DebugRemoveBreakAt only supported in the debug build of MathPiper"); - If(filebreakpoints[file] = Empty,filebreakpoints[file]:={}); - filebreakpoints[file] := Difference(filebreakpoints[file],{line}); -]; - - -DebugStop():=[debugging:=False;debugstopped:=True;CustomEval'Stop();]; -DebugVerbose(verbose):=[debugverbose:=verbose;]; -DebugAddBreakpoint(fname_IsString) <-- [ breakpoints := fname:breakpoints;]; -Macro(DebugBreakIf,{predicate}) -[ - breakpredicate:= Hold(@predicate); -]; - -BreakpointsClear() <-- -[ - breakpredicate:=False; - breakpoints := {}; -]; -Macro(DebugLocals,{}) -[ - Echo(""); - Echo("*************** Current locals on the stack ****************"); - ForEach(item,CustomEval'Locals()) - [ - Echo(" ",item," : ",Eval(item)); - ]; - Echo(""); -]; -DebugCallstack() <-- -[ - Echo(""); - Echo("*************** Function call stack ****************"); - ForEach(item,debugcallstack) - [ - if(IsFunction(item)) - Echo(" Function ",Type(item)," : ",item) - else - Echo(" Variable ",item); - ]; - Echo(""); -]; - -Macro(DebugEnter,{}) -[ - debugcallstack := CustomEval'Expression():debugcallstack; - // custom breakpoint (custom predicate thought up by the programmer) - If(debugging = False And - Eval(breakpredicate) = True, - [ - breakpredicate:=False; - debugging:=True; - ]); - - If(debugging = False And InDebugMode(), - [ - Local(file,line); - file := DebugFile(CustomEval'Expression()); - If(filebreakpoints[file] != Empty, - [ - line := DebugLine(CustomEval'Expression()); - If(Not(file = debugstepoverfile And line = debugstepoverline) And - Contains(filebreakpoints[file],line), - [ - debugging:=True; - ] - ); - ]); - ]); - - - // the standard breakpoint - If(debugging = False And - IsFunction(CustomEval'Expression()) And - Contains(breakpoints,Type(CustomEval'Expression())), debugging:=True); - nextdebugging:=False; - If (debugging, - [ - If(InDebugMode(),DebugShowCode()); - Echo(">>> ",CustomEval'Expression()); - While(debugging) - [ - Echo("DebugOut> ",Eval(FromString(ReadCmdLineString("Debug> "):";")Read())); - // If(debugging,Echo("DebugOut> ",debugRes)); - If(IsExitRequested(),debugging:=False); - ]; - ]); - debugging:=nextdebugging; - - If(IsExitRequested(),debugstopped:=True); - -]; -Macro(DebugLeave,{}) -[ - If(debugging = False And debugstopdepth >= 0 And Length(debugcallstack) = debugstopdepth, - [ - debugstepoverline := -1; - debugging := True; - debugstopdepth := -1; - ]); - - debugcallstack := Rest(debugcallstack); - If(debugverbose,Echo(CustomEval'Result()," <-- ",CustomEval'Expression())); -]; -Macro(Debug,{expression}) -ToStdout() -[ - DebugStart(); - CustomEval(DebugEnter(),DebugLeave(),If(debugstopped,Check(False,""),[debugging:=True;debugcallstack := Rest(debugcallstack);]),@expression); -]; - - -ProfileStart():= -[ - profilefn:={}; -]; -10 # ProfileEnter()_(IsFunction(CustomEval'Expression())) <-- -[ - Local(fname); - fname:=Type(CustomEval'Expression()); - If(profilefn[fname]=Empty,profilefn[fname]:=0); - profilefn[fname] := profilefn[fname]+1; -]; -Macro(Profile,{expression}) -[ - ProfileStart(); - CustomEval(ProfileEnter(),True,CustomEval'Stop(),@expression); - ForEach(item,profilefn) - Echo("Function ",item[1]," called ",item[2]," times"); -]; - -/// Measure the time taken by evaluation and print results. -Macro(EchoTime,{expression}) -[ - Local(result); - Echo(Time()Set(result, @expression), "seconds taken."); - result; -]; - - - -// ClearScreenString : the ascii escape codes to clear the screen -ClearScreenString := CharString(27):"[2J":CharString(27):"[1;1H"; - -// WriteLines: do the actual outputting of lines of a file to screen -WriteLines(filename,lines,from,nrlines,breakpoints,current):= -[ - Local(i,nr); - nr:=Length(lines); - WriteString(ClearScreenString); - Echo("File ",filename," at line ",current); - For(i:=from,i") - else - WriteString(" "); - if (Contains(breakpoints,i)) - WriteString("*") - else - WriteString(" "); - WriteString("| "); - Echo(lines[i][1]); - ]; -]; -Debug'FileLoaded := ""; -Debug'FileLines := {}; -Debug'NrLines:=20; - -// -// DebugShowCode: show the part of the file we are currently executing (based on the -// value returned by CustomEval'Expression() ). -// -// Currently unimplemented, should we remove? -// -DebugShowCode():= -[ - False; -]; - -]; //LocalSymbols - - -%/mathpiper - - - - -%mathpiper_docs,name="TraceExp",categories="User Functions;Control Flow" -*CMD TraceExp --- evaluate with tracing enabled -*CORE -*CALL - TraceExp(expr) - -*PARMS - -{expr} -- expression to trace - -*DESC - -The expression "expr" is evaluated with the tracing facility turned -on. This means that every subexpression, which is evaluated, is shown -before and after evaluation. Before evaluation, it is shown in the -form {TrEnter(x)}, where {x} -denotes the subexpression being evaluated. After the evaluation the -line {TrLeave(x,y)} is printed, where {y} is the result of the evaluation. The indentation -shows the nesting level. - -Note that this command usually generates huge amounts of output. A -more specific form of tracing (eg. {TraceRule}) is -probably more useful for all but very simple expressions. - -*E.G. notest - - In> TraceExp(2+3); - TrEnter(2+3); - TrEnter(2); - TrLeave(2, 2); - TrEnter(3); - TrLeave(3, 3); - TrEnter(IsNumber(x)); - TrEnter(x); - TrLeave(x, 2); - TrLeave(IsNumber(x),True); - TrEnter(IsNumber(y)); - TrEnter(y); - TrLeave(y, 3); - TrLeave(IsNumber(y),True); - TrEnter(True); - TrLeave(True, True); - TrEnter(MathAdd(x,y)); - TrEnter(x); - TrLeave(x, 2); - TrEnter(y); - TrLeave(y, 3); - TrLeave(MathAdd(x,y),5); - TrLeave(2+3, 5); - Out> 5; - -*SEE TraceStack, TraceRule -%/mathpiper_docs - - - - -%mathpiper_docs,name="EchoTime",categories="User Functions;Input/Output" -*CMD EchoTime --- measure the time taken by a function and echos it -*STD -*CALL - EchoTime()expr -*PARMS -{expr} -- any expression -*DESC - -The function {EchoTime()expr} evaluates the expression {expr} and prints the time in seconds needed for the evaluation. -The time is printed to the current output stream. -The built-in function {Time} is used for timing. - -The result is the "user time" as reported by the OS, not the real ("wall clock") time. -Therefore, any CPU-intensive processes running alongside MathPiper will not significantly affect the result of {EchoTime}. - -*E.G. notest - In> EchoTime() N(MathLog(1000),40) - 0.34 seconds taken - Out> 6.9077552789821370520539743640530926228033; - -*SEE Time, SystemTimer -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/debug/verbose_mode.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/debug/verbose_mode.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/debug/verbose_mode.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/debug/verbose_mode.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -%mathpiper,def="V;InVerboseMode" - -LocalSymbols(Verbose) [ - - Set(Verbose,False); - - - Function("V",{aNumberBody}) - [ - Local(prevVerbose,result); - Set(prevVerbose,Verbose); - Set(Verbose,True); - Set(result,Eval(aNumberBody)); - Set(Verbose,prevVerbose); - result; - ]; - - - Function("InVerboseMode",{}) Verbose; - -]; // LocalSymbols(Verbose) - -HoldArg("V",aNumberBody); -UnFence("V",1); - -%/mathpiper - - - - - -%mathpiper_docs,name="V;InVerboseMode",categories="User Functions;Input/Output" -*CMD V, InVerboseMode --- set verbose output mode -*STD -*CALL - V(expression) - InVerboseMode() - -*PARMS - -{expression} -- expression to be evaluated in verbose mode - -*DESC - -The function {V(expression)} will evaluate the expression in -verbose mode. Various parts of MathPiper can show extra information -about the work done while doing a calculation when using {V}. - -In verbose mode, {InVerboseMode()} will return {True}, otherwise -it will return {False}. - -*E.G. notest - - In> OldSolve({x+2==0},{x}) - Out> {{-2}}; - In> V(OldSolve({x+2==0},{x})) - Entering OldSolve - From x+2==0 it follows that x = -2 - x+2==0 simplifies to True - Leaving OldSolve - Out> {{-2}}; - In> InVerboseMode() - Out> False - In> V(InVerboseMode()) - Out> True - -*SEE Echo, N, OldSolve -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/colon_equals_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/colon_equals_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/colon_equals_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/colon_equals_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,278 +0,0 @@ -%mathpiper,def=":=" - -/* := assignment. */ -RuleBase(":=",{aLeftAssign,aRightAssign}); -UnFence(":=",2); -HoldArg(":=",aLeftAssign); -HoldArg(":=",aRightAssign); - -/* := assignment. */ -// assign a variable -Rule(":=",2,0,IsAtom(aLeftAssign)) -[ - Check( Not IsNumber(aLeftAssign), "Only a variable can be placed on the left side of an := operator." ); - - MacroSet(aLeftAssign,Eval(aRightAssign)); - - Eval(aLeftAssign); -]; - - - -// assign lists -Rule(":=",2,0,IsList(aLeftAssign)) -[ - Map(":=",{aLeftAssign,Eval(aRightAssign)}); -]; - -// auxiliary function to help assign arrays using := -RuleBase("AssignArray",{setlistterm,setlistindex,setlistresult}); -UnFence("AssignArray",3); -Rule("AssignArray",3,1,IsString(setlistindex)) -[ - Local(item); - item:=Assoc(setlistindex,setlistterm); - If(item = Empty, - DestructiveInsert(setlistterm,1,{setlistindex,setlistresult}), - DestructiveReplace(item,2,setlistresult) - ); - True; -]; -// assign generic arrays -Rule("AssignArray",3,1, - And( - Equals(IsGeneric(setlistterm),True), - Equals(GenericTypeName(setlistterm),"Array") - ) - ) -[ - ArraySet(setlistterm,setlistindex,setlistresult); -]; - - -Rule("AssignArray",3,2,True) -[ - DestructiveReplace(setlistterm ,setlistindex, setlistresult); - True; -]; - -// a[x] := ... assigns to an array element -Rule(":=",2,10,IsFunction(aLeftAssign) And (First(Listify(aLeftAssign)) = Nth)) -[ - Local(frst,scnd); - - Local(lst); - Set(lst,(Listify(aLeftAssign))); - Set(lst,Rest(lst)); - Set(frst, Eval(First(lst))); - Set(lst,Rest(lst)); - Set(scnd, Eval(First(lst))); - - AssignArray(frst,scnd,Eval(aRightAssign)); -]; - -// f(x):=... defines a new function -Rule(":=",2,30,IsFunction(aLeftAssign) And Not(Equals(aLeftAssign[0], Atom(":="))) ) -[ - Check( Not Equals(aLeftAssign[0], Atom("/")), "Only a variable can be placed on the left side of an := operator." ); - - Local(oper,args,arity); - Set(oper,String(aLeftAssign[0])); - Set(args,Rest(Listify(aLeftAssign))); - If( - And(GreaterThan(Length(args), 1), Equals( MathNth(args, Length(args)), Atom("...") )), - // function with variable number of arguments - [ - DestructiveDelete(args,Length(args)); // remove trailing "..." - Set(arity,Length(args)); - Retract(oper,arity); - MacroRuleBaseListed(oper, args); - ], - // function with a fixed number of arguments - [ - Set(arity,Length(args)); - Retract(oper,arity); - MacroRuleBase(oper, args); - ] - ); - UnHoldable(aRightAssign); - MacroRule(oper,arity,1025,True) aRightAssign; -]; - -%/mathpiper - - - -%mathpiper_docs,name=":=",categories="Operators" -*CMD := --- assign a variable or a list; define a function -*STD -*CALL - var := expr - {var1, var2, ...} := {expr1, expr2, ...} - var[i] := expr - fn(arg1, arg2, ...) := expr -Precedence: -*EVAL OpPrecedence(":=") - -*PARMS - -{var} -- atom, variable which should be assigned - -{expr} -- expression to assign to the variable or body of function - -{i} -- index (can be integer or string) - -{fn} -- atom, name of a new function to define - -{arg1}, {arg2} -- atoms, names of arguments of the new function {fn} - -*DESC - -The {:=} operator can be used -in a number of ways. In all cases, some sort of assignment or definition takes -place. - -The first form is the most basic one. It evaluates the expression on -the right-hand side and assigns it to the variable named on the -left-hand side. The left-hand side is not evaluated. The evaluated -expression is also returned. - -The second form is a small extension, which allows one to do multiple -assignments. The first entry in the list on the right-hand side is -assigned to the first variable mentioned in the left-hand side, the -second entry on the right-hand side to the second variable on the -left-hand side, etc. The list on the right-hand side must have at -least as many entries as the list on the left-hand side. Any excess -entries are silently ignored. The result of the expression is the list -of values that have been assigned. - -The third form allows one to change an entry in the list. If the index -"i" is an integer, the "i"-th entry in the list is changed to the -expression on the right-hand side. It is assumed that the length of -the list is at least "i". If the index "i" is a string, then -"var" is considered to be an associative list (sometimes called hash -table), and the key "i" is paired with the value "exp". In both -cases, the right-hand side is evaluated before the assignment and the -result of the assignment is {True}. - -The last form defines a function. For example, the assignment {fn(x) := x^2} removes any rules previously associated with {fn(x)} and defines the rule {fn(_x) <-- x^2}. Note that the left-hand side may take a different form if -{fn} is defined to be a prefix, infix or bodied function. This case -is special since the right-hand side is not evaluated -immediately, but only when the function {fn} is used. If this takes -time, it may be better to force an immediate evaluation with {Eval} (see the last example). If the expression on the right hand side begins with {Eval()}, then it will be evaluated before defining the new function. - -A variant of the function definition can be used to make a function accepting a variable number of arguments. The last argument - -*E.G. - -A simple assignment: - - In> a := Sin(x) + 3; - Out> Sin(x)+3; - In> a; - Out> Sin(x)+3; - -Multiple assignments: - - In> {a,b,c} := {1,2,3}; - Out> {1,2,3}; - In> a; - Out> 1; - In> b+c; - Out> 5; - -Assignment to a list: - - In> xs := { 1,2,3,4,5 }; - Out> {1,2,3,4,5}; - In> xs[3] := 15; - Out> True; - In> xs; - Out> {1,2,15,4,5}; - -Building an associative list: - - In> alist := {}; - Out> {}; - In> alist["cherry"] := "red"; - Out> True; - In> alist["banana"] := "yellow"; - Out> True; - In> alist["cherry"]; - Out> "red"; - In> alist; - Out> {{"banana","yellow"},{"cherry","red"}}; - -Defining a function: - - In> f(x) := x^2; - Out> True; - In> f(3); - Out> 9; - In> f(Sin(a)); - Out> Sin(a)^2; - -Defining a function with variable number of arguments: - - In> f(x, ...) := If(IsList(x),Sum(x),x); - Out> True; - In> f(2); - Out> 2; - In> f(1,2,3); - Out> 6; - -Defining a new infix operator: - - In> Infix("*&*",10); - Out> True; - In> x1 *&* x2 := x1/x2 + x2/x1; - Out> True; - In> Sin(a) *&* Cos(a); - Out> Tan(1)+Cos(1)/Sin(1); - In> Clear(a); - Out> True; - In> Sin(a) *&* Exp(a); - Out> Sin(a)/Exp(a)+Exp(a)/Sin(a); - -In the following example, it may take some time to compute the Taylor -expansion. This has to be done every time the function {f} is called. - - In> f(a) := Taylor(x,0,25) Sin(x); - Out> True; - In> f(1); - Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880- - x^11/39916800+x^13/6227020800-x^15/ - 1307674368000+x^17/355687428096000-x^19/ - 121645100408832000+x^21/51090942171709440000 - -x^23/25852016738884976640000+x^25 - /15511210043330985984000000; - In> f(2); - Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880- - x^11/39916800+x^13/6227020800-x^15 - /1307674368000+x^17/355687428096000-x^19/ - 121645100408832000+x^21/51090942171709440000 - -x^23/25852016738884976640000+x^25/ - 15511210043330985984000000; - -The remedy is to evaluate the Taylor expansion immediately. Now the -expansion is computed only once. - - In> f(a) := Eval(Taylor(x,0,25) Sin(x)); - Out> True; - In> f(1); - Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880- - x^11/39916800+x^13/6227020800-x^15/ - 1307674368000+x^17/355687428096000-x^19/ - 121645100408832000+x^21/51090942171709440000 - -x^23/25852016738884976640000+x^25 - /15511210043330985984000000; - In> f(2); - Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880- - x^11/39916800+x^13/6227020800-x^15 - /1307674368000+x^17/355687428096000-x^19/ - 121645100408832000+x^21/51090942171709440000 - -x^23/25852016738884976640000+x^25/ - 15511210043330985984000000; - -*SEE Set, Clear, [], Rule, Infix, Eval, Function -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/Function.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/Function.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/Function.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/Function.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -%mathpiper,def="Function" - -/* Defining a macro-like function that declares a function - * with only one rule. - */ -RuleBase("Function",{oper,args,body}); - - - -// function with variable number of arguments: Function("func",{x,y, ...})body; -Rule("Function",3,2047, - And(GreaterThan(Length(args), 1), Equals( MathNth(args, Length(args)), Atom("...") )) -) -[ - DestructiveDelete(args,Length(args)); // remove trailing "..." - Retract(oper,Length(args)); - MacroRuleBaseListed(oper,args); - MacroRule(oper,Length(args),1025,True) body; // at precedence 1025, for flexibility -]; - -// function with a fixed number of arguments -Rule("Function",3,2048,True) -[ - Retract(oper,Length(args)); - MacroRuleBase(oper,args); - MacroRule(oper,Length(args),1025,True) body; -]; - - -/// shorthand function declarations -RuleBase("Function",{oper}); -// function with variable number of arguments: Function() f(x,y, ...) -Rule("Function",1,2047, - And(IsFunction(oper), GreaterThan(Length(oper), 1), Equals( MathNth(oper, Length(oper)), Atom("...") )) -) -[ - Local(args); - Set(args,Rest(Listify(oper))); - DestructiveDelete(args,Length(args)); // remove trailing "..." - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - MacroRuleBaseListed(Type(oper),args) - ); -]; - - -// function with a fixed number of arguments -Rule("Function",1,2048, - And(IsFunction(oper)) -) -[ - Local(args); - Set(args,Rest(Listify(oper))); - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - MacroRuleBase(Type(oper),args) - ); -]; - - -HoldArg("Function",oper); -HoldArg("Function",args); -HoldArg("Function",body); - -%/mathpiper - - - -%mathpiper_docs,name="Function",categories="User Functions;Control Flow" -*CMD Function --- declare or define a function -*STD -*CALL - Function() func(arglist) - Function() func(arglist, ...) - Function("op", {arglist}) body - Function("op", {arglist, ...}) body - -*PARMS - -{func(args)} -- function declaration, e.g. {f(x,y)} - -{"op"} -- string, name of the function - -{{arglist}} -- list of atoms, formal arguments to the function - -{...} -- literal ellipsis symbol "{...}" used to denote a variable number of arguments - -{body} -- expression comprising the body of the function - -*DESC - -This command can be used to define a new function with named arguments. - - -The number of arguments of the new function and their names are determined by the list {arglist}. If the ellipsis "{...}" follows the last atom in {arglist}, a function with a variable number of arguments is declared (using {RuleBaseListed}). Note that the ellipsis cannot be the only element of {arglist} and must be preceded by an atom. - -A function with variable number of arguments can take more arguments than elements in {arglist}; in this case, it obtains its last argument as a list containing all extra arguments. - -The short form of the {Function} call merely declares a {RuleBase} for the new function but does not define any function body. This is a convenient shorthand for {RuleBase} and {RuleBaseListed}, when definitions of the function are to be supplied by rules. If the new function has been already declared with the same number of arguments (with or without variable arguments), {Function} returns false and does nothing. - -The second, longer form of the {Function} call declares a function and also defines a function body. It is equivalent to a -single rule such as {op(_arg1, _arg2) <-- body}. The rule will be declared at -precedence 1025. Any previous rules associated with {"op"} (with the same -arity) will be discarded. More complicated functions (with more than one body) -can be defined by adding more rules. - -*E.G. notest - -This will declare a new function with two or more arguments, but define no rules for it. This is equivalent to {RuleBase ("f1", {x, y, ...})}. - In> Function() f1(x,y,...); - Out> True; - In> Function() f1(x,y); - Out> False; - -This defines a function {FirstOf} which returns the -first element of a list. Equivalent definitions would be -{FirstOf(_list) <-- list[1]} or {FirstOf(list) := list[1]}. - In> Function("FirstOf", {list}) list[1]; - Out> True; - In> FirstOf({a,b,c}); - Out> a; - -The following function will print all arguments to a string: - In> Function("PrintAll",{x, ...}) If(IsList(x), - PrintList(x), ToString()Write(x)); - Out> True; - In> PrintAll(1): - Out> " 1"; - In> PrintAll(1,2,3); - Out> " 1 2 3"; - -*SEE TemplateFunction, Rule, RuleBase, RuleBaseListed, :=, Retract -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/HoldArgNr.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/HoldArgNr.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/HoldArgNr.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/HoldArgNr.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="HoldArgNr" - -Function("HoldArgNr",{function,arity,index}) -[ - Local(args); - args:=RuleBaseArgList(function,arity); -/* Echo({"holdnr ",args}); */ - ApplyPure("HoldArg",{function,args[index]}); -]; - -%/mathpiper - - - -%mathpiper_docs,name="HoldArgNr" -*CMD HoldArgNr --- specify argument as not evaluated -*STD -*CALL - HoldArgNr("function", arity, argNum) - -*PARMS -{"function"} -- string, function name - -{arity}, {argNum} -- positive integers - -*DESC - -Declares the argument numbered {argNum} of the function named {"function"} with -specified {arity} to be unevaluated ("held"). Useful if you don't know symbolic -names of parameters, for instance, when the function was not declared using an -explicit {RuleBase} call. Otherwise you could use {HoldArg}. - -*SEE HoldArg, RuleBase -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/Macro.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/Macro.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/Macro.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/Macro.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -%mathpiper,def="Macro" - -RuleBase("Macro",{oper,args,body}); -HoldArg("Macro",oper); -HoldArg("Macro",args); -HoldArg("Macro",body); - -// macro with variable number of arguments: Macro("func",{x,y, ...})body; -Rule("Macro",3,2047, - And(GreaterThan(Length(args), 1), Equals( MathNth(args, Length(args)), Atom("...") )) -) -[ - DestructiveDelete(args,Length(args)); // remove trailing "..." - Retract(oper,Length(args)); - `DefMacroRuleBaseListed(@oper,@args); - MacroRule(oper,Length(args),1025,True) body; // at precedence 1025, for flexibility -]; - -// macro with a fixed number of arguments -Rule("Macro",3,2048,True) -[ - Retract(oper,Length(args)); - `DefMacroRuleBase(@oper,@args); - MacroRule(oper,Length(args),1025,True) body; -]; - -RuleBase("Macro",{oper}); -// macro with variable number of arguments: Macro() f(x,y, ...) -Rule("Macro",1,2047, - And(IsFunction(oper), GreaterThan(Length(oper), 1), Equals( MathNth(oper, Length(oper)), Atom("...") )) -) -[ - Local(args,name); - Set(args,Rest(Listify(oper))); - DestructiveDelete(args,Length(args)); // remove trailing "..." - Set(name,Type(oper)); - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - `DefMacroRuleBaseListed(@name,@args) - ); -]; -// macro with a fixed number of arguments -Rule("Macro",1,2048, - And(IsFunction(oper)) -) -[ - Local(args,name); - Set(args,Rest(Listify(oper))); - Set(name,Type(oper)); - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - [ - `DefMacroRuleBase(@name,@args); - ] - ); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Macro",categories="User Functions;Control Flow" -*CMD Macro --- declare or define a macro -*STD -*CALL - Macro() func(arglist) - Macro() func(arglist, ...) - Macro("op", {arglist}) body - Macro("op", {arglist, ...}) body - -*PARMS - -{func(args)} -- function declaration, e.g. {f(x,y)} - -{"op"} -- string, name of the function - -{{arglist}} -- list of atoms, formal arguments to the function - -{...} -- literal ellipsis symbol "{...}" used to denote a variable number of arguments - -{body} -- expression comprising the body of the function - -*DESC - -This does the same as {Function}, but for macros. One can define a macro -easily with this function, in stead of having to use {DefMacroRuleBase}. - -*E.G. notest - -the following example defines a looping function. - - In> Macro("myfor",{init,pred,inc,body}) [@init;While(@pred)[@body;@inc;];True;]; - Out> True; - In> a:=10 - Out> 10; - -Here this new macro {myfor} is used to loop, using a variable {a} from the -calling environment. - - In> myfor(i:=1,i<10,i++,Echo(a*i)) - 10 - 20 - 30 - 40 - 50 - 60 - 70 - 80 - 90 - Out> True; - In> i - Out> 10; - -*SEE Function, DefMacroRuleBase -%/mathpiper_docs - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/TemplateFunction.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/TemplateFunction.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/TemplateFunction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/TemplateFunction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -%mathpiper,def="TemplateFunction" - -RuleBase("TemplateFunction",{oper,args,body}); -Bodied("TemplateFunction",60000); -HoldArg("TemplateFunction",oper); -HoldArg("TemplateFunction",args); -HoldArg("TemplateFunction",body); -Rule("TemplateFunction",3,2047,True) -[ - Retract(oper,Length(args)); - Local(arglist); - arglist:=FlatCopy(args); - - DestructiveAppend(arglist,{args,UnList({Hold,body})}); - arglist:=ApplyPure("LocalSymbols",arglist); - - MacroRuleBase(oper,arglist[1]); - MacroRule(oper,Length(args),1025,True) arglist[2]; - -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/Unholdable.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/Unholdable.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deffunc/Unholdable.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deffunc/Unholdable.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="UnHoldable",scope="private" - -// this will "unhold" a variable - used to make sure that := with Eval() -// immediately on the right hand side evaluates its argument -RuleBase("UnHoldable",{var}); -HoldArg("UnHoldable",var); -UnFence("UnHoldable",1); -Rule("UnHoldable",1,10,Equals(Type(Eval(var)),"Eval")) -[ - MacroSet(var,Eval(Eval(var))); -/* Echo({"unheld",var,Eval(var)}); */ -]; -Rule("UnHoldable",1,20,True) -[ -/* Echo({"held"}); */ - True; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/Curl.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/Curl.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/Curl.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/Curl.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="Curl" - -RuleBase("Curl", {aFunc, aBasis}); - -Rule("Curl", 2, 1, Length(aBasis)=Length(aFunc)) - { - Apply("D",{aBasis[2],aFunc[3]})-Apply("D",{aBasis[3],aFunc[2]}), - Apply("D",{aBasis[3],aFunc[1]})-Apply("D",{aBasis[1],aFunc[3]}), - Apply("D",{aBasis[1],aFunc[2]})-Apply("D",{aBasis[2],aFunc[1]}) - }; - -%/mathpiper - - - -%mathpiper_docs,name="Curl",categories="User Functions;Calculus Related (Symbolic)" -*CMD Curl --- curl of a vector field -*STD -*CALL - Curl(vector, basis) - -*PARMS - -{vector} -- vector field to take the curl of - -{basis} -- list of variables forming the basis - -*DESC - -This function takes the curl of the vector field "vector" with -respect to the variables "basis". The curl is defined in the usual way, - - Curl(f,x) = { - D(x[2]) f[3] - D(x[3]) f[2], - D(x[3]) f[1] - D(x[1]) f[3], - D(x[1]) f[2] - D(x[2]) f[1] - } -Both "vector" and "basis" should be lists of length 3. - -*E.G. - - In> Curl({x*y,x*y,x*y},{x,y,z}) - Out> {x,-y,y-x}; - -*SEE D, Diverge -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/Deriv.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/Deriv.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/Deriv.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/Deriv.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -%mathpiper,def="Deriv",scope="private" - - -5 # (Deriv(_var,1)_func) <-- Deriv(var)func; -5 # (Deriv(_var,0)_func) <-- func; -10 # (Deriv(_var,n_IsPositiveInteger)_func) <-- Deriv(var)Deriv(var,n-1)func; -10 # (Deriv(_var,n_IsNegativeInteger)_func) <-- Check(0,"Negative derivative"); - - -// Need to clean out Sec(x) and friends -0 # (Deriv(_var) (_var)) <-- 1; -1 # (Deriv(_var)func_IsAtom) <-- 0; -2 # (Deriv(_var)_x + _y) <-- (Deriv(var)x) + (Deriv(var)y); -2 # (Deriv(_var)- (_x) ) <-- -Deriv(var)x; -2 # (Deriv(_var)_x - _y) <-- (Deriv(var)x) - (Deriv(var)y); -2 # (Deriv(_var)_x * _y) <-- (x*Deriv(var)y) + (Deriv(var)x)*y; -2 # (Deriv(_var)Sin(_x)) <-- (Deriv(var)x)*Cos(x); -2 # (Deriv(_var)Sinh(_x))<-- (Deriv(var)x)*Cosh(x); -2 # (Deriv(_var)Cosh(_x))<-- (Deriv(var)x)*Sinh(x); -2 # (Deriv(_var)Cos(_x)) <-- -(Deriv(var)x)*Sin(x); -2 # (Deriv(_var)Csc(_x)) <-- -(Deriv(var)x)*Csc(x)*Cot(x); -2 # (Deriv(_var)Csch(_x)) <-- -(Deriv(var)x)*Csch(x)*Coth(x); -2 # (Deriv(_var)Sec(_x)) <-- (Deriv(var)x)*Sec(x)*Tan(x); -2 # (Deriv(_var)Sech(_x)) <-- -(Deriv(var)x)*Sech(x)*Tanh(x); -2 # (Deriv(_var)Cot(_x)) <-- -(Deriv(var)x)*Csc(x)^2; -2 # (Deriv(_var)Coth(_x)) <-- (Deriv(var)x)*Csch(x)^2; - -2 # (Deriv(_var)Tan(_x)) <-- ((Deriv(var) x) / (Cos(x)^2)); -2 # (Deriv(_var)Tanh(_x)) <-- (Deriv(var)x)*Sech(x)^2; - -2 # (Deriv(_var)Exp(_x)) <-- (Deriv(var)x)*Exp(x); - -// When dividing by a constant, this is faster -2 # (Deriv(_var)(_x / _y))_(IsFreeOf(var,y)) <-- (Deriv(var) x) / y; -3 # (Deriv(_var)(_x / _y)) <-- - (y* (Deriv(var) x) - x* (Deriv(var) y))/ (y^2); - -2 # (Deriv(_var)Ln(_x)) <-- ((Deriv(var) x) / x); -2 # (Deriv(_var)(_x ^ _n))_(IsRationalOrNumber(n) Or IsFreeOf(var, n)) <-- - n * (Deriv(var) x) * (x ^ (n - 1)); - -2 # (Deriv(_var)(Abs(_x))) <-- Sign(x)*(Deriv(var)x); -2 # (Deriv(_var)(Sign(_x))) <-- 0; - -2 # (Deriv(_var)(if(_cond)(_body))) <-- - UnList({Atom("if"),cond,Deriv(var)body}); -2 # (Deriv(_var)((_left) else (_right))) <-- - UnList({Atom("else"), (Deriv(var)left), (Deriv(var)right) } ); - -3 # (Deriv(_var)(_x ^ _n)) <-- (x^n)*Deriv(var)(n*Ln(x)); - -2 # (Deriv(_var)ArcSin(_x)) <-- (Deriv(var) x )/Sqrt(1 -(x ^ 2)); -2 # (Deriv(_var)ArcCos(_x)) <-- -(Deriv(var)x)/Sqrt(1 -(x^2)); -2 # (Deriv(_var)ArcTan(_x)) <-- (Deriv(var) x)/(1 + x^2); -2 # (Deriv(_var)Sqrt(_x)) <-- ((Deriv(var)x)/(2*Sqrt(x))); -2 # (Deriv(_var)Complex(_r,_i)) <-- Complex(Deriv(var)r,Deriv(var)i); - -LocalSymbols(var,var2,a,b,y)[ - 2 # (Deriv(_var)Integrate(_var)(_y)) <-- y; - 2 # (Deriv(_var)Integrate(_var2,_a,_b)(y_IsFreeOf(var))) <-- - (Deriv(var)b)*(y Where var2 == b) - - (Deriv(var)a)*(y Where var2 == a); - 3 # (Deriv(_var)Integrate(_var2,_a,_b)(_y)) <-- - (Deriv(var)b)*(y Where var2 == b) - - (Deriv(var)a)*(y Where var2 == a) + - Integrate(var2,a,b) Deriv(var) y; - ]; - - - -2 # (Deriv(_var)func_IsList)_(Not(IsList(var))) <-- - Map("Deriv",{FillList(var,Length(func)),func}); - - -2 # (Deriv(_var)UniVariate(_var,_first,_coefs)) <-- -[ - Local(result,m,i); - result:=FlatCopy(coefs); - m:=Length(result); - For(i:=1,i<=m,i++) - [ - result[i] := result[i] * (first+i-1); - ]; - UniVariate(var,first-1,result); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/Diverge.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/Diverge.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/Diverge.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/Diverge.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="Diverge" - -RuleBase("Diverge", {aFunc, aBasis}); -Rule("Diverge", 2, 1, IsList(aBasis) And IsList(aFunc) And Length(aBasis) = Length(aFunc)) - Add(Map("D", {aBasis,aFunc})); - -%/mathpiper - - - -%mathpiper_docs,name="Diverge",categories="User Functions;Calculus Related (Symbolic)" -*CMD Diverge --- divergence of a vector field -*STD -*CALL - Diverge(vector, basis) - -*PARMS - -{vector} -- vector field to calculate the divergence of - -{basis} -- list of variables forming the basis - -*DESC - -This function calculates the divergence of the vector field "vector" -with respect to the variables "basis". The divergence is defined as - - Diverge(f,x) = D(x[1]) f[1] + ... - + D(x[n]) f[n], -where {n} is the length of the lists "vector" and -"basis". These lists should have equal length. - -*E.G. - - In> Diverge({x*y,x*y,x*y},{x,y,z}) - Out> y+x; - -*SEE D, Curl -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/D.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/D.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/deriv/D.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/deriv/D.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -%mathpiper,def="D" - -RuleBase("D",{aVar,aFunc}); -RuleBase("D",{aVar,aCount,aFunc}); - -Rule("D",2,1,IsList(aVar) And Not(IsList(aFunc))) - Map("D",{aVar,FillList(aFunc, Length(aVar))}); -Rule("D",2,1,IsList(aVar) And IsList(aFunc)) - Map("D",{aVar,aFunc}); - -Rule("D",2,3,True) -[ - MacroLocal(aVar); - Apply("Deriv",{aVar,1,aFunc}); -]; - -Rule("D",3,1,IsList(aVar) And Not(IsList(aFunc))) - Map("D",{aVar, - FillList(aCount, Length(aVar)), - FillList(aFunc, Length(aVar))}); -Rule("D",3,1,IsList(aVar) And IsList(aFunc)) - Map("D",{aVar, - FillList(aCount, Length(aVar)), - aFunc}); -Rule("D",3,3,True) -[ - MacroLocal(aVar); - Apply("Deriv",{aVar,aCount,aFunc}); -]; - - -HoldArg("D",aVar); -HoldArg("D",aFunc); - -%/mathpiper - - - -%mathpiper_docs,name="D",categories="User Functions;Calculus Related (Symbolic)" -*CMD D --- take derivative of expression with respect to variable -*STD -*CALL - D(variable) expression - D(list) expression - D(variable,n) expression - -*PARMS - -{variable} -- variable - -{list} -- a list of variables - -{expression} -- expression to take derivatives of - -{n} -- order of derivative - -*DESC - -This function calculates the derivative of the expression {expr} with -respect to the variable {var} and returns it. If the third calling -format is used, the {n}-th derivative is determined. MathPiper knows -how to differentiate standard functions such as {Ln} -and {Sin}. - -The {D} operator is threaded in both {var} and -{expr}. This means that if either of them is a list, the function is -applied to each entry in the list. The results are collected in -another list which is returned. If both {var} and {expr} are a -list, their lengths should be equal. In this case, the first entry in -the list {expr} is differentiated with respect to the first entry in -the list {var}, the second entry in {expr} is differentiated with -respect to the second entry in {var}, and so on. - -The {D} operator returns the original function if $n=0$, a common -mathematical idiom that simplifies many formulae. - -*E.G. - - In> D(x)Sin(x*y) - Out> y*Cos(x*y); - In> D({x,y,z})Sin(x*y) - Out> {y*Cos(x*y),x*Cos(x*y),0}; - In> D(x,2)Sin(x*y) - Out> -Sin(x*y)*y^2; - In> D(x){Sin(x),Cos(x)} - Out> {Cos(x),-Sin(x)}; - -*SEE Integrate, Taylor, Diverge, Curl -%/mathpiper_docs - - %output,preserve="false" - -. %/output - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/equations/EquationLeft.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/equations/EquationLeft.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/equations/EquationLeft.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/equations/EquationLeft.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="EquationLeft" - -EquationLeft(_symbolicEquation)_(Type(symbolicEquation) = "==") <-- -[ - Local(listForm); - - listForm := Listify(symbolicEquation); - - listForm[2]; -]; -%/mathpiper - - - - -%mathpiper_docs,name="EquationLeft",categories="User Functions;Expression Manipulation" -*CMD EquationLeft --- return the left side of a symbolic equation -*STD -*CALL - EquationLeft(equation) - -*PARMS - -{equation} -- symbolic equation. - - -*DESC - -A symbolic equation is an equation which is defined using the == operator. This -function returns the left side of a symbolic equation. - -*E.G. - - In> e := y^2 == 4*p*x - Result> y^2==4*p*x - - In> EquLeft(e) - Result> y^2 - -*SEE ==, EquationRight -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/equations/EquationRight.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/equations/EquationRight.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/equations/EquationRight.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/equations/EquationRight.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="EquationRight" - -EquationRight(_symbolicEquation)_(Type(symbolicEquation) = "==") <-- -[ - Local(listForm); - - listForm := Listify(symbolicEquation); - - listForm[3]; -]; - -%/mathpiper - - - -%mathpiper_docs,name="EquationRight",categories="User Functions;Expression Manipulation" -*CMD EquationRight --- return the right side of a symbolic equation -*STD -*CALL - EquationRight(equation) - -*PARMS - -{equation} -- symbolic equation. - - -*DESC - -A symbolic equation is an equation which is defined using the == operator. This -function returns the right side of a symbolic equation. - -*E.G. - - In> e := y^2 == 4*p*x - Result> y^2==4*p*x - - In> EquationRight(e) - Result> 4*p*x - -*SEE ==, EquationLeft -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/example/Example.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/example/Example.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/example/Example.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/example/Example.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -%mathpiper,def="Example" - - - -examplelist:= -Hold( -{ - {40!, -"Simple factorial of a number. -" - }, - {D(x)Sin(x), -"Taking the derivative of a function (the derivative of Sin(x) with -respect to x in this case). -" - }, - {Taylor(x,0,5)Sin(x), -"Expanding a function into a taylor series. -" - }, - {Integrate(x,a,b)Sin(x), -"Integrate a function. -" - }, - {Solve(a+x*y==z,x), -"Solve a function for a variable. -" - }, - {Limit(x,0) Sin(x)/x, -"Take a limit. -" - }, - {Subst(x,Cos(a)) x+x, -"Substitute an expression with another in the main expression. -" - }, - {Expand((1+x)^3), -"Expand into a polynomial. -" - }, - {2^40, -"Big numbers. -" - }, - {1<<40, -"Bitwise operations -" - }, - {1 .. 4, -"Generating a list of numbers. -" - }, - {a:b:c:{}, -"Generating a list of items. -" - }, - {[Local(x);x:={a,b,c};Sin(x)^2;], -"Threading: Sin(..)^2 will be performed on all elements of the list -passed in. -" - }, - {[Local(list);list:={a,b,c,d,e,f}; list[2 .. 4];], -"Selecting a sublist from a list. -" - }, - {PermutationsList({a,b,c}), -"Generate all permutations of a list. -" - }, - {VarList(a+b*x), -"Show all variables that occur in an expression. -" - }, - {TrigSimpCombine(Cos(a)*Cos(a)+Sin(a)*Sin(a)), -"Convert factors between trigonometric functions to addition of -trigonometric functions. -" - } -} -); -exampleindex:=0; - -Example():= -[ - exampleindex++; - If (exampleindex>Length(examplelist),exampleindex:=1); - - Local(example); - example:=examplelist[exampleindex]; - WriteString("Current example : "); - Write(example[1]);WriteString(";");NewLine(); - NewLine(); - WriteString(example[2]); - NewLine(); - Eval(example[1]); -]; - - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/BinaryFactors.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/BinaryFactors.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/BinaryFactors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/BinaryFactors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,298 +0,0 @@ -%mathpiper,def="BinaryFactors",public="todo" - -LocalSymbols(lastcoef,OrdBuild, AddFoundSolutionSingle , AddFoundSolution, Fct, MkfactD) -[ - -LastCoef(_vector,_p) <-- -[ - Local(n); - n:=Length(vector); - Add(vector*p^(0 .. (n-1))); -]; - -/* -Ord(vector,q):= -[ - Local(n); - n:=Length(vector); - q*Coef(Simplify(LastCoef(vector,p+q)-LastCoef(vector,p)),q,1); -]; -*/ - -OrdBuild(vector,q):= -[ - Local(i,result,n); - Set(i,2); - Set(result, 0); - Set(n, Length(vector)); - While (i<=n) - [ - Set(result,result+(i-1)*vector[i]*p^(i-2)); - Set(i, i+2); - ]; - q*result; -]; - - -Function(AddFoundSolutionSingle,{p}) -[ - Local(calc); -// If ( Not Contains(result,p), -// [ - Set(calc, Eval(lastcoef)); - If (Equals(calc, 0), - [ - Local(newlist,count,root); - count:=0; - root := p; - Local(rem); - - rem:={-root,1}; - {testpoly,rem}:=MkfactD(testpoly,rem); - - rem:={-root,1}; - {newlist,rem}:=MkfactD(poly,rem); - While (rem = {}) - [ - count++; - Set(poly,newlist); - rem:={-root,1}; - {newlist,rem}:=MkfactD(poly,rem); - ]; - - Local(lgcd,lc); - Set(lgcd,Gcd({andiv,an,root})); - Set(lc,Div(an,lgcd)); - Set(result,{var+ (-(Div(root,lgcd)/lc)),count}:result); - Set(andiv,Div(andiv,lgcd^count)); - Set(anmul,anmul*lc^count); - -// factor:=(x-root); -// Set(result,{factor,count}:result); - - Local(p,q); - Set(lastcoef, LastCoef(testpoly,p)); - Set(ord, OrdBuild(testpoly,q)); - ]); -// ]); -]; -UnFence(AddFoundSolutionSingle,1); - -Function(AddFoundSolution,{p}) -[ - AddFoundSolutionSingle(p); - AddFoundSolutionSingle(-2*q+p); -]; -UnFence(AddFoundSolution,1); - -Function(Fct,{poly,var}) -[ - Local(maxNrRoots,result,ord,p,q,accu,calc,twoq,mask); - - Local(gcd); - [ - Set(gcd,Gcd(poly)); - If(poly[Length(poly)] < 0,Set(gcd, gcd * -1)); - Set(poly,poly/gcd); - ]; - - Local(unrat); - Set(unrat,Lcm(MapSingle("Denominator",poly))); - Set(poly,unrat*poly); - - Local(origdegree); - Set(origdegree,Length(poly)-1); - - Local(an,andiv,anmul); - Set(an,poly[Length(poly)]); - Set(poly,poly* (an^((origdegree-1) .. -1))); - Set(andiv,an^(origdegree-1)); - Set(anmul,1); - - Local(leadingcoef,lowestcoef); - Set(leadingcoef,poly[Length(poly)]); - [ - Local(i); - Set(i,1); - Set(lowestcoef,Abs(poly[i])); - While (lowestcoef = 0 And i<=Length(poly)) - [ - Set(i,i+1); - Set(lowestcoef,Abs(poly[i])); - ]; - ]; - // testpoly is the square-free version of the polynomial, used for finding - // the factors. the original polynomials is kept around to find the - // multiplicity of the factor. - Local(testpoly); -// Set(testpoly,Mkc(Div(polynom,Monic(Gcd(polynom,Deriv(var)polynom))),var)); - Local(deriv); - // First determine a derivative of the original polynomial - deriv:=Rest(poly); - [ - Local(i); - For (i:=1,i<=Length(deriv),i++) - [ - deriv[i] := deriv[i]*i; - ]; -// Echo("POLY = ",poly); -// Echo("DERIV = ",deriv); - ]; - [ - Local(q,r,next); - q:=poly; - r:=deriv; - While(r != {}) - [ -//Echo(q,r); - next := MkfactD(q,r)[2]; - q:=r; - r:=next; - ]; - // now q is the gcd of the polynomial and its first derivative. - - // Make it monic - q:=q/q[Length(q)]; - testpoly:=MkfactD(poly,q)[1]; -//Echo("TESTPOLY = ",testpoly); - ]; - -// Set(testpoly,poly); //@@@ - - Set(maxNrRoots,Length(testpoly)-1); - Set(result, {}); - - Set(lastcoef, LastCoef(testpoly,p)); - Set(ord, OrdBuild(testpoly,q)); - - Set(accu,{}); - Set(q,1); - Set(twoq,MultiplyN(q,2)); - Set(mask,AddN(twoq,MathNegate(1))); - if (IsEven(testpoly[1])) - [ - Set(accu,0:accu); - AddFoundSolutionSingle(0); - ]; - Set(p,1); - Set(calc, Eval(lastcoef)); - If (IsEven(calc), - [ - Set(accu,1:accu); - AddFoundSolution(1); - ]); - Set(q,twoq); - Set(twoq,MultiplyN(q,2)); - Set(mask,AddN(twoq,MathNegate(1))); - While(Length(result)0 And q<=Abs(testpoly[1])) - [ - Local(newaccu); - Set(newaccu,{}); - ForEach(p,accu) - [ - Set(calc,Eval(lastcoef)); - If (LessThan(calc,0), - Set(calc, AddN(calc,MultiplyN(twoq,DivN(AddN(MathNegate(calc),twoq),twoq)))) - ); - Set(calc, BitAnd(calc, mask)); - If ( Equals(calc, 0), - [ - Set(newaccu, p:newaccu); - AddFoundSolutionSingle(-2*q+p); - ]); - Set(calc, AddN(calc, Eval(ord))); - If (LessThan(calc,0), - Set(calc, AddN(calc,MultiplyN(twoq,DivN(AddN(MathNegate(calc),twoq),twoq)))) - ); - Set(calc, BitAnd(calc, mask)); - If ( Equals(calc, 0), - [ - Set(newaccu, AddN(p,q):newaccu); - AddFoundSolution(AddN(p,q)); - ]); - ]; - Set(accu, newaccu); - Set(q,twoq); - Set(twoq,MultiplyN(q,2)); - Set(mask,AddN(twoq,MathNegate(1))); - -//Echo("q = ",q); -//Echo("Length is",Length(accu),"accu = ",accu); -//Echo("result = ",result); - ]; - - // If the polynom is not one, it is a polynomial which is not reducible any further - // with this algorithm, return as is. - Set(poly,poly*an^(0 .. (Length(poly)-1))); - Set(poly,gcd*anmul*poly); - //TODO had to add this if statement, what was andiv again, and why would it become zero? This happens with for example Factor(2*x^2) - If(Not IsZero(unrat * andiv ),Set(poly,poly/(unrat * andiv ))); - If(poly != {1}, - [ - result:={(Add(poly*var^(0 .. (Length(poly)-1)))),1}:result; - ]); - result; -]; - - - -BinaryFactors(expr):= -[ - Local(result,uni,coefs); - uni:=MakeUni(expr,VarList(expr)[1]); - uni:=Listify(uni); - coefs:=uni[4]; - coefs:=Concat(ZeroVector(uni[3]),coefs); - result:=Fct(coefs,uni[2]); -// Echo(result,list); -// Echo((Add(list*x^(0 .. (Length(list)-1))))); -// Product(x-result)*(Add(list*x^(0 .. (Length(list)-1)))); - result; -]; - - - -MkfactD(numer,denom):= -[ - Local(q,r,i,j,ln,ld,nq); - DropEndZeroes(numer); - DropEndZeroes(denom); - Set(numer,Reverse(numer)); - Set(denom,Reverse(denom)); - Set(ln,Length(numer)); - Set(ld,Length(denom)); - Set(q,FillList(0,ln)); - Set(r,FillList(0,ln)); - - Set(i,1); - If(ld>0, - [ - While(Length(numer)>=Length(denom)) - [ - Set(nq,numer[1]/denom[1]); - q[ln-(Length(numer)-ld)] := nq; - For(j:=1,j<=Length(denom),j++) - [ - numer[j] := (numer[j] - nq*denom[j]); - ]; - r[i] := r[1] + numer[1]; - - Set(numer, Rest(numer)); - i++; - ]; - ]); - For(j:=0,j 1, // if this is > 1, we need to separate some factors. Gcd() is very fast - small'powers := TrialFactorize(n, 257), // value is {n1, {p1,q1}, {p2,q2}, ...} and n1=1 if completely factorized into these factors, and the remainder otherwise - small'powers := {n} // pretend we had run TrialFactorize without success - ); - n := small'powers[1]; // remainder - If(n=1, Rest(small'powers), - // if n!=1, need to factorize the remainder with Pollard Rho algorithm - [ - If(InVerboseMode(), Echo({"FactorizeInt: Info: remaining number ", n})); - SortFactorList( - PollardCombineLists(Rest(small'powers), PollardRhoFactorize(n)) - ); - ] - ); -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/Factor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/Factor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/Factor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/Factor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="Factor" - -// This is so Factor(Sin(x)) doesn't return FWatom(Sin(x)) -//Factor(_p) <-- FW(Factors(p)); -10 # Factor(p_CanBeUni) <-- FW(Factors(p)); - -%/mathpiper - - - -%mathpiper_docs,name="Factor",categories="User Functions;Number Theory" -*CMD Factor --- factorization (in pretty form) -*STD -*CALL - Factor(x) - -*PARMS - -{x} -- integer or univariate polynomial - -*DESC - -This function factorizes "x", similarly to {Factors}, but -it shows the result in a nicer human readable format. - -*E.G. - - In> PrettyForm(Factor(24)); - - 3 - 2 * 3 - - Out> True; - In> PrettyForm(Factor(2*x^3 + 3*x^2 - 1)); - - 2 / 1 \ - 2 * ( x + 1 ) * | x - - | - \ 2 / - - Out> True; - -*SEE Factors, IsPrime, PrettyForm -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FactorQS.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FactorQS.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FactorQS.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FactorQS.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -%mathpiper,def="FactorQS" - -// numbers - -// The bud of an Quadratic Seive algorithm -// congruence solving code must be written first -Function("FactorQS",{n})[ - Local(x,k,fb,j); - // optimal number of primes in factor base - // according to Fundamental Number Theory with Applications - Mollin, p130 - k:=Round(N(Sqrt(Exp(Sqrt(Ln(n)*Ln(Ln(n))))))); - fb:=ZeroVector(k); - For(j:=1,j<=k,j++)[ - fb[j]:=NextPrime(j); - ]; -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/Factors.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/Factors.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/Factors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/Factors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,237 +0,0 @@ -%mathpiper,def="Factors" - -Retract("Factors",*); -Retract("FactorsMultivariateSpecialCases",*); -Retract("FactorsSomethingElse",*); -Retract("CombineNumericalFactors",*); - -/* - * Factors() is the fundamental factorization algorithm. - * It works for integers, rational numbers, Gaussian integers, and polynomials - * When the argument is an integer, FactorizeInt() does the heavy lifting. - * When the argument is a polynomial, BinaryFactors() is the workhorse. - */ - -10 # Factors(p_IsPositiveInteger) <-- FactorizeInt(p); - -11 # Factors(p_IsInteger) <-- FactorizeInt(p); - // Added because otherwise negative integers (and 0) get processed as Gaussian Integers - -12 # Factors(p_IsRational)_(Denominator(p) != 1) <-- {{Factor(Numerator(p)) /Factor(Denominator(p)) , 1}}; - // Added to handle rational numbers with denominators that are not 1 - -14 # Factors(p_IsGaussianInteger) <-- GaussianFactors(p); - -20 # Factors(p_CanBeUni)_(Length(VarList(p)) = 1) <-- -[ - Local(x,coeffs,factorsList,result); - x := VarList(p)[1]; - /* p is the polynomial, x is its (only) variable */ - - factorsList := BinaryFactors(p); - // BinaryFactors is the internal MathPiper function that - // creates a double list of factors and their multiplicities - /* - * Now we check whether the input polynomial is "over the - * integers", by examining all its coefficients - */ - coeffs := Coef(p,x,0 .. Degree(p,x)); - If( AllSatisfy("IsInteger",coeffs), - [ - // Yes -- all integer coefficients - result := FactorsPolynomialOverIntegers(p,x); - ], - [ - // No -- at least one non-integer coefficient - // Check for FLOAT or RATIONAL coefficients - Local(notInt,rat,dd,lcm,newCoeffs,NewPoly,facs); - notInt := Select(Lambda({i},Not IsInteger(i)),coeffs); - rat := Rationalize(coeffs); - dd := MapSingle("Denominator",rat); - lcm := Lcm(dd); - newCoeffs := lcm * rat; - newPoly := NormalForm(UniVariate(x,0,newCoeffs)); - facs := FactorsPolynomialOverIntegers(newPoly); - If( InVerboseMode(), [ - Echo("coeffs ",coeffs); - Echo("notInt ",notInt); - Echo("rat ",rat); - Echo("dd ",dd); - Echo("lcm ",lcm); - Echo("newCoeffs ",newCoeffs); - Echo("newPoly ",newPoly); - Echo("facs ",facs); - ] - ); - result := {(1/lcm),1}:facs; - //NOT FINISHED YET - ] - ); - CombineNumericalFactors( result ); -]; - - -30 # Factors(p_CanBeUni) <-- -[ - /* - * This may be a multi-variate polynomial, or it may be something else. - * Original YY function Factors() did not attempt to factor such. - * If it is a multivariate polynomial, we will try certain - * Special cases which we can relatively easily factor. - * If it is "something else", we will have to check, on a - * case-by-case basis. - */ - Local(nvars,result); - nvars := Length(VarList(p)); - If (nvars > 1, - [ - If( InVerboseMode(), - [ - Echo("special ",p); - Echo(Coef(p,x,0 .. 8)); - ] - ); - result := FactorsMultivariateSpecialCases(p); - ], - result := FactorsSomethingElse(p) - ); - CombineNumericalFactors( result ); -]; - - -40 # Factors(_p) <-- -[ - /* - * This may may be a polynomial with non-integer exponents. Let's check. - */ - If( InVerboseMode(), Echo("Possibly trying to factor polynomial with non-integral exponents") ); - Local( result); - //Echo(40,p); - // NOT IMPLEMENTED YET - result := {{p,1}}; - CombineNumericalFactors( result ); - -]; - -//------------------------------------------------------------------------ -// S P E C I A L C A S E S -//------------------------------------------------------------------------ - -10 # FactorsMultivariateSpecialCases(-_expr) <-- {-1,1}:FactorsMultivariateSpecialCases(expr); - -10 # FactorsMultivariateSpecialCases(x_IsAtom + y_IsAtom) <-- {{x+y,1}}; - -10 # FactorsMultivariateSpecialCases(x_IsAtom - y_IsAtom) <-- {{x-y,1}}; - -10 # FactorsMultivariateSpecialCases(n_IsInteger*_x + m_IsInteger*_y)_(Gcd(n,m)>1) <-- {{Gcd(n,m),1},{(Simplify((n*x+m*y)/Gcd(n,m))),1}}; - -10 # FactorsMultivariateSpecialCases(n_IsInteger*_x - m_IsInteger*_y)_(Gcd(n,m)>1) <-- {{Gcd(n,m),1},{(Simplify((n*x-m*y)/Gcd(n,m))),1}}; - -10 # FactorsMultivariateSpecialCases(_n*_x + _n*_y) <-- {n,1}:FactorsMultivariateSpecialCases(x+y); - -10 # FactorsMultivariateSpecialCases(_n*_x - _n*_y) <-- {n,1}:FactorsMultivariateSpecialCases(x-y); - -10 # FactorsMultivariateSpecialCases(_x^2-_y^2) <-- {{x+y,1},{x-y,1}}; - -10 # FactorsMultivariateSpecialCases(_x^3-_y^3) <-- {{x-y,1},{x^2+y*x+y^2,1}}; - -10 # FactorsMultivariateSpecialCases(_x^3+_y^3) <-- {{x+y,1},{x^2-y*x+y^2,1}}; - -10 # FactorsMultivariateSpecialCases(_x^4-_y^4) <-- {{x+y,1},{x-y,1},{x^2+y^2,1}}; - -10 # FactorsMultivariateSpecialCases(_x^6-_y^6) <-- {{x+y,1},{x-y,1},{x^2+x*y+y^2,1},{x^2-x*y+y^2,1}}; - -20 # FactorsSomethingElse(_p) <-- - [ - If( InVerboseMode(), - [ - ECHO(" *** FactorsSomethingElse: NOT IMPLEMENTED YET ***"); - ] - ); - p; - ]; - -//------------------------------------------------------------------------ - - -10 # CombineNumericalFactors( factrs_IsList ) <-- - [ - If( InVerboseMode(), Tell("Combine",factrs) ); - Local(q,a,b,t,f,err); - err := False; - t := 1; - f := {}; - ForEach(q,factrs) - [ - If( InVerboseMode(), Tell(1,q) ); - If( IsList(q) And Length(q)=2, - [ - {a,b} := q; - If( InVerboseMode(), Echo(" ",{a,b}) ); - If( IsNumericList( {a,b} ), - t := t * a^b, - f := {a,b}:f - ); - ], - err := True - ); - ]; - If( InVerboseMode(), - [ - Echo(" t = ",t); - Echo(" f = ",f); - Echo(" err = ",err); - ] - ); - If(Not err And t != 1, {t,1}:Reverse(f), factrs); - ]; - -//--------------------------------------------------------------------- -%/mathpiper - - - - - - -%mathpiper_docs,name="Factors",categories="User Functions;Number Theory" -*CMD Factors --- factorization -*STD -*CALL - Factors(x) - -*PARMS - -{x} -- integer or univariate polynomial - -*DESC - -This function decomposes the integer number {x} into a product of -numbers. -Alternatively, if {x} is a univariate polynomial, it is -decomposed into irreducible polynomials. If {x} is a polynomial -"over the integers", the irreducible polynomial factors will also -be returned in the (unique) form with integer coefficients. - -The factorization is returned as a list of pairs. The first member of -each pair is the factor, while the second member denotes the power to -which this factor should be raised. So the factorization -$x = p1^n1 * ... * p9^n9$ -is returned as {{{p1,n1}, ..., {p9,n9}}}. - -Programmer: Yacas Team + Sherm Ostrowsky - -*E.G. - In> Factors(24) - Result: {{2,3},{3,1}} - - In> Factors(32*x^3+32*x^2-70*x-75) - Result: {{4*x+5,2},{2*x-3,1}} - -*SEE Factor, IsPrime, GaussianFactors -%/mathpiper_docs - - %output,preserve="false" - -. %/output - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FactorsPolynomialOverIntegers.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FactorsPolynomialOverIntegers.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FactorsPolynomialOverIntegers.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FactorsPolynomialOverIntegers.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,205 +0,0 @@ -%mathpiper,def="FactorsPolynomialOverIntegers",scope="private" - -Retract("FactorsPolynomialOverIntegers",*); -Retract("TryToReduceSpecialPolynomial",*); - -//--------------------------------------------------------------------------- - -10 # FactorsPolynomialOverIntegers(_expr)_IsPolynomialOverIntegers(expr) <-- -[ - Local(x); - x := VarList(expr)[1]; - FactorsPolynomialOverIntegers(expr,x); - -]; - -15 # FactorsPolynomialOverIntegers(_expr) <-- expr; - - -10 # FactorsPolynomialOverIntegers(_expr,_var)_(IsPolynomialOverIntegers(expr,var)) <-- -[ - Local(factorsList,factListTransp,factrs,multiplicities,factrsUnMonic); - Local(polyFactors,normalizations,normDivisor,polyFactors,factList); - Local(n,result,newResult,gtotal,r,rr,d,g); - factorsList := BinaryFactors(expr); - /* - * BinaryFactors is the internal MathPiper function that - * creates a double list of factors and their multiplicities - */ - - // By transposing factorsList (which has the form of a list of - // lists, hence a matrix), we convert it into a form which has - // a list of all the factors first, followed by a list of all - // the corresponding multiplicities. - - factListTransp := Transpose(factorsList); - factrs := factListTransp[1]; - multiplicities := factListTransp[2]; - - // Now, these factors are probably all in "monic" form, with the - // coefficient of the highest power of x in each factor being - // equal to 1, and all the "normalizing" factors being combined - // into a new leading numeric factor. We want to undo this - // monic-ization. The function Together() will accomplish this - // for each separate factor, while leaving untouched factors - // which do not need changing. - - factrsUnMonic := MapSingle("Together",factrs); - - // The result of this step is that each factor which had been - // "normalized" to a monic has now be un-normalized into a - // rational function consisting of a non-monic polynomial - // divided by a number. Now we just collect all the non-monic - // polynomials into one list, and all the normalizing denominators - // into another. - - {polyFactors,normalizations}:=Transpose(MapSingle("GetNumerDenom",factrsUnMonic)); - - // The next step is to make sure that each of the normalizing - // numbers is raised to the power of its corresponding - // multiplicity. Then all these powers of numbers are - // multiplied together, to form the overall normilizing - // divisor which must be used to remove the extra factor (if - // any) introduced during the monic-ization process. All this - // is condensed into one line of Functional code - - normDivisor := Product(Map("^",{normalizations,multiplicities})); - - // Notice that normDivisors is exactly equal in value to the - // 'extra' numeric factor introduced by the monic-ization, if - // any was indeed so introduced (it doesn't happen under all - // circumstances). I believe this will always be true, but I - // have not taken the time to prove it. So I proceed in a - // more general way. - - polyFactors[1] := Simplify(polyFactors[1]/normDivisor); - - // We can now replace the first sub-list in factListTransp by - // the un-monic-ized version - - factListTransp[1] := polyFactors; - factList := Transpose(factListTransp); - - - // .... and that is (supposedly) the answer. - result := factList; - - // However, let's find out if any of the factors needs more treatment. - Local(newResult,gtotal,d,g,rr); - newResult := {}; - gtotal := 1; - ForEach(r,result) [ - d := Degree(r[1],var); - g := Gcd(Coef(r[1],var,0 .. d)); - If( g > 1, // need to remove common numerical factor - [ gtotal:=g*gtotal; - r[1]:=Simplify(r[1]/g); - ] - ); - If(d > 2, - [ - // polynomial is NOT irreducible, but can we reduce it? - rr := TryToReduceSpecialPolynomial(r[1]); - If( IsList(rr),newResult := Concat(newResult,rr) ); - ], - If( r != {1,1}, newResult := r:newResult ) - ); - ]; - If(gtotal>1,newResult:={gtotal,1}:newResult); - newResult; -]; - - -//--------------------------------------------------------------------------- -// S P E C I A L C A S E S -//--------------------------------------------------------------------------- -/* - * Given an unreduced polynomial over the integers, of degree > 2, - * which was found as one of the "factors" of a polynomial over - * the integers, we know that it is factorable into irreducible - * quadratics. This function tries to find such quadratic factors. - * Lacking a good general attack on this problem, we will turn - * to special cases which we happen to be able to solve. - */ - -10 # TryToReduceSpecialPolynomial(_x^4+_x^2+1) <-- {{x^2+x+1,1},{x^2-x+1,1}}; - -10 # TryToReduceSpecialPolynomial(_x^6-1) <-- {{x+1,1},{x-1,1},{x^2+x+1,1},{x^2-x+1,1}}; - - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - - - - -%mathpiper_docs,name="FactorsPolynomialOverIntegers",categories="User Functions;Factors" -*CMD Factors --- factorization of univariate polynomials over the integers -*STD -*CALL - FactorsPolynomialOverIntegers(poly,x) - -*PARMS - -{poly} -- a polynomial which is univariate w.r.t. variable x -{x} -- variable of the polynomial - -*DESC - -This function decomposes the polynomial {poly}, considered as univariate -in the variable {x}, into a product of irreducible polynomials. - -This function is specialized for polynomials in {x} whose coefficients -are all integers. In such a case, it is often customary to expect the -irreducible polynomial factors to be given in a form which also has -only integer coefficients. However, the standard MathPiper function -Factors() follows a different convention, which returns the constituant -polynomial factors in a {monic} form. This means that the results may -have rational, rather than integer, coefficients. - -The present function offers an alternative which is guaranted to return -polynomial factors with integer coefficients. But it works only for -input {polynomials}, not {numbers}, and only for polynomials all of whose -coefficients are integers. For any other input, this function will simply -return the input expression unevaluated. - -The factorization is returned as a list of pairs. The first member of -each pair is the factor, while the second member denotes the power to -which this factor should be raised. So the factorization -$poly = p1^n1 * ... * p9^n9$ -is returned as {{{p1,n1}, ..., {p9,n9}}}. - -NOTE: If you want the factorization to be expressed in the nominal -form $poly = p1^n1 * ... * p9^n9$, -just apply the function FW() to the result returned by the present -function. - -Programmer: Sherm Ostrowsky - -*E.G. - -In> u:=Expand((2*x-3)^2*(3*x+5)^3) -Result: 108*x^5+216*x^4-477*x^3-985*x^2+525*x+1125 - -In> FactorsPolynomialOverIntegers(u,x) -Result: {{2*x-3,2},{3*x+5,3}} - -In> FW(%) -Result: (2*x-3)^2*(3*x+5)^3 - -In> FactorsPolynomialOverIntegers(y^2-4) -Result: {{y+2,1},{y-2,1}} - -In> FactorsPolynomialOverIntegers(x^4+x^2+1) -Result: {{x^2+x+1,1},{x^2-x+1,1}} - -*SEE Factor, Factors, FW -%/mathpiper_docs - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FindPrimeFactor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FindPrimeFactor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FindPrimeFactor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FindPrimeFactor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="FindPrimeFactor" - -// numbers - -/// Auxiliary function. Return the power of a given prime contained in a given integer and remaining integer. -/// E.g. FindPrimeFactor(63, 3) returns {7, 2} and FindPrimeFactor(42,17) returns {42, 0} -// use variable step loops, like in IntLog() -FindPrimeFactor(n, prime) := -[ - Local(power, factor, old'factor, step); - power := 1; - old'factor := 1; // in case the power should be 0 - factor := prime; - // first loop: increase step - While(Mod(n, factor)=0) // avoid division, just compute Mod() - [ - old'factor := factor; // save old value here, avoid sqrt - factor := factor^2; - power := power*2; - ]; - power := Div(power,2); - factor := old'factor; - n := Div(n, factor); - // second loop: decrease step - step := Div(power,2); - While(step>0 And n > 1) - [ - factor := prime^step; - If( - Mod(n, factor)=0, - [ - n := Div(n, factor); - power := power + step; - ] - ); - step := Div(step, 2); - ]; - {n, power}; -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FindPrimeFactorSimple.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FindPrimeFactorSimple.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FindPrimeFactorSimple.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FindPrimeFactorSimple.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="FindPrimeFactorSimple" - -// numbers - -/* simpler method but slower on worstcase such as p^n or n! */ -FindPrimeFactorSimple(n, prime) := -[ - Local(power, factor); - power := 0; - factor := prime; - While(Mod(n, factor)=0) - [ - factor := factor*prime; - power++; - ]; - {n/(factor/prime), power}; -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FWatom.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FWatom.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FWatom.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FWatom.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -%mathpiper,def="FWatom",scope="private" - -10 # FWatom({_a,1}) <-- a; -20 # FWatom({_a,_n}) <-- UnList({Atom("^"),a, n}); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FW.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FW.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/FW.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/FW.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -%mathpiper,def="FW" - -/* FW: pass FW the result of Factors, and it will show it in the - * form of p0^n0*p1^n1*... - */ - - -5 # FW(_list)_(Length(list) = 0) <-- 1; -10 # FW(_list)_(Length(list) = 1) <-- FWatom(list[1]); -20 # FW(_list) <-- -[ - Local(result); - result:=FWatom(First(list)); - ForEach(item,Rest(list)) - [ - result := UnList({ Atom("*"),result,FWatom(item)}); - ]; - result; -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/pollardrho/PollardCombineLists.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/pollardrho/PollardCombineLists.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/pollardrho/PollardCombineLists.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/pollardrho/PollardCombineLists.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -%mathpiper,def="PollardCombineLists",scope="private" -/* PollardCombineLists combines two assoc lists used for factoring. - the first element in each item list is the factor, and the second - the exponent. Thus, an assoc list of {{2,3},{3,5}} means 2^3*3^5. -*/ -PollardCombineLists(_left,_right) <-- -[ - ForEach(item,right) - [ - PollardMerge(left,item); - ]; - left; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/pollardrho/PollardMerge.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/pollardrho/PollardMerge.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/pollardrho/PollardMerge.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/pollardrho/PollardMerge.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -%mathpiper,def="PollardMerge",scope="private" - -5 # PollardMerge(_list,{1,_n}) <-- True; -10 # PollardMerge(_list,_item)_(Assoc(item[1],list) = Empty) <-- - DestructiveInsert(list,1,item); - -20 # PollardMerge(_list,_item) <-- -[ - Local(assoc); - assoc := Assoc(item[1],list); - assoc[2]:=assoc[2]+item[2]; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/pollardrho/PollardRhoFactorize.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/pollardrho/PollardRhoFactorize.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/pollardrho/PollardRhoFactorize.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/pollardrho/PollardRhoFactorize.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -%mathpiper,def="PollardRhoFactorize",scope="private" - -/* This is Pollard's Rho method of factorizing, as described in - * "Modern Computer Algebra". It is a rather fast algorithm for - * factoring, but doesn't scale to polynomials regrettably. - * - * It acts 'by chance'. This is the Floyd cycle detection trick, where - * you move x(i+1) = f(x(i)) and y(i+1) = f(f(y(i))), so the y goes twice - * as fast as x, and for a certain i x(i) will be equal to y(i). - * - * "Modern Computer Algebra" reasons that if f(x) = (x^2+1) mod n for - * the value n to be factored, then chances are good that gcd(x-y,n) - * is a factor of n. The function x^2+1 is arbitrary, a higher order - * polynomial could have been chosen also. - * - */ - -/* -Warning: The Pollard Rho algorithm cannot factor some numbers, e.g. 703, and -can enter an infinite loop. This currently results in an error message: "failed to factorize". -Hopefully the TrialFactorize() step will avoid these situations by excluding -small prime factors. -This problem could also be circumvented by trying a different random initial value for x when a loop is encountered -- hopefully another initial value will not get into a loop. (currently this is not implemented) -*/ - - - - -/// Polynomial for the Pollard Rho iteration -PollardRhoPolynomial(_x) <-- x^2+1; - -2# PollardRhoFactorize(n_IsPrimePower) <-- {GetPrimePower(n)}; -3# PollardRhoFactorize(_n) <-- -[ - Local(x,y,restarts,gcd,repeat); - gcd:=1; - restarts := 100; // allow at most this many restartings of the algorithm - While(gcd = 1 And restarts>=0) // outer loop: this will be typically executed only once but it is needed to restart the iteration if it "stalls" - [ - restarts--; - /* Pick a random value between 1 and n-1 */ - x:= RandomInteger(n-1); - - /* Initialize loop */ - gcd:=1; y:=x; - repeat := 4; // allow at most this many repetitions -// Echo({"debug PollardRho: entering gcd loop, n=", n}); - - /* loop until failure or success found */ - While(gcd = 1 And repeat>=0) - [ - x:= Mod( PollardRhoPolynomial(x), n); - y:= Mod( PollardRhoPolynomial( - Mod( PollardRhoPolynomial(y), n) // this is faster for large numbers - ), n); - If(x-y = 0, - [ - gcd := 1; - repeat--; // guard against "stalling" in an infinite loop but allow a few repetitions - ], - gcd:=Gcd(x-y,n) - ); -// Echo({"debug PollardRho: gcd=",gcd," x=", x," y=", y}); - ]; - If(InVerboseMode() And repeat<=0, Echo({"PollardRhoFactorize: Warning: stalled while factorizing ", n, "; counters ", x, y})); - ]; - Check(restarts>0, "PollardRhoFactorize: Error: failed to factorize " : String(n)); - If(InVerboseMode() And gcd > 1, Echo({"PollardRhoFactorize: Info: while factorizing ", n, " found factor ", gcd})); - /* Return result found */ - PollardCombineLists(PollardRhoFactorize(gcd), PollardRhoFactorize(Div(n,gcd))); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/Roots.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/Roots.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/Roots.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/Roots.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="Roots" - -// polynomials - -10 # Roots(poly_CanBeUni) <-- -[ - Local(factors,result,uni,root,i,deg); - factors:=Factors(poly); - result:={}; - ForEach(item,factors) - [ - uni:=MakeUni(item[1]); - deg:=Degree(uni); - If(deg > 0 And deg < 3, - [ - root:= PSolve(uni); - If(Not IsList(root),root:={root}); - For(i:=0,i 0 And deg < 3, - [ - root:= PSolve(uni); - If(Not IsList(root),root:={root}); - For(i:=1,i<=Length(root),i++) - result:= Concat({{root[i],item[2]}}, result); - ] - ); - ]; - result; -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/SortFactorList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/SortFactorList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/factors/SortFactorList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/factors/SortFactorList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="SortFactorList",scope="private" - -/// Sort the list of prime factors using HeapSort() -LocalSymbols(a,b, list) [ - -SortFactorList(list) := HeapSort(list, {{a,b}, a[1] 1,000,000. -/// Try all prime factors up to Sqrt(n). -/// Resulting factors are automatically sorted. -/// This function is not used any more. -/* -2# TrialFactorize(n_IsPrimePower) <-- {GetPrimePower(n)}; -3# TrialFactorize(n_IsInteger) <-- -[ - Local(factorization); - factorization := TrialFactorize(n, n); // TrialFactorize will limit to Sqrt(n) automatically - If( - First(factorization) = 1, // all factors were smaller than Sqrt(n) - Rest(factorization), - // the first element needs to be replaced - Concat(Rest(factorization), {{First(factorization),1}}) - ); -]; -*/ - - -/// Auxiliary function. Factorizes by trials. Return prime factors up to given limit and the remaining number. -/// E.g. TrialFactorize(42, 2) returns {21, {{2, 1}}} and TrialFactorize(37, 4) returns {37} -TrialFactorize(n, limit) := -[ - Local(power, prime, result); - result := {n}; // first element of result will be replaced by the final value of n - prime := 2; // first prime - While(prime <= limit And n>1 And prime*prime <= n) - [ // find the max power of prime which divides n - {n, power} := FindPrimeFactor(n, prime); - If( - power>0, - DestructiveAppend(result, {prime,power}) - ); - prime := NextPseudoPrime(prime); // faster than NextPrime and we don't need real primes here - ]; - // replace the first element which was n by the new n - DestructiveReplace(result, 1, n); -]; - - - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/atsign_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/atsign_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/atsign_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/atsign_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="@" - -RuleBase("@",{func,arg}); -Rule("@",2,1,IsList(arg)) Apply(func,arg); -Rule("@",2,2,True ) Apply(func,{arg}); - -%/mathpiper - - - -%mathpiper_docs,name="@",categories="Operators" -*CMD @ --- apply a function -*STD -*CALL - fn @ arglist -Precedence: -*EVAL OpPrecedence("@") - -*PARMS - -{fn} -- function to apply - -{arglist} -- single argument, or a list of arguments - -*DESC - -This function is a shorthand for {Apply}. It applies the -function "fn" to the argument(s) in "arglist" and returns the -result. The first parameter "fn" can either be a string containing -the name of a function or a pure function. - -This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. - -*E.G. - - In> "Sin" @ a - Out> Sin(a); - In> {{a},Sin(a)} @ a - Out> Sin(a); - In> "f" @ {a,b} - Out> f(a,b); - -*SEE Apply -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/colon_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/colon_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/colon_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/colon_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -%mathpiper,def=":" - -/* Operators for functional programming. todo:tk:move some of this documentation into the proper function's .mrw files. - * Examples: - * a:b:c:{} -> {a,b,c} - * "Sin" @ a -> Sin(a) - * "Sin" @ {a,b} -> Sin(a,b) - * "Sin" /@ {a,b} -> {Sin(a),Sin(b)} - * 1 .. 4 -> {1,2,3,4} - */ - - -/* a : b will now return unevaluated (rather than cause error of invalid argument in Concat) if neither a nor b is a list and if one of them is not a string -*/ -RuleBase(":",{head,tail}); -Rule(":",2,20,IsList(head) And Not IsList(tail) ) Concat(head,{tail}); -Rule(":",2,30,IsList(tail) ) Concat({head},tail); -Rule(":",2,10,IsString(tail) And IsString(head)) ConcatStrings(head,tail); -UnFence(":",2); - -%/mathpiper - - - -%mathpiper_docs,name=":",categories="Operators" -*CMD : --- prepend item to a list or concatenate strings -*STD -*CALL - item : list - string1 : string2 -Precedence: -*EVAL OpPrecedence(":") - -*PARMS -{item} -- an item to be prepended to a list - -{list} -- a list - -{string1} -- a string - -{string2} -- a string - -*DESC - -The first form prepends "item" as the first entry to the list -"list". The second form concatenates the strings "string1" and -"string2". - -This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. - -*E.G. - - In> a:b:c:{} - Out> {a,b,c}; - In> "This":"Is":"A":"String" - Out> "ThisIsAString"; - -*SEE Concat, ConcatStrings -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/dot_dot_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/dot_dot_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/dot_dot_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/dot_dot_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def=".." - -/* -.. operator is implemented with the Table function. -*/ -10 # (count'from_IsInteger .. count'to_IsInteger)_(count'from <= count'to) - <-- Table(i,i,count'from,count'to,1); -20 # (count'from_IsInteger .. count'to_IsInteger) - <-- Table(i,i,count'from,count'to,-1); - -%/mathpiper - - - -%mathpiper_docs,name="..",categories="Operators" -*CMD .. --- construct a list of consecutive integers - -*STD - -*CALL - n .. m - -*PARMS - -{n} -- integer. the first entry in the list - -{m} -- integer, the last entry in the list - -*DESC - -This command returns the list {{n, n+1, n+2, ..., m}}. If {m} is -smaller than {n}, the empty list is returned. Note that the -{..} operator should be surrounded by spaces to keep the -parser happy, if "n" is a number. So one should write "{1 .. 4}" instead of "{1..4}". - -This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. - -*E.G. - - In> 1 .. 4 - Out> {1,2,3,4}; - -*SEE Table -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/NFunction.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/NFunction.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/NFunction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/NFunction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -%mathpiper,def="NFunction" - -/* NFunction("new'func", "old'func" {arg'list}) will define a wrapper function -around "old'func", called "new'func", which will return "old'func(arg'list)" -only when all arguments are numbers and will return unevaluated -"new'func(arg'list)" otherwise. */ -LocalSymbols(NFunction'Numberize) -[ -NFunction(new'name_IsString, old'name_IsString, arg'list_IsList) <-- [ - MacroRuleBase(new'name, arg'list); - MacroRule(new'name, Length(arg'list), 0, // check whether all args are numeric - UnList({IsNumericList, arg'list}) - ) - - /* this is the rule defined for the new function. - // this expression should evaluate to the body of the rule. - // the body looks like this: - // NFunction'Numberize(old'name(arg'list)) - */ - NFunction'Numberize(UnList({Atom("@"), old'name, arg'list})); - // cannot use bare '@' b/c get a syntax error - -]; - -// this function is local to NFunction. -// special handling for numerical errors: return Undefined unless given a number. -10 # NFunction'Numberize(x_IsNumber) <-- x; -20 # NFunction'Numberize(x_IsAtom) <-- Undefined; -// do nothing unless given an atom - -]; // LocalSymbols() - -%/mathpiper - - - -%mathpiper_docs,name="NFunction",categories="User Functions;Functional Operators" -*CMD NFunction --- make wrapper for numeric functions -*STD -*CALL - NFunction("newname","funcname", {arglist}) - -*PARMS -{"newname"} -- name of new function - -{"funcname"} -- name of an existing function - -{arglist} -- symbolic list of arguments - -*DESC -This function will define a function named "newname" -with the same arguments as an existing function named "funcname". The new function will evaluate and return the expression "funcname(arglist)" only when -all items in the argument list {arglist} are numbers, and return unevaluated otherwise. - -This can be useful when plotting functions defined through other MathPiper routines that cannot return unevaluated. - -If the numerical calculation does not return a number (for example, -it might return the atom {nan}, "not a number", for some arguments), -then the new function will return {Undefined}. - -This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. - - -*E.G. notest - In> f(x) := N(Sin(x)); - Out> True; - In> NFunction("f1", "f", {x}); - Out> True; - In> f1(a); - Out> f1(a); - In> f1(0); - Out> 0; -Suppose we need to define a complicated function {t(x)} which cannot be evaluated unless {x} is a number: - - In> t(x) := If(x<=0.5, 2*x, 2*(1-x)); - Out> True; - In> t(0.2); - Out> 0.4; - In> t(x); - In function "If" : - bad argument number 1 (counting from 1) - CommandLine(1) : Invalid argument -Then, we can use {NFunction()} to define a wrapper {t1(x)} around {t(x)} which will not try to evaluate {t(x)} unless {x} is a number. - - In> NFunction("t1", "t", {x}) - Out> True; - In> t1(x); - Out> t1(x); - In> t1(0.2); - Out> 0.4; -Now we can plot the function. - - In> Plot2D(t1(x), -0.1: 1.1) - Out> True; - -*SEE MacroRule -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -OMDef( ":" , "mathpiper","prepend" ); -OMDef( "@" , "mathpiper","apply" ); -OMDef( "/@" , "mathpiper","list_apply" ); -OMDef( ".." , "interval1","integer_interval" ); -OMDef( "NFunction", "mathpiper","NFunction" ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/slash_atsign_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/slash_atsign_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/functional/slash_atsign_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/functional/slash_atsign_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -%mathpiper,def="/@" - -Function("/@",{func,lst}) Apply("MapSingle",{func,lst}); - -%/mathpiper - - - -%mathpiper_docs,name="/@",categories="Operators" -*CMD /@ --- apply a function to all entries in a list -*STD -*CALL - fn /@ list -Precedence: -*EVAL OpPrecedence("/@") - -*PARMS - -{fn} -- function to apply - -{list} -- list of arguments - -*DESC -This function is a shorthand for {MapSingle}. It -successively applies the function "fn" to all the entries in -"list" and returns a list contains the results. The parameter "fn" -can either be a string containing the name of a function or a pure -function. - -This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. - -*E.G. - - In> "Sin" /@ {a,b} - Out> {Sin(a),Sin(b)}; - In> {{a},Sin(a)*a} /@ {a,b} - Out> {Sin(a)*a,Sin(b)*b}; - -*SEE MapSingle, Map, MapArgs -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/html/html.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/html/html.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/html/html.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/html/html.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,252 +0,0 @@ -%mathpiper,def="HtmlNewParagraph;HtmlAnchor;HtmlLink;HtmlTable;HtmlCaption;HtmlTitle;HtmlFrameSetRows;HtmlFrameSetCols;HtmlFrame;HtmlTag;HtmlForm;Bullets;Bullet;HtmlTextArea;HtmlTextField;HtmlSubmitButton;SetHtmlDirectory;HtmlFile;ClearSite;LoadSite;SaveSite;MySQLQuery" - -/* def file definitions -HtmlNewParagraph -HtmlAnchor -HtmlLink -HtmlTable -HtmlCaption -HtmlTitle -HtmlFrameSetRows -HtmlFrameSetCols -HtmlFrame -HtmlTag -HtmlForm -Bullets -Bullet -HtmlTextArea -HtmlTextField -HtmlSubmitButton -SetHtmlDirectory -HtmlFile -ClearSite -LoadSite -SaveSite -MySQLQuery -*/ - - -/* code to generate html */ - - -/* Global defines */ -anchor:={}; -anchor["0"]:="a"; -anchor["name"]:=""; - -link:={}; -link["0"]:="a"; -link["href"]:=""; - -frameset:={}; -frameset["0"]:="frameset"; -frameset["border"]:="0"; - -frame:={}; -frame["0"]:="frame"; - -caption:={}; -caption["0"]:="caption"; - -table:={}; -table["0"]:="table"; - -form:={}; -form["0"]:="form"; - -textarea:={}; -textarea["0"]:="textarea"; - -textfield:={}; -textfield["0"]:="input"; -textfield["TYPE"]:="text"; - -button:={}; -button["0"]:="input"; -button["TYPE"]:="submit"; - -bullets:={}; -bullets["0"]:="ul"; - -bullet:={}; -bullet["0"]:="li"; - -newline:=" -"; -Gt():=">"; -Lt():="<"; - - - - -HtmlNewParagraph():= (newline : "

    " : newline); - -HtmlTitle(title):= -[ -" - " : title : " - -"; -]; - -HtmlAnchor(name):= -[ - anchor["name"]:=name; - HtmlTag(anchor,""); -]; -Bodied("HtmlAnchor",60000); - -HtmlTable(cellpadding,width,body):= -[ - table["cellpadding"]:=String(cellpadding); - table["width"]:=width; - HtmlTag(table,body); -]; - -Bullets(list):=HtmlTag(bullets,list); -Bullet (list):=HtmlTag(bullet ,list); - - -HtmlCaption(title):= -[ - HtmlTag(caption,title); -]; - -HtmlForm(action,body):= -[ - form["method"]:="get"; - form["action"]:=action; - HtmlTag(form,body); -]; - - -HtmlTextArea(name,width,height,body) := -[ - textarea["name"]:=name; - textarea["cols"]:=String(width); - textarea["rows"]:=String(height); - HtmlTag(textarea,body); -]; - -HtmlTextField(name,size,value):= -[ - textfield["name"]:=name; - textfield["size"]:=String(size); - textfield["value"]:=value; - HtmlTag(textfield,""); -]; - -HtmlSubmitButton(name,value):= -[ - button["name"]:=name; - button["value"]:=value; - HtmlTag(button,""); -]; - - -HtmlLink(description,file,tag,target):= -[ - If(tag != "", - link["href"]:= file : "#" : tag, - link["href"]:= file); - - If(target != "",link["target"] :=target); - HtmlTag(link,description); -]; - -HtmlFrameSetRows(columns,body):= -[ - frameset["cols"]:=""; - frameset["rows"]:=columns; - HtmlTag(frameset,body); -]; - -HtmlFrameSetCols(columns,body):= -[ - frameset["cols"]:=columns; - frameset["rows"]:=""; - HtmlTag(frameset,body); -]; - -HtmlFrame(source,name):= -[ - frame["src"]:=source; - frame["name"]:=name; - HtmlTag(frame,""); -]; - - -/* export a html tag type, using the specifications in the - tags assoc list. - */ -HtmlTag(tags,content):= -[ - Local(result,tag,analytics); - result:="<" : tags["0"]; - ForEach(tag,AssocIndices(tags)) - [ - If (tag != "0" And tags[tag] != "", - result:= result : " " : tag : "=" : "\"" : tags[tag] : "\"" - ); - ]; - - analytics:=""; - If(tags["0"] = "body", - analytics:=" - -"); - - - result:= result : ">" : newline : - content : newline : - analytics : "" : newline; - - result; -]; - -/* output directory management */ -htmldir:=""; -SetHtmlDirectory(dir):= [htmldir:=dir;]; -HtmlFile(file) := [htmldir : file;]; - - -/* loading and saving site info */ -site:={}; -ClearSite() := [site:={};]; -LoadSite():= -[ - FromFile("siteall") - [ - site:=Read(); - ]; -]; - -SaveSite():= -[ - ToFile("siteall") - [ - Write(site); - WriteString(";"); - ]; -]; - -MySQLQuery(pidstr,string):= -[ - Local(result); - ToFile("sqlin":pidstr) WriteString(string); - SystemCall("mysql mysql < ":"sqlin":pidstr:" > sqlout":pidstr); - SystemCall(FindFile("tools/mysqlstubs"):" sqlout":pidstr:" sqlout_":pidstr); - result:= FromFile("sqlout_":pidstr)Read(); - SystemCall("rm -rf sqlin":pidstr); - SystemCall("rm -rf sqlout":pidstr); - SystemCall("rm -rf sqlout_":pidstr); - result; -]; - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/mathpiperinit/mathpiperinit.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/mathpiperinit/mathpiperinit.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/mathpiperinit/mathpiperinit.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/mathpiperinit/mathpiperinit.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -%mathpiper,def="" - - - -/* This is the basic initialization file for MathPiper. It gets loaded - * each time MathPiper is started. All the basic files are loaded. - */ - -/* Set up drivers, configurable in the .mpiperrc - * Set(MultiNomialDriver,"org/mathpiper/assembledscripts/multivar.rep/sparsenomial.mpi"); - * or - * Set(MultiNomialDriver,"org/mathpiper/assembledscripts/multivar.rep/partialdensenomial.mpi"); - */ - -/* The truly required files (MathPiper NEEDS to load). */ -// syntax must be loaded first -Use("org/mathpiper/assembledscripts/initialization.rep/stdopers.mpi"); - -/* Set of functions to define very simple functions. There are scripts that can - be compiled to plugins. So MathPiper either loads the plugin, or loads the - scripts at this point. The functions in these plugins need to be defined with - these "Defun" functions. - */ -DefMacroRuleBase("Defun",{func,args,body}); -Rule("Defun",3,0,True) -[ - Local(nrargs); - Set(nrargs,Length(@args)); - Retract(@func, `(@nrargs)); - RuleBase(@func,@args); - Local(fn,bd); - Set(fn,Hold(@func)); Set(bd,Hold(@body)); - `Rule(@fn, @nrargs, 0,True)(@bd); -]; - -//TODO remove? Use("org/mathpiper/assembledscripts/base.rep/math.mpi"); - -Use("org/mathpiper/assembledscripts/patterns.rep/code.mpi"); -// at this point <-- can be used - -Use("org/mathpiper/assembledscripts/deffunc.rep/code.mpi"); - -// at this point := and Function() can be used - -Use("org/mathpiper/assembledscripts/constants.rep/code.mpi"); -Use("org/mathpiper/assembledscripts/initialization.rep/standard.mpi"); -Use("org/mathpiper/assembledscripts/initialization.rep/stdarith.mpi"); - -// at this point arithmetic can be used - -/* Load the def files for the other modules. The def files contain lists - * of functions defined in that file. So, in solve.def you can find the - * functions defined in the file solve. Each time a function is invoked - * for which the interpreter can not find a definition, the file is loaded. - */ - -RuleBase(LoadPackages,{packages}); -Rule(LoadPackages, 1, 1, True) -[ - If(Equals(packages,{}), True, - [ - DefLoad(First(packages)); - LoadPackages(Rest(packages)); - ]); -]; - -Use("org/mathpiper/assembledscripts/initialization.rep/packages.mpi"); -LoadPackages(DefFileList()); - - -/* The read-eval-print loop */ -RuleBase("REP",{}); -LocalSymbols(input,stringOut,result,errorString) -Rule("REP",0,1,True) -[ - Local(input,stringOut,result); - While(Not(IsExitRequested())) - [ - Set(errorString, ""); - If(And(IsString(PrettyReader'Get()),Not(PrettyReader'Get() = "")), - TrapError(Set(input, FromString(ReadCmdLineString("In> "))ApplyPure(PrettyReader'Get(),{})),Set(errorString,GetCoreError())), - TrapError(Set(input, FromString(ConcatStrings(ReadCmdLineString("In> "),";"))Read()),Set(errorString,GetCoreError()))); - If(Not(errorString = ""), WriteString(errorString)); - If (Not(IsExitRequested()) And errorString="", - [ - Set(stringOut,""); - Set(result,False); - Set(stringOut,ToString()[TrapError(Set(result,Eval(input)),Set(errorString,GetCoreError()));]); - If(Not(stringOut = ""), WriteString(stringOut)); - If(Not(errorString = ""), WriteString(errorString)); - SetGlobalLazyVariable(%,result); - If(PrettyPrinter'Get()="", - [ - Write(Atom("Out> "),result); - NewLine(); - ], - Apply(PrettyPrinter'Get(),{result})); - ]); - ]; -]; - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/miscdocs/miscellaneousdocs.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/miscdocs/miscellaneousdocs.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/miscdocs/miscellaneousdocs.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/miscdocs/miscellaneousdocs.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ - - -%mathpiper_docs,name="quit;restart",categories="User Functions;Built In" -*CMD quit --- stop MathPiper from running (from the command line) -*CMD restart --- restart MathPiper (to start with a clean slate) -*CORE -*CALL - quit - restart - -*DESC - -Type {quit} or {restart} at the MathPiper prompt to exit or to restart the interpreter. - -The directives {quit} and {restart} are not reserved words or variable names. -They take effect only when typed as first characters at a prompt. - -Pressing {Ctrl-C} will stop the currently running calculation. -If there is no currently running calculation, {Ctrl-C} will quit the interpreter. - -When the interpreter quits, it saves the command history -(so quitting by {Ctrl-C} does not mean a "crash"). - -This command is not a function but a special directive that only applies while running MathPiper interactively. It should not be used in scripts. - -*E.G. - -To be effective, the directive must be typed immediately after the prompt: - In> quit - Quitting... -We can use variables named {quit}: - In> 1+quit - Out> quit+1; -There is no effect if we type some spaces first: - In> restart - Out> restart; - -*SEE Exit -%/mathpiper_docs - - - - -%mathpiper_docs,name="%_v2",categories="Operators" -*CMD % --- previous result -*CORE -*CALL - % - -*DESC - -{%} evaluates to the previous result on the command line. {%} is a global -variable that is bound to the previous result from the command line. -Using {%} will evaluate the previous result. (This uses the functionality -offered by the {SetGlobalLazyVariable} command). - -Typical examples are {Simplify(%)} and {PrettyForm(%)} to simplify and show the result in a nice -form respectively. - -*E.G. - - In> Taylor(x,0,5)Sin(x) - Out> x-x^3/6+x^5/120; - In> PrettyForm(%) - - 3 5 - x x - x - -- + --- - 6 120 - - - -*SEE SetGlobalLazyVariable -%/mathpiper_docs - - - - - - -%mathpiper_docs,name="True;False",categories="User Functions;Constants (System)" -*CMD True --- boolean constant representing true -*CMD False --- boolean constant representing false -*CORE -*CALL - True - False - -*DESC - -{True} and {False} are typically a result -of boolean expressions such as {2 < 3} or {True And False}. - -*SEE And, Or, Not -%/mathpiper_docs - - - - - - -%mathpiper_docs,name="EndOfFile",categories="User Functions;Constants (System)" -*CMD EndOfFile --- end-of-file marker -*CORE -*CALL - EndOfFile - -*DESC - -End of file marker when reading from file. If a file -contains the expression {EndOfFile;} the -operation will stop reading the file at that point. -%/mathpiper_docs - - - - - -%mathpiper_docs,name="Infinity",categories="User Functions;Constants (Mathematical)" - -*CMD Infinity --- constant representing mathematical infinity -*STD -*CALL - Infinity - -*DESC - -Infinity represents infinitely large values. It can be the result of certain -calculations. - -Note that for most analytic functions MathPiper understands {Infinity} as a positive number. -Thus {Infinity*2} will return {Infinity}, and {a < Infinity} will evaluate to {True}. - -*E.G. - - In> 2*Infinity - Out> Infinity; - In> 2 True; -%/mathpiper_docs - - - - - -%mathpiper_docs,name="Undefined",categories="User Functions;Constants (Mathematical)" -*CMD Undefined --- constant signifying an undefined result -*STD -*CALL - Undefined - -*DESC - -{Undefined} is a token that can be returned by a function when it considers -its input to be invalid or when no meaningful answer can be given. The result is then "undefined". - -Most functions also return {Undefined} when evaluated on it. - -*E.G. - - In> 2*Infinity - Out> Infinity; - In> 0*Infinity - Out> Undefined; - In> Sin(Infinity); - Out> Undefined; - In> Undefined+2*Exp(Undefined); - Out> Undefined; - -*SEE Infinity -%/mathpiper_docs - - - - -%mathpiper_docs,name="/*;*/;//",categories="Operators" -*CMD /* --- Start of comment -*CMD */ --- end of comment -*CMD // --- Beginning of one-line comment -*CORE -*CALL - /* comment */ - // comment - -*DESC - -Introduce a comment block in a source file, similar to C++ comments. -{//} makes everything until the end of the line a comment, while {/*} and {*/} may delimit a multi-line comment. - -*E.G. - - a+b; // get result - a + /* add them */ b; -%/mathpiper_docs - - - - -%mathpiper_docs,name="[;]",categories="Operators" -*CMD [ --- beginning of block of statements -*CMD ] --- end of block of statements -*CORE -*CALL - - [ statement1; statement2; ... ] - -*PARMS - -{statement1}, {statement2} -- expressions - -*DESC - -The {Prog} and the {[ ... ]} construct have the same effect: they evaluate all -arguments in order and return the result of the last evaluated expression. - -{Prog(a,b);} is the same as typing {[a;b;];} and is very useful for writing out -function bodies. The {[ ... ]} construct is a syntactically nicer version of the -{Prog} call; it is converted into {Prog(...)} during the parsing stage. - -*SEE Prog -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/ampersand_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/ampersand_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/ampersand_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/ampersand_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="&" - -a_IsNonNegativeInteger & b_IsNonNegativeInteger <-- BitAnd(a,b); - -%/mathpiper - - - - -%mathpiper_docs,name="&",categories="Operators" -*CMD --- bitwise AND operator -*STD -*CALL - a & b - -*PARMS - -{a} -- non negative integer - -{b} -- non negative integer - -*DESC - -This operator performs a bitwise AND on two integers. - -*E.G. - -In> 15 & 4 -Result: 4 - -*SEE | -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/A_Nth.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/A_Nth.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/A_Nth.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/A_Nth.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -%mathpiper,def="Nth" - -/* Implementation of Nth that allows extending. */ -RuleBase("Nth",{alist,aindex}); -Rule("Nth",2,10, - And(Equals(IsFunction(alist),True), - Equals(IsInteger(aindex),True), - Not(Equals(First(Listify(alist)),Nth)) - )) - MathNth(alist,aindex); - - - - -Rule("Nth",2,14, - And(Equals(IsString(alist),True),IsList(aindex)) - ) -[ - Local(result); - result:=""; - ForEach(i,aindex) [ result := result : StringMidGet(i,1,alist); ]; - result; -]; - -Rule("Nth",2,15,Equals(IsString(alist),True)) -[ - StringMidGet(aindex,1,alist); -]; - - -Rule("Nth",2,20,Equals(IsList(aindex),True)) -[ - Map({{ii},alist[ii]},{aindex}); -]; - -Rule("Nth",2,30, - And( - Equals(IsGeneric(alist),True), - Equals(GenericTypeName(alist),"Array"), - Equals(IsInteger(aindex),True) - ) - ) -[ - ArrayGet(alist,aindex); -]; - - - -Rule("Nth",2,40,Equals(IsString(aindex),True)) -[ - Local(as); - as := Assoc(aindex,alist); - If (Not(Equals(as,Empty)),Set(as,Nth(as,2))); - as; -]; - - -%/mathpiper - - - -%mathpiper_docs,name="Nth",categories="User Functions;Lists (Operations)" -*CMD Nth --- return the $n$-th element of a list -*CORE -*CALL - Nth(list, n) - -*PARMS - -{list} -- list to choose from - -{n} -- index of entry to pick - -*DESC - -The entry with index "n" from "list" is returned. The first entry -has index 1. It is possible to pick several entries of the list by -taking "n" to be a list of indices. - -More generally, {Nth} returns the n-th operand of the -expression passed as first argument. - -An alternative but equivalent form of {Nth(list, n)} is -{list[n]}. - -*E.G. - - In> lst := {a,b,c,13,19}; - Out> {a,b,c,13,19}; - In> Nth(lst, 3); - Out> c; - In> lst[3]; - Out> c; - In> Nth(lst, {3,4,1}); - Out> {c,13,a}; - In> Nth(b*(a+c), 2); - Out> a+c; - -*SEE Select, Nth -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/B_NrArgs.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/B_NrArgs.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/B_NrArgs.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/B_NrArgs.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="NrArgs" - -Function("NrArgs",{aLeft}) Length(Listify(aLeft))-1; - -%/mathpiper - - - - -%mathpiper_docs,name="NrArgs",categories="User Functions;Lists (Operations)" -*CMD NrArgs --- return number of top-level arguments -*STD -*CALL - NrArgs(expr) - -*PARMS - -{expr} -- expression to examine - -*DESC - -This function evaluates to the number of top-level arguments of the -expression "expr". The argument "expr" may not be an atom, since -that would lead to an error. - -*E.G. - - In> NrArgs(f(a,b,c)) - Out> 3; - In> NrArgs(Sin(x)); - Out> 1; - In> NrArgs(a*(b+c)); - Out> 2; - -*SEE Type, Length -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/Denominator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/Denominator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/Denominator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/Denominator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="Denominator" - -1 # Denominator(_x / _y) <-- y; -2 # Denominator(x_IsNumber) <-- 1; - -%/mathpiper - - - -%mathpiper_docs,name="Denominator",categories="User Functions;Numbers (Operations)" -*CMD Denominator --- denominator of an expression -*STD -*CALL - Denominator(expr) - -*PARMS - -{expr} -- expression to determine denominator of - -*DESC - -This function determines the denominator of the rational expression -"expr" and returns it. As a special case, if its argument is numeric -but not rational, it returns {1}. If "expr" is -neither rational nor numeric, the function returns unevaluated. - -*E.G. - - In> Denominator(2/7) - Out> 7; - In> Denominator(a / x^2) - Out> x^2; - In> Denominator(5) - Out> 1; - -*SEE Numerator, IsRational, IsNumber -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/equals_equals_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/equals_equals_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/equals_equals_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/equals_equals_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="==" - -RuleBase("==",{left,right}); - -%/mathpiper - - - - -%mathpiper_docs,name="==",categories="Operators" -*CMD == --- symbolic equality operator -*STD -*CALL - expression == expression - -*PARMS - -{expression} -- an expression - -*DESC - -This operator is used to symbolically represent the equality -of two expressions as opposed to the = operator which performs -a comparison operation on two expressions. - -*E.G. - -In> Solve(y == m*x + b, x) -Result: {x==(y-b)/m} - -*SEE !== -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/exclamationpoint_equals_equals_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/exclamationpoint_equals_equals_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/exclamationpoint_equals_equals_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/exclamationpoint_equals_equals_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -%mathpiper,def="!==" - -RuleBase("!==",{left,right}); - -%/mathpiper - - - - -%mathpiper_docs,name="!==",categories="Operators" -*CMD !== --- symbolic inequality operator -*STD -*CALL - expression !== expression - -*PARMS - -{expression} -- an expression - -*DESC - -This operator is used to symbolically represent the inequality -of two expressions as opposed to the != operator which performs -a comparison operation on two expressions. - - -*SEE == -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/IsNonObject.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/IsNonObject.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/IsNonObject.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/IsNonObject.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsNonObject" - -10 # IsNonObject(Object(_x)) <-- False; -20 # IsNonObject(_x) <-- True; - -%/mathpiper - - - - - -%mathpiper_docs,name="IsNonObject",categories="User Functions;Predicates" -*CMD IsNonObject --- test whether argument is not an {Object()} -*STD -*CALL - IsNonObject(expr) - -*PARMS - -{expr} -- the expression to examine - -*DESC - -This function returns {True} if "expr" is not of -the form {Object(...)} and {False} -otherwise. - -*HEAD Bugs - -In fact, the result is always {True}. - -*SEE Object -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/minus_minus_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/minus_minus_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/minus_minus_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/minus_minus_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="--" - -Function("--",{aVar}) -[ - MacroSet(aVar,SubtractN(Eval(aVar),1)); -]; - -UnFence("--",1); - -HoldArg("--",aVar); - -%/mathpiper - - - - -%mathpiper_docs,name="--",categories="Operators" -*CMD -- --- decrement variable -*STD -*CALL - var-- - -*PARMS - -{var} -- variable to decrement - -*DESC - -The variable with name "var" is decremented, i.e. the number 1 is -subtracted from it. The expression {x--} is -equivalent to the assignment {x := x - 1}, except -that the assignment returns the new value of {x} -while {x--} always returns true. In this respect, -MathPiper' {--} differs from the corresponding operator -in the programming language C. - -*E.G. - - In> x := 5; - Out> 5; - In> x--; - Out> True; - In> x; - Out> 4; - -*SEE ++, := -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/NormalForm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/NormalForm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/NormalForm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/NormalForm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="NormalForm" - -RuleBase("NormalForm",{expression}); -Rule("NormalForm",1,1000,True) expression; - -%/mathpiper - - - - -%mathpiper_docs,name="NormalForm",categories="User Functions;Lists (Operations)" -*CMD NormalForm --- return expression in normal form -*STD -*CALL - NormalForm(expression) - -*PARMS - -{expression} -- an expression - -*DESC - -This functions returns an expression in normal form. - - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/Numerator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/Numerator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/Numerator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/Numerator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -%mathpiper,def="Numerator" - -1 # Numerator(_x / _y) <-- x; -2 # Numerator(x_IsNumber) <-- x; - -%/mathpiper - - - - -%mathpiper_docs,name="Numerator",categories="User Functions;Numbers (Operations)" -*CMD Numerator --- numerator of an expression -*STD -*CALL - Numerator(expr) - -*PARMS - -{expr} -- expression to determine numerator of - -*DESC - -This function determines the numerator of the rational expression -"expr" and returns it. As a special case, if its argument is numeric -but not rational, it returns this number. If "expr" is neither -rational nor numeric, the function returns unevaluated. - -*E.G. - - In> Numerator(2/7) - Out> 2; - In> Numerator(a / x^2) - Out> a; - In> Numerator(5) - Out> 5; - -*SEE Denominator, IsRational, IsNumber -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/numeric.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/numeric.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/numeric.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/numeric.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,216 +0,0 @@ -%mathpiper,def="N;NonN;InNumericMode" - -//"+-;/-;*-;^-;:=-;:=+" These were in the def list. - -/* See the documentation on the assignment of the precedence of the rules. - */ - -/* Some very basic functions that are used always any way... */ - - - - - - - -/* Implementation of numeric mode */ -LocalSymbols(numericMode) -[ - - Set(numericMode, False); - - - // N function: evaluate numerically with given precision. - LocalSymbols(previousNumericMode, previousPrecision, numericResult) Macro("N",{expression, precision}) - [ - // we were in non-numeric mode - - Local(previousNumericMode, previousPrecision, numericResult, errorString); - - Set(previousPrecision, BuiltinPrecisionGet()); - - BuiltinPrecisionSet(@precision); - - AssignCachedConstantsN(); - - Set(previousNumericMode, numericMode); - - Set(numericMode, True); - - Set(errorString,""); - - TrapError(Set(numericResult, Eval(@expression)),Set(errorString,GetCoreError())); - - Set(numericMode,previousNumericMode); - - If(Not numericMode, - [ - // clear constants - ClearCachedConstantsN(); - ]); - - BuiltinPrecisionSet(previousPrecision); - - Check(errorString="",errorString); - - numericResult; - - ]; - - - - - // N function: evaluate numerically with default precision. - LocalSymbols(precision,heldExpression) Macro("N",{expression}) - [ - Local(precision, heldExpression); - - Set(precision, BuiltinPrecisionGet()); - - Set(heldExpression, Hold(@expression)); - - `N(@heldExpression, @precision); - ]; - - - - - - // NoN function. - LocalSymbols(result) Macro("NonN",{expression}) - [ - Local(result); - - GlobalPush(numericMode); - - numericMode := False; - - result := (@expression); - - numericMode := GlobalPop(); - - result; - ]; - - - // InNumericMode function. - Function("InNumericMode",{}) numericMode; - - - -]; //LocalSymbols(numericMode) - - - - - - -%/mathpiper - - - - - - -%mathpiper_docs,name="N",categories="User Functions;Numbers (Operations)" -*CMD N --- try to determine an numerical approximation of expression - -*STD -*CALL - N(expression) - N(expression, precision) -*PARMS - -{expression} -- expression to evaluate - -{precision} -- integer, precision to use - -*DESC - -The function {N} instructs {MathPiper} to try to coerce an expression in to a numerical approximation to the -expression {expr}, using {prec} digits precision if the second calling -sequence is used, and the default precision otherwise. This overrides the normal -behaviour, in which expressions are kept in symbolic form (eg. {Sqrt(2)} instead of {1.41421}). - -Application of the {N} operator will make MathPiper -calculate floating point representations of functions whenever -possible. In addition, the variable {Pi} is bound to -the value of $Pi$ calculated at the current precision. -(This value is a "cached constant", so it is not recalculated each time {N} is used, unless the precision is increased.) - - -{N} is a macro. Its argument {expr} will only -be evaluated after switching to numeric mode. - -*E.G. - - In> 1/2 - Out> 1/2; - In> N(1/2) - Out> 0.5; - In> Sin(1) - Out> Sin(1); - In> N(Sin(1),10) - Out> 0.8414709848; - In> Pi - Out> Pi; - In> N(Pi,20) - Out> 3.14159265358979323846; - -*SEE Pi -%/mathpiper_docs - - - - - - - - -%mathpiper_docs,name="InNumericMode;NonN" -*CMD InNumericMode --- determine if currently in numeric mode -*CMD NonN --- calculate part in non-numeric mode - -*STD -*CALL - NonN(expr) - InNumericMode() -*PARMS - -{expr} -- expression to evaluate - -{prec} -- integer, precision to use - -*DESC - -When in numeric mode, {InNumericMode()} will return {True}, else it will -return {False}. {MathPiper} is in numeric mode when evaluating an expression -with the function {N}. Thus when calling {N(expr)}, {InNumericMode()} will -return {True} while {expr} is being evaluated. - -{InNumericMode()} would typically be used to define a transformation rule -that defines how to get a numeric approximation of some expression. One -could define a transformation rule - - f(_x)_InNumericMode() <- [... some code to get a numeric approximation of f(x) ... ]; - -{InNumericMode()} usually returns {False}, so transformation rules that check for this -predicate are usually left alone. - -When in numeric mode, {NonN} can be called to switch back to non-numeric -mode temporarily. - -{NonN} is a macro. Its argument {expr} will only -be evaluated after the numeric mode has been set appropriately. - -*E.G. - - In> InNumericMode() - Out> False - In> N(InNumericMode()) - Out> True - In> N(NonN(InNumericMode())) - Out> False - -*SEE N, BuiltinPrecisionSet, BuiltinPrecisionGet, Pi, CachedConstant -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/percent_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/percent_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/percent_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/percent_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="%" - -a_IsNonNegativeInteger % b_IsPositiveInteger <-- Mod(a,b); - -%/mathpiper - - - - -%mathpiper_docs,name="%_v1",categories="Operators" -*CMD % --- modulus operator -*STD -*CALL - a % b - -*PARMS - -{a} -- non negative integer - -{b} -- non negative integer - -*DESC - -Divides a by b and returns the remainder of the division. - -*E.G. -In> 8 % 5 -Result: 3 - -*SEE / -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/plus_plus_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/plus_plus_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/plus_plus_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/plus_plus_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="++" - -Function("++",{aVar}) -[ - MacroSet(aVar,AddN(Eval(aVar),1)); -]; - -UnFence("++",1); - -HoldArg("++",aVar); - -%/mathpiper - - - - -%mathpiper_docs,name="++",categories="Operators" -*CMD ++ --- increment variable -*STD -*CALL - var++ - -*PARMS - -{var} -- variable to increment - -*DESC - -The variable with name "var" is incremented, i.e. the number 1 is -added to it. The expression {x++} is equivalent to -the assignment {x := x + 1}, except that the -assignment returns the new value of {x} while {x++} always returns true. In this respect, MathPiper' {++} differs from the corresponding operator in the -programming language C. - -*E.G. - - In> x := 5; - Out> 5; - In> x++; - Out> True; - In> x; - Out> 6; - -*SEE --, := -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/vertical_bar_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/vertical_bar_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/standard/vertical_bar_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/standard/vertical_bar_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="|" - -a_IsNonNegativeInteger | b_IsNonNegativeInteger <-- BitOr(a,b); - -%/mathpiper - - - - -%mathpiper_docs,name="|",categories="Operators" -*CMD --- bitwise OR operator -*STD -*CALL - a | b - -*PARMS - -{a} -- non negative integer - -{b} -- non negative integer - -*DESC - -This operator performs a bitwise OR on two integers. - -*E.G. - -In> 3 | 4 -Result: 7 - -*SEE & -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/asterisk_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/asterisk_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/asterisk_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/asterisk_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,130 +0,0 @@ -%mathpiper,def="*" - -/* Multiplication */ - -50 # x_IsNumber * y_IsNumber <-- MultiplyN(x,y); -100 # 1 * _x <-- x; -100 # _x * 1 <-- x; -100 # (_f * _x)_(f= -1) <-- -x; -100 # (_x * _f)_(f= -1) <-- -x; -105 # (f_IsNegativeNumber * _x) <-- -(-f)*x; -105 # (_x * f_IsNegativeNumber) <-- -(-f)*x; - -95 # x_IsMatrix * y_IsMatrix <-- -[ - Local(i,j,k,row,result); - result:=ZeroMatrix(Length(x),Length(y[1])); - For(i:=1,i<=Length(x),i++) - For(j:=1,j<=Length(y),j++) - For(k:=1,k<=Length(y[1]),k++) - [ - row:=result[i]; - row[k]:= row[k]+x[i][j]*y[j][k]; - ]; - result; -]; - - -96 # x_IsMatrix * y_IsList <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(x),i++) - [ DestructiveInsert(result,i,x[i] . y); ]; - result; -]; - - -97 # (x_IsList * y_IsNonObject)_Not(IsList(y)) <-- y*x; -98 # (x_IsNonObject * y_IsList)_Not(IsList(x)) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x * y[i]); ]; - result; -]; - - -50 # _x * Undefined <-- Undefined; -50 # Undefined * _y <-- Undefined; - - -100 # 0 * Infinity <-- Undefined; -100 # Infinity * 0 <-- Undefined; - -101 # 0 * (_x) <-- 0; -101 # (_x) * 0 <-- 0; - -100 # x_IsNumber * (y_IsNumber * _z) <-- (x*y)*z; -100 # x_IsNumber * (_y * z_IsNumber) <-- (x*z)*y; - -100 # (_x * _y) * _y <-- x * y^2; -100 # (_x * _y) * _x <-- y * x^2; -100 # _y * (_x * _y) <-- x * y^2; -100 # _x * (_x * _y) <-- y * x^2; -100 # _x * (_y / _z) <-- (x*y)/z; -// fractions -100 # (_y / _z) * _x <-- (x*y)/z; -100 # (_x * y_IsNumber)_Not(IsNumber(x)) <-- y*x; - -100 # (_x) * (_x) ^ (n_IsConstant) <-- x^(n+1); -100 # (_x) ^ (n_IsConstant) * (_x) <-- x^(n+1); -100 # (_x * _y)* _x ^ n_IsConstant <-- y * x^(n+1); -100 # (_y * _x)* _x ^ n_IsConstant <-- y * x^(n+1); - -105 # x_IsNumber * -(_y) <-- (-x)*y; -105 # (-(_x)) * (y_IsNumber) <-- (-y)*x; - -106 # _x * -(_y) <-- -(x*y); -106 # (- _x) * _y <-- -(x*y); - -107 # -( (-(_x))/(_y)) <-- x/y; -107 # -( (_x)/(-(_y))) <-- x/y; - - -250 # x_IsNumber * y_IsInfinity <-- Sign(x)*y; -250 # x_IsInfinity * y_IsNumber <-- Sign(y)*x; - - -/* Note: this rule MUST be past all the transformations on - * matrices, since they are lists also. - */ -230 # (aLeft_IsList * aRight_IsList)_(Length(aLeft)=Length(aRight)) <-- - Map("*",{aLeft,aRight}); -// fractions -242 # (x_IsInteger / y_IsInteger) * (v_IsInteger / w_IsInteger) <-- (x*v)/(y*w); -243 # x_IsInteger * (y_IsInteger / z_IsInteger) <-- (x*y)/z; -243 # (y_IsInteger / z_IsInteger) * x_IsInteger <-- (x*y)/z; - -400 # (_x) * (_x) <-- x^2; - -%/mathpiper - - -%mathpiper_docs,name="*",categories="Operators" -*CMD * --- arithmetic multiplication -*STD -*CALL - - x*y -Precedence: -*EVAL OpPrecedence("*") - -*PARMS - -{x} and {y} -- objects for which arithmetic multiplication is defined - -*DESC - -The multiplication operator can work on integers, -rational numbers, complex numbers, vectors, matrices and lists. - -This operator is implemented in the standard math library (as opposed -to being built-in). This means that they can be extended by the user. - -*E.G. - - In> 2*3 - Out> 6; -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/caret_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/caret_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/caret_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/caret_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -%mathpiper,def="^" - -/* Faster version of raising power to 0.5 */ -50 # _x ^ (1/2) <-- Sqrt(x); -50 # (x_IsPositiveNumber ^ (1/2))_IsInteger(SqrtN(x)) <-- SqrtN(x); -58 # 1 ^ n_IsInfinity <-- Undefined; -59 # _x ^ 1 <-- x; -59 # 1 ^ _n <-- 1; -59 # x_IsZero ^ y_IsZero <-- Undefined; -60 # (x_IsZero ^ n_IsRationalOrNumber)_(n>0) <-- 0; -60 # (x_IsZero ^ n_IsRationalOrNumber)_(n<0) <-- Infinity; -// This is to fix: -// In> 0.0000^2 -// Out> 0.0000^2; -// In> 0.0^2/2 -// Out> 0.0^2/2; -//60 # (x_IsNumber ^ n_IsRationalOrNumber)_(x+1=1) <-- 0; - -59 # _x ^ Undefined <-- Undefined; -59 # Undefined ^ _x <-- Undefined; - -/* Regular raising to the power. */ -61 # Infinity ^ (y_IsNegativeNumber) <-- 0; -61 # (-Infinity) ^ (y_IsNegativeNumber) <-- 0; -//61 # x_IsPositiveNumber ^ y_IsPositiveNumber <-- PowerN(x,y); -//61 # x_IsPositiveNumber ^ y_IsNegativeNumber <-- (1/PowerN(x,-y)); -// integer powers are very fast -61 # x_IsPositiveNumber ^ y_IsPositiveInteger <-- MathIntPower(x,y); -61 # x_IsPositiveNumber ^ y_IsNegativeInteger <-- 1/MathIntPower(x,-y); -65 # (x_IsPositiveNumber ^ y_IsNumber)_InNumericMode() <-- Exp(y*Ln(x)); - -90 # (-_x)^m_IsEven <-- x^m; -91 # (x_IsConstant ^ (m_IsOdd / p_IsOdd))_(IsNegativeNumber(Re(N(Eval(x))))) <-- - -((-x)^(m/p)); -92 # (x_IsNegativeNumber ^ y_IsNumber)_InNumericMode() <-- Exp(y*Ln(x)); - - -70 # (_x ^ m_IsRationalOrNumber) ^ n_IsRationalOrNumber <-- x^(n*m); - -80 # (x_IsNumber/y_IsNumber) ^ n_IsPositiveInteger <-- x^n/y^n; -80 # (x_IsNumber/y_IsNumber) ^ n_IsNegativeInteger <-- y^(-n)/x^(-n); -80 # x_IsNegativeNumber ^ n_IsEven <-- (-x)^n; -80 # x_IsNegativeNumber ^ n_IsOdd <-- -((-x)^n); - - -100 # ((_x)*(_x ^ _m)) <-- x^(m+1); -100 # ((_x ^ _m)*(_x)) <-- x^(m+1); -100 # ((_x ^ _n)*(_x ^ _m)) <-- x^(m+n); - -100 # ((x_IsNumber)^(n_IsInteger/(_m)))_(n>1) <-- MathIntPower(x,n)^(1/m); - -100 # Sqrt(_n)^(m_IsEven) <-- n^(m/2); - - -200 # x_IsMatrix ^ n_IsPositiveInteger <-- x*(x^(n-1)); -204 # (xlist_IsList ^ nlist_IsList)_(Length(xlist)=Length(nlist)) <-- - Map("^",{xlist,nlist}); -205 # (xlist_IsList ^ n_IsConstant)_(Not(IsList(n))) <-- - Map({{xx},xx^n},{xlist}); -206 # (_x ^ n_IsList)_(Not(IsList(x))) <-- Map({{xx},x^xx},{n}); -249 # x_IsInfinity ^ 0 <-- Undefined; -250 # Infinity ^ (_n) <-- Infinity; -250 # Infinity ^ (_x_IsComplex) <-- Infinity; -250 # ((-Infinity) ^ (n_IsNumber))_(IsEven(n)) <-- Infinity; -250 # ((-Infinity) ^ (n_IsNumber))_(IsOdd(n)) <-- -Infinity; - -250 # (x_IsNumber ^ Infinity)_(x> -1 And x < 1) <-- 0; -250 # (x_IsNumber ^ Infinity)_(x> 1) <-- Infinity; - -// these Magnitude(x)s should probably be changed to Abs(x)s - -250 # (x_IsComplex ^ Infinity)_(Magnitude(x) > 1) <-- Infinity; -250 # (x_IsComplex ^ Infinity)_(Magnitude(x) < -1) <-- -Infinity; -250 # (x_IsComplex ^ Infinity)_(Magnitude(x) > -1 And Magnitude(x) < 1) <-- 0; - -250 # (x_IsNumber ^ -Infinity)_(x> -1 And x < 1) <-- Infinity; -250 # (x_IsNumber ^ -Infinity)_(x< -1) <-- 0; -250 # (x_IsNumber ^ -Infinity)_(x> 1) <-- 0; - -255 # (x_IsComplex ^ Infinity)_(Abs(x) = 1) <-- Undefined; -255 # (x_IsComplex ^ -Infinity)_(Abs(x) = 1) <-- Undefined; - - - -400 # _x ^ 0 <-- 1; - -%/mathpiper - - -%mathpiper_docs,name="^",categories="Operators" -*CMD ^ --- arithmetic power -*STD -*CALL - - x^y -Precedence: -*EVAL OpPrecedence("^") - -*PARMS - -{x} and {y} -- objects for which arithmetic operations are defined - -*DESC - -These are the basic arithmetic operations. They can work on integers, -rational numbers, complex numbers, vectors, matrices and lists. - -These operators are implemented in the standard math library (as opposed -to being built-in). This means that they can be extended by the user. - -*E.G. - - In> 2^3 - Out> 8; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/minus_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/minus_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/minus_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/minus_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -%mathpiper,def="-" - -/* Subtraction arity 1 */ - -//50 # -0 <-- 0; -51 # -Undefined <-- Undefined; -54 # - (- _x) <-- x; -55 # (- (x_IsNumber)) <-- SubtractN(0,x); -100 # _x - n_IsConstant*(_x) <-- (1-n)*x; -100 # n_IsConstant*(_x) - _x <-- (n-1)*x; - -110 # - (_x - _y) <-- y-x; -111 # - (x_IsNumber / _y) <-- (-x)/y; -LocalSymbols(x) -[ - 200 # - (x_IsList) <-- MapSingle("-",x); -]; - -/* Subtraction arity 2 */ -50 # x_IsNumber - y_IsNumber <-- SubtractN(x,y); -50 # x_IsNumber - y_IsNumber <-- SubtractN(x,y); -60 # Infinity - Infinity <-- Undefined; -100 # 0 - _x <-- -x; -100 # _x - 0 <-- x; -100 # _x - _x <-- 0; - -110 # _x - (- _y) <-- x + y; -110 # _x - (y_IsNegativeNumber) <-- x + (-y); -111 # (_x + _y)- _x <-- y; -111 # (_x + _y)- _y <-- x; -112 # _x - (_x + _y) <-- - y; -112 # _y - (_x + _y) <-- - x; -113 # (- _x) - _y <-- -(x+y); -113 # (x_IsNegativeNumber) - _y <-- -((-x)+y); -113 # (x_IsNegativeNumber)/_y - _z <-- -((-x)/y+z); - - -/* TODO move to this precedence everywhere? */ -LocalSymbols(x,y,xarg,yarg) -[ - 10 # ((x_IsList) - (y_IsList))_(Length(x)=Length(y)) <-- - [ - Map({{xarg,yarg},xarg-yarg},{x,y}); - ]; -]; - -240 # (x_IsList - y_IsNonObject)_Not(IsList(y)) <-- -(y-x); - -241 # (x_IsNonObject - y_IsList)_Not(IsList(x)) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x - y[i]); ]; - result; -]; - -250 # z_IsInfinity - Complex(_x,_y) <-- Complex(-x+z,-y); -250 # Complex(_x,_y) - z_IsInfinity <-- Complex(x-z,y); - -251 # z_IsInfinity - _x <-- z; -251 # _x - z_IsInfinity <-- -z; - -250 # Undefined - _y <-- Undefined; -250 # _x - Undefined <-- Undefined; -// fractions -210 # x_IsNumber - (y_IsNumber / z_IsNumber) <--(x*z-y)/z; -210 # (y_IsNumber / z_IsNumber) - x_IsNumber <--(y-x*z)/z; -210 # (x_IsNumber / v_IsNumber) - (y_IsNumber / z_IsNumber) <--(x*z-y*v)/(v*z); - -%/mathpiper - - -%mathpiper_docs,name="-",categories="Operators" -*CMD - --- arithmetic subtraction or negation -*STD -*CALL - - x-y -Precedence: left-side: -*EVAL OpPrecedence("-") -, right-side: -*EVAL OpRightPrecedence("-") - - -x - -*PARMS - -{x} and {y} -- objects for which subtraction is defined - -*DESC - -The subtraction operators can work on integers, -rational numbers, complex numbers, vectors, matrices and lists. - -These operators are implemented in the standard math library (as opposed -to being built-in). This means that they can be extended by the user. - -*E.G. - - In> 2-3 - Out> -1; - In> - 3 - Out> -3; -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/plus_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/plus_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/plus_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/plus_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -%mathpiper,def="+" - -/* Addition */ - -100 # + _x <-- x; - -50 # x_IsNumber + y_IsNumber <-- AddN(x,y); - -100 # 0 + _x <-- x; -100 # _x + 0 <-- x; -100 # _x + _x <-- 2*x; -100 # _x + n_IsConstant*(_x) <-- (n+1)*x; -100 # n_IsConstant*(_x) + _x <-- (n+1)*x; -101 # _x + - _y <-- x-y; -101 # _x + (- _y)/(_z) <-- x-(y/z); -101 # (- _y)/(_z) + _x <-- x-(y/z); -101 # (- _x) + _y <-- y-x; -102 # _x + y_IsNegativeNumber <-- x-(-y); -102 # _x + y_IsNegativeNumber * _z <-- x-((-y)*z); -102 # _x + (y_IsNegativeNumber)/(_z) <-- x-((-y)/z); -102 # (y_IsNegativeNumber)/(_z) + _x <-- x-((-y)/z); -102 # (x_IsNegativeNumber) + _y <-- y-(-x); -// fractions -150 # _n1 / _d + _n2 / _d <-- (n1+n2)/d; - -200 # (x_IsNumber + _y)_Not(IsNumber(y)) <-- y+x; -200 # ((_y + x_IsNumber) + _z)_Not(IsNumber(y) Or IsNumber(z)) <-- (y+z)+x; -200 # ((x_IsNumber + _y) + z_IsNumber)_Not(IsNumber(y)) <-- y+(x+z); -200 # ((_x + y_IsNumber) + z_IsNumber)_Not(IsNumber(x)) <-- x+(y+z); -// fractions -210 # x_IsNumber + (y_IsNumber / z_IsNumber) <--(x*z+y)/z; -210 # (y_IsNumber / z_IsNumber) + x_IsNumber <--(x*z+y)/z; -210 # (x_IsNumber / v_IsNumber) + (y_IsNumber / z_IsNumber) <--(x*z+y*v)/(v*z); - - -// 220 # + x_IsList <-- MapSingle("+",x); // this rule is never active - -220 # (xlist_IsList + ylist_IsList)_(Length(xlist)=Length(ylist)) <-- Map("+",{xlist,ylist}); - -SumListSide(_x, y_IsList) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x + y[i]); ]; - result; -]; - -240 # (x_IsList + _y)_Not(IsList(y)) <-- SumListSide(y,x); -241 # (_x + y_IsList)_Not(IsList(x)) <-- SumListSide(x,y); - -250 # z_IsInfinity + Complex(_x,_y) <-- Complex(x+z,y); -250 # Complex(_x,_y) + z_IsInfinity <-- Complex(x+z,y); - -251 # z_IsInfinity + _x <-- z; -251 # _x + z_IsInfinity <-- z; - - -250 # Undefined + _y <-- Undefined; -250 # _x + Undefined <-- Undefined; - -%/mathpiper - - - - -%mathpiper,scope="nobuild",subtype="test_suite" -//This fold is used to test the + operator. - Verify(3 + 2 , 5); -%/mathpiper - - - -%mathpiper_docs,name="+",categories="Operators" -*CMD + --- arithmetic addition -*STD -*CALL - - x+y - +x -Precedence: -*EVAL OpPrecedence("+") - -*PARMS - -{x} and {y} -- objects for which arithmetic addition is defined - - -*DESC - -The addition operators can work on integers, -rational numbers, complex numbers, vectors, matrices and lists. - -These operators are implemented in the standard math library (as opposed -to being built-in). This means that they can be extended by the user. - -*E.G. - - In> 2+3 - Out> 5; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/slash_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/slash_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdarith/slash_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdarith/slash_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -%mathpiper,def="/" - -/* Division */ - -50 # 0 / 0 <-- Undefined; - -52 # x_IsPositiveNumber / 0 <-- Infinity; -52 # x_IsNegativeNumber / 0 <-- -Infinity; -55 # (_x / y_IsNumber)_(IsZero(y)) <-- Undefined; -55 # 0 / _x <-- 0; -60 # (x_IsNumber / y_IsNumber)_(InNumericMode() /* Sorry, Serge Or - Not(IsInteger(x) And IsInteger(y)) */ ) <-- - DivideN(x,y); - -// unnecessary rule (see #100 below). TODO: REMOVE -//55 # x_IsNumber / y_IsNegativeNumber <-- (-x)/(-y); - -56 # (x_IsNonZeroInteger / y_IsNonZeroInteger)_(GcdN(x,y) > 1) <-- - [ - Local(gcd); - Set(x,x); - Set(y,y); - Set(gcd,GcdN(x,y)); - DivN(x,gcd)/DivN(y,gcd); - ]; - - -90 # x_IsInfinity / y_IsInfinity <-- Undefined; -95 # x_IsInfinity / y_IsNumber <-- Sign(y)*x; -95 # x_IsInfinity / y_IsComplex <-- Infinity; - -90 # Undefined / _y <-- Undefined; -90 # _y / Undefined <-- Undefined; - - -100 # _x / _x <-- 1; -100 # _x / 1 <-- x; -100 # (_x / y_IsNegativeNumber) <-- -x/(-y); -100 # (_x / - _y) <-- -x/y; -// fractions -200 # (_x / _y)/ _z <-- x/(y*z); -230 # _x / (_y / _z) <-- (x*z)/y; - -240 # (xlist_IsList / ylist_IsList)_(Length(xlist)=Length(ylist)) <-- - Map("/",{xlist,ylist}); - - -250 # (x_IsList / _y)_(Not(IsList(y))) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(x),i++) - [ DestructiveInsert(result,i,x[i] / y); ]; - result; -]; - -250 # (_x / y_IsList)_(Not(IsList(x))) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x/y[i]); ]; - result; -]; - -250 # _x / Infinity <-- 0; -250 # _x / (-Infinity) <-- 0; - - -400 # 0 / _x <-- 0; - -%/mathpiper - - -%mathpiper_docs,name="/",categories="Operators" -*CMD / --- arithmetic division -*STD -*CALL - - x/y -Precedence: -*EVAL OpPrecedence("/") - -*PARMS - -{x} and {y} -- objects for which arithmetic division is defined - -*DESC - -The division operator can work on integers, -rational numbers, complex numbers, vectors, matrices and lists. - -This operator is implemented in the standard math library (as opposed -to being built-in). This means that they can be extended by the user. - -*E.G. - - In> 6/2 - Out> 3; - -*SEE %_v1 -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdopers/stdopers.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdopers/stdopers.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/initialization/stdopers/stdopers.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/initialization/stdopers/stdopers.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,121 +0,0 @@ -%mathpiper,def="" - - -/* stdopers is loaded immediately after MathPiper is started. It contains - * the definitions of the infix operators, so the parser can already - * parse expressions containing these operators, even though the - * function hasn't been defined yet. - */ - -Infix("=",90); -Infix("And",1000); -RightAssociative("And"); -Infix("Or", 1010); -Prefix("Not", 100); -Infix("<",90); -Infix(">",90); -Infix("<=",90); -Infix(">=",90); -Infix("!=",90); - -Infix(":=",10000); -RightAssociative(":="); - -Infix("+",70); -Infix("-",70); -RightPrecedence("-",40); -Infix("/",30); -Infix("*",40); -Infix("^",20); -RightAssociative("^"); -Prefix("+",50); -Prefix("-",50); -RightPrecedence("-",40); -Bodied("For",60000); -Bodied("Until",60000); -Postfix("++",5); -Postfix("--",5); -Bodied("ForEach",60000); -Infix("<<",10); -Infix(">>",10); -Bodied("D",60000); -Bodied("Deriv",60000); -Infix("X",30); -Infix(".",30); -Infix("o",30); -Postfix("!", 30); -Postfix("!!", 30); -Infix("***", 50); -Bodied("Integrate",60000); - -Bodied("Limit",60000); - -Bodied("EchoTime", 60000); - -Bodied("Repeat", 60000); - -Infix("->",600); - -/* functional operators */ -Infix(":",70); -RightAssociative(":"); -Infix("@",600); -Infix("/@",600); -Infix("..",600); - -Bodied("Taylor",60000); -Bodied("Taylor1",60000); -Bodied("Taylor2",60000); -Bodied("Taylor3",60000); -Bodied("InverseTaylor",60000); - -Infix("<--",10000); -Infix("#",9900); - -Bodied("TSum",60000); -Bodied("TExplicitSum",60000); -Bodied("TD",5); /* Tell the MathPiper interpreter that TD is to be used as TD(i)f */ - -/* Operator to be used for non-evaluating comparisons */ -Infix("==",90); -Infix("!==",90); - -/* Operators needed for propositional logic theorem prover */ -Infix("=>",10000); /* implication, read as 'implies' */ - - -Bodied("if",5); -Infix("else",60000); -RightAssociative("else"); -/* Bitwise operations we REALLY need. Perhaps we should define them - also as MathPiper operators? - */ -Infix("&",50); -Infix("|",50); -Infix("%",50); - -/* local pattern replacement operators */ -Infix("/:",20000); -Infix("/::",20000); -Infix("<-",10000); - -/* Operators used for manual layout */ -Infix("<>", OpPrecedence("=")); -Infix("<=>", OpPrecedence("=")); - -/* Operators for Solve: Where and AddTo */ -Infix("Where", 11000); -Infix("AddTo", 2000); - -Bodied("Function",60000); -Bodied("Macro",60000); - -Bodied(Assert, 60000); - -// Defining very simple functions, in scripts that can be converted to plugin. -Bodied("Defun",0); - - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/AntiDeriv.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/AntiDeriv.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/AntiDeriv.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/AntiDeriv.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,268 +0,0 @@ -%mathpiper,def="AntiDeriv",scope="private" - -//todo:tk:this file need to be broken down further. - -//tk:this code was moved here from Integrate.mrw because it was causing a -// "rulebase with this arity already defined" error. -//hso:but the RuleBase line causes hang when processing in fold -//RuleBase("IntegrateMultiplicative",{var,from,a,b}); - -//////////////////////////////////////////////// -// -// Anti-derivative of a univariate polynomial -// -//////////////////////////////////////////////// -5 # AntiDeriv(_var, poly_CanBeUni(var) ) - <-- NormalForm(AntiDeriv(var,`MakeUni(@poly,@var))); -5 # AntiDeriv(_var,UniVariate(_var,_first,_coefs)) <-- -[ - Local(result,i); - result:=FlatCopy(coefs); - For(i:=1,i<=Length(result),i++) - [ - result[i]:= result[i]/(first+i); - ]; - UniVariate(var,first+1,result); -]; - - -//////////////////////////////////////////////// -// -// Standard additive properties of integration. -// -//////////////////////////////////////////////// -10 # AntiDeriv(_var,_x + _y) <-- AntiDeriv(var,x) + AntiDeriv(var,y); -10 # AntiDeriv(_var,_x - _y) <-- AntiDeriv(var,x) - AntiDeriv(var,y); -10 # AntiDeriv(_var, - _y) <-- - AntiDeriv(var,y); - -10 # AntiDeriv(_var,_x/c_IsFreeOf(var) )_(HasExpr(x,var)) <-- AntiDeriv(var,x)/c; -10 # AntiDeriv(_var,c_IsFreeOf(var)/_x )_(HasExpr(x,var) And c!= 1) - <-- c*AntiDeriv(var,1/x); - - -//////////////////////////////////////////////// -// -// Multiplying a polynomial with another (integrable) -// function, Integrate by parts. -// -//////////////////////////////////////////////// -1570 # IntegrateMultiplicative(_var,(exy_CanBeUni(var)) * _exx,_dummy1,_dummy2) - <-- IntByParts(var,exy*exx,AntiDeriv(var,exx)); -1570 # IntegrateMultiplicative(_var,_exx * (exy_CanBeUni(var)),_dummy1,_dummy2) - <-- IntByParts(var,exy*exx,AntiDeriv(var,exx)); -10 # IntByParts(_var,_exy * _exx,Integrate(_var)(_something)) <-- - `Hold(AntiDeriv(@var,((@exy)*(@exx)))); -20 # IntByParts(_var,_exy * _exx,_anti)_(Not IsFreeOf(anti,exx)) <-- - `Hold(AntiDeriv(@var,((@exy)*(@exx)))); -30 # IntByParts(_var,_exy * _exx,_anti) <-- - [ - Local(cf); - cf:=anti*Deriv(var)exy; -// Echo({exy*anti,exy*exx,cf}); - exy*anti - `(AntiDeriv(@var,@cf)); - ]; - -//////////////////////////////////////////////// -// -// Rational functions: f(x)/g(x) where f and g are -// polynomials. -// -//////////////////////////////////////////////// -1570 # IntegrateMultiplicative(_var,(exy_CanBeUni(var)) / (exx_CanBeUni(var)),_dummy1,_dummy2) <-- - IntRat(var,exy/exx,MakeUni(exy,var),MakeUni(exx,var)); - -10 # IntRat(_var,_exy / _exx,_exyu,_exxu)_ - (Degree(exyu) > Degree(exxu) Or Degree(Gcd(exyu,exxu)) > 0) <-- - [ - Local(gcd); - gcd:=Gcd(exxu,exyu); - exyu:=Div(exyu,gcd); - exxu:=Div(exxu,gcd); - AntiDeriv(var,NormalForm(Div(exyu,exxu))) + - AntiDeriv(var,NormalForm(Mod(exyu,exxu))/NormalForm(exxu)); - ]; - -11 # IntRat(_var,_exy / _exx,_exyu,_exxu)_ - (Degree(exxu,var) > 1 And LeadingCoef(exxu)=1 And - IsNumericList(Coef(exxu,var,0 .. Degree(exxu)))) <-- -[ - Local(ee); - ee:=Apart(exy/exx,var); - `AntiDeriv(@var,@ee); -]; - - -20 # IntRat(_var,_exy / _exx,_exyu,_exxu) <-- - `Hold(AntiDeriv(@var,((@exy)/(@exx)))); - - -30 # AntiDeriv(_var,Deriv(_var)(_expr)) <-- expr; - -//////////////////////////////////////////////// -// -// No simple form, try something else -// -//////////////////////////////////////////////// -100 # AntiDeriv(_var,_exp) <-- -[ - IntegrateMultiplicative(var,exp,a,b); -]; - - -//////////////////////////////////////////////// -// -// Special anti-derivatives can be added here. -// -//////////////////////////////////////////////// - -// integrating expressions containing if: -10 # IntegrateMultiplicative(_var,if(_cond)(_body),_a,_b) - <-- - [ - body := AntiDeriv(var,body); - `Hold(if(@cond)(@body)); - ]; -// integrating expressions containing else -10 # IntegrateMultiplicative(_var,(_left) else (_right),_a,_b) - <-- - [ - left := AntiDeriv(var,left); - right := AntiDeriv(var,right); - `Hold( (@left) else (@right) ); - ]; - - -//////////////////////////////////////////////// -// -// Could not find anti-derivative, return unsimplified -// -//////////////////////////////////////////////// -1600 # IntegrateMultiplicative(_var,_exp,_a,_b) <-- `Hold(Integrate(@var)(@exp)); - -//////////////////////////////////////////////// -// -// IntFunc declares the anti-derivative of a function -// that has one argument. -// Calling sequence: IntFunc(variable,from,to); -// Example: IntFunc(x,Cos(_x),Sin(x)); -// -//////////////////////////////////////////////// -LocalSymbols(intpred) -[ - intpred := 50; - IntFunc(_vr,_from,_to) <-- - [ - `((@intpred) # IntegrateMultiplicative(_var,@from,_dummy1,_dummy2)_MatchLinear(var,@vr) <-- (@to)/Matched'a()); - intpred++; - ]; -]; - - -IntPureSquare(_vr,_from,_sign2,_sign0,_to) <-- -[ - `(50 # IntegrateMultiplicative(_var,@from,_dummy1,_dummy2)_MatchPureSquared(var,@sign2,@sign0,@vr) <-- (@to)); -]; - - - - -//////////////////////////////////////////////// -// -// Declaration of the anti-derivatives of a few analytic functions -// -//////////////////////////////////////////////// - - -IntFunc(x,Sqrt(_x),(2*Sqrt(x)^(3))/3); -IntFunc(x,1/_x^(_n),x^(1-n)/(1-n) ); -IntFunc(x,Sin(_x),-Cos(x)); -IntFunc(x,1/Sin(_x), Ln( 1/Sin(x) - Cos(x)/Sin(x) ) ); -IntFunc(x,Cos(_x),Sin(x)); -IntFunc(x,1/Cos(_x),Ln(1/Cos(x)+Tan(x))); -IntFunc(x,Tan(_x),-Ln(Cos(x))); -IntFunc(x,1/Tan(_x),Ln(Sin(x)) ); -IntFunc(x,Cos(_x)/Sin(_x),Ln(Sin(x))); -IntFunc(x,Exp(_x),Exp(x)); -IntFunc(x,(C_IsFreeOf(var))^(_x),C^x/Ln(C)); -// we don't need Ln(Abs(x)) -IntFunc(x,num_IsFreeOf(var) / (_x),num*Ln(x)); -IntFunc(x,Ln(_x),x*Ln(x)-x); -// where did these 1+1's come from? -IntFunc(x,(_x)*Ln(_x),(1/(1+1))*x^(1+1)*Ln(x) - (1/(1+1)^2)*x^(1+1) ); -IntFunc(x,Ln(_x)*(_x),(1/(1+1))*x^(1+1)*Ln(x) - (1/(1+1)^2)*x^(1+1) ); - -IntFunc(x,1/Sin(_x)^2,-Cos(x)/Sin(x) ); -IntFunc(x,1/Cos(_x)^2,Tan(x) ); -IntFunc(x,1/(Sin(_x)*Tan(_x)),-1/Sin(x)); -IntFunc(x,Tan(_x)/Cos(_x),1/Cos(x)); -IntFunc(x,1/Sinh(_x)^2,-1/Tanh(x)); -IntFunc(x,1/Cosh(_x)^2,Tanh(x)); -IntFunc(x,1/(Sinh(_x)*Tan(_x)),-1/Sinh(x)); -IntFunc(x,Tanh(_x)/Cosh(_x),-1/Cosh(x)); - -IntFunc(x,1/Sqrt(m_IsFreeOf(x)-_x^2),ArcSin(x/Sqrt(m)) ); - -IntFunc(x,Exp(n_IsNumber*_x)*Sin(m_IsNumber*_x),Exp(n*x)*(n*Sin(m*x)- m*Cos(m*x))/(m^2+n^2) ); - -// n>0 -IntFunc(x,Ln(_x)*(_x)^n_IsNumber,(1/(n+1))*x^(n+1)*Ln(x) - (1/(n+1)^2)*x^(n+1) ); - -// n>0 -IntFunc(x,Ln(A_IsNumber*_x)*(_x)^n_IsNumber,(1/(n+1))*x^(n+1)*Ln(A*x) - (1/(n+1)^2)*x^(n+1) ); - -IntFunc(x,Sin(Ln(_x)),x*Sin(Ln(x))/2 - x*Cos(Ln(x))/2 ); -IntFunc(x,Cos(Ln(_x)),x*Sin(Ln(x))/2 - x*Cos(Ln(x))/2 ); - -IntFunc(x,1/((_x)*Ln(_x)),Ln(Ln(x))); - -IntFunc(x,(_x)^(-1),Ln(x)); - -IntFunc(x,(_x)^(n_IsFreeOf(x)),x^(n+1)/(n+1)); -IntFunc(x,Sinh(_x),Cosh(x)); -IntFunc(x,Sinh(_x)^2,Sinh(2*x)/4 - x/2); -IntFunc(x,1/Sinh(_x),Ln(Tanh(x/2))); -IntFunc(x,Cosh(_x),Sinh(x)); -IntFunc(x,Cosh(_x)^2,Sinh(2*x)/4 + x/2); -IntFunc(x,1/Cosh(_x),ArcTan(Sinh(x))); -IntFunc(x,Tanh(_x),Ln(Cosh(x))); -IntFunc(x,Tanh(_x)/Cosh(_x),-1/Cosh(x)); -IntFunc(x,1/Cosh(_x)^2,Tanh(x)); -//IntFunc(x,1/Sech(_x)*Coth(_x),-1/Sinh(x)); -IntFunc(x,1/Tanh(_x),Ln(Sinh(x))); - -IntFunc(x,Abs(_x),Abs(x)*x/2); // not 2*a - -IntFunc(x,ArcTan(_x),x*ArcTan(x) - Ln(x^2 + 1)/2); -//IntFunc(x,ArcSin(_x),(x*ArcSin(x)) + Sqrt(1-x^2) ); -IntFunc(x,ArcCos(_x),x*ArcCos(x) - Sqrt(1-x^2) ); - -IntFunc(x,ArcTanh(_x),x*ArcTanh(x) + Ln(1-x^2)/2 ); -IntFunc(x,ArcSinh(_x),x*ArcSinh(x) - Sqrt(x^2 + 1) ); -IntFunc(x,ArcCosh(_x),x*ArcCosh(x) - Sqrt(x-1)*Sqrt(x+1) ); - - -// n^2 > x^2 -//IntFunc(x,num_IsFreeOf(var)/(-(_x)^2 + n_IsNumber),num*ArcTanh(x/Sqrt(n))/n); - -// x^2 > n^2 -//IntFunc(x,num_IsFreeOf(var)/((_x)^2 - n_IsNumber),num * -ArcCoth(x/Sqrt(n))/Sqrt(n)); - -// n^2 > x^2 -//IntFunc(x,num_IsFreeOf(var)/Sqrt(n_IsNumber - (_x)^2),num*ArcSin(x/Sqrt(n))); - -// previous code is killing this.... -IntFunc(x,num_IsFreeOf(var)/(A_IsNumber + B_IsNumber*(_x))^2,-num/(A*b + B^2*x)); - -// Code works now? -IntFunc(x,num_IsFreeOf(var)/(n_IsNumber + m_IsNumber*Exp(p_IsNumber*(_x))),num*x/n - num*Ln(n + m*Exp(p*x))/(n*p)); -IntFunc(x,num_IsFreeOf(var)/(m_IsNumber*Exp(p_IsNumber*(_x)) + n_IsNumber),num*x/n - num*Ln(n + m*Exp(p*x))/(n*p)); - -// note:hso: removed erroneous "a" in denominator of function below -IntPureSquare(x,num_IsFreeOf(var)/(_x),1,1,(num/(Sqrt(Matched'b()/Matched'a())))*ArcTan(var/Sqrt(Matched'b()/Matched'a()))); - -///// Integrating Special Functions -IntFunc(x,Erf(_x), x*Erf(x)+ 1/(Exp(x^2)*Sqrt(Pi)) ); - -UnFence("IntegrateMultiplicative",4); - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/Integrate.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/Integrate.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/Integrate.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/Integrate.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -%mathpiper,def="Integrate" - -//todo:tk:this file need to be broken down further. - - -10# (Integrate(_var)(expr_IsList)) - <-- Map("Integrate",{FillList(var,Length(expr)),expr}); -20 # (Integrate(_var)(_expr)) <-- IntSub(var,expr,AntiDeriv(var,IntClean(var,expr))); - - -10 # IntSub(_var,_expr,Integrate(_var)(_expr2)) <-- - `Hold(Integrate(@var)(@expr)); -20 # IntSub(_var,_expr,_result) <-- result; // + UniqueConstant(); - -//////////////////////////////////////////////// -// -// Integrate over a range -// -//////////////////////////////////////////////// -10# (Integrate(_var,_from,_to)(expr_IsList)) - <-- Map("Integrate",{FillList(var,Length(expr)), - FillList(from,Length(expr)), - FillList(to,Length(expr)), - expr}); - -20 # (Integrate(_var,_from,_to)(_expr)) - <-- defIntegrate(var,from,to,expr,a,b); - -//////////////////////////////////////////////// -// -// separate rules can be added here for specific integrals -// to defIntegrate -// -//////////////////////////////////////////////// - -10 # defIntegrate(_var,_from,_to,_expr,_a,_b)_(from = -to And IsOddFunction(expr,var)) <-- 0; - -// We need to define this case (integrating from 0 to 0 over an even function) -// explicitly, otherwise the integration ends up going in to infinite recursion. -// Extended it a little bit more, since if you are integrating from A to A, -// then the result is obviously zero. There are perhaps situations where -// this does not work, where we need to simplify (to-from) first. A naive -// implementation caused a test to fail. - -10 # defIntegrate(_var,_from,_from,_expr,_a,_b) <-- 0; - -12 # defIntegrate(_var,_from,_to,_expr,_a,_b)_(from = -to And IsEvenFunction(expr,var)) - <-- 2*defIntegrate(var,0,to,expr,a,b); - -100 # defIntegrate(_var,_from,_to,_expr,_a,_b)_(Type(AntiDeriv(var,IntClean(var,expr))) != "AntiDeriv") - <-- IntegrateRange(var,expr,from,to,AntiDeriv(var,IntClean(var,expr))); - -101 # defIntegrate(_var,_from,_to,_expr,_a,_b) - <-- `Hold(Integrate(@var,@from,@to)(@expr)); -// <-- IntegrateRange(var,expr,from,to,AntiDeriv(var,expr)); - - -//////////////////////////////////////////////// -// -// No anti-derivative found, return unavaluated. -// -//////////////////////////////////////////////// -10 # IntegrateRange(_var,_expr,_from,_to,Integrate(_var)_expr2) - <-- `Hold(Integrate(@var,@from,@to)@expr); - -//////////////////////////////////////////////// -// -// Anti-derivative found, return result. -// -//////////////////////////////////////////////// -20 # IntegrateRange(_var,_expr,_from,_to,_antideriv) - <-- `(@antideriv Where @var == @to) - `(@antideriv Where @var == @from); - -//////////////////////////////////////////////// -// -// IntClean cleans up an expression before passing -// it on to integration. This function normalizes -// an expression in a way desirable for integration. -// TrigSimpCombine, for instance, expands expressions -// containing trigonometric functions so that they are -// additive as opposed to multiplicative. -// -// If the expression doesn't contain the variable, -// just return it as-is. This fixes: -// In> Integrate(x) z^100 -// -// If the expression can be considered to be a sum -// of terms in var, then avoid premature simplification. -//////////////////////////////////////////////// -10 # IntClean(_var,_expr) <-- -[ - if( IsFreeOf(var,expr) Or IsSumOfTerms(var,expr) )[ - expr; - ] else if ( HasFunc(expr,Sin) Or HasFunc(expr,Cos) )[ - Simplify(TrigSimpCombine(expr)); - ] else [ - Simplify(expr); - ]; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Integrate",categories="User Functions;Calculus Related (Symbolic)" -*CMD Integrate --- integration - -*STD -*CALL - Integrate(var, x1, x2) expr - Integrate(var) expr - -*PARMS - -{var} -- atom, variable to integrate over - -{x1} -- first point of definite integration - -{x2} -- second point of definite integration - -{expr} -- expression to integrate - -*DESC - -This function integrates the expression {expr} with respect to the -variable {var}. The first calling format is used to perform -definite integration: the integration is carried out from $var=x1$ -to $var=x2$. The second form is for indefinite integration. - -Some simple integration rules have currently been -implemented. Polynomials, some quotients of polynomials, -trigonometric functions and their inverses, hyperbolic functions -and their inverses, {Exp}, and {Ln}, and products of these -functions with polynomials can be integrated. - -*E.G. - - In> Integrate(x,a,b) Cos(x) - Out> Sin(b)-Sin(a); - In> Integrate(x) Cos(x) - Out> Sin(x); - -*SEE D, UniqueConstant -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/MatchLinear.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/MatchLinear.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/MatchLinear.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/MatchLinear.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -%mathpiper,def="MatchLinear;MatchPureSquared" - -/* -todo:tk:MatchPureSquared() is in this file because it is grouped with MatchLinear in a -LocalSymbols() block. -*/ - -/* Def file definitions -MatchPureSquared -*/ - -/** MatchLinear(variable,expression) - */ -LocalSymbols(a,b)[ - -10 # MatchLinear(var_IsAtom,expr_CanBeUni(var)) <-- -[ - Set(expr,MakeUni(expr,var)); - MatchLinear(expr); -]; -20 # MatchLinear(_var,_expr) <-- False; - -10 # MatchLinear(_expr)_(Degree(expr,var)<2) <-- -[ - Check(IsUniVar(expr),ToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"})); - -//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way? -// Check(a = Hold(a), ToString()(Echo({"Found bound variable a which should have been unbound, in MatchLinear: ", a, "=", Eval(a)}))); -// Check(b = Hold(b), ToString()(Echo({"Found bound variable b which should have been unbound, in MatchLinear: ", b, "=", Eval(b)}))); - - a := Coef(expr,1); - b := Coef(expr,0); - True; -]; -20 # MatchLinear(_expr) <-- False; -UnFence("MatchLinear",1); -UnFence("MatchLinear",2); - -/** MatchPureSquared(variable,expression) - matches expressions - * of the form a*x^2+b. - */ -10 # MatchPureSquared(var_IsAtom,_sign2,_sign0,expr_CanBeUni(var)) <-- -[ - Set(expr,MakeUni(expr,var)); - MatchPureSquared(expr,sign2,sign0); -]; -20 # MatchPureSquared(_var,_sign2,_sign0,_expr) <-- False; - -10 # MatchPureSquared(_expr,_sign2,_sign0)_(Degree(expr,var)=2 And - Coef(expr,1) = 0 And - IsNumber(Coef(expr,0)) And - IsNumber(Coef(expr,2)) And - Coef(expr,0)*sign0 > 0 And - Coef(expr,2)*sign2 > 0 - ) <-- -[ - Check(IsUniVar(expr),ToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"})); -//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way? -// Check(a = Hold(a), "Found bound variable which should have been unbound, in MatchLinear"); -// Check(b = Hold(b), "Found bound variable which should have been unbound, in MatchLinear"); - a := Coef(expr,2); - b := Coef(expr,0); - True; -]; -20 # MatchPureSquared(_expr,_sign2,_sign0) <-- False; -UnFence("MatchPureSquared",3); -UnFence("MatchPureSquared",4); - -Matched'a() := a; -Matched'b() := b; - - - -]; // LocalSymbols a,b - - -%/mathpiper - - - -%mathpiper_docs,name="MatchLinear",categories="User Functions;Predicates" -*CMD MatchLinear --- match an expression to a polynomial of degree one in a variable -*STD -*CALL - MatchLinear(x,expr) - -*PARMS - -{x} -- variable to express the univariate polynomial in - -{expr} -- expression to match - -*DESC - -{MatchLinear} tries to match an expression to a linear (degree less than -two) polynomial. The function returns {True} if it could match, and -it stores the resulting coefficients in the variables "{a}" and "{b}" -as a side effect. The function calling this predicate should declare -local variables "{a}" and "{b}" for this purpose. -{MatchLinear} tries to match to constant coefficients which don't -depend on the variable passed in, trying to find a form "{a*x+b}" -with "{a}" and "{b}" not depending on {x} if {x} is given as the variable. - -*E.G. - - In> MatchLinear(x,(R+1)*x+(T-1)) - Out> True; - In> {a,b}; - Out> {R+1,T-1}; - In> MatchLinear(x,Sin(x)*x+(T-1)) - Out> False; - -*SEE Integrate -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/integrate/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/integrate/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -OMDef( "Integrate", "calculus1","defint", // Same argument reordering as Sum. - { $, _2 .. _3, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }, - { $, _{2,2,1}, _{1,1}, _{1,2}, _{2,3} } - ); -OMDef( "AntiDeriv", mathpiper,"AntiDeriv" ); - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Assert.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Assert.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Assert.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Assert.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -%mathpiper,def="Assert" - -/// post an error if assertion fails -(Assert(_error'class, _error'object) _predicate) <-- -[ - CheckErrorTableau(); - If(Equals(predicate, True), // if it does not evaluate to True, it's an error - True, - [ // error occurred, need to post error'object - DestructiveAppend(GetErrorTableau(), {error'class, error'object}); - False; - ] - ); -]; - -/// interface -(Assert(_error'class) _predicate) <-- Assert(error'class, True) predicate; - -/// interface -(Assert() _predicate) <-- Assert("generic", True) predicate; - -%/mathpiper - - - -%mathpiper_docs,name="Assert",categories="Programmer Functions;Error Reporting" -*CMD Assert --- signal "soft" custom error -*STD -*CALL - Assert("str", expr) pred - Assert("str") pred - Assert() pred -Precedence: -*EVAL OpPrecedence("Assert") - -*PARMS - -{pred} -- predicate to check - -{"str"} -- string to classify the error - -{expr} -- expression, error object - -*DESC - -{Assert} is a global error reporting mechanism. It can be used to check for -errors and report them. An error is considered to occur when the predicate -{pred} evaluates to anything except {True}. In this case, the function returns -{False} and an error object is created and posted to the global error tableau. -Otherwise the function returns {True}. - -Unlike the "hard" error function {Check}, the function {Assert} does not stop -the execution of the program. - -The error object consists of the string {"str"} and an arbitrary -expression {expr}. The string should be used to classify the kind of error that -has occurred, for example "domain" or "format". The error object can be any expression that might be useful for handling the error later; -for example, a list of erroneous values and explanations. -The association list of error objects is currently obtainable through -the function {GetErrorTableau()}. - -If the parameter {expr} is missing, {Assert} substitutes {True}. If both optional parameters {"str"} and {expr} are missing, {Assert} creates an error of class {"generic"}. - -Errors can be handled by a -custom error handler in the portion of the code that is able to handle a certain class of -errors. The functions {IsError}, {GetError} and {ClearError} can be used. - -Normally, all errors posted to the error tableau during evaluation of an expression should -be eventually printed to the screen. This is the behavior of prettyprinters -{DefaultPrint}, {Print}, {PrettyForm} and {TeXForm} (but not of the -inline prettyprinter, which is enabled by default); they call -{DumpErrors} after evaluating the expression. - -*E.G. - - In> Assert("bad value", "must be zero") 1=0 - Out> False; - In> Assert("bad value", "must be one") 1=1 - Out> True; - In> IsError() - Out> True; - In> IsError("bad value") - Out> True; - In> IsError("bad file") - Out> False; - In> GetError("bad value"); - Out> "must be zero"; - In> DumpErrors() - Error: bad value: must be zero - Out> True; -No more errors left: - In> IsError() - Out> False; - In> DumpErrors() - Out> True; - -*SEE IsError, DumpErrors, Check, GetError, ClearError, ClearErrors, GetErrorTableau - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/DefaultPrint.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/DefaultPrint.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/DefaultPrint.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/DefaultPrint.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -%mathpiper,def="DefaultPrint" - -/// The new default pretty-printer: DefaultPrint -Function("DefaultPrint", {x}) -[ - DumpErrors(); - WriteString("Out> "); - Write(x); - WriteString("; -"); -]; -HoldArg("DefaultPrint", x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/DumpErrors.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/DumpErrors.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/DumpErrors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/DumpErrors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper,def="DumpErrors" - -/// print all errors and clear the tableau -DumpErrors() <-- -[ - Local(error'object, error'word); - CheckErrorTableau(); - ForEach(error'object, GetErrorTableau()) - [ // error'object might be e.g. {"critical", {"bad bad", -1000}} - If( - IsList(error'object), - [ - If( // special case: error class "warning" - Length(error'object) > 0 And error'object[1] = "warning", - [ - error'word := "Warning"; - error'object[1] := ""; // don't print the word "warning" again - ], - error'word := "Error: " // important hack: insert ": " here but not after "Warning" - ); - - If( // special case: {"error'class", True} - Length(error'object)=2 And error'object[2]=True, - Echo(error'word, error'object[1]), - [ - Echo(error'word, error'object[1], ": ", - PrintList(Rest(error'object))); - ] - ); - ], - // error'object is not a list: just print it - Echo("Error: ", error'object) - ); - ]; - ClearErrors(); -]; - -%/mathpiper - - - - -%mathpiper_docs,name="DumpErrors",categories="Programmer Functions;Error Reporting" -*CMD DumpErrors --- simple error handlers -*STD -*CALL - DumpErrors() - -*DESC - -{DumpErrors} is a simple error handler for the global error reporting mechanism. It prints all errors posted using {Assert} and clears the error tableau. - -*SEE Assert, IsError, ClearErrors - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Echo.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Echo.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Echo.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Echo.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -%mathpiper,def="Echo" - -10 # EchoInternal(string_IsString) <-- -[ - WriteString(string); -]; - -20 # EchoInternal(_item) <-- -[ - Write(item);Space(); -]; - -RuleBaseListed("Echo",{args}); -10 # Echo(list_IsList)<-- -[ - ForEach(item,list) EchoInternal(item); - NewLine(); -]; -20 # Echo(_item)<-- -[ - EchoInternal(item); - NewLine(); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Echo",categories="User Functions;Input/Output" -*CMD Echo --- high-level printing routine -*STD -*CALL - Echo(item) - Echo(list) - Echo(item,item,item,...) - -*PARMS - -{item} -- the item to be printed - -{list} -- a list of items to be printed - -*DESC - -If passed a single item, {Echo} will evaluate it and print it to the -current output, followed by a newline. If {item} is a string, it is -printed without quotation marks. - -If there is one argument, and it is a list, {Echo} will print all the -entries in the list subsequently to the current output, followed by a -newline. Any strings in the list are printed without quotation -marks. All other entries are followed by a space. - -{Echo} can be called with a variable number of arguments, they will all -be printed, followed by a newline. - -{Echo} always returns {True}. - -*E.G. notest - - In> Echo(5+3); - 8 - Out> True; - In> Echo({"The square of two is ", 2*2}); - The square of two is 4 - Out> True; - In> Echo("The square of two is ", 2*2); - The square of two is 4 - Out> True; - -Note that one must use the second calling format if one wishes to -print a list: - - In> Echo({a,b,c}); - a b c - Out> True; - In> Echo({{a,b,c}}); - {a,b,c} - Out> True; - -*SEE PrettyForm, Write, WriteString, RuleBaseListed -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/GetErrorTableau.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/GetErrorTableau.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/GetErrorTableau.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/GetErrorTableau.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -%mathpiper,def="GetErrorTableau;ClearErrors;GetError" - -/* def file definitions -ClearErrors -GetError -*/ - -////////////////////////////////////////////////// -/// ErrorTableau, Assert, IsError --- global error reporting -////////////////////////////////////////////////// - -LocalSymbols(ErrorTableau) [ - - /// global error tableau. Its entries do not have to be lists. - Set(ErrorTableau, {}); - - GetErrorTableau() := ErrorTableau; - - ClearErrors() <-- Set(ErrorTableau, {}); - - /// aux function to check for corrupt tableau - CheckErrorTableau() <-- - If( - Not IsList(ErrorTableau), - Set(ErrorTableau, {{"general", "corrupted ErrorTableau"}}) - ); - -]; // LocalSymbols(ErrorTableau) - - -/// obtain error object -GetError(error'class_IsString) <-- -[ - Local(error); - error := GetErrorTableau()[error'class]; - If( - error != Empty, - error, - False - ); -]; - - -/// delete error -ClearError(error'class_IsString) <-- AssocDelete(GetErrorTableau(), error'class); - -%/mathpiper - - - - -%mathpiper_docs,name="ClearErrors",categories="Programmer Functions;Error Reporting" -*CMD ClearErrors --- simple error handlers -*STD -*CALL - ClearErrors() - -*DESC - -{ClearErrors} is a trivial error handler that does nothing except it clears the tableau. - -*SEE Assert, IsError, DumpErrors - -%/mathpiper_docs - - - - -%mathpiper_docs,name="GetError;ClearError;GetErrorTableau",categories="Programmer Functions;Error Reporting" -*CMD GetError --- custom errors handlers -*CMD ClearError --- custom errors handlers -*CMD GetErrorTableau --- custom errors handlers -*STD -*CALL - GetError("str") - ClearError("str") - GetErrorTableau() - -*PARMS - -{"str"} -- string to classify the error - -*DESC - -These functions can be used to create a custom error handler. - -{GetError} returns the error object if a custom error of class {"str"} has been -reported using {Assert}, or {False} if no errors of this class have been -reported. - -{ClearError("str")} deletes the same error object that is returned by -{GetError("str")}. It deletes at most one error object. It returns {True} if an -object was found and deleted, and {False} otherwise. - -{GetErrorTableau()} returns the entire association list of currently reported errors. - -*E.G. - - In> x:=1 - Out> 1; - In> Assert("bad value", {x,"must be zero"}) x=0 - Out> False; - In> GetError("bad value") - Out> {1, "must be zero"}; - In> ClearError("bad value"); - Out> True; - In> IsError() - Out> False; - -*SEE IsError, Assert, Check, ClearErrors - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/IsError.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/IsError.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/IsError.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/IsError.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="IsError" - -/// check for errors -IsError() <-- -[ - CheckErrorTableau(); - Length(GetErrorTableau())>0; -]; - -/// check for errors of a given kind -IsError(error'class_IsString) <-- -[ - CheckErrorTableau(); - GetErrorTableau()[error'class] != Empty; -]; - -%/mathpiper - - - - -%mathpiper_docs,name="IsError",categories="Programmer Functions;Error Reporting;Predicates" -*CMD IsError --- check for custom error -*STD -*CALL - IsError() - IsError("str") - -*PARMS - -{"str"} -- string to classify the error - -*DESC - -{IsError()} returns {True} if any custom errors have been reported using {Assert}. -The second form takes a parameter {"str"} that designates the class of the -error we are interested in. It returns {True} if any errors of the given class -{"str"} have been reported. - -*SEE GetError, ClearError, Assert, Check - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/PrettyForm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/PrettyForm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/PrettyForm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/PrettyForm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,508 +0,0 @@ -%mathpiper,def="PrettyForm;EvalFormula" - -/* def file definitions -EvalFormula -*/ - - -/* -TODO: -- Func(a=b) prematurely evaluates a=b -- clean up the code! - - document the code!!! -- prefix/postfix currently not used!!! -- some rules for rendering the formula are slooooww.... - -- bin, derivative, sqrt, integral, summation, limits, - ___ - / a | - \ / - - \/ b - - / - | - | - | - / - - d - --- f( x ) - d x - - 2 - d - ---- f( x ) - 2 - d x - - Infinity - ___ - \ - \ n - / x - /__ - n = 0 - Sin(x) - lim ------ - x -> Infinity x - - - -*/ - -/* -NLog(str):= -[ - WriteString(str); - NewLine(); -]; -*/ - -CharList(length,item):= -[ - Local(line,i); - line:=""; - For(Set(i,0),LessThan(i,length),Set(i,AddN(i,1))) - Set(line, line:item); - line; -]; - -CharField(width,height) := ArrayCreate(height,CharList(width," ")); - -WriteCharField(charfield):= -[ - Local(i,len); - len:=Length(charfield); - For(Set(i,1),i<=len,Set(i,AddN(i,1))) - [ - WriteString(charfield[i]); - NewLine(); - ]; - True; -]; - -ColumnFilled(charfield,column):= -[ - Local(i,result,len); - result:=False; - len:=Length(charfield); - For(Set(i, 1),(result = False) And (i<=len),Set(i,AddN(i,1))) - [ - If(StringMidGet(column,1,charfield[i]) != " ",result:=True); - ]; - result; -]; -WriteCharField(charfield,width):= -[ - Local(pos,length,len); - Set(length, Length(charfield[1])); - Set(pos, 1); - While(pos<=length) - [ - Local(i,thiswidth); - Set(thiswidth, width); - If(thiswidth>(length-pos)+1, - [ - Set(thiswidth, AddN(SubtractN(length,pos),1)); - ], - [ - While (thiswidth>1 And ColumnFilled(charfield,pos+thiswidth-1)) - [ - Set(thiswidth,SubtractN(thiswidth,1)); - ]; - If(thiswidth = 1, Set(thiswidth, width)); - ] - ); - len:=Length(charfield); - For(Set(i, 1),i<=len,Set(i,AddN(i,1))) - [ - WriteString(StringMidGet(pos,thiswidth,charfield[i])); - NewLine(); - ]; - Set(pos, AddN(pos, thiswidth)); - NewLine(); - ]; - True; -]; - - - -PutString(charfield,x,y,string):= -[ - cf[y] := StringMidSet(x,string,cf[y]); - True; -]; - -MakeOper(x,y,width,height,oper,args,base):= -[ - Local(result); - Set(result,ArrayCreate(7,0)); - ArraySet(result,1,x); - ArraySet(result,2,y); - ArraySet(result,3,width); - ArraySet(result,4,height); - ArraySet(result,5,oper); - ArraySet(result,6,args); - ArraySet(result,7,base); - result; -]; - - -MoveOper(f,x,y):= -[ - f[1]:=AddN(f[1], x); /* move x */ - f[2]:=AddN(f[2], y); /* move y */ - f[7]:=AddN(f[7], y); /* move base */ -]; - -AlignBase(i1,i2):= -[ - Local(base); - Set(base, Max(i1[7],i2[7])); - MoveOper(i1,0,SubtractN(base,(i1[7]))); - MoveOper(i2,0,SubtractN(base,(i2[7]))); -]; - -10 # BuildArgs({}) <-- Formula(Atom(" ")); -20 # BuildArgs({_head}) <-- head; -30 # BuildArgs(_any) <-- - [ - Local(item1,item2,comma,base,newitem); - Set(item1, any[1]); - Set(item2, any[2]); - Set(comma, Formula(Atom(","))); - Set(base, Max(item1[7],item2[7])); - MoveOper(item1,0,SubtractN(base,(item1[7]))); - MoveOper(comma,AddN(item1[3],1),base); - - MoveOper(item2,comma[1]+comma[3]+1,SubtractN(base,(item2[7]))); - Set(newitem, MakeOper(0,0,AddN(item2[1],item2[3]),Max(item1[4],item2[4]),"Func",{item1,comma,item2},base)); - BuildArgs(newitem:Rest(Rest(any))); - ]; - - - -FormulaBracket(f):= -[ - Local(left,right); - Set(left, Formula(Atom("("))); - Set(right, Formula(Atom(")"))); - left[4]:=f[4]; - right[4]:=f[4]; - MoveOper(left,f[1],f[2]); - MoveOper(f,2,0); - MoveOper(right,f[1]+f[3]+1,f[2]); - MakeOper(0,0,right[1]+right[3],f[4],"Func",{left,f,right},f[7]); -]; - - -/* RuleBase("Formula",{f}); */ - -1 # Formula(f_IsAtom) <-- - MakeOper(0,0,Length(String(f)),1,"Atom",String(f),0); - -2 # Formula(_xx ^ _yy) <-- -[ - Local(l,r); - Set(l, BracketOn(Formula(xx),xx,OpLeftPrecedence("^"))); - Set(r, BracketOn(Formula(yy),yy,OpRightPrecedence("^"))); - MoveOper(l,0,r[4]); - MoveOper(r,l[3],0); - MakeOper(0,0,AddN(l[3],r[3]),AddN(l[4],r[4]),"Func",{l,r},l[2]+l[4]-1); -]; - - - -10 # FormulaArrayItem(xx_IsList) <-- -[ - Local(sub,height); - sub := {}; - height := 0; - ForEach(item,xx) - [ - Local(made); - made := FormulaBracket(Formula(item)); - If(made[4] > height,Set(height,made[4])); - DestructiveAppend(sub,made); - ]; - MakeOper(0,0,0,height,"List",sub,height>>1); -]; - - -20 # FormulaArrayItem(_item) <-- Formula(item); - -2 # Formula(xx_IsList) <-- -[ - Local(sub,width,height); - sub:={}; - width := 0; - height := 1; - - ForEach(item,xx) - [ - Local(made); - made := FormulaArrayItem(item); - - If(made[3] > width,Set(width,made[3])); - MoveOper(made,0,height); - Set(height,AddN(height,AddN(made[4],1))); - DestructiveAppend(sub,made); - ]; - - Local(thislength,maxlength); - maxlength:=0; - ForEach(item,xx) - [ - thislength:=0; - if(IsList(item)) [thislength:=Length(item);]; - if (maxlength0, - [ - Local(i,j); - width:=0; - For(j:=1,j<=maxlength,j++) - [ - Local(w); - w := 0; - For(i:=1,i<=Length(sub),i++) - [ - if (IsList(xx[i]) And j<=Length(xx[i])) - If(sub[i][6][j][3] > w,w := sub[i][6][j][3]); - ]; - - For(i:=1,i<=Length(sub),i++) - [ - if (IsList(xx[i]) And j<=Length(xx[i])) - MoveOper(sub[i][6][j],width,0); - ]; - width := width+w+1; - ]; - For(i:=1,i<=Length(sub),i++) - [ - sub[i][3] := width; - ]; - ] - ); - - sub := MakeOper(0,0,width,height,"List",sub,height>>1); - FormulaBracket(sub); -]; - -2 # Formula(_xx / _yy) <-- -[ - Local(l,r,dash,width); -/* - Set(l, BracketOn(Formula(xx),xx,OpLeftPrecedence("/"))); - Set(r, BracketOn(Formula(yy),yy,OpRightPrecedence("/"))); -*/ - Set(l, Formula(xx)); - Set(r, Formula(yy)); - Set(width, Max(l[3],r[3])); - Set(dash, Formula(Atom(CharList(width,"-")))); - MoveOper(dash,0,l[4]); - MoveOper(l,(SubtractN(width,l[3])>>1),0); - MoveOper(r,(SubtractN(width,r[3])>>1),AddN(dash[2], dash[4])); - MakeOper(0,0,width,AddN(r[2], r[4]),"Func",{l,r,dash},dash[2]); -]; - -RuleBase("BracketOn",{op,f,prec}); -Rule("BracketOn",3,1,IsFunction(f) And NrArgs(f) = 2 - And IsInfix(Type(f)) And OpPrecedence(Type(f)) > prec) -[ - FormulaBracket(op); -]; -Rule("BracketOn",3,2,True) -[ - op; -]; - -10 # Formula(f_IsFunction)_(NrArgs(f) = 2 And IsInfix(Type(f))) <-- -[ - Local(l,r,oper,width,height,base); - Set(l, Formula(f[1])); - Set(r, Formula(f[2])); - - Set(l, BracketOn(l,f[1],OpLeftPrecedence(Type(f)))); - Set(r, BracketOn(r,f[2],OpRightPrecedence(Type(f)))); - - Set(oper, Formula(f[0])); - Set(base, Max(l[7],r[7])); - MoveOper(oper,AddN(l[3],1),SubtractN(base,(oper[7]))); - MoveOper(r,oper[1] + oper[3]+1,SubtractN(base,(r[7]))); - MoveOper(l,0,SubtractN(base,(l[7]))); - Set(height, Max(AddN(l[2], l[4]),AddN(r[2], r[4]))); - - MakeOper(0,0,AddN(r[1], r[3]),height,"Func",{l,r,oper},base); -]; - -11 # Formula(f_IsFunction) <-- -[ - Local(head,args,all); - Set(head, Formula(f[0])); - Set(all, Rest(Listify(f))); - - Set(args, FormulaBracket(BuildArgs(MapSingle("Formula",Apply("Hold",{all}))))); - AlignBase(head,args); - MoveOper(args,head[3],0); - - MakeOper(0,0,args[1]+args[3],Max(head[4],args[4]),"Func",{head,args},head[7]); -]; - - - -RuleBase("RenderFormula",{cf,f,x,y}); - -/* -/ / / -\ | | - \ | - \ -*/ - -Rule("RenderFormula",4,1,f[5] = "Atom" And f[6] = "(" And f[4] > 1) -[ - Local(height,i); - Set(x, AddN(x,f[1])); - Set(y, AddN(y,f[2])); - Set(height, SubtractN(f[4],1)); - - cf[y] := StringMidSet(x, "/", cf[y]); - cf[AddN(y,height)] := StringMidSet(x, "\\", cf[AddN(y,height)]); - For (Set(i,1),LessThan(i,height),Set(i,AddN(i,1))) - cf[AddN(y,i)] := StringMidSet(x, "|", cf[AddN(y,i)]); -]; - -Rule("RenderFormula",4,1,f[5] = "Atom" And f[6] = ")" And f[4] > 1) -[ - Local(height,i); - Set(x, AddN(x,f[1])); - Set(y, AddN(y,f[2])); - Set(height, SubtractN(f[4],1)); - cf[y] := StringMidSet(x, "\\", cf[y]); - cf[y+height] := StringMidSet(x, "/", cf[y+height]); - For (Set(i,1),LessThan(i,height),Set(i,AddN(i,1))) - cf[AddN(y,i)] := StringMidSet(x, "|", cf[AddN(y,i)]); -]; - -Rule("RenderFormula",4,5,f[5] = "Atom") -[ - cf[AddN(y, f[2]) ]:= - StringMidSet(AddN(x,f[1]),f[6],cf[AddN(y, f[2]) ]); -]; - -Rule("RenderFormula",4,6,True) -[ - ForEach(item,f[6]) - [ - RenderFormula(cf,item,AddN(x, f[1]),AddN(y, f[2])); - ]; -]; - -LocalSymbols(formulaMaxWidth) [ - SetFormulaMaxWidth(width):= - [ - formulaMaxWidth := width; - ]; - FormulaMaxWidth() := formulaMaxWidth; - SetFormulaMaxWidth(60); -]; // LocalSymbols(formulaMaxWidth) - -Function("PrettyForm",{ff}) -[ - Local(cf,f); - - f:=Formula(ff); - - cf:=CharField(f[3],f[4]); - RenderFormula(cf,f,1,1); - - NewLine(); - WriteCharField(cf,FormulaMaxWidth()); - - DumpErrors(); - True; -]; -/* -HoldArg("PrettyForm",ff); -*/ - -EvalFormula(f):= -[ - Local(result); - result:= UnList({Atom("="),f,Eval(f)}); - PrettyForm(result); - True; -]; -HoldArg("EvalFormula",f); - -/* -{x,y,width,height,oper,args,base} -*/ - -%/mathpiper - - - -%mathpiper_docs,name="PrettyForm",categories="User Functions;Input/Output" -*CMD PrettyForm --- print an expression nicely with ASCII art -*STD -*CALL - PrettyForm(expr) - -*PARMS - -{expr} -- an expression - -*DESC - -{PrettyForm} renders an expression in a nicer way, using ascii art. -This is generally useful when the result of a calculation is more -complex than a simple number. - -*E.G. - - In> Taylor(x,0,9)Sin(x) - Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880; - In> PrettyForm(%) - - 3 5 7 9 - x x x x - x - -- + --- - ---- + ------ - 6 120 5040 362880 - - Out> True; - -*SEE EvalFormula, PrettyPrinter'Set -%/mathpiper_docs - - - -%mathpiper_docs,name="EvalFormula",categories="User Functions;Input/Output" -*CMD EvalFormula --- print an evaluation nicely with ASCII art -*STD -*CALL - EvalFormula(expr) - -*PARMS - -{expr} -- an expression - -*DESC - -Show an evaluation in a nice way, using {PrettyPrinter'Set} -to show 'input = output'. - -*E.G. - - In> EvalFormula(Taylor(x,0,7)Sin(x)) - - 3 5 - x x - Taylor( x , 0 , 5 , Sin( x ) ) = x - -- + --- - 6 120 - - -*SEE PrettyForm -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Print.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Print.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Print.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Print.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,120 +0,0 @@ -%mathpiper,def="Print" - - -/* A reference print implementation. Expand at own leisure. - * - * This file implements Print, a scripted expression printer. - */ - - -/* 60000 is the maximum precedence allowed for operators */ -10 # Print(_x) <-- -[ - Print(x,60000); - NewLine(); - DumpErrors(); -]; - -/* Print an argument within an environment of precedence n */ -10 # Print(x_IsAtom,_n) <-- Write(x); -10 # Print(_x,_n)_(IsInfix(Type(x))And NrArgs(x) = 2) <-- -[ - Local(bracket); - bracket:= (OpPrecedence(Type(x)) > n); - If(bracket,WriteString("(")); - Print(x[1],OpLeftPrecedence(Type(x))); - Write(x[0]); - Print(x[2],OpRightPrecedence(Type(x))); - If(bracket,WriteString(")")); -]; - -10 # Print(_x,_n)_(IsPrefix(Type(x)) And NrArgs(x) = 1) <-- -[ - Local(bracket); - bracket:= (OpPrecedence(Type(x)) > n); - Write(x[0]); - If(bracket,WriteString("(")); - Print(x[1],OpRightPrecedence(Type(x))); - If(bracket,WriteString(")")); -]; - -10 # Print(_x,_n)_(IsPostfix(Type(x))And NrArgs(x) = 1) <-- -[ - Local(bracket); - bracket:= (OpPrecedence(Type(x)) > n); - If(bracket,WriteString("(")); - Print(x[1],OpLeftPrecedence(Type(x))); - Write(x[0]); - If(bracket,WriteString(")")); -]; - -20 # Print(_x,_n)_(Type(x) = "List") <-- -[ - WriteString("{"); - PrintArg(x); - WriteString("}"); -]; - -20 # Print(_x,_n)_(Type(x) = "Prog") <-- -[ - WriteString("["); - PrintArgProg(Rest(Listify(x))); - WriteString("]"); -]; -20 # Print(_x,_n)_(Type(x) = "Nth") <-- -[ - Print(x[1],0); - WriteString("["); - Print(x[2],60000); - WriteString("]"); -]; - -100 # Print(x_IsFunction,_n) <-- - [ - Write(x[0]); - WriteString("("); - PrintArg(Rest(Listify(x))); - WriteString(")"); - ]; - - -/* Print the arguments of an ordinary function */ -10 # PrintArg({}) <-- True; - -20 # PrintArg(_list) <-- -[ - Print(First(list),60000); - PrintArgComma(Rest(list)); -]; -10 # PrintArgComma({}) <-- True; -20 # PrintArgComma(_list) <-- -[ - WriteString(","); - Print(First(list),60000); - PrintArgComma(Rest(list)); -]; - - -18 # Print(Complex(0,1),_n) <-- [WriteString("I");]; -19 # Print(Complex(0,_y),_n) <-- [WriteString("I*");Print(y,4);]; -19 # Print(Complex(_x,1),_n) <-- [Print(x,7);WriteString("+I");]; -20 # Print(Complex(_x,_y),_n) <-- [Print(x,7);WriteString("+I*");Print(y,4);]; - - -/* Tail-recursive printing the body of a compound statement */ -10 # PrintArgProg({}) <-- True; -20 # PrintArgProg(_list) <-- -[ - Print(First(list),60000); - WriteString(";"); - PrintArgProg(Rest(list)); -]; - - - - - - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Show.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Show.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Show.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Show.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -%mathpiper,def="Show" -Macro("Show",{id}) [SysOut("<< ",@id," >>");]; -Macro("Show",{id,x}) [SysOut("<< ",@id," >> ",Hold(@x),": ",Eval(@x));]; -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - -%mathpiper_docs,name="Show",categories="Programmer Functions;Testing" - -*CMD Show --- debug routine using SysOut to print ID and (optional) variable(s) - -*STD -*CALL - Show(ID) - Show(ID,list) - -*PARMS - -{ID} -- an arbitrary identifier for this printout - -{list} -- a list of items to be printed (may be a single item) - -*DESC - -If passed a single item, {Show} will display it using SysOut(). -The dispayed value will be enclosed with << >> (see below). -If ID consists of more than one word, it should be quoted. - -If there are two arguments, the first should be an ID as above, and the second -should be a list of variables which are bound to values at the place where -{Show} is called. Using SysOut(), the list of variable names will be printed -out, along with a list of their currently bound values. - -{Show} can be called with any number of variable names in the list. - -{Show} always returns {True}. - -Because {Show} uses SysOut() to print its output, the output will be visible -both on Standard Output and also on the Shell console (if MathPiper is started -this way), or on the MathRider Activity Log (if started in MathRider). -The latter is very useful for debugging programs which hang in a loop or -otherwise, because standard output may not then be visible, but the alternative -output will usually be available. - -*E.G. notest - In> var1:=123 - Result> 123 - In> var2:= "a string" - Result> "a string" - In> var3:=Sin(x)+Exp(x) - Result> Sin(x)+Exp(x) - In> Show(ID1) - Result> True - Side Effects> - << ID1 >> - In> Show(ID2,{var1}) - Result> True - Side Effects> - << ID2 >> {var1}: {123} - In> Show(ID3,{var1,var2}) - Result> True - Side Effects> - << ID3 >> {var1,var2}: {123,a string} - In> Show(ID4,{var1,var2,var3}) - Result> True - Side Effects> - << ID4 >> {var1,var2,var3}: {123,a string,Sin(x)+Exp(x)} - -*SEE Tell -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/TableForm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/TableForm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/TableForm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/TableForm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="TableForm" - -Function("TableForm",{list}) -[ - Local(i); - ForEach(i,list) - [ - Write(i); - NewLine(); - ]; - True; -]; - -%/mathpiper - - - - -%mathpiper_docs,name="TableForm",categories="User Functions;Lists (Operations)" -*CMD TableForm --- print each entry in a list on a line -*STD -*CALL - TableForm(list) - -*PARMS - -{list} -- list to print - -*DESC - -This functions writes out the list {list} in a better readable form, by -printing every element in the list on a separate line. - -*E.G. - - In> TableForm(Table(i!, i, 1, 10, 1)); - - 1 - 2 - 6 - 24 - 120 - 720 - 5040 - 40320 - 362880 - 3628800 - Out> True; - -*SEE PrettyForm, Echo, Table -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Tell.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Tell.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/io/Tell.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/io/Tell.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -%mathpiper,def="Tell" -Macro("Tell",{id}) [Echo(<<,@id,>>);]; -Macro("Tell",{id,x}) [Echo(<<,@id,>>,Hold(@x),": ",Eval(@x));]; -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - -%mathpiper_docs,name="Tell",categories="Programmer Functions;Testing" - -*CMD Tell --- debug routine using Echo to print ID and (optional) variable(s) - -*STD -*CALL - Tell(ID) - Tell(ID,list) - -*PARMS - -{ID} -- an arbitrary identifier for this printout - -{list} -- a list of items to be printed (may be a single item) - -*DESC - -If passed a single item, {Tell} will display it using Echo(). -The dispayed value will be enclosed with << >> (see below). -If ID consists of more than one word, it should be quoted. - -If there are two arguments, the first should be an ID as above, and the second -should be a list of variables which are bound to values at the place where -{Tell} is called. Using Echo(), the list of variable names will be printed -out, along with a list of their currently bound values. - -{Tell} can be called with any number of variable names in the list. - -{Tell} always returns {True}. - -Because {Tell} uses Echo(), it prints to Standard Output. If you are debuging -a program which may hang, you may get no printout. In that case, use {Show} -instead of {Tell} - -*E.G. notest - In> var1:=123 - Result> 123 - In> var2:= "a string" - Result> "a string" - In> var3:=Sin(x)+Exp(x) - Result> Sin(x)+Exp(x) - In> Tell(ID1) - Result> True - Side Effects> - << ID1 >> - In> Tell(ID2,{var1}) - Result> True - Side Effects> - << ID2 >> {var1} : {123} - In> Tell(ID3,{var1,var2}) - Result> True - Side Effects> - << ID3 >> {var1,var2} {123,"a string"} - In> Tell(ID4,{var1,var2,var3}) - Result> True - Side Effects> - << ID4 >> {var1,var2,var3} : {123,"a string",Sin(x)+Exp(x)} - - -*SEE Show -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/limit/Limit.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/limit/Limit.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/limit/Limit.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/limit/Limit.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,209 +0,0 @@ -%mathpiper,def="Limit" - -/* */ -/* Limit operator rule base */ -/* */ - - -/* Exponentiation rules */ - -/* Special limit #1: 0 ^ 0; #2: 1 ^ Infinity; #3: Infinity ^ 0 */ -200 # Lim(_var, _tar, _dir, _x ^ _y)_ -( [ - Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); - ((IsZero(lx) And IsZero(ly)) Or ((lx = 1) And IsInfinity(ly)) Or (IsInfinity(lx) And IsZero(ly))); -] ) -<-- Exp(Lim(var, tar, dir, y * Ln(x))); - -/* Default rule */ -210 # Lim(_var, _tar, _dir, _x ^ _y) -<-- Lim(var, tar, dir, x)^Lim(var, tar, dir, y); - - -/* Division rules */ - -/* Special limit #4: 0 / 0; #5: Infinity / Infinity */ -300 # Lim(_var, _tar, _dir, _x / _y)_ -( [ - Local(lx,ly,infx,infy); - lx := Lim(var, tar, dir, x); - ly := Lim(var, tar, dir, y); - infx := (IsInfinity(lx) Or (IsZero(Re(lx)) And IsInfinity(Im(lx)))); - infy := (IsInfinity(ly) Or (IsZero(Re(ly)) And IsInfinity(Im(ly)))); - ((IsZero(lx) And IsZero(ly)) Or - (infx And infy) - ); -] ) -<-- Lim(var, tar, dir, ApplyPure("D", {var, x})/ApplyPure("D", {var, y})); - -/* Special limit #6: null denominator */ -/* Probably there are still some problems. */ - -Dir(Right) <-- 1; -Dir(Left) <-- -1; - -/* To get the sign of the denominator on one side: */ -Sign(_var, _tar, _dir, _exp, _n) -<-- [ - Local(der, coef); der := ApplyPure("D", {var, exp}); - coef := Eval(ApplyPure("Subst", {var, tar, der})); - If ( coef = 0, - Sign(var, tar, dir, der, n+1), - (Sign(coef)*Dir(dir)) ^ n - ); -]; - -/* To avoid infinite recursion (with 1/Exp(-x) for instance) */ -310 # Lim(_var, _tar, _dir, _x / _y)_ -(IsInfinity(tar) And IsZero(Lim(var, tar, dir, y))) -<-- Sign(Lim(var, tar, dir, x))*Sign(Lim(var, tar, dir, ApplyPure("D", {var, y})))*tar; - -320 # Lim(_var, _tar, _dir, _x / _y)_IsZero(Lim(var, tar, dir, y)) -<-- Sign(Lim(var, tar, dir, x))*Sign(var, tar, dir, y, 1)*Infinity; - - -/* Default rule */ -330 # Lim(_var, _tar, _dir, _x / _y) -<-- Lim(var, tar, dir, x)/Lim(var, tar, dir, y); ]; - - -/* Multiplication rules */ - -/* To avoid some infinite recursions */ -400 # Lim(_var, _tar, _dir, _x * Exp(_y))_ -(IsInfinity(Lim(var, tar, dir, x)) And (Lim(var, tar, dir, y) = -Infinity)) -<-- Lim(var, tar, dir, x/Exp(-y)); -400 # Lim(_var, _tar, _dir, Exp(_x) * _y)_ -((Lim(var, tar, dir, x) = -Infinity) And IsInfinity(Lim(var, tar, dir, y))) -<-- Lim(var, tar, dir, y/Exp(-x)); -400 # Lim(_var, _tar, _dir, Ln(_x) * _y)_ -(IsZero(Lim(var, tar, dir, x)) And IsZero(Lim(var, tar, dir, y))) -<-- Lim(var, tar, dir, y*Ln(x)); - -/* Special limit #7: 0 * Infinity */ -410 # Lim(_var, _tar, _dir, _x * _y)_ -((IsZero(Lim(var, tar, dir, x)) And IsInfinity(Lim(var, tar, dir, y))) - Or (IsInfinity(Lim(var, tar, dir, x)) And IsZero(Lim(var, tar, dir, y)))) -<-- Lim(var, tar, dir, Simplify(ApplyPure("D", {var, y})/ApplyPure("D", -{var, 1/x}))); - -/* Default rule */ -420 # Lim(_var, _tar, _dir, _x * _y) -<-- Lim(var, tar, dir, x) * Lim(var, tar, dir, y); - - -/* Substraction rules */ - -/* Special limit #8: Infinity - Infinity */ -500 # Lim(_var, _tar, _dir, _x - _y)_ -( [ - Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); - ((lx = Infinity) And (ly = Infinity)) Or ((lx = -Infinity) And (ly = -Infinity)); -] ) -<-- Lim(var, tar, dir, x*(1-y/x)); - -/* Default rule */ -510 # Lim(_var, _tar, _dir, _x - _y) -<-- Lim(var, tar, dir, x)-Lim(var, tar, dir, y); - -/* Unary minus */ -520 # Lim(_var, _tar, _dir, - _x) -<-- - Lim(var, tar, dir, x); - - -/* Addition rules */ - -/* Special limit #9: Infinity + (-Infinity) */ -600 # Lim(_var, _tar, _dir, _x + _y)_ -( [ - Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); - ((lx = Infinity) And (ly = -Infinity)) Or ((lx = -Infinity) And (ly = Infinity)); -] ) -<-- Lim(var, tar, dir, x*(1+y/x)); - -/* Default rule */ -610 # Lim(_var, _tar, _dir, _x + _y) -<-- Lim(var, tar, dir, x)+Lim(var, tar, dir, y); - -/* Global default rule : evaluate expression */ - -700 # Lim(_var, _tar, _dir, exp_IsFunction) -<-- Eval(MapArgs(exp,"LimitArgs")); - -LimitArgs(_arg) <-- Lim(var,tar,dir,arg); -UnFence("LimitArgs",1); /* Allow LimitArgs to have access to the local variables of the caller. */ - -701 # Lim(_var, _tar, _dir, _exp) -<-- Eval(ApplyPure("Subst", {var, tar, exp})); - - -/* Limit without direction */ - -10 # Lim(_var, tar_IsInfinity, _exp) <-- Lim(var, tar, None, exp); - -20 # Lim(_var, _tar, _exp) -<-- [ - Local(l); l := Lim(var, tar, Left, exp); - If ( l = Lim(var, tar, Right, exp), - l, - Undefined - ); -]; - - - - -/* User-callable function */ - -(Limit(_var,_lim)(_fie)) <-- Lim(var,lim,fie); -(Limit(_var,_lim,_direction)(_fie)) <-- Lim(var,lim,direction,fie); -UnFence("Limit",3); - - -%/mathpiper - - - -%mathpiper_docs,name="Limit",categories="User Functions;Calculus Related (Symbolic)" -*CMD Limit --- limit of an expression -*STD -*CALL - Limit(var, val) expr - Limit(var, val, dir) expr - -*PARMS - -{var} -- a variable - -{val} -- a number - -{dir} -- a direction ({Left} or {Right}) - -{expr} -- an expression - -*DESC - -This command tries to determine the value that the expression "expr" -converges to when the variable "var" approaches "val". One may use -{Infinity} or {-Infinity} for -"val". The result of {Limit} may be one of the -symbols {Undefined} (meaning that the limit does not -exist), {Infinity}, or {-Infinity}. - -The second calling sequence is used for unidirectional limits. If one -gives "dir" the value {Left}, the limit is taken as -"var" approaches "val" from the positive infinity; and {Right} will take the limit from the negative infinity. - -*E.G. - - In> Limit(x,0) Sin(x)/x - Out> 1; - In> Limit(x,0) (Sin(x)-Tan(x))/(x^3) - Out> -1/2; - In> Limit(x,0) 1/x - Out> Undefined; - In> Limit(x,0,Left) 1/x - Out> -Infinity; - In> Limit(x,0,Right) 1/x - Out> Infinity; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/limit/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/limit/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/limit/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/limit/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -OMDef("Limit", "limit1","limit", - { _0, _2, OMS("limit1", "under"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) - |{ _0, _2, OMS("limit1", "above"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) - |{ _0, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, - { _0, _{3,2,1}, _1, Left, _{3,3}}_(_2=OMS("limit1", "below")) - |{_0, _{3,2,1}, _1, Right, _{3,3}}_(_2=OMS("limit1", "above")) - |{_0, _{3,2,1}, _1, _{3,3}} - ); -// Test [result Limit(x,0,Right)1/x]: FromString(ToString()OMForm(Limit(x,0,Right) 1/x))OMRead() - -// As explained in the manual, "limit1:both_sides" and "fns1:lambda" will -// be handled as OMS("limit1", "both_sides") and OMS("fns1", "lambda"), so -// we don't need to define bogus mappings for them: -// OMDef("OMSymbolLimit1BothSides", "limit1", "both_sides"); -// OMDef("OMSymbolLambda", "fns1", "lambda"); -// The same applies to "Left" and "Right", which are undefined symbols -// that are used only inside limit expressions, so they don't need a mapping -// of their own. -// We could define them as follows: -//OMDef("Left", "limit1","below"); -//OMDef("Right", "limit1","above"); -// and then use the following rules instead: -// { _0, _2, Left, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) -// |{ _0, _2, Right, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) -// |{ _0, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, -// { _0, _{3,2,1}, _1, _2, _{3,3}}_(_2=Left Or _2=Right) -// |{_0, _{3,2,1}, _1, _{3,3}} -// The result is exactly the same. The only difference is when producing the -// OMForm of the symbols themselves, outside the limit expression. - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/BaseVector.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/BaseVector.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/BaseVector.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/BaseVector.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="BaseVector" - -Function("BaseVector",{row,n}) -[ - Local(i,result); - result:=ZeroVector(n); - result[row] := 1; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="BaseVector",categories="User Functions;Linear Algebra" -*CMD BaseVector --- base vector -*STD -*CALL - BaseVector(k, n) - -*PARMS - -{k} -- index of the base vector to construct - -{n} -- dimension of the vector - -*DESC - -This command returns the "k"-th base vector of dimension "n". This -is a vector of length "n" with all zeroes except for the "k"-th -entry, which contains a 1. - -*E.G. - - In> BaseVector(2,4) - Out> {0,1,0,0}; - -*SEE ZeroVector, Identity -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Cholesky.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Cholesky.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Cholesky.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Cholesky.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -%mathpiper,def="Cholesky" - -// Cholesky Decomposition, adapted from: -// Fundamentals Of Matrix Computation (2nd), David S. Watkins, pp38 -// This algorithm performs O(n^3) flops where A is nxn -// Given the positive definite matrix A, a matrix R is returned such that -// A = Transpose(R) * R - -10 # Cholesky(A_IsMatrix) <-- -[ - Local(matrix,n,k,j); - n:=Length(A); - matrix:=ZeroMatrix(n); - - // copy entries of A into matrix - ForEach(i,1 .. n) - ForEach(j,1 .. n) - matrix[i][j] := A[i][j]; - - // in place algorithm for cholesky decomp - ForEach(i,1 .. n)[ - For(k:=1,k<=(i-1),k++) - matrix[i][i] := matrix[i][i] - matrix[k][i]^2; - Check( matrix[i][i] > 0, "Cholesky: Matrix is not positive definite"); - matrix[i][i] := Sqrt(matrix[i][i]); - //Echo({"matrix[",i,"][",i,"] = ", matrix[i][i] }); - For(j:=i+1,j<=n,j++)[ - For(k:=1,k<=(i-1),k++) - matrix[i][j]:= matrix[i][j] - matrix[k][i]*matrix[k][j]; - matrix[i][j] := matrix[i][j]/matrix[i][i]; - //Echo({"matrix[",i,"][",j,"] = ", matrix[i][j] }); - ]; - ]; - // cholesky factorization is upper triangular - ForEach(i,1 .. n) - ForEach(j,1 .. n) - If(i>j,matrix[i][j] := 0); - matrix; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Cholesky",categories="User Functions;Linear Algebra" -*CMD Cholesky --- find the Cholesky Decomposition -*STD -*CALL - Cholesky(A) - -*PARMS - -{A} -- a square positive definite matrix - -*DESC - -{Cholesky} returns a upper triangular matrix {R} such that {Transpose(R)*R = A}. -The matrix {A} must be positive definite, {Cholesky} will notify the user if the matrix -is not. Some families of positive definite matrices are all symmetric matrices, diagonal -matrices with positive elements and Hilbert matrices. - -*E.G. - - In> A:={{4,-2,4,2},{-2,10,-2,-7},{4,-2,8,4},{2,-7,4,7}} - Out> {{4,-2,4,2},{-2,10,-2,-7},{4,-2,8,4},{2,-7,4,7}}; - In> R:=Cholesky(A); - Out> {{2,-1,2,1},{0,3,0,-2},{0,0,2,1},{0,0,0,1}}; - In> Transpose(R)*R = A - Out> True; - In> Cholesky(4*Identity(5)) - Out> {{2,0,0,0,0},{0,2,0,0,0},{0,0,2,0,0},{0,0,0,2,0},{0,0,0,0,2}}; - In> Cholesky(HilbertMatrix(3)) - Out> {{1,1/2,1/3},{0,Sqrt(1/12),Sqrt(1/12)},{0,0,Sqrt(1/180)}}; - In> Cholesky(ToeplitzMatrix({1,2,3})) - In function "Check" : - CommandLine(1) : "Cholesky: Matrix is not positive definite" - -*SEE IsSymmetric, IsDiagonal, Diagonal -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/CoFactor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/CoFactor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/CoFactor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/CoFactor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -%mathpiper,def="CoFactor" - -Function("CoFactor",{matrix,ii,jj}) -[ - Local(perms,indices,result); - indices:=Table(i,i,1,Length(matrix),1); - perms:=PermutationsList(indices); - result:=0; - ForEach(item,perms) - If(item[ii] = jj, - result:=result+ - Product(i,1,Length(matrix), - If(ii=i,1,matrix[i][item[i] ]) - )*LeviCivita(item)); - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="CoFactor",categories="User Functions;Linear Algebra" -*CMD CoFactor --- cofactor of a matrix -*STD -*CALL - CoFactor(M,i,j) - -*PARMS - -{M} -- a matrix - -{i}, {j} - positive integers - -*DESC - -{CoFactor} returns the cofactor of a matrix around -the element ($i$, $j$). The cofactor is the minor times -$(-1)^(i+j)$. - -*E.G. - - In> A := {{1,2,3}, {4,5,6}, {7,8,9}}; - Out> {{1,2,3},{4,5,6},{7,8,9}}; - In> PrettyForm(A); - - / \ - | ( 1 ) ( 2 ) ( 3 ) | - | | - | ( 4 ) ( 5 ) ( 6 ) | - | | - | ( 7 ) ( 8 ) ( 9 ) | - \ / - Out> True; - In> CoFactor(A,1,2); - Out> 6; - In> Minor(A,1,2); - Out> -6; - In> Minor(A,1,2) * (-1)^(1+2); - Out> 6; - -*SEE Minor, Determinant, Inverse -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/CrossProduct.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/CrossProduct.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/CrossProduct.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/CrossProduct.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper,def="CrossProduct" - -Function("CrossProduct",{aLeft,aRight}) -[ - Local(length); - length:=Length(aLeft); - Check(length = 3,"OutProduct: error, vectors not of dimension 3"); - Check(length = Length(aRight),"OutProduct: error, vectors not of the same dimension"); - - Local(perms); - perms := PermutationsList({1,2,3}); - - Local(result); - result:=ZeroVector(3); - - Local(term); - ForEach(term,perms) - [ - result[ term[1] ] := result[ term[1] ] + - LeviCivita(term) * aLeft[ term[2] ] * aRight[ term[3] ] ; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="CrossProduct",categories="User Functions;Linear Algebra" -*CMD CrossProduct --- outer product of vectors -*STD -*CALL - CrossProduct(a,b) - a X b -Precedence: -*EVAL OpPrecedence("X") - -*PARMS - -{a}, {b} -- three-dimensional vectors - -*DESC - -The cross product of the vectors "a" -and "b" is returned. The result is perpendicular to both "a" and -"b" and its length is the product of the lengths of the vectors. -Both "a" and "b" have to be three-dimensional. - -*E.G. - - In> {a,b,c} X {d,e,f}; - Out> {b*f-c*e,c*d-a*f,a*e-b*d}; - -*SEE InProduct -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Deteminant.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Deteminant.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Deteminant.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Deteminant.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%mathpiper,def="Determinant" - -10 # Determinant(_matrix)_(IsUpperTriangular(matrix) Or IsLowerTriangular(matrix)) <-- -[ - Local(result); - result:=1; - ForEach(i, Diagonal(matrix) ) - result:=result*i; - result; -]; - -// -// The fast determinant routine that does the determinant numerically, rule 20, -// divides things by the elements on the diagonal of the matrix. So if one of these -// elements happens to be zero, the result is something like Infinity or Undefined. -// Use the symbolic determinant in that case, as it is slower but much more robust. -// -15 # Determinant(_matrix)_(Length(Select("IsZero",Diagonal(matrix))) > 0) <-- SymbolicDeterminant(matrix); - -// Not numeric entries, so lets treat it symbolically. -16 # Determinant(_matrix)_(VarList(matrix) != {}) <-- SymbolicDeterminant(matrix); - -20 # Determinant(_matrix) <-- GaussianDeterminant(matrix); - -%/mathpiper - - - -%mathpiper_docs,name="Determinant",categories="User Functions;Linear Algebra" -*CMD Determinant --- determinant of a matrix -*STD -*CALL - Determinant(M) - -*PARMS - -{M} -- a matrix - -*DESC - -Returns the determinant of a matrix M. - -*E.G. - - In> A:=DiagonalMatrix(1 .. 4) - Out> {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; - In> Determinant(A) - Out> 24; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/DiagonalMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/DiagonalMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/DiagonalMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/DiagonalMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="DiagonalMatrix" - -Function("DiagonalMatrix",{list}) -[ - Local(result,i,n); - n:=Length(list); - result:=Identity(n); - For(i:=1,i<=n,i++) - [ - result[i][i] := list[i]; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="DiagonalMatrix",categories="User Functions;Linear Algebra" -*CMD DiagonalMatrix --- construct a diagonal matrix -*STD -*CALL - DiagonalMatrix(d) - -*PARMS - -{d} -- list of values to put on the diagonal - -*DESC - -This command constructs a diagonal matrix, that is a square matrix -whose off-diagonal entries are all zero. The elements of the vector -"d" are put on the diagonal. - -*E.G. - - In> DiagonalMatrix(1 .. 4) - Out> {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; - -*SEE Identity, ZeroMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Diagonal.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Diagonal.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Diagonal.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Diagonal.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="Diagonal" - -// -// Diagonal: return a vector with the diagonal elements of the matrix -// -Function("Diagonal",{A}) -[ - Local(result,i,n); - n:=Length(A); - result:=ZeroVector(n); - For(i:=1,i<=n,i++) - [ - result[i] := A[i][i]; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Diagonal",categories="User Functions;Linear Algebra" -*CMD Diagonal --- extract the diagonal from a matrix -*STD -*CALL - Diagonal(A) - -*PARMS - -{A} -- matrix - -*DESC - -This command returns a vector of the diagonal components -of the matrix {A}. - - -*E.G. - - In> Diagonal(5*Identity(4)) - Out> {5,5,5,5}; - In> Diagonal(HilbertMatrix(3)) - Out> {1,1/3,1/5}; - -*SEE DiagonalMatrix, IsDiagonal -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Dimensions.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Dimensions.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Dimensions.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Dimensions.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="Dimensions" - -/* Code that returns the list of the dimensions of a tensor - Code submitted by Dirk Reusch. - */ - -LocalSymbols(x,i,n,m,aux,dim,result) -[ -1 # Dimensions(x_IsList) <-- - [ - Local(i,n,m,aux,dim,result); - result:=List(Length(x)); -//Echo("GETTING ",x); -//Echo(Length(Select(IsList,x))); -//Echo("END"); - If(Length(x)>0 And Length(Select(IsList,x))=Length(x), - [ - n:=Length(x); - dim:=MapSingle(Dimensions,x); - m:=Min(MapSingle(Length,dim)); - - For(i:=1,i<=m,i++) - [ - aux:=Table(dim[j][i],j,1,n,1); - If(Min(aux)=Max(aux), - result:=DestructiveAppend(result,dim[1][i]), - i:=m+1); - ]; - ]); -//Echo(x,result); - result; - ]; - -2 # Dimensions(_x) <-- List(); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Dot.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Dot.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Dot.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Dot.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -%mathpiper,def="Dot" - -////// -// dot product for vectors and matrices (dr) -////// - -LocalSymbols(Dot0,Dot1) -[ -// vector . vector -Dot(t1_IsVector,t2_IsVector)_(Length(t1)=Length(t2)) <-- - Dot0(t1,t2,Length(t1)); - -// matrix . vector -Dot(t1_IsMatrix,t2_IsVector)_(Length(t1[1])=Length(t2)) <-- -[ - Local(i,n,m,result); - n:=Length(t1); - m:=Length(t2); - result:=List(); - For(i:=1,i<=n,i++) - DestructiveInsert(result,1,Dot0(t1[i],t2,m)); - DestructiveReverse(result); -]; - -// vector . matrix -Dot(t1_IsVector,t2_IsMatrix)_(Length(t1)=Length(t2) - And Length(t2[1])>0) <-- - Dot1(t1,t2,Length(t1),Length(t2[1])); - -// matrix . matrix -Dot(t1_IsMatrix,t2_IsMatrix)_(Length(t1[1])=Length(t2) - And Length(t2[1])>0) <-- -[ - Local(i,n,k,l,result); - n:=Length(t1); - k:=Length(t2); - l:=Length(t2[1]); - result:=List(); - For(i:=1,i<=n,i++) - DestructiveInsert(result,1,Dot1(t1[i],t2,k,l)); - DestructiveReverse(result); -]; - -// vector . vector -Dot0(_t1,_t2,_n) <-- -[ - Local(i,result); - result:=0; - For(i:=1,i<=n,i++) - result:=result+t1[i]*t2[i]; - result; -]; - -// vector . matrix -// m vector length -// n number of matrix cols -Dot1(_t1,_t2,_m,_n) <-- -[ - Local(i,j,result); - result:=ZeroVector(n); - For(i:=1,i<=n,i++) - For(j:=1,j<=m,j++) - result[i]:=result[i]+t1[j]*t2[j][i]; - result; -]; - -]; // LocalSymbols(Dot0,Dot1) - -%/mathpiper - - - -%mathpiper_docs,name="Dot",categories="User Functions;Linear Algebra" -*CMD Dot, . --- get dot product of tensors -*STD -*CALL - Dot(t1,t2) - t1 . t2 -Precedence: -*EVAL OpPrecedence(".") - -*PARMS - -{t1,t2} -- tensor lists (currently only vectors and matrices are supported) - -*DESC - -{Dot} returns the dot (aka inner) product of two tensors t1 and t2. The last -index of t1 and the first index of t2 are contracted. Currently {Dot} works -only for vectors and matrices. {Dot}-multiplication of two vectors, a matrix -with a vector (and vice versa) or two matrices yields either a scalar, a -vector or a matrix. - -*E.G. - - In> Dot({1,2},{3,4}) - Out> 11; - In> Dot({{1,2},{3,4}},{5,6}) - Out> {17,39}; - In> Dot({5,6},{{1,2},{3,4}}) - Out> {23,34}; - In> Dot({{1,2},{3,4}},{{5,6},{7,8}}) - Out> {{19,22},{43,50}}; - - Or, using the "."-Operator: - - In> {1,2} . {3,4} - Out> 11; - In> {{1,2},{3,4}} . {5,6} - Out> {17,39}; - In> {5,6} . {{1,2},{3,4}} - Out> {23,34}; - In> {{1,2},{3,4}} . {{5,6},{7,8}} - Out> {{19,22},{43,50}}; - -*SEE Outer, Cross, IsScalar, IsVector, IsMatrix, . -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/FrobeniusNorm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/FrobeniusNorm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/FrobeniusNorm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/FrobeniusNorm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -%mathpiper,def="FrobeniusNorm" - -FrobeniusNorm(matrix_IsMatrix) <-- -[ - Local(i,j,result); - result:=0; - For(i:=1,i<=Length(matrix),i++) - For(j:=1,j<=Length(matrix[1]),j++) - result:=result+Abs(matrix[i][j])^2; - - Sqrt(result); - -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/GaussianDeterminant.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/GaussianDeterminant.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/GaussianDeterminant.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/GaussianDeterminant.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="GaussianDeterminant",scope="private" - -GaussianDeterminant(matrix):= -[ - Local(n,s,result); - n:=Length(matrix); - result:=1; - - [ - matrix:=FlatCopy(matrix); - Local(i); - For(i:=1,i<=n,i++) - [ - matrix[i]:=FlatCopy(matrix[i]); - ]; - ]; - - // gaussian elimination - ForEach(i, 1 .. (n-1) ) - [ - ForEach(k, (i+1) .. n ) - [ - s:=matrix[k][i]; - ForEach(j, i .. n ) - [ - matrix[k][j] := matrix[k][j] - (s/matrix[i][i])*matrix[i][j]; - //Echo({"matrix[",k,"][",j,"] =", aug[k][j]," - ", - // matrix[k][i],"/",matrix[i][i],"*",matrix[i][j]," k i =", k,i }); - ]; - ]; - ]; - -//Echo("mat: ",matrix); -//Echo("diagmat: ",Diagonal(matrix)); - // now upper triangular - ForEach(i, Diagonal(matrix) ) - result:=result*i; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/GenMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/GenMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/GenMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/GenMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="GenMatrix" - -Function("GenMatrix",{func,m,n}) -[ - Local(i,j,result); - result:=ZeroMatrix(m,n); - - For(i:=1,i<=m,i++) - For(j:=1,j<=n,j++) - result[i][j]:=ApplyPure(func,{i,j}); - - result; -]; -HoldArg("GenMatrix",func); -UnFence("GenMatrix",3); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HankelMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HankelMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HankelMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HankelMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="HankelMatrix" - -// The arguments of the following functions should be checked -HankelMatrix(n):=GenMatrix({{i,j}, If(i+j-1>n,0,i+j-1) }, n,n ); -HankelMatrix(m,n):=GenMatrix({{i,j}, If(i+j-1>n,0,i+j-1)}, m,n ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HessianMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HessianMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HessianMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HessianMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -%mathpiper,def="HessianMatrix" - -// The arguments of the following functions should be checked -// this takes 1 func in N vars -HessianMatrix(f,v):=GenMatrix({{i,j}, Deriv(v[i]) Deriv(v[j]) f},Length(v),Length(v)); - -%/mathpiper - - - -%mathpiper_docs,name="HessianMatrix",categories="User Functions;Matrices (Special)" -*CMD HessianMatrix --- create the Hessian matrix -*STD -*CALL - HessianMatrix(function,var) -*PARMS - -{function} -- a function in $n$ variables - -{var} -- an $n$-dimensional vector of variables - -*DESC - -The function {HessianMatrix} calculates the Hessian matrix -of a vector. - -If $f(x)$ is a function of an $n$-dimensional vector $x$, then the ($i$,$j$)-th element of the Hessian matrix of the function $f(x)$ is defined as -$ Deriv(x[i]) Deriv(x[j]) f(x) $. If the third -order mixed partials are continuous, then the Hessian -matrix is symmetric (a standard theorem of calculus). - -The Hessian matrix is used in the second derivative test -to discern if a critical point is a local maximum, a local -minimum or a saddle point. - - -*E.G. - - In> HessianMatrix(3*x^2-2*x*y+y^2-8*y, {x,y} ) - Out> {{6,-2},{-2,2}}; - In> PrettyForm(%) - - / \ - | ( 6 ) ( -2 ) | - | | - | ( -2 ) ( 2 ) | - \ / -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HilbertInverseMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HilbertInverseMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HilbertInverseMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HilbertInverseMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="HilbertInverseMatrix" - -HilbertInverseMatrix(n):=GenMatrix({{i,j}, - (-1)^(i+j)*(i+j-1)*BinomialCoefficient(n+i-1,n-j)*BinomialCoefficient(n+j-1,n-i)*BinomialCoefficient(i+j-2,i-1)^2},n,n); - -%/mathpiper - - - -%mathpiper_docs,name="HilbertInverseMatrix",categories="User Functions;Matrices (Special)" -*CMD HilbertInverseMatrix --- create a Hilbert inverse matrix -*STD -*CALL - HilbertInverseMatrix(n) -*PARMS - -{n} -- positive integer - -*DESC - -The function {HilbertInverseMatrix} returns the {n} by {n} inverse of the -corresponding Hilbert matrix. All Hilbert inverse matrices have integer -entries that grow in magnitude rapidly. - -*E.G. - In> PrettyForm(HilbertInverseMatrix(4)) - - / \ - | ( 16 ) ( -120 ) ( 240 ) ( -140 ) | - | | - | ( -120 ) ( 1200 ) ( -2700 ) ( 1680 ) | - | | - | ( 240 ) ( -2700 ) ( 6480 ) ( -4200 ) | - | | - | ( -140 ) ( 1680 ) ( -4200 ) ( 2800 ) | - \ / - -*SEE HilbertMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HilbertMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HilbertMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/HilbertMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/HilbertMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%mathpiper,def="HilbertMatrix" - -// The arguments of the following functions should be checked -// notoriously hard to manipulate numerically -HilbertMatrix(n):=GenMatrix({{i,j}, 1/(i+j-1)}, n,n ); -HilbertMatrix(m,n):=GenMatrix({{i,j}, 1/(i+j-1)}, m,n ); - - -%/mathpiper - - - -%mathpiper_docs,name="HilbertMatrix",categories="User Functions;Matrices (Special)" -*CMD HilbertMatrix --- create a Hilbert matrix -*STD -*CALL - HilbertMatrix(n) - HilbertMatrix(n,m) -*PARMS - -{n,m} -- positive integers - -*DESC - -The function {HilbertMatrix} returns the {n} by {m} Hilbert matrix -if given two arguments, and the square {n} by {n} Hilbert matrix -if given only one. The Hilbert matrix is defined as {A(i,j) = 1/(i+j-1)}. -The Hilbert matrix is extremely sensitive to manipulate and invert numerically. - -*E.G. - - In> PrettyForm(HilbertMatrix(4)) - - / \ - | ( 1 ) / 1 \ / 1 \ / 1 \ | - | | - | | - | | - | | - | \ 2 / \ 3 / \ 4 / | - | | - | / 1 \ / 1 \ / 1 \ / 1 \ | - | | - | | - | | - | | - | | - | \ 2 / \ 3 / \ 4 / \ 5 / | - | | - | / 1 \ / 1 \ / 1 \ / 1 \ | - | | - | | - | | - | | - | | - | \ 3 / \ 4 / \ 5 / \ 6 / | - | | - | / 1 \ / 1 \ / 1 \ / 1 \ | - | | - | | - | | - | | - | | - | \ 4 / \ 5 / \ 6 / \ 7 / | - \ / - -*SEE HilbertInverseMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Identity.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Identity.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Identity.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Identity.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="Identity" - -Identity(n_IsNonNegativeInteger) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=n,i++) - [ - DestructiveAppend(result,BaseVector(i,n)); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Identity",categories="User Functions;Linear Algebra" -*CMD Identity --- make identity matrix -*STD -*CALL - Identity(n) - -*PARMS - -{n} -- size of the matrix - -*DESC - -This commands returns the identity matrix of size "n" by "n". This -matrix has ones on the diagonal while the other entries are zero. - -*E.G. - - In> Identity(3) - Out> {{1,0,0},{0,1,0},{0,0,1}}; - -*SEE BaseVector, ZeroMatrix, DiagonalMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/InProduct.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/InProduct.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/InProduct.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/InProduct.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="InProduct" - -Function("InProduct",{aLeft,aRight}) -[ - Local(length); - length:=Length(aLeft); - Check(length = Length(aRight),"InProduct: error, vectors not of the same dimension"); - - Local(result); - result:=0; - Local(i); - For(i:=1,i<=length,i++) - [ - result := result + aLeft[i] * aRight[i]; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="InProduct",categories="User Functions;Linear Algebra" -*CMD InProduct --- inner product of vectors (deprecated) -*STD -*CALL - InProduct(a,b) - -*PARMS - -{a}, {b} -- vectors of equal length - -*DESC - -The inner product of the two vectors "a" and "b" is returned. The -vectors need to have the same size. - -This function is superceded by the {.} operator. - -*E.G. - - In> {a,b,c} . {d,e,f}; - Out> a*d+b*e+c*f; - -*SEE Dot, CrossProduct -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Inverse.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Inverse.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Inverse.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Inverse.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -%mathpiper,def="Inverse" - -Function("Inverse",{matrix}) -[ - Local(perms,indices,inv,det,n); - n:=Length(matrix); - indices:=Table(i,i,1,n,1); - perms:=PermutationsList(indices); - inv:=ZeroMatrix(n,n); - det:=0; - ForEach(item,perms) - [ - Local(i,lc); - lc := LeviCivita(item); - det:=det+Product(i,1,n,matrix[i][item[i] ])* lc; - For(i:=1,i<=n,i++) - [ - inv[item[i] ][i] := inv[item[i] ][i]+ - Product(j,1,n, - If(j=i,1,matrix[j][item[j] ]))*lc; - ]; - ]; - Check(det != 0, "Zero determinant"); - (1/det)*inv; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Inverse",categories="User Functions;Linear Algebra" -*CMD Inverse --- get inverse of a matrix -*STD -*CALL - Inverse(M) - -*PARMS - -{M} -- a matrix - -*DESC - -Inverse returns the inverse of matrix $M$. The determinant of $M$ should -be non-zero. Because this function uses {Determinant} for calculating -the inverse of a matrix, you can supply matrices with non-numeric (symbolic) -matrix elements. - -*E.G. - - In> A:=DiagonalMatrix({a,b,c}) - Out> {{a,0,0},{0,b,0},{0,0,c}}; - In> B:=Inverse(A) - Out> {{(b*c)/(a*b*c),0,0},{0,(a*c)/(a*b*c),0}, - {0,0,(a*b)/(a*b*c)}}; - In> Simplify(B) - Out> {{1/a,0,0},{0,1/b,0},{0,0,1/c}}; - -*SEE Determinant -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/JacobianMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/JacobianMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/JacobianMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/JacobianMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="JacobianMatrix" - -// The arguments of the following functions should be checked -// this takes N funcs in N vars -JacobianMatrix(f,v):=GenMatrix({{i,j},Deriv(v[j])f[i]},Length(f),Length(f)); - -%/mathpiper - - - -%mathpiper_docs,name="JacobianMatrix",categories="User Functions;Matrices (Special)" -*CMD JacobianMatrix --- calculate the Jacobian matrix of $n$ functions in $n$ variables -*STD -*CALL - JacobianMatrix(functions,variables) - -*PARMS - -{functions} -- an $n$-dimensional vector of functions - -{variables} -- an $n$-dimensional vector of variables - -*DESC - -The function {JacobianMatrix} calculates the Jacobian matrix -of n functions in n variables. - -The ($i$,$j$)-th element of the Jacobian matrix is defined as the derivative -of $i$-th function with respect to the $j$-th variable. - -*E.G. - - In> JacobianMatrix( {Sin(x),Cos(y)}, {x,y} ); - Out> {{Cos(x),0},{0,-Sin(y)}}; - In> PrettyForm(%) - - / \ - | ( Cos( x ) ) ( 0 ) | - | | - | ( 0 ) ( -( Sin( y ) ) ) | - \ / -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/LeviCivita.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/LeviCivita.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/LeviCivita.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/LeviCivita.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -%mathpiper,def="LeviCivita" - -/* Levi-civita symbol */ -Function("LeviCivita",{indices}) -[ - Local(i,j,length,left,right,factor); - length:=Length(indices); - factor:=1; - - For (j:=length,j>1,j--) - [ - For(i:=1,i LeviCivita({1,2,3}) - Out> 1; - In> LeviCivita({2,1,3}) - Out> -1; - In> LeviCivita({2,2,3}) - Out> 0; - -*SEE PermutationsList -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/LU.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/LU.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/LU.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/LU.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="LU" - -// In place LU decomposition -// Pivotting is not implemented -// Adapted from Numerical Methods with Matlab -// Gerald Recktenwald, Sec 8.4 -10 # LU(A_IsSquareMatrix) <-- -[ - Local(n,matrix,L,U); - n:=Length(A); - L:=ZeroMatrix(n,n); - U:=ZeroMatrix(n,n); - matrix:=ZeroMatrix(n,n); - - ForEach(i,1 .. n) - ForEach(j,1 .. n) - matrix[i][j] := A[i][j]; - - // loop over pivot rows - ForEach(i,1 ..(n-1))[ - // loop over column below the pivot - ForEach(k,i+1 .. n)[ - // compute multiplier and store it in L - matrix[k][i] := matrix[k][i] / matrix[i][i]; - // loop over elements in row k - ForEach(j,i+1 .. n)[ - matrix[k][j] := matrix[k][j] - matrix[k][i]*matrix[i][j]; - ]; - ]; - ]; - ForEach(i,1 .. n)[ - ForEach(j,1 .. n)[ - If(i<=j,U[i][j]:=matrix[i][j],L[i][j]:=matrix[i][j]); - ]; - // diagonal of L is always 1's - L[i][i]:=1; - ]; - - {L,U}; -]; - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixColumn.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixColumn.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixColumn.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixColumn.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="MatrixColumn" - -Function("MatrixColumn",{matrix,col}) -[ - Local(m); - m:=matrix[1]; - - Check(col > 0, "MatrixColumn: column index out of range"); - Check(col <= Length(m), "MatrixColumn: column index out of range"); - - Local(i,result); - result:={}; - For(i:=1,i<=Length(matrix),i++) - DestructiveAppend(result,matrix[i][col]); - - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixPower.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixPower.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixPower.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixPower.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="MatrixPower" - -////// -// power of a matrix (dr) -////// - -MatrixPower(x_IsSquareMatrix, n_IsNonNegativeInteger) <-- -[ - Local(result); - result:=Identity(Length(x)); - While(n != 0) - [ - If(IsOdd(n), - result:=Dot(result,x)); - x:=Dot(x,x); - n:=n>>1; - ]; - result; -]; - -MatrixPower(x_IsSquareMatrix, n_IsNegativeInteger) <-- - MatrixPower(Inverse(x),-n); - -%/mathpiper - - - -%mathpiper_docs,name="MatrixPower",categories="User Functions;Linear Algebra" -*CMD MatrixPower --- get nth power of a square matrix -*STD -*CALL - MatrixPower(mat,n) - -*PARMS - -{mat} -- a square matrix - -{n} -- an integer - -*DESC - -{MatrixPower(mat,n)} returns the {n}th power of a square matrix {mat}. For -positive {n} it evaluates dot products of {mat} with itself. For negative -{n} the nth power of the inverse of {mat} is returned. For {n}=0 the identity -matrix is returned. - -*E.G. - In> A:={{1,2},{3,4}} - Out> {{1,2},{3,4}}; - In> MatrixPower(A,0) - Out> {{1,0},{0,1}}; - In> MatrixPower(A,1) - Out> {{1,2},{3,4}}; - In> MatrixPower(A,3) - Out> {{37,54},{81,118}}; - In> MatrixPower(A,-3) - Out> {{-59/4,27/4},{81/8,-37/8}}; - -*SEE IsSquareMatrix, Inverse, Dot -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixRow.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixRow.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixRow.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixRow.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -%mathpiper,def="MatrixRow" - -Function("MatrixRow",{matrix,row}) -[ - Check(row > 0, "MatrixRow: row index out of range"); - Check(row <= Length(matrix), "MatrixRow: row index out of range"); - - Local(result); - result:=matrix[row]; - - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixSolve.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixSolve.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/MatrixSolve.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/MatrixSolve.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -%mathpiper,def="MatrixSolve" - -10 # MatrixSolve(matrix_IsDiagonal,b_IsVector) <-- -[ - Local(rowsm,rowsb,x); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - x:=ZeroVector(rowsb); - ForEach(i,1 .. rowsb) - x[i]:=b[i]/matrix[i][i]; - x; -]; - -// Backward Substitution -15 # MatrixSolve(matrix_IsUpperTriangular,b_IsVector) <-- -[ - Local(rowsm,rowsb,x,s); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - x:=ZeroVector(rowsb); - - x[rowsb]:=b[rowsb]/matrix[rowsb][rowsb]; - If(InVerboseMode(),Echo({"set x[",rowsb,"] = ",b[rowsb]/matrix[rowsb][rowsb]})); - - ForEach(i,(rowsb-1) .. 1 )[ - s:=b[i]; - ForEach(j,i+1 .. rowsb )[ - s:= s - matrix[i][j]*x[j]; - ]; - x[i]:= s/matrix[i][i]; - If(InVerboseMode(),Echo({"set x[",i,"] = ",s/matrix[i][i]})); - ]; - x; -]; - -// Forward Substitution -15 # MatrixSolve(matrix_IsLowerTriangular,b_IsVector) <-- -[ - Local(rowsm,rowsb,x,s); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - x:=ZeroVector(rowsb); - - x[1]:=b[1]/matrix[1][1]; - If(InVerboseMode(),Echo({"set x[1] = ",b[1]/matrix[1][1]})); - - ForEach(i,2 .. rowsb )[ - s:=b[i]; - ForEach(j,1 .. (i-1) )[ - s:= s - matrix[i][j]*x[j]; - ]; - x[i]:= s/matrix[i][i]; - If(InVerboseMode(),Echo({"set x[",i,"] = ",s/matrix[i][i]})); - ]; - x; -]; -// Gaussian Elimination and Back Substitution -// pivoting not implemented yet -20 # MatrixSolve(matrix_IsMatrix,b_IsVector) <-- -[ - Local(aug,rowsm,rowsb,x,s); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - aug:=ZeroMatrix(rowsb,rowsb+1); - x:=ZeroVector(rowsb); - - // create augmented matrix - ForEach(i, 1 .. rowsb ) - ForEach(j, 1 .. rowsb ) - aug[i][j] := matrix[i][j]; - ForEach(i, 1 .. rowsb ) - aug[i][rowsb+1] := b[i]; - - // gaussian elimination - ForEach(i, 1 .. (rowsb-1) )[ - // If our pivot element is 0 we need to switch - // this row with a row that has a nonzero element - If(aug[i][i] = 0, [ - Local(p,tmp); - p:=i+1; - While( aug[p][p] = 0 )[ p++; ]; - If(InVerboseMode(), Echo({"switching row ",i,"with ",p}) ); - tmp:=aug[i]; - aug[i]:=aug[p]; - aug[p]:=tmp; - ]); - - - ForEach(k, (i+1) .. rowsb )[ - s:=aug[k][i]; - ForEach(j, i .. (rowsb+1) )[ - aug[k][j] := aug[k][j] - (s/aug[i][i])*aug[i][j]; - //Echo({"aug[",k,"][",j,"] =", aug[k][j]," - ", - // aug[k][i],"/",aug[i][i],"*",aug[i][j]," k i =", k,i }); - ]; - ]; - ]; - //PrettyForm(aug); - x[rowsb]:=aug[rowsb][rowsb+1]/aug[rowsb][rowsb]; - If(InVerboseMode(),Echo({"set x[",rowsb,"] = ",x[rowsb] })); - - ForEach(i,(rowsb-1) .. 1 )[ - s:=aug[i][rowsb+1]; - ForEach(j,i+1 .. rowsb)[ - s := s - aug[i][j]*x[j]; - ]; - x[i]:=s/aug[i][i]; - If(InVerboseMode(),Echo({"set x[",i,"] = ",x[i] })); - ]; - x; - -]; - -%/mathpiper - - - -%mathpiper_docs,name="MatrixSolve",categories="User Functions;Solvers (Symbolic)" -*CMD MatrixSolve --- solve a system of equations -*STD -*CALL - MatrixSolve(A,b) - -*PARMS - -{A} -- coefficient matrix - -{b} -- row vector - -*DESC - -{MatrixSolve} solves the matrix equations {A*x = b} using Gaussian Elimination -with Backward substitution. If your matrix is triangular or diagonal, it will -be recognized as such and a faster algorithm will be used. - -*E.G. - - In> A:={{2,4,-2,-2},{1,2,4,-3},{-3,-3,8,-2},{-1,1,6,-3}}; - Out> {{2,4,-2,-2},{1,2,4,-3},{-3,-3,8,-2},{-1,1,6,-3}}; - In> b:={-4,5,7,7}; - Out> {-4,5,7,7}; - In> MatrixSolve(A,b); - Out> {1,2,3,4}; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Minor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Minor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Minor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Minor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="Minor" - -Minor(matrix,i,j) := CoFactor(matrix,i,j)*(-1)^(i+j); - -%/mathpiper - - - -%mathpiper_docs,name="Minor",categories="User Functions;Linear Algebra" -*CMD Minor --- get principal minor of a matrix -*STD -*CALL - Minor(M,i,j) - -*PARMS - -{M} -- a matrix - -{i}, {j} - positive integers - -*DESC - -Minor returns the minor of a matrix around -the element ($i$, $j$). The minor is the determinant of the matrix obtained from $M$ by -deleting the $i$-th row and the $j$-th column. - -*E.G. - - In> A := {{1,2,3}, {4,5,6}, {7,8,9}}; - Out> {{1,2,3},{4,5,6},{7,8,9}}; - In> PrettyForm(A); - - / \ - | ( 1 ) ( 2 ) ( 3 ) | - | | - | ( 4 ) ( 5 ) ( 6 ) | - | | - | ( 7 ) ( 8 ) ( 9 ) | - \ / - Out> True; - In> Minor(A,1,2); - Out> -6; - In> Determinant({{2,3}, {8,9}}); - Out> -6; - -*SEE CoFactor, Determinant, Inverse -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Normalize.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Normalize.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Normalize.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Normalize.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="Normalize" - -Function("Normalize",{vector}) -[ - Local(norm); - norm:=0; - ForEach(item,vector) - [ - norm:=norm+item*item; - ]; - (1/(norm^(1/2)))*vector; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Normalize",categories="User Functions;Linear Algebra" -*CMD Normalize --- normalize a vector -*STD -*CALL - Normalize(v) - -*PARMS - -{v} -- a vector - -*DESC - -Return the normalized (unit) vector parallel to {v}: a vector having the same -direction but with length 1. - -*E.G. - - In> v:=Normalize({3,4}) - Out> {3/5,4/5}; - In> v . v - Out> 1; - -*SEE InProduct, CrossProduct -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Norm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Norm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Norm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Norm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="Norm" - -10 # Norm(_v) <-- PNorm(v,2); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/o_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/o_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/o_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/o_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="o" - -_x o _y <-- Outer(x,y); - -%/mathpiper - - - -%mathpiper_docs,name="o",categories="Operators" -*CMD o --- get outer tensor product -*STD -*CALL - t1 o t2 -Precedence: -*EVAL OpPrecedence("o") - -*PARMS - -{t1,t2} -- tensor lists (currently only vectors are supported) - -*DESC - -See the {Outer} function for more information. - -*SEE Outer -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/OrthogonalBasis.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/OrthogonalBasis.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/OrthogonalBasis.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/OrthogonalBasis.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -%mathpiper,def="OrthogonalBasis" - -// This is the standard textbook definition of the Gram-Schmidt -// Orthogonalization process, from: -// Friedberg,Insel,Spence "Linear Algebra" (1997) -// TODO: This function does not check if the input vectors are LI, it -// only checks for zero vectors -Function("OrthogonalBasis",{W})[ - Local(V,j,k); - - V:=ZeroMatrix(Length(W),Length(W[1]) ); - - V[1]:=W[1]; - For(k:=2,k<=Length(W),k++)[ - Check(Not IsZero(Norm(W[k])) , - "OrthogonalBasis: Input vectors must be linearly independent"); - V[k]:=W[k]-Sum(j,1,k-1,InProduct(W[k],V[j])*V[j]/Norm(V[j])^2); - ]; - V; -]; - -%/mathpiper - - - -%mathpiper_docs,name="OrthogonalBasis",categories="User Functions;Linear Algebra" -*CMD OrthogonalBasis --- create an orthogonal basis -*STD -*CALL - OrthogonalBasis(W) - -*PARMS - -{W} - A linearly independent set of row vectors (aka a matrix) - -*DESC - -Given a linearly independent set {W} (constructed of rows vectors), -this command returns an orthogonal basis {V} for {W}, which means -that span(V) = span(W) and {InProduct(V[i],V[j]) = 0} when {i != j}. -This function uses the Gram-Schmidt orthogonalization process. - -*E.G. - - In> OrthogonalBasis({{1,1,0},{2,0,1},{2,2,1}}) - Out> {{1,1,0},{1,-1,1},{-1/3,1/3,2/3}}; - - -*SEE OrthonormalBasis, InProduct -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/OrthonormalBasis.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/OrthonormalBasis.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/OrthonormalBasis.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/OrthonormalBasis.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="OrthonormalBasis" - -// Like orthogonalization, only normalize all vectors -Function("OrthonormalBasis",{W})[ - Local(i); - W:=OrthogonalBasis(W); - For(i:=1,i<=Length(W),i++)[ - W[i]:=W[i]/Norm(W[i]); - ]; - W; -]; - -%/mathpiper - - - -%mathpiper_docs,name="OrthonormalBasis",categories="User Functions;Linear Algebra" -*CMD OrthonormalBasis --- create an orthonormal basis -*STD -*CALL - OrthonormalBasis(W) - -*PARMS - -{W} - A linearly independent set of row vectors (aka a matrix) - -*DESC - -Given a linearly independent set {W} (constructed of rows vectors), -this command returns an orthonormal basis {V} for {W}. This is done -by first using {OrthogonalBasis(W)}, then dividing each vector by its -magnitude, so as the give them unit length. - -*E.G. - - In> OrthonormalBasis({{1,1,0},{2,0,1},{2,2,1}}) - Out> {{Sqrt(1/2),Sqrt(1/2),0},{Sqrt(1/3),-Sqrt(1/3),Sqrt(1/3)}, - {-Sqrt(1/6),Sqrt(1/6),Sqrt(2/3)}}; - -*SEE OrthogonalBasis, InProduct, Normalize -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Outer.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Outer.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Outer.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Outer.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper,def="Outer" - -// outer product of vectors -Outer(t1_IsVector, t2_IsVector) <-- -[ - Local(i,j,n,m,result); - n:=Length(t1); - m:=Length(t2); - result:=ZeroMatrix(n,m); - For(i:=1,i<=n,i++) - For(j:=1,j<=m,j++) - result[i][j]:=t1[i]*t2[j]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Outer",categories="User Functions;Linear Algebra" -*CMD Outer, o --- get outer tensor product -*STD -*CALL - Outer(t1,t2) - t1 o t2 -Precedence: -*EVAL OpPrecedence("o") - -*PARMS - -{t1,t2} -- tensor lists (currently only vectors are supported) - -*DESC - -{Outer} returns the outer product of two tensors t1 and t2. Currently -{Outer} work works only for vectors, i.e. tensors of rank 1. The outer -product of two vectors yields a matrix. - -*E.G. - - In> Outer({1,2},{3,4,5}) - Out> {{3,4,5},{6,8,10}}; - In> Outer({a,b},{c,d}) - Out> {{a*c,a*d},{b*c,b*d}}; - - Or, using the "o"-Operator: - - In> {1,2} o {3,4,5} - Out> {{3,4,5},{6,8,10}}; - In> {a,b} o {c,d} - Out> {{a*c,a*d},{b*c,b*d}}; - - -*SEE Dot, Cross -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/period_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/period_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/period_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/period_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="." - -////// -// dot product for vectors and matrices (dr) -////// - -_x . _y <-- Dot(x,y); - -%/mathpiper - - - - -%mathpiper_docs,name=".",categories="Operators" -*CMD . --- get dot product of tensors -*STD -*CALL - t1 . t2 -Precedence: -*EVAL OpPrecedence(".") - -*PARMS - -{t1,t2} -- tensor lists (currently only vectors and matrices are supported) - -*DESC - -See the {Dot} function for more information. - -*SEE Dot -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/PNorm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/PNorm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/PNorm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/PNorm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -%mathpiper,def="PNorm" - -// p-norm, reduces to euclidean norm when p = 2 -Function("PNorm",{v,p}) -[ - Local(result,i); - Check(p>=1,"PNorm: p must be >= 1"); - - result:=0; - For(i:=1,i<=Length(v),i++)[ - result:=result+Abs(v[i])^p; - ]; - - // make it look nicer when p = 2 - If(p=2,Sqrt(result),(result)^(1/p) ); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/RecursiveDeterminant.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/RecursiveDeterminant.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/RecursiveDeterminant.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/RecursiveDeterminant.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="RecursiveDeterminant",scope="private" - -/* Recursive calculation of determinant, provided by Sebastian Ferraro - */ -20 # RecursiveDeterminant(_matrix) <-- -[ - /* - Computes a determinant recursively by summing the product of each (nonzero) element on the first row of the matrix - by +/- the determinant of the submatrix with the corresponding row and column deleted. - */ - Local(result); - If(Equals(Length(matrix),1),matrix[1][1],[ - result:=0; - ForEach(i,1 .. Length(matrix)) - //Consider only non-zero entries - If(Not(Equals(matrix[1][i],0)), - //Transpose and Drop eliminate row 1, column i - result:=result+matrix[1][i]*(-1)^(i+1)* RecursiveDeterminant(Transpose(Drop(Transpose(Drop(matrix,{1,1})),{i,i})))); - result; - ]); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Sparsity.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Sparsity.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Sparsity.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Sparsity.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -%mathpiper,def="Sparsity" - -Function("Sparsity",{matrix}) -[ - Local(rows,cols,nonzero); - nonzero:=0; - rows:=Length(matrix); - cols:=Length(matrix[1]); - ForEach(i, 1 .. rows ) - ForEach(j, 1 .. cols ) - If(matrix[i][j] != 0, nonzero:=nonzero+1 ); - - N(1 - nonzero/(rows*cols)); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Sparsity",categories="User Functions;Linear Algebra" -*CMD Sparsity --- get the sparsity of a matrix -*STD -*CALL - Sparsity(matrix) -*PARMS - -{matrix} -- a matrix - -*DESC - -The function {Sparsity} returns a number between {0} and {1} which -represents the percentage of zero entries in the matrix. Although -there is no definite critical value, a sparsity of {0.75} or more -is almost universally considered a "sparse" matrix. These type of -matrices can be handled in a different manner than "full" matrices -which speedup many calculations by orders of magnitude. - -*E.G. - - In> Sparsity(Identity(2)) - Out> 0.5; - In> Sparsity(Identity(10)) - Out> 0.9; - In> Sparsity(HankelMatrix(10)) - Out> 0.45; - In> Sparsity(HankelMatrix(100)) - Out> 0.495; - In> Sparsity(HilbertMatrix(10)) - Out> 0; - In> Sparsity(ZeroMatrix(10,10)) - Out> 1; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/SylvesterMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/SylvesterMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/SylvesterMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/SylvesterMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -%mathpiper,def="SylvesterMatrix" - -/* SylvesterMatrix */ - -Function("SylvesterMatrix",{poly1, poly2, var}) -[ - Local(i,m,p,q,y,z,result); - y:=Degree(poly1,var); - z:=Degree(poly2,var); - m:=y+z; - p:={}; - q:={}; - result:=ZeroMatrix(m,m); - - For(i:=y,i>=0,i--) - DestructiveAppend(p,Coef(poly1,var,i)); - For(i:=z,i>=0,i--) - DestructiveAppend(q,Coef(poly2,var,i)); - - For(i:=1,i<=z,i++) - [ - Local(j,k); - k:=1; - For(j:=i,k<=Length(p),j++) - [ - result[i][j]:=p[k]; - k++; - ]; - ]; - - For(i:=1,i<=y,i++) - [ - Local(j,k); - k:=1; - For(j:=i,k<=Length(q),j++) - [ - result[i+z][j]:=q[k]; - k++; - ]; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="SylvesterMatrix",categories="User Functions;Matrices (Special)" -*CMD SylvesterMatrix --- calculate the Sylvester matrix of two polynomials -*STD -*CALL - SylvesterMatrix(poly1,poly2,variable) - -*PARMS - -{poly1} -- polynomial - -{poly2} -- polynomial - -{variable} -- variable to express the matrix for - -*DESC - -The function {SylvesterMatrix} calculates the Sylvester matrix -for a pair of polynomials. - -The Sylvester matrix is closely related to the resultant, which -is defined as the determinant of the Sylvester matrix. Two polynomials -share common roots only if the resultant is zero. - -*E.G. - - In> ex1:= x^2+2*x-a - Out> x^2+2*x-a; - In> ex2:= x^2+a*x-4 - Out> x^2+a*x-4; - In> A:=SylvesterMatrix(ex1,ex2,x) - Out> {{1,2,-a,0},{0,1,2,-a}, - {1,a,-4,0},{0,1,a,-4}}; - In> B:=Determinant(A) - Out> 16-a^2*a- -8*a-4*a+a^2- -2*a^2-16-4*a; - In> Simplify(B) - Out> 3*a^2-a^3; - -The above example shows that the two polynomials have common -zeros if $ a = 3 $. - -*SEE Determinant, Simplify, Solve, PSolve -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/SymbolicDeterminant.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/SymbolicDeterminant.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/SymbolicDeterminant.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/SymbolicDeterminant.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -%mathpiper,def="SymbolicDeterminant",scope="private" - -20 # SymbolicDeterminant(_matrix) <-- -[ - Local(perms,indices,result); - Check((IsMatrix(matrix)),"Determinant: Argument must be a matrix"); - indices:=Table(i,i,1,Length(matrix),1); - perms:=PermutationsList(indices); - result:=0; - ForEach(item,perms) - result:=result+Product(i,1,Length(matrix),matrix[i][item[i] ])* - LeviCivita(item); - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/ToeplitzMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/ToeplitzMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/ToeplitzMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/ToeplitzMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -%mathpiper,def="ToeplitzMatrix" - -// The arguments of the following functions should be checked -ToeplitzMatrix(N):=GenMatrix({{i,j},N[Abs(i-j)+1]}, Length(N), Length(N) ); - -%/mathpiper - - - -%mathpiper_docs,name="ToeplitzMatrix",categories="User Functions;Matrices (Special)" -*CMD ToeplitzMatrix --- create a Toeplitz matrix -*STD -*CALL - ToeplitzMatrix(N) -*PARMS - -{N} -- an $n$-dimensional row vector - -*DESC - -The function {ToeplitzMatrix} calculates the Toeplitz matrix given -an $n$-dimensional row vector. This matrix has the same entries in -all diagonal columns, from upper left to lower right. - -*E.G. - - In> PrettyForm(ToeplitzMatrix({1,2,3,4,5})) - - / \ - | ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) | - | | - | ( 2 ) ( 1 ) ( 2 ) ( 3 ) ( 4 ) | - | | - | ( 3 ) ( 2 ) ( 1 ) ( 2 ) ( 3 ) | - | | - | ( 4 ) ( 3 ) ( 2 ) ( 1 ) ( 2 ) | - | | - | ( 5 ) ( 4 ) ( 3 ) ( 2 ) ( 1 ) | - \ / -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Trace.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Trace.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Trace.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Trace.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -%mathpiper,def="Trace" - -Trace(matrix_IsList) <-- Tr(matrix); - -%/mathpiper - - - -%mathpiper_docs,name="Trace",categories="User Functions;Linear Algebra" -*CMD Trace --- trace of a matrix -*STD -*CALL - Trace(M) - -*PARMS - -{M} -- a matrix - -*DESC - -{Trace} returns the trace of a matrix $M$ (defined as the sum of the -elements on the diagonal of the matrix). - -*E.G. - - In> A:=DiagonalMatrix(1 .. 4) - Out> {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; - In> Trace(A) - Out> 10; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Transpose.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Transpose.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Transpose.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Transpose.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="Transpose" - -Transpose(matrix_IsList)_(Length(Dimensions(matrix))>1) <-- -[ - Local(i,j,result); - result:=ZeroMatrix(Length(matrix[1]),Length(matrix)); - For(i:=1,i<=Length(matrix),i++) - For(j:=1,j<=Length(matrix[1]),j++) - result[j][i]:=matrix[i][j]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Transpose",categories="User Functions;Linear Algebra" -*CMD Transpose --- get transpose of a matrix -*STD -*CALL - Transpose(M) - -*PARMS - -{M} -- a matrix - -*DESC - -{Transpose} returns the transpose of a matrix $M$. Because matrices are -just lists of lists, this is a useful operation too for lists. - -*E.G. - - In> Transpose({{a,b}}) - Out> {{a},{b}}; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Tr.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Tr.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/Tr.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/Tr.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -%mathpiper,def="Tr" - -Tr(x_IsList) <-- -[ - Local(i,j,n,d,r,aux,result); - d:=Dimensions(x); - r:=Length(d); // tensor rank - n:=Min(d); // minimal dim - result:=0; - For(i:=1,i<=n,i++) - [ - aux:=x[i]; - For(j:=2,j<=r,j++) - aux:=aux[i]; - result:=result+aux; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/VandermondeMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/VandermondeMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/VandermondeMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/VandermondeMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="VandermondeMatrix" - -Function("VandermondeMatrix",{vector})[ - Local(len,i,j,item,matrix); - len:=Length(vector); - matrix:=ZeroMatrix(len,len); - - For(i:=1,i<=Length(matrix),i++)[ - For(j:=1,j<=Length(matrix[1]),j++)[ - matrix[j][i]:=vector[i]^(j-1); - ]; - ]; - - matrix; -]; - -%/mathpiper - - - -%mathpiper_docs,name="VandermondeMatrix",categories="User Functions;Matrices (Special)" -*CMD VandermondeMatrix --- create the Vandermonde matrix -*STD -*CALL - VandermondeMatrix(vector) -*PARMS - -{vector} -- an $n$-dimensional vector - -*DESC - -The function {VandermondeMatrix} calculates the Vandermonde matrix -of a vector. - -The ($i$,$j$)-th element of the Vandermonde matrix is defined as $i^(j-1)$. - -*E.G. - In> VandermondeMatrix({1,2,3,4}) - Out> {{1,1,1,1},{1,2,3,4},{1,4,9,16},{1,8,27,64}}; - In>PrettyForm(%) - - / \ - | ( 1 ) ( 1 ) ( 1 ) ( 1 ) | - | | - | ( 1 ) ( 2 ) ( 3 ) ( 4 ) | - | | - | ( 1 ) ( 4 ) ( 9 ) ( 16 ) | - | | - | ( 1 ) ( 8 ) ( 27 ) ( 64 ) | - \ / -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/WilkinsonMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/WilkinsonMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/WilkinsonMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/WilkinsonMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -%mathpiper,def="WilkinsonMatrix",scope="private" - -// Used to test numerical eigenvalue algorithms, because it -// has eigenvalues extremely close to each other. -// WilkinsonMatrix(21) has 2 eigenvalues near 10.7 that agree -// to 14 decimal places -// Leto: I am not going to document this until we actually have -// numerical eigenvalue algorithms -WilkinsonMatrix(N):=GenMatrix({{i,j}, - If( Abs(i-j)=1,1, - [ If(i=j,Abs( (N-1)/2 - i+1 ),0 ); ] )}, N,N ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/WronskianMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/WronskianMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/WronskianMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/WronskianMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="WronskianMatrix" - -// The arguments of the following functions should be checked -// this takes N funcs in 1 var -WronskianMatrix(f,v):=GenMatrix({{i,j}, Deriv(v,i-1) f[j]}, Length(f), Length(f) ); - -%/mathpiper - - - -%mathpiper_docs,name="WronskianMatrix",categories="User Functions;Matrices (Special)" -*CMD WronskianMatrix --- create the Wronskian matrix -*STD -*CALL - WronskianMatrix(func,var) -*PARMS - -{func} -- an $n$-dimensional vector of functions - -{var} -- a variable to differentiate with respect to - -*DESC - -The function {WronskianMatrix} calculates the Wronskian matrix -of $n$ functions. - -The Wronskian matrix is created by putting each function as the -first element of each column, and filling in the rest of each -column by the ($i-1$)-th derivative, where $i$ is the current row. - -The Wronskian matrix is used to verify that the $n$ functions are linearly -independent, usually solutions to a differential equation. -If the determinant of the Wronskian matrix is zero, then the functions -are dependent, otherwise they are independent. - -*E.G. - In> WronskianMatrix({Sin(x),Cos(x),x^4},x); - Out> {{Sin(x),Cos(x),x^4},{Cos(x),-Sin(x),4*x^3}, - {-Sin(x),-Cos(x),12*x^2}}; - In> PrettyForm(%) - - / \ - | ( Sin( x ) ) ( Cos( x ) ) / 4 \ | - | \ x / | - | | - | ( Cos( x ) ) ( -( Sin( x ) ) ) / 3 \ | - | \ 4 * x / | - | | - | ( -( Sin( x ) ) ) ( -( Cos( x ) ) ) / 2 \ | - | \ 12 * x / | - \ / -The last element is a linear combination of the first two, so the determinant is zero: - In> A:=Determinant( WronskianMatrix( {x^4,x^3,2*x^4 - + 3*x^3},x ) ) - Out> x^4*3*x^2*(24*x^2+18*x)-x^4*(8*x^3+9*x^2)*6*x - +(2*x^4+3*x^3)*4*x^3*6*x-4*x^6*(24*x^2+18*x)+x^3 - *(8*x^3+9*x^2)*12*x^2-(2*x^4+3*x^3)*3*x^2*12*x^2; - In> Simplify(A) - Out> 0; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/X_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/X_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/X_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/X_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="X" - -x X y := CrossProduct(x,y); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/ZeroMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/ZeroMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/ZeroMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/ZeroMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="ZeroMatrix" - -5 # ZeroMatrix(n_IsNonNegativeInteger) <-- ZeroMatrix(n,n); - -10 # ZeroMatrix(n_IsNonNegativeInteger,m_IsNonNegativeInteger) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=n,i++) - DestructiveInsert(result,i,ZeroVector(m)); - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="ZeroMatrix",categories="User Functions;Linear Algebra" -*CMD ZeroMatrix --- make a zero matrix -*STD -*CALL - ZeroMatrix(n) - ZeroMatrix(n, m) - -*PARMS - -{n} -- number of rows - -{m} -- number of columns - -*DESC - -This command returns a matrix with {n} rows and {m} columns, -completely filled with zeroes. If only given one parameter, -it returns the square {n} by {n} zero matrix. - -*E.G. - - In> ZeroMatrix(3,4) - Out> {{0,0,0,0},{0,0,0,0},{0,0,0,0}}; - In> ZeroMatrix(3) - Out> {{0,0,0},{0,0,0},{0,0,0}}; - - -*SEE ZeroVector, Identity -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/ZeroVector.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/ZeroVector.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/linalg/ZeroVector.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/linalg/ZeroVector.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -%mathpiper,def="ZeroVector" - -Function("ZeroVector",{n}) -[ - Local(i,result); - result:={}; - For(i:=1,i<=n,i++) - [ - DestructiveInsert(result,1,0); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="ZeroVector",categories="User Functions;Linear Algebra" -*CMD ZeroVector --- create a vector with all zeroes -*STD -*CALL - ZeroVector(n) - -*PARMS - -{n} -- length of the vector to return - -*DESC - -This command returns a vector of length "n", filled with zeroes. - -*E.G. - - In> ZeroVector(4) - Out> {0,0,0,0}; - -*SEE BaseVector, ZeroMatrix, IsZeroVector -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Append.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Append.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Append.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Append.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="Append" - -Function("Append",{list,element}) -[ - Check(IsList(list), "The first argument must be a list."); - - Insert(list,Length(list)+1,element); -]; - - -%/mathpiper - - - -%mathpiper_docs,name="Append",categories="User Functions;Lists (Operations)" -*CMD Append --- append an entry at the end of a list -*STD -*CALL - Append(list, expr) - -*PARMS - -{list} -- list to append "expr" to - -{expr} -- expression to append to the list - -*DESC - -The expression "expr" is appended at the end of "list" and the -resulting list is returned. - -Note that due to the underlying data structure, the time it takes to -append an entry at the end of a list grows linearly with the length of -the list, while the time for prepending an entry at the beginning is -constant. - -*E.G. - - In> Append({a,b,c,d}, 1); - Out> {a,b,c,d,1}; - -*SEE Concat, :, DestructiveAppend -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/BSearch.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/BSearch.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/BSearch.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/BSearch.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -%mathpiper,def="BSearch" - -LocalSymbols(max,f,result) -[ - BSearch(max,f) := - [ - Local(result); - Set(result, FindIsq(max,f)); - If(Apply(f,{result})!=0,Set(result,-1)); - result; - ]; -]; -UnFence("BSearch",2); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/BubbleSort.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/BubbleSort.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/BubbleSort.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/BubbleSort.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -%mathpiper,def="BubbleSort" - -Function("BubbleSort",{list,compare}) -[ - Local(i,j,length,left,right); - - list:=FlatCopy(list); - length:=Length(list); - - For (j:=length,j>1,j--) - [ - For(i:=1,i BubbleSort({4,7,23,53,-2,1}, "<"); - Out> {-2,1,4,7,23,53}; - In> HeapSort({4,7,23,53,-2,1}, ">"); - Out> {53,23,7,4,1,-2}; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Contains.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Contains.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Contains.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Contains.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="Contains" - -Function("Contains",{list,element}) -[ - Local(result); - Set(result,False); - While(And(Not(result), Not(Equals(list, {})))) - [ - If(Equals(First(list),element), - Set(result, True), - Set(list, Rest(list)) - ); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Contains",categories="User Functions;Lists (Operations)" -*CMD Contains --- test whether a list contains a certain element -*STD -*CALL - Contains(list, expr) - -*PARMS - -{list} -- list to examine - -{expr} -- expression to look for in "list" - -*DESC - -This command tests whether "list" contains the expression "expr" -as an entry. It returns {True} if it does and -{False} otherwise. Only the top level of "list" is -examined. The parameter "list" may also be a general expression, in -that case the top-level operands are tested for the occurrence of -"expr". - -*E.G. - - In> Contains({a,b,c,d}, b); - Out> True; - In> Contains({a,b,c,d}, x); - Out> False; - In> Contains({a,{1,2,3},z}, 1); - Out> False; - In> Contains(a*b, b); - Out> True; - -*SEE Find, Count -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Count.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Count.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Count.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Count.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="Count" - -Function("Count",{list,element}) -[ - Local(result); - Set(result,0); - ForEach(item,list) If(Equals(item, element), Set(result,AddN(result,1))); - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Count",categories="User Functions;Lists (Operations)" -*CMD Count --- count the number of occurrences of an expression -*STD -*CALL - Count(list, expr) - -*PARMS - -{list} -- the list to examine - -{expr} -- expression to look for in "list" - -*DESC - -This command counts the number of times that the expression "expr" -occurs in "list" and returns this number. - -*E.G. - - In> lst := {a,b,c,b,a}; - Out> {a,b,c,b,a}; - In> Count(lst, a); - Out> 2; - In> Count(lst, c); - Out> 1; - In> Count(lst, x); - Out> 0; - -*SEE Length, Select, Contains -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/DestructiveAppendList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/DestructiveAppendList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/DestructiveAppendList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/DestructiveAppendList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -%mathpiper,def="DestructiveAppendList" - -Function("DestructiveAppendList",{list,toadd}) -[ - Local(i,nr); - nr:=Length(toadd); - For(i:=1,i<=nr,i++) - [ - DestructiveAppend(list,toadd[i]); - ]; - True; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/DestructiveAppend.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/DestructiveAppend.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/DestructiveAppend.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/DestructiveAppend.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%mathpiper,def="DestructiveAppend" - -Function("DestructiveAppend",{list,element}) -[ - DestructiveInsert(list,Length(list)+1,element); -]; - -%/mathpiper - - - -%mathpiper_docs,name="DestructiveAppend",categories="User Functions;Lists (Operations)" -*CMD DestructiveAppend --- destructively append an entry to a list -*STD -*CALL - DestructiveAppend(list, expr) - -*PARMS - -{list} -- list to append "expr" to - -{expr} -- expression to append to the list - -*DESC - -This is the destructive counterpart of {Append}. This -command yields the same result as the corresponding call to -{Append}, but the original list is modified. So if a -variable is bound to "list", it will now be bound to the list with -the expression "expr" inserted. - -Destructive commands run faster than their nondestructive counterparts -because the latter copy the list before they alter it. - -*E.G. - - In> lst := {a,b,c,d}; - Out> {a,b,c,d}; - In> Append(lst, 1); - Out> {a,b,c,d,1}; - In> lst - Out> {a,b,c,d}; - In> DestructiveAppend(lst, 1); - Out> {a,b,c,d,1}; - In> lst; - Out> {a,b,c,d,1}; - -*SEE Concat, :, Append -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Difference.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Difference.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Difference.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Difference.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="Difference" - -Function("Difference",{list1,list2}) -[ - Local(l2,index,result); - l2:=FlatCopy(list2); - result:=FlatCopy(list1); - ForEach(item,list1) - [ - Set(index,Find(l2,item)); - If(index>0, - [ - DestructiveDelete(l2,index); - DestructiveDelete(result,Find(result,item)); - ] - ); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Difference",categories="User Functions;Lists (Operations)" -*CMD Difference --- return the difference of two lists -*STD -*CALL - Difference(l1, l2) - -*PARMS - -{l1}, {l2} -- two lists - -*DESC - -The difference of the lists "l1" and "l2" is determined and -returned. The difference contains all elements that occur in "l1" -but not in "l2". The order of elements in "l1" is preserved. If a -certain expression occurs "n1" times in the first list and "n2" -times in the second list, it will occur "n1-n2" times in the result -if "n1" is greater than "n2" and not at all otherwise. - -*E.G. - - In> Difference({a,b,c}, {b,c,d}); - Out> {a}; - In> Difference({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); - Out> {a,i}; - In> Difference({1,2,2,3,3,3}, {2,2,3,4,4}); - Out> {1,3,3}; - -*SEE Intersection, Union -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Drop.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Drop.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Drop.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Drop.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -%mathpiper,def="Drop" - -/* ���� Drop ���� */ - -/* Needs to check the parameters */ - -/* - * Drop( list, n ) gives 'list' with its first n elements dropped - * Drop( list, -n ) gives 'list' with its last n elements dropped - * Drop( list, {m,n} ) gives 'list' with elements m through n dropped - */ - -RuleBase("Drop", {lst, range}); - -Rule("Drop", 2, 1, IsList(range)) - Concat(Take(lst,range[1]-1), Drop(lst, range[2])); - -Rule("Drop", 2, 2, range >= 0) - If( range = 0 Or lst = {}, lst, Drop( Rest(lst), range-1 )); - -Rule("Drop", 2, 2, range < 0) - Take( lst, Length(lst) + range ); - -%/mathpiper - - - -%mathpiper_docs,name="Drop",categories="User Functions;Lists (Operations)" -*CMD Drop --- drop a range of elements from a list - -*STD - -*CALL - Drop(list, n) - Drop(list, -n) - Drop(list, {m,n}) - -*PARMS - -{list} -- list to act on - -{n}, {m} -- positive integers describing the entries to drop - -*DESC - -This command removes a sublist of "list" and returns a list -containing the remaining entries. The first calling sequence drops the -first "n" entries in "list". The second form drops the last "n" -entries. The last invocation drops the elements with indices "m" -through "n". - -*E.G. - - In> lst := {a,b,c,d,e,f,g}; - Out> {a,b,c,d,e,f,g}; - In> Drop(lst, 2); - Out> {c,d,e,f,g}; - In> Drop(lst, -3); - Out> {a,b,c,d}; - In> Drop(lst, {2,4}); - Out> {a,e,f,g}; - -*SEE Take, Select, Remove -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FillList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FillList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FillList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FillList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="FillList" - -Function("FillList", {aItem, aLength}) -[ - Local(i, aResult); - aResult:={}; - For(i:=0, i FillList(x, 5); - Out> {x,x,x,x,x}; - -*SEE MakeVector, ZeroVector, RandomIntegerVector -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FindIsq.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FindIsq.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FindIsq.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FindIsq.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -%mathpiper,def="FindIsq" - -LocalSymbols(max,f,low,high,mid,current) -[ -FindIsq(max,f) := -[ - Local(low,high,mid,current); - low:=1; - high:=max+1; - Set(mid,((high+low)>>1)); - While(high>low And mid>1) - [ - Set(mid,((high+low)>>1)); - Set(current,Apply(f,{mid})); -//Echo({low,high,current}); - If(current = 0, - high:=low-1, - If(current > 0, - Set(high,mid), - Set(low,mid+1) - ) - ); - ]; - mid; -]; -]; -UnFence("FindIsq",2); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Find.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Find.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Find.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Find.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -%mathpiper,def="Find" - -Function("Find",{list,element}) -[ - Local(result,count); - Set(result, -1); - Set(count, 1); - While(And(result<0, Not(Equals(list, {})))) - [ - If(Equals(First(list), element), - Set(result, count) - ); - Set(list,Rest(list)); - Set(count,AddN(count,1)); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Find",categories="User Functions;Lists (Operations)" -*CMD Find --- get the index at which a certain element occurs -*STD -*CALL - Find(list, expr) - -*PARMS - -{list} -- the list to examine - -{expr} -- expression to look for in "list" - -*DESC - -This commands returns the index at which the expression "expr" -occurs in "list". If "expr" occurs more than once, the lowest -index is returned. If "expr" does not occur at all, -{-1} is returned. - -*E.G. - - In> Find({a,b,c,d,e,f}, d); - Out> 4; - In> Find({1,2,3,2,1}, 2); - Out> 2; - In> Find({1,2,3,2,1}, 4); - Out> -1; - -*SEE Contains -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FindPredicate.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FindPredicate.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FindPredicate.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FindPredicate.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -%mathpiper,def="FindPredicate" - -// Find the first thingy that matches a predicate -Function("FindPredicate",{list,predicate}) -[ - Local(result,count); - Set(result, -1); - Set(count, 1); - While(And(result<0, Not(Equals(list, {})))) - [ - If(Apply(predicate,{First(list)}), - Set(result, count) - ); - Set(list,Rest(list)); - Set(count,AddN(count,1)); - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FuncListArith.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FuncListArith.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FuncListArith.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FuncListArith.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="FuncListArith" - -/* FuncListArith() is defined to only look at arithmetic operations +, -, *, /. */ - -FuncListArith(expr) := FuncList(expr, {Atom("+"), Atom("-"), *, /}); - -HoldArgNr("FuncListArith", 1, 1); - -%/mathpiper - - - -%mathpiper_docs,name="FuncListArith",categories="User Functions;Lists (Operations)" -*CMD FuncList --- list of functions used in an expression -*CMD FuncListArith --- list of functions used in an expression -*CMD FuncListSome --- list of functions used in an expression -*STD -*CALL - FuncList(expr) - FuncListArith(expr) - FuncListSome(expr, list) - -*PARMS - -{expr} -- an expression - -{list} -- list of function atoms to be considered "transparent" - -*DESC - -The command {FuncList(expr)} returns a list of all function atoms that appear -in the expression {expr}. The expression is recursively traversed. - -The command {FuncListSome(expr, list)} does the same, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain any other functions). -For example, {FuncListSome(a + Sin(b-c))} will see that the expression has a "{-}" operation and return {{+,Sin,-}}, but {FuncListSome(a + Sin(b-c), {+})} will not look at arguments of {Sin()} and will return {{+,Sin}}. - -{FuncListArith} is defined through {FuncListSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. notest - - In> FuncList(x+y*Cos(Ln(x)/x)) - Out> {+,*,Cos,/,Ln}; - In> FuncListArith(x+y*Cos(Ln(x)/x)) - Out> {+,*,Cos}; - In> FuncListSome({a+b*2,c/d},{List}) - Out> {List,+,/}; - -*SEE VarList, HasExpr, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FuncList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FuncList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FuncList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FuncList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -%mathpiper,def="FuncList" - -////////////////////////////////////////////////// -/// FuncList --- list all function atoms used in an expression -////////////////////////////////////////////////// -/// like VarList except collects functions - -10 # FuncList(expr_IsAtom) <-- {}; -20 # FuncList(expr_IsFunction) <-- -RemoveDuplicates( - Concat( - {First(Listify(expr))}, - Apply("Concat", - MapSingle("FuncList", Rest(Listify(expr))) - ) - ) -); - -/* -This is like FuncList except only looks at arguments of a given list of functions. All other functions become "opaque". - -*/ -10 # FuncList(expr_IsAtom, look'list_IsList) <-- {}; -// a function not in the looking list - return its type -20 # FuncList(expr_IsFunction, look'list_IsList)_(Not Contains(look'list, Atom(Type(expr)))) <-- {Atom(Type(expr))}; -// a function in the looking list - traverse its arguments -30 # FuncList(expr_IsFunction, look'list_IsList) <-- -RemoveDuplicates( - Concat( - {First(Listify(expr))}, - [ // gave up trying to do it using Map and MapSingle... so writing a loop now. - // obtain a list of functions, considering only functions in look'list - Local(item, result); - result := {}; - ForEach(item, expr) result := Concat(result, FuncList(item, look'list)); - result; - ] - ) -); - -HoldArgNr("FuncList", 1, 1); -HoldArgNr("FuncList", 2, 1); - -%/mathpiper - - - -%mathpiper_docs,name="FuncList",categories="User Functions;Lists (Operations)" -*CMD FuncList --- list of functions used in an expression -*CMD FuncListArith --- list of functions used in an expression -*CMD FuncListSome --- list of functions used in an expression -*STD -*CALL - FuncList(expr) - FuncListArith(expr) - FuncListSome(expr, list) - -*PARMS - -{expr} -- an expression - -{list} -- list of function atoms to be considered "transparent" - -*DESC - -The command {FuncList(expr)} returns a list of all function atoms that appear -in the expression {expr}. The expression is recursively traversed. - -The command {FuncListSome(expr, list)} does the same, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain any other functions). -For example, {FuncListSome(a + Sin(b-c))} will see that the expression has a "{-}" operation and return {{+,Sin,-}}, but {FuncListSome(a + Sin(b-c), {+})} will not look at arguments of {Sin()} and will return {{+,Sin}}. - -{FuncListArith} is defined through {FuncListSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. notest - - In> FuncList(x+y*Cos(Ln(x)/x)) - Out> {+,*,Cos,/,Ln}; - In> FuncListArith(x+y*Cos(Ln(x)/x)) - Out> {+,*,Cos}; - In> FuncListSome({a+b*2,c/d},{List}) - Out> {List,+,/}; - -*SEE VarList, HasExpr, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FuncListSome.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FuncListSome.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/FuncListSome.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/FuncListSome.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="" - -//todo:tk:not defined in the scripts. - -%/mathpiper - - - -%mathpiper_docs,name="FuncListSome",categories="User Functions;Lists (Operations)" -*CMD FuncList --- list of functions used in an expression -*CMD FuncListArith --- list of functions used in an expression -*CMD FuncListSome --- list of functions used in an expression -*STD -*CALL - FuncList(expr) - FuncListArith(expr) - FuncListSome(expr, list) - -*PARMS - -{expr} -- an expression - -{list} -- list of function atoms to be considered "transparent" - -*DESC - -The command {FuncList(expr)} returns a list of all function atoms that appear -in the expression {expr}. The expression is recursively traversed. - -The command {FuncListSome(expr, list)} does the same, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain any other functions). -For example, {FuncListSome(a + Sin(b-c))} will see that the expression has a "{-}" operation and return {{+,Sin,-}}, but {FuncListSome(a + Sin(b-c), {+})} will not look at arguments of {Sin()} and will return {{+,Sin}}. - -{FuncListArith} is defined through {FuncListSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. notest - - In> FuncList(x+y*Cos(Ln(x)/x)) - Out> {+,*,Cos,/,Ln}; - In> FuncListArith(x+y*Cos(Ln(x)/x)) - Out> {+,*,Cos}; - In> FuncListSome({a+b*2,c/d},{List}) - Out> {List,+,/}; - -*SEE VarList, HasExpr, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/global_stack.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/global_stack.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/global_stack.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/global_stack.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -%mathpiper,def="GlobalPush;GlobalPop" - -////////////////////////////////////////////////// -/// Global stack operations on variables -////////////////////////////////////////////////// - - -LocalSymbols(GlobalStack, x) -[ - GlobalStack := {}; - - GlobalPop(x_IsAtom) <-- - [ - Check(Length(GlobalStack)>0, "GlobalPop: Error: empty GlobalStack"); - MacroSet(x, PopFront(GlobalStack)); - Eval(x); - ]; - - HoldArgNr("GlobalPop", 1, 1); - - GlobalPop() <-- - [ - Check(Length(GlobalStack)>0, "GlobalPop: Error: empty GlobalStack"); - PopFront(GlobalStack); - ]; - - GlobalPush(_x) <-- - [ - Push(GlobalStack, x); - x; - ]; -]; - -%/mathpiper - - - -%mathpiper_docs,name="GlobalPop;GlobalPush",categories="User Functions;Lists (Operations)" -*CMD GlobalPop --- restore variables using a global stack -*CMD GlobalPush --- save variables using a global stack -*STD -*CALL - GlobalPop(var) - GlobalPop() - GlobalPush(expr) - -*PARMS - -{var} -- atom, name of variable to restore from the stack - -{expr} -- expression, value to save on the stack - -*DESC - -These functions operate with a global stack, currently implemented as a list that is not accessible externally (it is protected -through {LocalSymbols}). - -{GlobalPush} stores a value on the stack. {GlobalPop} removes the last pushed value from the stack. If a variable name is given, the variable is assigned, otherwise the popped value is returned. - -If the global stack is empty, an error message is printed. - -*E.G. - - In> GlobalPush(3) - Out> 3; - In> GlobalPush(Sin(x)) - Out> Sin(x); - In> GlobalPop(x) - Out> Sin(x); - In> GlobalPop(x) - Out> 3; - In> x - Out> 3; - -*SEE Push, PopFront -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/HeapSort.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/HeapSort.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/HeapSort.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/HeapSort.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -%mathpiper,def="HeapSort" - -HeapSort(list, compare) := HeapSort(list, ArrayCreate(Length(list), 0), 1, Length(list), compare); - -// this will sort "list" and mangle "tmplist" -1 # HeapSort(_list, _tmplist, _first, _last, _compare) _ (last - first <= 2) <-- SmallSort(list, first, last, compare); -2 # HeapSort(_list, _tmplist, _first, _last, _compare) <-- -[ // See: J. W. J. Williams, Algorithm 232 (Heapsort), Com. of ACM, vol. 7, no. 6, p. 347 (1964) - // sort two halves recursively, then merge two halves - // cannot merge in-place efficiently, so need a second list - Local(mid, ileft, iright, pleft); - mid := first+((last-first)>>1); - HeapSort(list, tmplist, first, mid, compare); - HeapSort(list, tmplist, mid+1, last, compare); - // copy the lower part to temporary array - For(ileft := first, ileft <= mid, ileft++) - tmplist[ileft] := list[ileft]; - For( - [ileft := first; pleft := first; iright := mid+1;], - ileft <= mid, // if the left half is finished, we don't have to do any more work - pleft++ // one element is stored at each iteration - ) // merge two halves - // elements before pleft have been stored - // the smallest element of the right half is at iright - // the smallest element of the left half is at ileft, access through tmplist - If( // we copy an element from ileft either if it is smaller or if the right half is finished; it is unnecessary to copy the remainder of the right half since the right half stays in the "list" - iright>last Or Apply(compare,{tmplist[ileft],list[iright]}), - [ // take element from ileft - list[pleft] := tmplist[ileft]; - ileft++; - ], - [ // take element from iright - list[pleft] := list[iright]; - iright++; - ] - ); - - list; -]; - -%/mathpiper - - - -%mathpiper_docs,name="HeapSort",categories="User Functions;Lists (Operations)" -*CMD BubbleSort --- sort a list -*CMD HeapSort --- sort a list -*STD -*CALL - BubbleSort(list, compare) - HeapSort(list, compare) - -*PARMS - -{list} -- list to sort - -{compare} -- function used to compare elements of {list} - -*DESC - -This command returns {list} after it is sorted using {compare} to -compare elements. The function {compare} should accept two arguments, -which will be elements of {list}, and compare them. It should return -{True} if in the sorted list the second argument -should come after the first one, and {False} -otherwise. - -The function {BubbleSort} uses the so-called "bubble sort" algorithm to do the -sorting by swapping elements that are out of order. This algorithm is easy to -implement, though it is not particularly fast. The sorting time is proportional -to $n^2$ where $n$ is the length of the list. - -The function {HeapSort} uses a recursive algorithm "heapsort" and is much -faster for large lists. The sorting time is proportional to $n*Ln(n)$ where $n$ -is the length of the list. - -*E.G. - - In> BubbleSort({4,7,23,53,-2,1}, "<"); - Out> {-2,1,4,7,23,53}; - In> HeapSort({4,7,23,53,-2,1}, ">"); - Out> {53,23,7,4,1,-2}; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Intersection.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Intersection.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Intersection.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Intersection.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%mathpiper,def="Intersection" - -Function("Intersection",{list1,list2}) -[ - Local(l2,index,result); - l2:=FlatCopy(list2); - result:={}; - ForEach(item,list1) - [ - Set(index, Find(l2,item)); - If(index>0, - [ - DestructiveDelete(l2,index); - DestructiveInsert(result,1,item); - ] - ); - ]; - DestructiveReverse(result); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Intersection",categories="User Functions;Lists (Operations)" -*CMD Intersection --- return the intersection of two lists -*STD -*CALL - Intersection(l1, l2) - -*PARMS - -{l1}, {l2} -- two lists - -*DESC - -The intersection of the lists "l1" and "l2" is determined and -returned. The intersection contains all elements that occur in both -lists. The entries in the result are listed in the same order as in -"l1". If an expression occurs multiple times in both "l1" and -"l2", then it will occur the same number of times in the result. - -*E.G. - - In> Intersection({a,b,c}, {b,c,d}); - Out> {b,c}; - In> Intersection({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); - Out> {e,o,u}; - In> Intersection({1,2,2,3,3,3}, {1,1,2,2,3,3}); - Out> {1,2,2,3,3}; - -*SEE Union, Difference -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MacroMapArgs.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MacroMapArgs.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MacroMapArgs.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MacroMapArgs.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="MacroMapArgs" - -/* Another Macro... hack for /: to work. */ -Macro("MacroMapArgs",{expr,oper}) -[ - Local(ex,tl,op); - Set(op,@oper); - Set(ex,Listify(@expr)); - Set(tl,Rest(ex)); - - UnList(Concat({ex[1]}, - `MacroMapSingle(@op,Hold(@tl))) - ); -]; - -UnFence("MacroMapArgs",2); -HoldArg("MacroMapArgs",oper); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MacroMapSingle.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MacroMapSingle.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MacroMapSingle.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MacroMapSingle.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -%mathpiper,def="MacroMapSingle" - -/* Another Macro... hack for /: to work. */ -TemplateFunction("MacroMapSingle",{func,list}) -[ - Local(mapsingleresult); - mapsingleresult:={}; - - ForEach(mapsingleitem,list) - [ - DestructiveInsert(mapsingleresult,1, - `ApplyPure(func,{Hold(Hold(@mapsingleitem))})); - ]; - DestructiveReverse(mapsingleresult); -]; -UnFence("MacroMapSingle",2); -HoldArg("MacroMapSingle",func); -HoldArg("MacroMapSingle",list); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MapArgs.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MapArgs.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MapArgs.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MapArgs.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="MapArgs" - -TemplateFunction("MapArgs",{expr,oper}) -[ - Set(expr,Listify(expr)); - UnList(Concat({expr[1]}, - Apply("MapSingle",{oper,Rest(expr)}) - ) ); -]; -UnFence("MapArgs",2); -HoldArg("MapArgs",oper); - -%/mathpiper - - - -%mathpiper_docs,name="MapArgs",categories="User Functions;Control Flow" -*CMD MapArgs --- apply a function to all top-level arguments -*STD -*CALL - MapArgs(expr, fn) - -*PARMS - -{expr} -- an expression to work on - -{fn} -- an operation to perform on each argument - -*DESC - -Every top-level argument in "expr" is substituted by the result of -applying "fn" to this argument. Here "fn" can be either the name -of a function or a pure function (see Apply for more information on -pure functions). - -*E.G. - - In> MapArgs(f(x,y,z),"Sin"); - Out> f(Sin(x),Sin(y),Sin(z)); - In> MapArgs({3,4,5,6}, {{x},x^2}); - Out> {9,16,25,36}; - -*SEE MapSingle, Map, Apply -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Map.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Map.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Map.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Map.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%mathpiper,def="Map" - -LocalSymbols(func,lists,mapsingleresult,mapsingleitem) -[ - Function("Map",{func,lists}) - [ - Local(mapsingleresult,mapsingleitem); - mapsingleresult:={}; - lists:=Transpose(lists); - ForEach(mapsingleitem,lists) - [ - DestructiveInsert(mapsingleresult,1,Apply(func,mapsingleitem)); - ]; - DestructiveReverse(mapsingleresult); - ]; - UnFence("Map",2); - HoldArg("Map",func); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Map",categories="User Functions;Lists (Operations)" -*CMD Map --- apply an $n$-ary function to all entries in a list -*STD -*CALL - Map(fn, list) - -*PARMS - -{fn} -- function to apply - -{list} -- list of lists of arguments - -*DESC - -This function applies "fn" to every list of arguments to be found in -"list". So the first entry of "list" should be a list containing -the first, second, third, ... argument to "fn", and the same goes -for the other entries of "list". The function can either be given as -a string or as a pure function (see Apply for more information on -pure functions). - -*E.G. - - In> MapSingle("Sin",{a,b,c}); - Out> {Sin(a),Sin(b),Sin(c)}; - In> Map("+",{{a,b},{c,d}}); - Out> {a+c,b+d}; - -*SEE MapSingle, MapArgs, Apply -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MapSingle.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MapSingle.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/MapSingle.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/MapSingle.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -%mathpiper,def="MapSingle" - -TemplateFunction("MapSingle",{func,list}) -[ - Local(mapsingleresult); - mapsingleresult:={}; - - ForEach(mapsingleitem,list) - [ - DestructiveInsert(mapsingleresult,1, - Apply(func,{mapsingleitem})); - ]; - DestructiveReverse(mapsingleresult); -]; -UnFence("MapSingle",2); -HoldArg("MapSingle",func); - -%/mathpiper - - - -%mathpiper_docs,name="MapSingle",categories="User Functions;Lists (Operations)" -*CMD MapSingle --- apply a unary function to all entries in a list -*STD -*CALL - MapSingle(fn, list) - -*PARMS - -{fn} -- function to apply - -{list} -- list of arguments - -*DESC - -The function "fn" is successively applied to all entries in -"list", and a list containing the respective results is -returned. The function can be given either as a string or as a pure -function (see Apply for more information on pure functions). - -The {/@} operator provides a shorthand for -{MapSingle}. - -*E.G. - - In> MapSingle("Sin",{a,b,c}); - Out> {Sin(a),Sin(b),Sin(c)}; - In> MapSingle({{x},x^2}, {a,2,c}); - Out> {a^2,4,c^2}; - -*SEE Map, MapArgs, /@, Apply -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Partition.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Partition.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Partition.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Partition.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="Partition" - -/* ���� Partition ���� */ - -/* Partition( list, n ) partitions 'list' into non-overlapping sublists of length n */ - -Partition(lst, len):= - If( Length(lst) < len Or len = 0, {}, - Concat( {Take(lst,len)}, Partition(Drop(lst,len), len) )); - -%/mathpiper - - - -%mathpiper_docs,name="Partition",categories="User Functions;Lists (Operations)" -*CMD Partition --- partition a list in sublists of equal length -*STD -*CALL - Partition(list, n) - -*PARMS - -{list} -- list to partition - -{n} -- length of partitions - -*DESC - -This command partitions "list" into non-overlapping sublists of -length "n" and returns a list of these sublists. The first "n" -entries in "list" form the first partition, the entries from -position "n+1" up to "2n" form the second partition, and so on. If -"n" does not divide the length of "list", the remaining entries -will be thrown away. If "n" equals zero, an empty list is -returned. - -*E.G. - - In> Partition({a,b,c,d,e,f,}, 2); - Out> {{a,b},{c,d},{e,f}}; - In> Partition(1 .. 11, 3); - Out> {{1,2,3},{4,5,6},{7,8,9}}; - -*SEE Take, PermutationsList -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/PopBack.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/PopBack.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/PopBack.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/PopBack.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="PopBack" - -Function("PopBack",{stack}) Pop(stack,Length(stack)); - -%/mathpiper - - - -%mathpiper_docs,name="PopBack",categories="User Functions;Lists (Operations)" -*CMD PopBack --- remove an element from the bottom of a stack -*STD -*CALL - PopBack(stack) - -*PARMS - -{stack} -- a list (which serves as the stack container) - -*DESC - -This is part of a simple implementation of a stack, internally -represented as a list. This command removes the element at the bottom -of the stack and returns this element. Of course, the stack should not -be empty. - -*E.G. - - In> stack := {}; - Out> {}; - In> Push(stack, x); - Out> {x}; - In> Push(stack, x2); - Out> {x2,x}; - In> Push(stack, x3); - Out> {x3,x2,x}; - In> PopBack(stack); - Out> x; - In> stack; - Out> {x3,x2}; - -*SEE Push, Pop, PopFront -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/PopFront.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/PopFront.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/PopFront.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/PopFront.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="PopFront" - -Function("PopFront",{stack}) Pop(stack,1); - -%/mathpiper - - - -%mathpiper_docs,name="PopFront",categories="User Functions;Lists (Operations)" -*CMD PopFront --- remove an element from the top of a stack -*STD -*CALL - PopFront(stack) - -*PARMS - -{stack} -- a list (which serves as the stack container) - -*DESC - -This is part of a simple implementation of a stack, internally -represented as a list. This command removes the element on the top of -the stack and returns it. This is the last element that is pushed onto -the stack. - -*E.G. - - In> stack := {}; - Out> {}; - In> Push(stack, x); - Out> {x}; - In> Push(stack, x2); - Out> {x2,x}; - In> Push(stack, x3); - Out> {x3,x2,x}; - In> PopFront(stack); - Out> x3; - In> stack; - Out> {x2,x}; - -*SEE Push, Pop, PopBack -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Pop.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Pop.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Pop.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Pop.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="Pop" - -Function("Pop",{stack,index}) -[ - Local(result); - result:=stack[index]; - DestructiveDelete(stack,index); - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Pop",categories="User Functions;Lists (Operations)" -*CMD Pop --- remove an element from a stack -*STD -*CALL - Pop(stack, n) - -*PARMS - -{stack} -- a list (which serves as the stack container) - -{n} -- index of the element to remove - -*DESC - -This is part of a simple implementation of a stack, internally -represented as a list. This command removes the element with index -"n" from the stack and returns this element. The top of the stack is -represented by the index 1. Invalid indices, for example indices -greater than the number of element on the stack, lead to an error. - -*E.G. - - In> stack := {}; - Out> {}; - In> Push(stack, x); - Out> {x}; - In> Push(stack, x2); - Out> {x2,x}; - In> Push(stack, x3); - Out> {x3,x2,x}; - In> Pop(stack, 2); - Out> x2; - In> stack; - Out> {x3,x}; - -*SEE Push, PopFront, PopBack -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/PrintList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/PrintList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/PrintList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/PrintList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="PrintList" - -////////////////////////////////////////////////// -/// Print a list using a padding string -////////////////////////////////////////////////// - -10 # PrintList(list_IsList) <-- PrintList(list, ", "); -10 # PrintList({}, padding_IsString) <-- ""; -20 # PrintList(list_IsList, padding_IsString) <-- ToString() [ - Local(i); - ForEach(i, list) [ - If(Not(Equals(i, First(list))), WriteString(padding)); - If (IsString(i), WriteString(i), If(IsList(i), WriteString("{" : PrintList(i, padding) : "}"), Write(i))); - ]; -]; - -%/mathpiper - - - -%mathpiper_docs,name="PrintList",categories="User Functions;Lists (Operations)" -*CMD PrintList --- print list with padding -*STD -*CALL - PrintList(list) - PrintList(list, padding); - -*PARMS - -{list} -- a list to be printed - -{padding} -- (optional) a string - -*DESC - -Prints {list} and inserts the {padding} string between each pair of items of the list. Items of the list which are strings are printed without quotes, unlike {Write()}. Items of the list which are themselves lists are printed inside braces {{}}. If padding is not specified, a standard one is used (comma, space). - -*E.G. - - In> PrintList({a,b,{c, d}}, " .. ") - Out> " a .. b .. { c .. d}"; - -*SEE Write, WriteString -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Push.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Push.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Push.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Push.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="Push" - -Function("Push",{stack,element}) -[ - DestructiveInsert(stack,1,element); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Push",categories="User Functions;Lists (Operations)" -*CMD Push --- add an element on top of a stack -*STD -*CALL - Push(stack, expr) - -*PARMS - -{stack} -- a list (which serves as the stack container) - -{expr} -- expression to push on "stack" - -*DESC - -This is part of a simple implementation of a stack, internally -represented as a list. This command pushes the expression "expr" on -top of the stack, and returns the stack afterwards. - -*E.G. - - In> stack := {}; - Out> {}; - In> Push(stack, x); - Out> {x}; - In> Push(stack, x2); - Out> {x2,x}; - In> PopFront(stack); - Out> x2; - -*SEE Pop, PopFront, PopBack -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/RemoveDuplicates.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/RemoveDuplicates.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/RemoveDuplicates.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/RemoveDuplicates.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="RemoveDuplicates" - -Function("RemoveDuplicates",{list}) -[ - Local(result); - Set(result,{}); - ForEach(item,list) - If(Not(Contains(result,item)),DestructiveAppend(result,item)); - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="RemoveDuplicates",categories="User Functions;Lists (Operations)" -*CMD RemoveDuplicates --- remove any duplicates from a list -*STD -*CALL - RemoveDuplicates(list) - -*PARMS - -{list} -- list to act on - -*DESC - -This command removes all duplicate elements from a given list and returns the resulting list. -To be -precise, the second occurrence of any entry is deleted, as are the -third, the fourth, etc. - -*E.G. - - In> RemoveDuplicates({1,2,3,2,1}); - Out> {1,2,3}; - In> RemoveDuplicates({a,1,b,1,c,1}); - Out> {a,1,b,c}; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Remove.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Remove.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Remove.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Remove.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="Remove" - -Remove(list, expression) := -[ - Local(result); - Set(result,{}); - ForEach(item,list) - If(item != expression, DestructiveAppend(result,item)); - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Remove" -*CMD Remove --- remove all occurrences of an expression from a list -*STD -*CALL - Remove(list, expr) - -*PARMS - -{list} -- list to act on - -{expr} -- expression to look for in "list" - -*DESC - -This command removes all elements that match a given expression from a given list and returns the resulting list. - -*E.G. - - In> Remove({a,b,a,b,c,a,c},a) - Result> {b,b,c,c} - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Reverse.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Reverse.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Reverse.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Reverse.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="Reverse" - -// Non-destructive Reverse operation -Reverse(list):=DestructiveReverse(FlatCopy(list)); - -%/mathpiper - - - -%mathpiper_docs,name="Reverse",categories="User Functions;Lists (Operations)" -*CMD Reverse --- return the reversed list (without touching the original) -*STD -*CALL - Reverse(list) - -*PARMS - -{list} -- list to reverse - -*DESC - -This function returns a list reversed, without changing the -original list. It is similar to {DestructiveReverse}, but safer -and slower. - - -*E.G. - - In> lst:={a,b,c,13,19} - Out> {a,b,c,13,19}; - In> revlst:=Reverse(lst) - Out> {19,13,c,b,a}; - In> lst - Out> {a,b,c,13,19}; - -*SEE FlatCopy, DestructiveReverse -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/scopestack/scopestack.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/scopestack/scopestack.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/scopestack/scopestack.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/scopestack/scopestack.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -%mathpiper,def="NewStack;PushStackFrame;PopStackFrame;StackDepth;AddToStack;IsOnStack;FindOnStack" - -/* def file list -NewStack -PushStackFrame -PopStackFrame -StackDepth -AddToStack -IsOnStack -FindOnStack - -*/ - - -/* - Stack simulator. Api: - - NewStack() - creates a stack simulation - PushStackFrame(stack,unfenced) - push frame on stack, (un)fenced - PushStackFrame(stack,fenced) - PopStackFrame(stack) - pop stack frame - StackDepth(_stack) - return stack depth - AddToStack(stack,element) - add element to top stack frame - - IsOnStack(stack,element) - returns True if element is accessible - on current stack, False otherwise - FindOnStack(stack,element) - return assoc list for element. - Check first with IsOnStack that it is available! - -*/ - -NewStack() := {{},{}}; - -10 # PushStackFrame(_stack,unfenced) - <-- - [ - DestructiveInsert(stack[1],1,{}); - DestructiveInsert(stack[2],1,True); - ]; -10 # PushStackFrame(_stack,fenced) - <-- - [ - DestructiveInsert(stack[1],1,{}); - DestructiveInsert(stack[2],1,False); - ]; -PopStackFrame(stack):= -[ - DestructiveDelete(stack[1],1); - DestructiveDelete(stack[2],1); -]; -StackDepth(_stack) <-- Length(stack[1]); - -AddToStack(stack,element) := -[ - DestructiveInsert(stack[1][1],1,{element,{}}); -]; - -DropOneFrame(_stack) <-- {Rest(stack[1]),Rest(stack[2])}; - -10 # IsOnStack({{},{}},_element) <-- False; -11 # IsOnStack(_stack,_element)_(stack[1][1][element] != Empty) <-- True; -20 # IsOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) - <-- IsOnStack(DropOneFrame(stack),element); -30 # IsOnStack(_stack,_element) <-- -[ -//Echo("stack depth = ",StackDepth(stack)); -//Echo(stack[2][1]); -False; -]; -10 # FindOnStack(_stack,_element)_(stack[1][1][element] != Empty) - <-- stack[1][1][element]; -20 # FindOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) - <-- FindOnStack(DropOneFrame(stack),element); -30 # FindOnStack(_stack,_element) <-- Check(False,"Illegal stack access! Use IsOnStack."); - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/SmallSort.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/SmallSort.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/SmallSort.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/SmallSort.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -%mathpiper,def="SmallSort" - -/// fast in-place sorting of a list (or array!) -/// SmallSort sorts up to 3 elements, HeapSort sorts 4 and more elements -SmallSort(_list, _first, _last, _compare) _ (last=first) <-- list; -SmallSort(_list, _first, _last, _compare) _ (last=first+1) <-- -[ - Local(temp); - temp := list[first]; - If( - Apply(compare,{temp,list[last]}), - list, - [ - list[first] := list[last]; - list[last] := temp; - ] //Swap(list, first, last) - ); - list; -]; -SmallSort(_list, _first, _last, _compare) _ (last=first+2) <-- -[ - Local(temp); - temp := list[first]; - If( - Apply(compare,{list[first+1],temp}), - [ - list[first] := list[first+1]; - list[first+1] := temp; - ] //Swap(list, first, first+1) // x>y, z - ); - // xx 1, 2, 3 - list[last] := list[first+1]; - list[first+1] := list[first]; - list[first] := temp; - ] - ); - list; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Swap.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Swap.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Swap.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Swap.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="Swap" - -Function("Swap",{list,index1,index2}) -[ - Local(item1,item2); - item1:=list[index1]; - item2:=list[index2]; - list[index1] := item2; - list[index2] := item1; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Swap",categories="User Functions;Lists (Operations)" -*CMD Swap --- swap two elements in a list -*STD -*CALL - Swap(list, i1, i2) - -*PARMS - -{list} -- the list in which a pair of entries should be swapped - -{i1, i2} -- indices of the entries in "list" to swap - -*DESC - -This command swaps the pair of entries with entries "i1" and "i2" -in "list". So the element at index "i1" ends up at index "i2" -and the entry at "i2" is put at index "i1". Both indices should be -valid to address elements in the list. Then the updated list is -returned. - -{Swap()} works also on generic arrays. - -*E.G. - - In> lst := {a,b,c,d,e,f}; - Out> {a,b,c,d,e,f}; - In> Swap(lst, 2, 4); - Out> {a,d,c,b,e,f}; - -*SEE Replace, DestructiveReplace, Array'Create -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Table.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Table.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Table.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Table.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -%mathpiper,def="Table" - -/* Juan: TemplateFunction (as defined in the file "deffunc") - * also makes the arguments to the function local symbols. - * Use HoldArgNr to specify the index of a variable to hold - * (since they are defined as local symbols). - */ - -LocalSymbols(result,nr,ii) -TemplateFunction("Table",{body,var,count'from,count'to,step}) - [ - MacroLocal(var); - result:={}; - nr := (count'to - count'from) / step; - ii := 0; - While( ii <= nr ) - [ - MacroSet( var, count'from + ii * step ); - DestructiveInsert( result,1,Eval(body) ); - Set(ii,AddN(ii,1)); - ]; - DestructiveReverse(result); - ]; -HoldArgNr("Table",5,1); /* body */ -HoldArgNr("Table",5,2); /* var */ -UnFence("Table",5); - -%/mathpiper - - - -%mathpiper_docs,name="Table",categories="User Functions;Lists (Operations)" -*CMD Table --- evaluate while some variable ranges over interval -*STD -*CALL - Table(body, var, from, to, step) - -*PARMS - -{body} -- expression to evaluate multiple times - -{var} -- variable to use as loop variable - -{from} -- initial value for "var" - -{to} -- final value for "var" - -{step} -- step size with which "var" is incremented - -*DESC - -This command generates a list of values from "body", by assigning -variable "var" values from "from" up to "to", incrementing -"step" each time. So, the variable "var" first gets the value -"from", and the expression "body" is evaluated. Then the value -"from"+"step" is assigned to "var" and the expression "body" -is again evaluated. This continues, incrementing "var" with "step" -on every iteration, until "var" exceeds "to". At that moment, all -the results are assembled in a list and this list is returned. - -*E.G. - - In> Table(i!, i, 1, 9, 1); - Out> {1,2,6,24,120,720,5040,40320,362880}; - In> Table(i, i, 3, 16, 4); - Out> {3,7,11,15}; - In> Table(i^2, i, 10, 1, -1); - Out> {100,81,64,49,36,25,16,9,4,1}; - -*SEE For, MapSingle, .., TableForm -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Take.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Take.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Take.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Take.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="Take" - -/* ���� Take ���� */ - -/* Needs to check the parameters */ - -/* - * Take( list, n ) gives the first n elements of 'list' - * Take( list, -n ) gives the last n elements of 'list' - * Take( list, {m,n} ) elements m through n of 'list' - */ - -RuleBase("Take", {lst, range}); - -Rule("Take", 2, 1, IsList(range)) - Take( Drop(lst, range[1] -1), range[2] - range[1] + 1); - -Rule("Take", 2, 2, range >= 0) - If( Length(lst)=0 Or range=0, {}, - Concat({First(lst)}, Take(Rest(lst), range-1))); - -Rule("Take", 2, 2, range < 0) - Drop( lst, Length(lst) + range ); - -%/mathpiper - - - -%mathpiper_docs,name="Take",categories="User Functions;Lists (Operations)" -*CMD Take --- take a sublist from a list (dropping the rest) -*STD -*CALL - Take(list, n) - Take(list, -n) - Take(list, {m,n}) - -*PARMS - -{list} -- list to act on - -{n}, {m} -- positive integers describing the entries to take - -*DESC - -This command takes a sublist of "list", drops the rest, and returns -the selected sublist. The first calling sequence selects the first -"n" entries in "list". The second form takes the last "n" -entries. The last invocation selects the sublist beginning with entry -number "m" and ending with the "n"-th entry. - -*E.G. - - In> lst := {a,b,c,d,e,f,g}; - Out> {a,b,c,d,e,f,g}; - In> Take(lst, 2); - Out> {a,b}; - In> Take(lst, -3); - Out> {e,f,g}; - In> Take(lst, {2,4}); - Out> {b,c,d}; - -*SEE Drop, Select, Remove -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Union.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Union.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/Union.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/Union.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -%mathpiper,def="Union" - -Function("Union",{list1,list2}) -[ - RemoveDuplicates(Concat(list1,list2)); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Union",categories="User Functions;Lists (Operations)" -*CMD Union --- return the union of two lists -*STD -*CALL - Union(l1, l2) - -*PARMS - -{l1}, {l2} -- two lists - -*DESC - -The union of the lists "l1" and "l2" is determined and -returned. The union contains all elements that occur in one or both of -the lists. In the resulting list, any element will occur only once. - -*E.G. - - In> Union({a,b,c}, {b,c,d}); - Out> {a,b,c,d}; - In> Union({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); - Out> {a,e,i,o,u,f,r,t,n}; - In> Union({1,2,2,3,3,3}, {2,2,3,3,4,4}); - Out> {1,2,3,4}; - -*SEE Intersection, Difference -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarListAll.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarListAll.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarListAll.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarListAll.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -%mathpiper,def="VarListAll" - -/* - * RuleBase for VarListAll: recursively traverse an expression looking - * up all variables the expression depends on. - */ -/* Accept any variable. */ - -VarListAll(_expr) <-- VarListAll(expr,"IsVariable"); - -10 # VarListAll(_expr,_filter)_(Apply(filter,{expr}) = True) <-- - {expr}; - -/* Otherwise check all leafs of a function. */ -20 # VarListAll(expr_IsFunction,_filter) <-- -[ - Local(item,result, flatlist); - Set(flatlist,Rest(Listify(expr))); - Set(result,{}); - ForEach(item,flatlist) - Set(result,Concat(result,VarListAll(item,filter))); - result; -]; - -/* Else it doesn't depend on any variable. */ -30 # VarListAll(_expr,_filter) <-- {}; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarListArith.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarListArith.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarListArith.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarListArith.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -%mathpiper,def="VarListArith" - -/// VarListArith --- obtain arithmetic variables -// currently the VarList(x,y) semantic is convoluted so let's introduce a new name; but in principle this needs to be cleaned up -VarListArith(expr) := VarListSome(expr, {Atom("+"), Atom("-"), *, /}); - -%/mathpiper - - - -%mathpiper_docs,name="VarListArith",categories="User Functions;Lists (Operations)" -*CMD VarList --- list of variables appearing in an expression -*CMD VarListArith --- list of variables appearing in an expression -*CMD VarListSome --- list of variables appearing in an expression -*STD -*CALL - VarList(expr) - VarListArith(expr) - VarListSome(expr, list) - -*PARMS - -{expr} -- an expression - -{list} -- a list of function atoms - -*DESC - -The command {VarList(expr)} returns a list of all variables that appear in the -expression {expr}. The expression is traversed recursively. - -The command {VarListSome} looks only at arguments of functions in the {list}. All other functions are considered "opaque" (as if they do not contain any variables) and their arguments are not checked. -For example, {VarListSome(a + Sin(b-c))} will return {{a, b, c}}, but {VarListSome(a*Sin(b-c), {*})} will not look at arguments of {Sin()} and will return {{a,Sin(b-c)}}. Here {Sin(b-c)} is considered a "variable" because the function {Sin} does not belong to {list}. - - -The command {VarListArith} returns a list of all variables that appear -arithmetically in the expression {expr}. This is implemented through -{VarListSome} by restricting to the arithmetic functions {+}, {-}, {*}, {/}. -Arguments of other functions are not checked. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> VarList(Sin(x)) - Out> {x}; - In> VarList(x+a*y) - Out> {x,a,y}; - In> VarListSome(x+a*y, {Atom("+")}) - Out> {x,a*y}; - In> VarListArith(x+y*Cos(Ln(x)/x)) - Out> {x,y,Cos(Ln(x)/x)} - In> VarListArith(x+a*y^2-1) - Out> {x,a,y^2}; - -*SEE IsFreeOf, IsVariable, FuncList, HasExpr, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -%mathpiper,def="VarList" - -/* VarList: return the variables this expression depends on. */ -VarList(_expr) <-- VarList(expr,"IsVariable"); - -Function("VarList",{expr,filter}) -[ - RemoveDuplicates(VarListAll(expr,filter)); -]; - -%/mathpiper - - - -%mathpiper_docs,name="VarList",categories="User Functions;Lists (Operations)" -*CMD VarList --- list of variables appearing in an expression -*CMD VarListArith --- list of variables appearing in an expression -*CMD VarListSome --- list of variables appearing in an expression -*STD -*CALL - VarList(expr) - VarListArith(expr) - VarListSome(expr, list) - -*PARMS - -{expr} -- an expression - -{list} -- a list of function atoms - -*DESC - -The command {VarList(expr)} returns a list of all variables that appear in the -expression {expr}. The expression is traversed recursively. - -The command {VarListSome} looks only at arguments of functions in the {list}. All other functions are considered "opaque" (as if they do not contain any variables) and their arguments are not checked. -For example, {VarListSome(a + Sin(b-c))} will return {{a, b, c}}, but {VarListSome(a*Sin(b-c), {*})} will not look at arguments of {Sin()} and will return {{a,Sin(b-c)}}. Here {Sin(b-c)} is considered a "variable" because the function {Sin} does not belong to {list}. - - -The command {VarListArith} returns a list of all variables that appear -arithmetically in the expression {expr}. This is implemented through -{VarListSome} by restricting to the arithmetic functions {+}, {-}, {*}, {/}. -Arguments of other functions are not checked. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> VarList(Sin(x)) - Out> {x}; - In> VarList(x+a*y) - Out> {x,a,y}; - In> VarListSome(x+a*y, {Atom("+")}) - Out> {x,a*y}; - In> VarListArith(x+y*Cos(Ln(x)/x)) - Out> {x,y,Cos(Ln(x)/x)} - In> VarListArith(x+a*y^2-1) - Out> {x,a,y^2}; - -*SEE IsFreeOf, IsVariable, FuncList, HasExpr, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarListSome.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarListSome.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/lists/VarListSome.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/lists/VarListSome.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -%mathpiper,def="VarListSome" - -/// VarListSome is just like FuncList(x,y) - -10 # VarListSome({}, _look'list) <-- {}; -// an atom should be a variable to qualify -10 # VarListSome(expr_IsVariable, _look'list) <-- {expr}; -15 # VarListSome(expr_IsAtom, _look'list) <-- {}; -// a function not in the looking list - return it whole -20 # VarListSome(expr_IsFunction, look'list_IsList)_(Not Contains(look'list, Atom(Type(expr)))) <-- {expr}; -// a function in the looking list - traverse its arguments -30 # VarListSome(expr_IsFunction, look'list_IsList) <-- -RemoveDuplicates( - [ // obtain a list of functions, considering only functions in look'list - Local(item, result); - result := {}; - ForEach(item, expr) result := Concat(result, VarListSome(item, look'list)); - result; - ] -); - -%/mathpiper - - - -%mathpiper_docs,name="VarListSome",categories="User Functions;Lists (Operations)" -*CMD VarList --- list of variables appearing in an expression -*CMD VarListArith --- list of variables appearing in an expression -*CMD VarListSome --- list of variables appearing in an expression -*STD -*CALL - VarList(expr) - VarListArith(expr) - VarListSome(expr, list) - -*PARMS - -{expr} -- an expression - -{list} -- a list of function atoms - -*DESC - -The command {VarList(expr)} returns a list of all variables that appear in the -expression {expr}. The expression is traversed recursively. - -The command {VarListSome} looks only at arguments of functions in the {list}. All other functions are considered "opaque" (as if they do not contain any variables) and their arguments are not checked. -For example, {VarListSome(a + Sin(b-c))} will return {{a, b, c}}, but {VarListSome(a*Sin(b-c), {*})} will not look at arguments of {Sin()} and will return {{a,Sin(b-c)}}. Here {Sin(b-c)} is considered a "variable" because the function {Sin} does not belong to {list}. - - -The command {VarListArith} returns a list of all variables that appear -arithmetically in the expression {expr}. This is implemented through -{VarListSome} by restricting to the arithmetic functions {+}, {-}, {*}, {/}. -Arguments of other functions are not checked. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> VarList(Sin(x)) - Out> {x}; - In> VarList(x+a*y) - Out> {x,a,y}; - In> VarListSome(x+a*y, {Atom("+")}) - Out> {x,a*y}; - In> VarListArith(x+y*Cos(Ln(x)/x)) - Out> {x,y,Cos(Ln(x)/x)} - In> VarListArith(x+a*y^2-1) - Out> {x,a,y^2}; - -*SEE IsFreeOf, IsVariable, FuncList, HasExpr, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/AddTo.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/AddTo.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/AddTo.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/AddTo.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -%mathpiper,def="AddTo" - -// (a or b) and (c or d) -> (a and c) or (a and d) or (b and c) or (b and d) -20 # (list_IsList AddTo _rest) <-- -[ - Local(res); - res:={}; - ForEach(item,list) - [ - res := Concat(res,item AddTo rest); - ]; - res; -]; -30 # (_a'item AddTo list_IsList) <-- -[ - MapSingle({{orig},a'item And orig},list); -]; -40 # (_a'item AddTo _b) <-- a'item And b; - -%/mathpiper - - - -%mathpiper_docs,name="AddTo",categories="User Functions;Functional Operators" -*CMD AddTo --- add an equation to a set of equations or set of set of equations -*STD -*CALL - eq1 AddTo eq2 - -*PARMS - -{eq} - (set of) set of equations - -*DESC - -Given two (sets of) sets of equations, the command AddTo combines -multiple sets of equations into one. - -A list {a,b} means that a is a solution, OR b is a solution. -AddTo then acts as a AND operation: - - (a or b) and (c or d) => - (a or b) Addto (c or d) => - (a and c) or (a and d) or (b and c) - or (b and d) - -This function is useful for adding an identity to an already -existing set of equations. Suppose a solve command returned -{a>=0 And x==a,a<0 And x== -a} from an expression x==Abs(a), -then a new identity a==2 could be added as follows: - - In> a==2 AddTo {a>=0 And x==a,a<0 And x== -a} - Out> {a==2 And a>=0 And x==a,a==2 And a<0 - And x== -a}; - -Passing this set of set of identities back to solve, solve -should recognize that the second one is not a possibility -any more, since a==2 And a<0 can never be true at the same time. - -This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. - -*E.G. - - In> {A==2,c==d} AddTo {b==3 And d==2} - Out> {A==2 And b==3 And d==2,c==d - And b==3 And d==2}; - In> {A==2,c==d} AddTo {b==3, d==2} - Out> {A==2 And b==3,A==2 And d==2,c==d - And b==3,c==d And d==2}; - -*SEE Where, Solve -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/CompilePatterns.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/CompilePatterns.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/CompilePatterns.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/CompilePatterns.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -%mathpiper,def="CompilePatterns" - -LocalSymbols(LocResult) [ - - Set(LocResult,True); - 10 # LocPredicate(exp_IsAtom) <-- - [ - Local(tr,result); - tr:=patterns; - result:=False; - While (tr != {}) - [ - If (First(First(tr)) = exp, - [ - Set(LocResult,Eval(First(Rest(First(tr))))); - result := True; - tr:={}; - ], - [ - tr := Rest(tr); - ]); - ]; - result; - ]; - - 10 # LocPredicate(exp_IsFunction) <-- - [ - Local(tr,result,head); - tr:=patterns; - result:=False; - While (tr != {}) - [ - Set(head, First(First(tr))); - If (Not(IsAtom(head)) And exp[0]=head[1] And Pattern'Matches(head[2], exp), - [ - Set(LocResult,Eval(First(Rest(First(tr))))); - Set(result, True); - Set(tr,{}); - ], - [ - Set(tr, Rest(tr)); - ]); - ]; - result; - ]; - 20 # LocPredicate(_exp) <-- False; - - LocChange(_exp) <-- LocResult; -]; // LocalSymbols(LocResult) - -UnFence("LocPredicate",1); -UnFence("LocChange",1); - -10 # LocProcessSingle({_pat,_post,_exp}) <-- { {pat[0],Pattern'Create(pat,post)},exp }; - -20 # LocProcessSingle({pat_IsFunction,_exp}) <-- { {pat[0],Pattern'Create(pat,True)},exp }; - -30 # LocProcessSingle({pat_IsAtom,_exp}) <-- { pat,exp }; - -/* - 40 # LocProcessSingle(pat_IsFunction <- _exp) <-- { {pat[0],Pattern'Create(pat,True)},exp }; - todo:tk:this rule was not handling post predicates so I replaced it with a new version that does. - I suspect that the other rules for this Rulebase have problems too. -*/ -40 # LocProcessSingle(pat_IsFunction <- _exp) <-- -[ - Local(justPattern, postPredicate); - - If(Type(pat) = "_", - [ - //A post predicate was submitted. - justPattern := pat[1]; - postPredicate := pat[2]; - ], - [ - //No post predicate was submitted. - justPattern := pat; - postPredicate := True; - ] - ); - - { {justPattern[0],Pattern'Create(justPattern,postPredicate)},exp }; -]; - -50 # LocProcessSingle(pat_IsAtom <- _exp) <-- { pat,exp }; - -LocProcess(patterns) := -[ - MapSingle("LocProcessSingle",patterns); -]; - -CompilePatterns(patterns) := LocPatterns(LocProcess(patterns)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/lessthan_minus_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/lessthan_minus_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/lessthan_minus_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/lessthan_minus_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="<-" - -RuleBase("<-",{left,right}); -HoldArg("<-",left); -HoldArg("<-",right); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/slash_colon_colon_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/slash_colon_colon_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/slash_colon_colon_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/slash_colon_colon_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -%mathpiper,def="/::" - -5 # (_expression /:: LocPatterns(_patterns)) <-- -[ - MacroSubstitute(expression,"LocPredicate","LocChange"); -]; -10 # (_expression /:: _patterns) <-- -[ - Local(old); - Set(patterns, LocProcess(patterns)); - Set(old, expression); - Set(expression, MacroSubstitute(expression,"LocPredicate","LocChange")); - While (expression != old) - [ - Set(old, expression); - Set(expression, MacroSubstitute(expression,"LocPredicate","LocChange")); - ]; - expression; -]; - - -%/mathpiper - - - -%mathpiper_docs,name="/::",categories="Operators" -*CMD /: --- local simplification rules -*CMD /:: --- local simplification rules -*STD -*CALL - expression /: patterns - expressions /:: patterns -Precedence: -*EVAL OpPrecedence("/:") - - -*PARMS - -{expression} -- an expression - -{patterns} -- a list of patterns - -*DESC - -Sometimes you have an expression, and you want to use specific -simplification rules on it that are not done by default. This -can be done with the {/:} and the {/::} operators. Suppose we have the -expression containing things such as {Ln(a*b)}, and we want -to change these into {Ln(a)+Ln(b)}, the easiest way -to do this is using the {/:} operator, as follows: - - In> Sin(x)*Ln(a*b) - Out> Sin(x)*Ln(a*b); - In> % /: { Ln(_x*_y) <- Ln(x)+Ln(y) } - Out> Sin(x)*(Ln(a)+Ln(b)); - -A whole list of simplification rules can be built up in the list, -and they will be applied to the expression on the left hand side -of {/:} . - -The forms the patterns can have are one of: - - pattern <- replacement - {pattern,replacement} - {pattern,postpredicate,replacement} - -Note that for these local rules, {<-} should be used instead of -{<--} which would be used in a global rule. - -The {/:} operator traverses an expression much as {Subst} does, that is, top -down, trying to apply the rules from the beginning of the list of -rules to the end of the list of rules. If the rules cannot be applied -to an expression, it will try subexpressions of that -expression and so on. - -It might be necessary sometimes to use the {/::} operator, which -repeatedly applies the {/:} operator until the result doesn't change -any more. Caution is required, since rules can contradict each other, -which could result in an infinite loop. To detect this situation, -just use /: repeatedly on the expression. The repetitive nature -should become apparent. - -*E.G. - - In> Sin(u)*Ln(a*b) /: {Ln(_x*_y) <- Ln(x)+Ln(y)} - Out> Sin(u)*(Ln(a)+Ln(b)); - In> Sin(u)*Ln(a*b) /:: { a <- 2, b <- 3 } - Out> Sin(u)*Ln(6); - -*SEE Subst -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/slash_colon_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/slash_colon_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/slash_colon_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/slash_colon_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -%mathpiper,def="/:" - -5 # (_expression /: LocPatterns(_patterns)) <-- -[ - MacroSubstitute(expression,"LocPredicate","LocChange"); -]; - - -10 # (_expression /: _patterns) <-- -[ - Set(patterns, LocProcess(patterns)); - MacroSubstitute(expression,"LocPredicate","LocChange"); -]; - -%/mathpiper - - - -%mathpiper_docs,name="/:",categories="Operators" -*CMD /: --- local simplification rules -*CMD /:: --- local simplification rules -*STD -*CALL - expression /: patterns - expressions /:: patterns -Precedence: -*EVAL OpPrecedence("/:") - - -*PARMS - -{expression} -- an expression - -{patterns} -- a list of patterns - -*DESC - -Sometimes you have an expression, and you want to use specific -simplification rules on it that are not done by default. This -can be done with the {/:} and the {/::} operators. Suppose we have the -expression containing things such as {Ln(a*b)}, and we want -to change these into {Ln(a)+Ln(b)}, the easiest way -to do this is using the {/:} operator, as follows: - - In> Sin(x)*Ln(a*b) - Out> Sin(x)*Ln(a*b); - In> % /: { Ln(_x*_y) <- Ln(x)+Ln(y) } - Out> Sin(x)*(Ln(a)+Ln(b)); - -A whole list of simplification rules can be built up in the list, -and they will be applied to the expression on the left hand side -of {/:} . - -The forms the patterns can have are one of: - - pattern <- replacement - {pattern,replacement} - {pattern,postpredicate,replacement} - -Note that for these local rules, {<-} should be used instead of -{<--} which would be used in a global rule. - -The {/:} operator traverses an expression much as {Subst} does, that is, top -down, trying to apply the rules from the beginning of the list of -rules to the end of the list of rules. If the rules cannot be applied -to an expression, it will try subexpressions of that -expression and so on. - -It might be necessary sometimes to use the {/::} operator, which -repeatedly applies the {/:} operator until the result doesn't change -any more. Caution is required, since rules can contradict each other, -which could result in an infinite loop. To detect this situation, -just use /: repeatedly on the expression. The repetitive nature -should become apparent. - -*E.G. - - In> Sin(u)*Ln(a*b) /: {Ln(_x*_y) <- Ln(x)+Ln(y)} - Out> Sin(u)*(Ln(a)+Ln(b)); - In> Sin(u)*Ln(a*b) /:: { a <- 2, b <- 3 } - Out> Sin(u)*Ln(6); - -*SEE Subst -%/mathpiper_docs - - -/* -Examples to add to docs in the future. - -Hold((a + b) * (1 + 2) * (2 + 1) * (1/2 + c) * (3/4 + d) ) /: - { - (x_IsOdd + y_IsEven) <- m1, - (x_IsEven + y_IsOdd) <- m2, - (x_IsRational + y_IsAtom)_(Denominator(x) = 2) <- m3, - }; - - %output,preserve="false" - Result: (a+b)*m1*m2*m3*(3/4+d) -. %/output - -*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/Where.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/Where.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/localrules/Where.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/localrules/Where.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -%mathpiper,def="Where" - -RuleBase("Where",{left,right}); -//HoldArg("Where",left); -//HoldArg("Where",right); -UnFence("Where",2); -10 # (_body Where var_IsAtom == _value) - <-- `[Local(@var);@var := @value;@body;]; -20 # (_body Where (_a And _b)) - <-- -[ - Set(body,`(@body Where @a)); - `(@body Where @b); -]; - -30 # (_body Where {}) <-- {}; -40 # (_body Where list_IsList)_IsList(list[1]) - <-- - [ - Local(head,rest); - head:=First(list); - rest:=Rest(list); - rest:= `(@body Where @rest); - `(@body Where @head) : rest; - ]; - -50 # (_body Where list_IsList) - <-- - [ - Local(head,rest); - While (list != {}) - [ - head:=First(list); - body := `(@body Where @head); - list:=Rest(list); - ]; - body; - ]; - - -60 # (_body Where _var == _value) <-- Subst(var,value)body; - -%/mathpiper - - - -%mathpiper_docs,name="Where",categories="User Functions;Functional Operators" -*CMD Where --- substitute result into expression -*STD -*CALL - expr Where x==v - expr Where x1==v1 And x2==v2 And ... - expr Where {x1==v1 And x2==v2,x1==v3 - And x2==v4,...} - -*PARMS - -{expr} - expression to evaluate - -{x} - variable to set - -{v} - value to substitute for variable - -*DESC - -The operator {Where} fills in values for variables, in its simplest form. -It accepts sets of variable/value pairs defined as - - var1==val1 And var2==val2 And ... - -and fills in the corresponding values. Lists of value pairs are -also possible, as: - - {var1==val1 And var2==val2, var1==val3 - And var2==val4} - -These values might be obtained through {Solve}. - -This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. - -*E.G. - - In> x^2+y^2 Where x==2 - Out> y^2+4; - In> x^2+y^2 Where x==2 And y==3 - Out> 13; - In> x^2+y^2 Where {x==2 And y==3} - Out> {13}; - In> x^2+y^2 Where {x==2 And y==3,x==4 And y==5} - Out> {13,41}; - -*SEE Solve, AddTo -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/CanProve.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/CanProve.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/CanProve.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/CanProve.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -%mathpiper,def="CanProve" - -/* Small theorem prover for propositional logic, based on the - * resolution principle. - * Written by Ayal Pinkus, based on the simple theorem prover from "Prolog, Ivan Bratko, chapter 20" - * Version 0.1 initial implementation. - * - * - * Examples: -CanProve(( (a=>b) And (b=>c)=>(a=>c) )) <-- True -CanProve(a Or Not a) <-- True -CanProve(True Or a) <-- True -CanProve(False Or a) <-- a -CanProve(a And Not a) <-- False -CanProve(a Or b Or (a And b)) <-- a Or b - */ - - // <==> LogicSimplify(expr, 3) - -/* CanProve tries to prove that the negation of the negation of - the proposition is true. Negating twice is just a trick to - allow all the simplification rules a la De Morgan to operate - */ -/*CanProve(_proposition) <-- CanProveAux( Not CanProveAux( Not proposition));*/ - -CanProveAux(_proposition) <-- LogicSimplify(proposition, 3); - -CanProve(_proposition) <-- CanProveAux( proposition ); - -%/mathpiper - - - -%mathpiper_docs,name="CanProve",categories="User Functions;Propositional Logic" -*CMD CanProve --- try to prove statement -*STD -*CALL - CanProve(proposition) - -*PARMS - -{proposition} -- an expression with logical operations - -*DESC - -MathPiper has a small built-in propositional logic theorem prover. -It can be invoked with a call to {CanProve}. - -An example of a proposition is: "if a implies b and b implies c then -a implies c". MathPiper supports the following logical operations: - -{Not} : negation, read as "not" - -{And} : conjunction, read as "and" - -{Or} : disjunction, read as "or" - -{=>} : implication, read as "implies" - -The abovementioned proposition would be represented by the following expression, - - ( (a=>b) And (b=>c) ) => (a=>c) - -MathPiper can prove that is correct by applying {CanProve} -to it: - - In> CanProve(( (a=>b) And (b=>c) ) => (a=>c)) - Out> True; - -It does this in the following way: in order to prove a proposition $p$, it -suffices to prove that $Not p$ is false. It continues to simplify $Not p$ -using the rules: - - Not ( Not x) --> x -(eliminate double negation), - x=>y --> Not x Or y -(eliminate implication), - Not (x And y) --> Not x Or Not y -(De Morgan's law), - Not (x Or y) --> Not x And Not y -(De Morgan's law), - (x And y) Or z --> (x Or z) And (y Or z) -(distribution), - x Or (y And z) --> (x Or y) And (x Or z) -(distribution), -and the obvious other rules, such as, - True Or x --> True -etc. -The above rules will translate a proposition into a form - - (p1 Or p2 Or ...) And (q1 Or q2 - Or ...) And ... -If any of the clauses is false, the entire expression will be false. -In the next step, clauses are scanned for situations of the form: - - (p Or Y) And ( Not p Or Z) --> (Y Or Z) -If this combination {(Y Or Z)} is empty, it is false, and -thus the entire proposition is false. - -As a last step, the algorithm negates the result again. This has the -added advantage of simplifying the expression further. - -*E.G. - - In> CanProve(a Or Not a) - Out> True; - In> CanProve(True Or a) - Out> True; - In> CanProve(False Or a) - Out> a; - In> CanProve(a And Not a) - Out> False; - In> CanProve(a Or b Or (a And b)) - Out> a Or b; - - -*SEE True, False, And, Or, Not -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/CNF.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/CNF.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/CNF.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/CNF.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -%mathpiper,def="CNF" - - - // former LogicSimplify - -/* - Simplify a boolean expression. CNF is responsible - for converting an expression to the following form: - (p1 Or p2 Or ...) And (q1 Or q2 Or ...) And ... - That is, a conjunction of disjunctions. -*/ - - -// Trivial simplifications -10 # CNF( Not True) <-- False; -11 # CNF( Not False) <-- True; -12 # CNF(True And (_x)) <-- CNF(x); -13 # CNF(False And (_x)) <-- False; -14 # CNF(_x And True) <-- CNF(x); -15 # CNF(_x And False) <-- False; -16 # CNF(True Or (_x)) <-- True; -17 # CNF(False Or (_x)) <-- CNF(x); -18 # CNF((_x) Or True ) <-- True; -19 # CNF((_x) Or False) <-- CNF(x); - -// A bit more complext -21 # CNF(_x Or _x) <-- CNF(x); -22 # CNF(_x And _x) <-- CNF(x); -23 # CNF(_x Or Not (_x)) <-- True; -14 # CNF(Not (_x) Or _x) <-- True; -25 # CNF(_x And Not (_x)) <-- False; -26 # CNF(Not (_x) And _x) <-- False; - -// Simplifications that deal with (in)equalities -25 # CNF(((_x) == (_y)) Or ((_x) !== (_y))) <-- True; -25 # CNF(((_x) !== (_y)) Or ((_x) == (_y))) <-- True; -26 # CNF(((_x) == (_y)) And ((_x) !== (_y))) <-- False; -26 # CNF(((_x) !== (_y)) And ((_x) == (_y))) <-- False; - -27 # CNF(((_x) >= (_y)) And ((_x) < (_y))) <-- False; -27 # CNF(((_x) < (_y)) And ((_x) >= (_y))) <-- False; -28 # CNF(((_x) >= (_y)) Or ((_x) < (_y))) <-- True; -28 # CNF(((_x) < (_y)) Or ((_x) >= (_y))) <-- True; - - -// some things that are more complex -120 # CNF((_x) Or (_y)) <-- LogOr(x, y, CNF(x), CNF(y)); -10 # LogOr(_x,_y,_x,_y) <-- x Or y; -20 # LogOr(_x,_y,_u,_v) <-- CNF(u Or v); - -130 # CNF( Not (_x)) <-- LogNot(x, CNF(x)); -10 # LogNot(_x, _x) <-- Not (x); -20 # LogNot(_x, _y) <-- CNF(Not (y)); - -40 # CNF( Not ( Not (_x))) <-- CNF(x); // eliminate double negation -45 # CNF((_x)=>(_y)) <-- CNF((Not (x)) Or (y)); // eliminate implication - -50 # CNF( Not ((_x) And (_y))) <-- CNF((Not x) Or (Not y)); // De Morgan's law -60 # CNF( Not ((_x) Or (_y))) <-- CNF(Not (x)) And CNF(Not (y)); // De Morgan's law - -/* -70 # CNF((_x) And ((_y) Or (_z))) <-- CNF(x And y) Or CNF(x And z); -70 # CNF(((_x) Or (_y)) And (_z)) <-- CNF(x And z) Or CNF(y And z); - -80 # CNF((_x) Or ((_y) And (_z))) <-- CNF(x Or y) And CNF(x Or z); -80 # CNF(((_x) And (_y)) Or (_z)) <-- CNF(x Or z) And CNF(y Or z); -*/ - -70 # CNF(((_x) And (_y)) Or (_z)) <-- CNF(x Or z) And CNF(y Or z); // Distributing Or over And -80 # CNF((_x) Or ((_y) And (_z))) <-- CNF(x Or y) And CNF(x Or z); - -90 # CNF((_x) And (_y)) <-- CNF(x) And CNF(y); // Transform subexpression - -101 # CNF( (_x) < (_y) ) <-- Not CNFInEq(x >= y); -102 # CNF( (_x) > (_y) ) <-- CNFInEq(x > y); -103 # CNF( (_x) >= (_y) ) <-- CNFInEq(x >= y); -104 # CNF( (_x) <= (_y) ) <-- Not CNFInEq(x > y); -105 # CNF( (_x) == (_y) ) <-- CNFInEq(x == y); -106 # CNF( (_x) !== (_y) ) <-- Not CNFInEq(x == y); - -111 # CNF( Not((_x) < (_y)) ) <-- CNFInEq( x >= y ); -113 # CNF( Not((_x) <= (_y)) ) <-- CNFInEq( x > y ); -116 # CNF( Not((_x) !== (_y)) ) <-- CNFInEq( x == y ); - -/* Accept as fully simplified, fallthrough case */ -200 # CNF(_x) <-- x; - -20 # CNFInEq((_xex) == (_yex)) <-- (CNFInEqSimplify(xex-yex) == 0); -20 # CNFInEq((_xex) > (_yex)) <-- (CNFInEqSimplify(xex-yex) > 0); -20 # CNFInEq((_xex) >= (_yex)) <-- (CNFInEqSimplify(xex-yex) >= 0); -30 # CNFInEq(_exp) <-- (CNFInEqSimplify(exp)); - -10 # CNFInEqSimplify((_x) - (_x)) <-- 0; // strictly speaking, this is not always valid, i.e. 1/0 - 1/0 != 0... -100# CNFInEqSimplify(_x) <-- [/*Echo({"Hit the bottom of CNFInEqSimplify with ", x, Nl()});*/ x;]; - // former "Simplify"; - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/Contradict.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/Contradict.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/Contradict.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/Contradict.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="Contradict",scope="private" - -10 # Contradict((_x) - (_y) == 0, (_x) - (_z) == 0)_(y != z) <-- True; -12 # Contradict((_x) == (_y), (_x) == (_z))_(y != z) <-- True; -13 # Contradict((_x) - (_y) == 0, (_x) - (_z) >= 0)_(z > y) <-- True; -14 # Contradict((_x) - (_y) == 0, (_x) - (_z) > 0)_(z > y) <-- True; -14 # Contradict(Not (_x) - (_y) >= 0, (_x) - (_z) > 0)_(z > y) <-- True; -15 # Contradict(_a, _b) <-- Equals(SimpleNegate(a), b); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/DoUnitSubsumptionAndResolution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/DoUnitSubsumptionAndResolution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/DoUnitSubsumptionAndResolution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/DoUnitSubsumptionAndResolution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="DoUnitSubsumptionAndResolution",scope="private" - -// perform unit subsumption and resolutiuon for a unit clause # i -// a boolean indicated whether there was a change is returned -DoUnitSubsumptionAndResolution(_list) <-- -[ - Local(i, j, k, isFalse, isTrue, changed); - Set(isFalse, False); - Set(isTrue, False); - Set(changed, True); - - //Echo({"In DoUnitSubsumptionAndResolution", Nl()}); - - While(changed) [ - Set(changed, False); - - For(i:=1, (Not isFalse And Not isTrue) And i <= Length(list), i++) - [ - If(Length(list[i]) = 1, [ - Local(x); Set(x, list[i][1]); //n := SimpleNegate(x); - //Echo({"Unit clause ", x, Nl()}); - - // found a unit clause, {x}, not use it to modify other clauses - For(j:=1, (Not isFalse And Not isTrue) And j <= Length(list), j++) - [ - If(i !=j, [ - Local(deletedClause); Set(deletedClause, False); - For(k:=1, (Not isFalse And Not isTrue And Not deletedClause) And k <= Length(list[j]), k++) - [ - // In both of these, if a clause becomes empty, the whole thing is False - - //Echo({" ", x, " subsumes ", list[j][k], i,j, Subsumes(x, list[j][k]), Nl()}); - - // unit subsumption -- this kills clause j - If(Subsumes(x, list[j][k]), [ - // delete this clause - DestructiveDelete(list, j); - j--; - If(i>j, i--); // i also needs to be decremented - Set(deletedClause, True); - Set(changed, True); - If(Length(list) = 0, [Set(isTrue, True);]); - ], - // else, try unit resolution - If(Contradict(x, list[j][k]), [ - //Echo({x, " contradicts", list[j][k], Nl()}); - DestructiveDelete(list[j], k); - k--; - Set(changed, True); - If(Length(list[j]) = 0, [Set(isFalse, True);]); - ]) - ); - ]; - ]); - ]; - ]); - ]; - ]; - - list; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/equals_greaterthan_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/equals_greaterthan_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/equals_greaterthan_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/equals_greaterthan_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="=>" - -RuleBase("=>",{a,b}); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicCombine.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicCombine.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicCombine.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicCombine.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="LogicCombine",scope="private" - -/* LogicCombine is responsible for scanning a list of lists, which represent - a form (p1 Or p2 Or ...) And (q1 Or q2 Or ...) And ... by scanning the lists - for combinations x Or Y And Not x Or Z <-- Y Or Z . If Y Or Z is empty then this clause - is false, and thus the entire proposition is false. -*/ -LogicCombine(_list) <-- -[ - Local(i, j); - For(Set(i,1), i<=Length(list), Set(i,AddN(i,1))) - [ - //Echo({"list[", i, "/", Length(list), "]: ", list[i], Nl()}); - - For(j := 1, (j<=Length(list[i])), j++) - [ - Local(tocombine, n, k); - Set(n, list[i][j]); - - {tocombine, k} := LogicFindWith(list, i, n);// search forward for n, tocombine is the list we - // will combine the current one with - If(tocombine != -1, - [ - Local(combination); - Check(k != -1, "k is -1"); - - Set(combination, LogicRemoveTautologies(Concat(list[i], list[tocombine]))); - If(combination = {}, // the combined clause is false, so the whole thing is false - [Set(list, {{}}); Set(i, Length(list)+1);], [/*Set(i, 0);*/]); - ]); - ]; - ]; - list; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicFindWith.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicFindWith.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicFindWith.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicFindWith.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="LogicFindWith",scope="private" - -/* find the number of the list that contains n in it, a pointer to a list of lists in passed */ -LogicFindWith(_list, _i, _n) <-- -[ - Local(result, index, j); - Set(result, -1); Set(index, -1); - - For(j := i+1, (result<0) And (j <= Length(list)), j++) - [ - Local(k, len); Set(len, Length(list[j])); - For(k := 1, (result<0) And (k<=len), k++) - [ - Local(el); Set(el, list[j][k]); - - If(Contradict(n, el), - [Set(result, j); Set(index, k);]); - ]; - ]; - {result, index}; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicRemoveTautologies.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicRemoveTautologies.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicRemoveTautologies.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicRemoveTautologies.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -%mathpiper,def="LogicRemoveTautologies",scope="private" - - // not clear is this will stay, but it is eq. to LogicSimplify(expr, 2) - -1 # SimpleNegate(Not (_x)) <-- x; -2 # SimpleNegate(_x) <-- Not(x); - -/* LogicRemoveTautologies scans a list representing e1 Or e2 Or ... to find - if there are elements p and Not p in the list. This signifies p Or Not p, - which is always True. These pairs are removed. Another function that is used - is RemoveDuplicates, which converts p Or p into p. -*/ - -/* this can be optimized to walk through the lists a bit more efficiently and also take -care of duplicates in one pass */ -LocalCmp(_e1, _e2) <-- LessThan(ToString() Write(e1), ToString() Write(e2)); - -// we may want to add other expression simplifers for new expression types -100 # SimplifyExpression(_x) <-- x; - -// Return values: -// {True} means True -// {} means False -LogicRemoveTautologies(_e) <-- -[ - Local(i, len, negationfound); Set(len, Length(e)); - Set(negationfound, False); - - //Echo(e); - e := BubbleSort(e, "LocalCmp"); - - For(Set(i, 1), (i <= len) And (Not negationfound), i++) - [ - Local(x, n, j); - // we can register other simplification rules for expressions - //e[i] := MathNth(e,i) /:: {gamma(_y) <- SimplifyExpression(gamma(y))}; - Set(x, MathNth(e,i)); - Set(n, SimpleNegate(x)); /* this is all we have to do because of - the kind of expressions we can have coming in */ - - For(Set(j, i+1), (j <= len) And (Not negationfound), j++) [ - Local(y); - Set(y, MathNth(e,j)); - - If(Equals(y, n), - [ - //Echo({"Deleting from ", e, " i=", i, ", j=", j, Nl()}); - - Set(negationfound, True); - //Echo({"Removing clause ", i, Nl()}); - ], - If(Equals(y, x), - [ - //Echo({"Deleting from ", e, " j=", j, Nl()}); - DestructiveDelete(e, j); - Set(len,SubtractN(len,1)); - ]) - ); - ]; - Check(len = Length(e), "The length computation is incorrect"); - ]; - - If(negationfound, {True}, e); /* note that a list is returned */ -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicSimplify.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicSimplify.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/LogicSimplify.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/LogicSimplify.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper,def="LogicSimplify" - - // (expression, level=1..3 - -// Some shortcuts to match prev interface - -10 # LogicSimplify(_proposition, _level)_(level<2) <-- CNF(proposition); - -20 # LogicSimplify(_proposition, _level) <-- -[ - Local(cnf, list, clauses); - Check(level > 1, "Wrong level"); - // First get the CNF version of the proposition - Set(cnf, CNF(proposition)); - - If(level <= 1, cnf, [ - Set(list, Flatten(cnf, "And")); - Set(clauses, {}); - ForEach(clause, list) - [ - Local(newclause); - //newclause := BubbleSort(LogicRemoveTautologies(Flatten(clause, "Or")), LessThan); - Set(newclause, LogicRemoveTautologies(Flatten(clause, "Or"))); - If(newclause != {True}, DestructiveAppend(clauses, newclause)); - ]; - - /* - Note that we sort each of the clauses so that they look the same, - i.e. if we have (A And B) And ( B And A), only the first one will - persist. - */ - Set(clauses, RemoveDuplicates(clauses)); - - If(Equals(level, 3) And (Length(clauses) != 0), [ - Set(clauses, DoUnitSubsumptionAndResolution(clauses)); - Set(clauses, LogicCombine(clauses)); - ]); - - Set(clauses, RemoveDuplicates(clauses)); - - If(Equals(Length(clauses), 0), True, [ - /* assemble the result back into a boolean expression */ - Local(result); - Set(result, True); - ForEach(item,clauses) - [ - Set(result, result And UnFlatten(item, "Or", False)); - ]; - - result; - ]); - ]); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -OMDef( "=>" , "logic1","implies" ); -OMDef( "CNF" , mathpiper,"cnf" ); -OMDef( "LogicSimplify", mathpiper,"logic_simplify" ); -OMDef( "CanProve" , mathpiper,"can_prove" ); -OMDef( "LogicRemoveTautologies", mathpiper,"logic_remove_tautologies" ); -OMDef( "Subsumes" , mathpiper,"subsumes" ); -// The following appear in the def file, but commented out: -// "~", mathpiper, "Not" -// "|", mathpiper, "Or" -// "&", mathpiper, "And" - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/Subsumes.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/Subsumes.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/logic/Subsumes.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/logic/Subsumes.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -%mathpiper,def="Subsumes" - -10 # Subsumes((_x) - (_y) == 0, Not ((_x) - (_z)==0))_(y!=z) <-- True; -// suif_tmp0_127_1-72==0 And 78-suif_tmp0_127_1>=0 -20 # Subsumes((_x) - (_y) == 0, (_z) - (_x) >= 0)_(z>=y) <-- True; -20 # Subsumes((_x) - (_y) == 0, (_z) - (_x) > 0)_(z>y) <-- True; -// suif_tmp0_127_1-72==0 And suif_tmp0_127_1-63>=0 -30 # Subsumes((_x) - (_y) == 0, (_x) - (_z) >= 0)_(y>=z) <-- True; -30 # Subsumes((_x) - (_y) == 0, (_x) - (_z) > 0)_(y>z) <-- True; - -90 # Subsumes((_x), (_x)) <-- True; - -100# Subsumes((_x), (_y)) <-- False; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/Groebner.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/Groebner.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/Groebner.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/Groebner.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="Groebner" - -/* - Groebner : Calculate the Groebner basis of a set of polynomials. - Nice example of its power is - -In> TableForm(Groebner({x*(y-1),y*(x-1)})) - x*y-x - x*y-y - y-x - y^2-y -In> Factor(y^2-y) -Out> y*(y-1); - -From which you can see that x = y, and x^2 = x so x is 0 or 1. - -*/ - -Groebner(f_IsList) <-- -[ - Local(vars,i,j,S,nr,r); - nr:=Length(f); - vars:=VarList(f); - For(i:=1,i<=nr,i++) - [ - f[i] := MakeMultiNomial(f[i],vars); - ]; - S:={}; - For(i:=1,i0) - [ - If(n&1 != 0, Set(result, MultiNomialMultiply(result,mult))); - Set(n,n>>1); - If(n!=0,Set(mult,MultiNomialMultiply(mult,mult))); - ]; - result; - ]; - - 15 # MakeMultiNomial(_x ^ _n,vars_IsList)_(Not(IsInteger(n)) And IsInteger(Simplify(n))) <-- - MakeMultiNomial( x ^ Simplify(n),vars); - - 50 # MakeMultiNomial(_x ^ (_n),vars_IsList)_(Contains(vars,x)) <-- - [ - Set(n,Simplify(n)); - If(IsInteger(n), - MultiSingleFactor(vars,x,n), - MultiSingleFactor(vars,x^n,1) - ); - ]; -]; - - -x_IsMulti + (y_IsMulti/z_IsMulti) <-- ((x*z+y)/z); -(y_IsMulti/z_IsMulti) + x_IsMulti <-- ((x*z+y)/z); -(y_IsMulti/z_IsMulti) + (x_IsMulti/w_IsMulti) <-- ((y*w+x*z)/(z*w)); -(y_IsMulti/z_IsMulti) - (x_IsMulti/w_IsMulti) <-- ((y*w-x*z)/(z*w)); -(y_IsMulti/z_IsMulti) * (x_IsMulti/w_IsMulti) <-- ((y*x)/(z*w)); -(y_IsMulti/z_IsMulti) / (x_IsMulti/w_IsMulti) <-- ((y*w)/(z*x)); -x_IsMulti - (y_IsMulti/z_IsMulti) <-- ((x*z-y)/z); -(y_IsMulti/z_IsMulti) - x_IsMulti <-- ((y-x*z)/z); -(a_IsMulti/(c_IsMulti/b_IsMulti)) <-- ((a*b)/c); -((a_IsMulti/c_IsMulti)/b_IsMulti) <-- (a/(b*c)); -((a_IsMulti/b_IsMulti) * c_IsMulti) <-- ((a*c)/b); -(a_IsMulti * (c_IsMulti/b_IsMulti)) <-- ((a*c)/b); -- ((a_IsMulti)/(b_IsMulti)) <-- (-a)/b; - - -MultiNomialMultiply( - MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2), - MultiNomial(_vars,_terms3)/MultiNomial(_vars,_terms4)) <-- -[ - MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ - MultiNomialMultiply(MultiNomial(vars,terms2),MultiNomial(vars,terms4)); -]; -MultiNomialMultiply( - MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2), - MultiNomial(_vars,_terms3)) <-- -[ - MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ - MultiNomial(vars,terms2); -]; -MultiNomialMultiply( - MultiNomial(_vars,_terms3), - MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2)) <-- -[ - MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ - MultiNomial(vars,terms2); -]; - -10 # MultiNomialMultiply(_a,_b) <-- -[ - Echo({"ERROR!",a,b}); - Echo({"ERROR!",Type(a),Type(b)}); -]; - - - - - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MM.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MM.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MM.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MM.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -%mathpiper,def="MM" - -MM(_expr) <-- MM(expr,MultiExpressionList(expr)); -MM(_expr,_vars) <-- MakeMultiNomial(expr,vars); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiDivide.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiDivide.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiDivide.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiDivide.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -%mathpiper,def="MultiDivide" - -/************************************************************* - MultiDivide : - input - f - a multivariate polynomial - g[1 .. n] - a list of polynomials to divide by - output - {q[1 .. n],r} such that f = q[1]*g[1] + ... + q[n]*g[n] + r - - Basically quotient and remainder after division by a group of - polynomials. -**************************************************************/ -20 # MultiDivide(_f,g_IsList) <-- -[ - Local(i,v,q,r,nr); - v:=MultiExpressionList(f+Sum(g)); - f:=MakeMultiNomial(f,v); - nr := Length(g); - For(i:=1,i<=nr,i++) - [ - g[i] := MakeMultiNomial(g[i],v); - ]; - {q,r}:=MultiDivide(f,g); - q:=MapSingle("NormalForm",q); - r:=NormalForm(r); - {q,r}; -]; - -10 # MultiDivide(f_IsMulti,g_IsList) <-- -[ - Local(i,nr,q,r,p,v,finished); - Set(nr, Length(g)); - Set(v, MultiVars(f)); - Set(q, FillList(0,nr)); - Set(r, 0); - Set(p, f); - Set(finished,MultiZero(p)); - Local(plt,glt); - While (Not finished) - [ - Set(plt, MultiLT(p)); - For(i:=1,i<=nr,i++) - [ - Set(glt, MultiLT(g[i])); - - if (MultiLM(glt) = MultiLM(plt) Or MultiTermLess({MultiLM(glt),1}, {MultiLM(plt),1})) - if (Select({{n},n<0},MultiLM(plt)-MultiLM(glt)) = {}) - [ - Local(ff); - Set(ff, CreateTerm(v,{MultiLM(plt)-MultiLM(glt),MultiLC(plt)/MultiLC(glt)})); - q[i] := q[i] + ff; - Local(ltbefore,ltafter); - Set(ltbefore,MultiLeadingTerm(p)); -// Echo(ltbefore,MultiLeadingTerm(p)); - Set(p, p - ff*g[i]); - Set(ltafter,MultiLeadingTerm(p)); -// Echo(ltbefore,MultiLeadingTerm(p)); - if (ltbefore[1] = ltafter[1]) - [ - Set(ltafter,MultiLT(p)); - Set(p,p-ltafter); - ]; -// Echo(ltbefore,MultiLeadingTerm(p)); - Set(i,nr+2); - ]; - ]; - - If (i = nr+1, - [ - Set(r, r + LocalSymbols(a,b)(Subst(a,b)plt)); - Set(p, p - LocalSymbols(a,b)(Subst(a,b)plt)); - ]); -//Echo(p); - Set(finished,MultiZero(p)); - ]; - {q,r}; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiDivTerm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiDivTerm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiDivTerm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiDivTerm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="MultiDivTerm",scope="private" - -MultiDivTerm(MultiNomial(_vars,_term1),MultiNomial(_vars,_term2)) <-- -[ - Local(lm1,lm2); - Set(lm1,MultiLeadingTerm(MultiNomial(vars,term1)) ); - Set(lm2,MultiLeadingTerm(MultiNomial(vars,term2)) ); - CreateTerm(vars,{lm1[1]-lm2[1],lm1[2] / lm2[2]}); -]; -MultiS(_g,_h,MultiNomial(_vars,_terms)) <-- -[ - Local(gamma); - - gamma :=Max(MultiDegree(g),MultiDegree(h)); - Local(result,topterm); - topterm := MM(Product(vars^gamma)); - - result := - MultiDivTerm(topterm,MultiLT(g))*g - - MultiDivTerm(topterm,MultiLT(h))*h; - - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiGcd.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiGcd.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiGcd.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiGcd.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="MultiGcd" - -//TODO optimize this! keeps on converting to and from internal format! - -10 # MultiGcd( 0,_g) <-- g; -10 # MultiGcd(_f, 0) <-- f; - -20 # MultiGcd(_f,_g) <-- -[ - Local(v); - v:=MultiExpressionList(f+g); //hier - NormalForm(MultiGcd(MakeMultiNomial(f,v),MakeMultiNomial(g,v))); -]; - - -5 # MultiGcd(f_IsMulti,g_IsMulti)_(MultiTermLess({MultiLM(f),1},{MultiLM(g),1})) <-- -[ -//Echo("lesser"); - MultiGcd(g,f); -]; - -5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(MultiLM(MultiNomial(vars,terms)) = MultiLM(g)) - <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); - -5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(Select({{n},n<0},MultiLM(MultiNomial(vars,terms))-MultiLM(g)) != {}) - <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); - -5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(NormalForm(g) = 0) - <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); -10 # MultiGcd(f_IsMulti,g_IsMulti) <-- -[ - LocalSymbols(a) - [ - Set(f,Subst(a,a)f); - Set(g,Subst(a,a)g); - ]; - Local(new); - While(g != 0) - [ -//Echo("before f",f,NormalForm(f)); -//Echo("before g",g,NormalForm(g)); - Set(new, MultiDivide(f,{g})); -//Echo("new g",NormalForm(new[1][1]),NormalForm(new[2])); -If(new[1][1]=0, -[ - g:=MakeMultiNomial(1,MultiVars(f)); -//Echo("PRIM ",MultiPrimitivePart(g)); - new[2]:=0; -]); - Set(new, new[2]); - Set(f,g); - Set(g,new); - -//Echo("after f",f,NormalForm(f)); -//Echo("after g",g,NormalForm(g)); - ]; - MultiPrimitivePart(f); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiNomial.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiNomial.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiNomial.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiNomial.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="MultiNomial" - -// The basic container for multivariates -RuleBase("MultiNomial",{vars,terms}); - -// using the sparse tree driver for multivariate polynomials -//Use("org/mathpiper/assembledscripts/multivar.rep/sparsenomial.mpi"); -//Use("org/mathpiper/assembledscripts/multivar.rep/partialdensenomial.mpi"); - -If(IsBound(MultiNomialDriver), - `Use(@MultiNomialDriver), - Use("org/mathpiper/assembledscripts/multivar.rep/sparsenomial.mpi")); - -// Code that can build the internal representation of a multivariate polynomial -Use("org/mathpiper/assembledscripts/multivar.rep/makemulti.mpi"); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiSimp.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiSimp.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/MultiSimp.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/MultiSimp.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -%mathpiper,def="MultiSimp" - -MultiSimp(_expr) <-- -[ - Local(vars); - vars:=MultiExpressionList(expr); -//Echo({"step1 ",MM(expr,vars)}); - MultiSimp2(MM(expr,vars)); -]; - -10 # MultiSimp2(_a / _b) <-- -[ - Local(c1,c2,gcd,cmn,vars); - - - c1 := MultiContentTerm(a); - c2 := MultiContentTerm(b); - gcd:=Gcd(c1[2],c2[2]); - c1[2] := c1[2]/gcd; - c2[2] := c2[2]/gcd; - - cmn:=Min(c1[1],c2[1]); - c1[1] := c1[1] - cmn; - c2[1] := c2[1] - cmn; - - vars:=MultiVars(a); - Check(vars = MultiVars(a),"incompatible Multivars to simplify"); - - (NormalForm(CreateTerm(vars,c1))/NormalForm(CreateTerm(vars,c2))) - *(NormalForm(MultiPrimitivePart(a))/NormalForm(MultiPrimitivePart(b))); -]; - -20 # MultiSimp2(expr_IsMulti) <-- -[ - NormalForm(MultiContent(expr))*NormalForm(MultiPrimitivePart(expr)); -]; -30 # MultiSimp2(_expr) <-- expr; - -MultiContent(multi_IsMulti) -<-- -[ - Local(least,gcd); - Set(least, MultiDegree(multi)); - Set(gcd,MultiLeadingCoef(multi)); - ScanMultiNomial("MultiContentScan",multi); - CreateTerm(MultiVars(multi),MultiContentTerm(multi)); -]; - -MultiContentTerm(multi_IsMulti) -<-- -[ - Local(least,gcd); - Set(least, MultiDegree(multi)); - Set(gcd,MultiLeadingCoef(multi)); - ScanMultiNomial("MultiContentScan",multi); - {least,gcd}; -]; - -MultiContentScan(_coefs,_fact) <-- -[ - Set(least,Min({least,coefs})); - Set(gcd,Gcd(gcd,fact)); -]; -UnFence("MultiContentScan",2); - -MultiPrimitivePart(MultiNomial(vars_IsList,_terms)) -<-- -[ - Local(cont); - Set(cont,MultiContentTerm(MultiNomial(vars,terms))); - Set(cont,CreateTerm(vars,{-cont[1],1/(cont[2])})); - MultiNomialMultiply(MultiNomial(vars,terms), cont); -]; - -10 # MultiRemoveGcd(x_IsMulti/y_IsMulti) <-- -[ - Local(gcd); - Set(gcd,MultiGcd(x,y)); - Set(x,MultiDivide(x,{gcd})[1][1]); - Set(y,MultiDivide(y,{gcd})[1][1]); - x/y; -]; -20 # MultiRemoveGcd(_x) <-- x; - - - -5 # MultiDegree(MultiNomial(_vars,_term))_(Not(IsList(term))) <-- {}; -10 # MultiDegree(MultiNomial(_vars,{})) <-- FillList(-Infinity,Length(vars)); -20 # MultiDegree(MultiNomial(_vars,_terms)) - <-- (MultiLeadingTerm(MultiNomial(vars,terms))[1]); - - -10 # MultiLeadingCoef(MultiNomial(_vars,_terms)) - <-- (MultiLeadingTerm(MultiNomial(vars,terms))[2]); - -10 # MultiLeadingMono(MultiNomial(_vars,{})) <-- 0; -20 # MultiLeadingMono(MultiNomial(_vars,_terms)) - <-- Product(vars^(MultiDegree(MultiNomial(vars,terms)))); - -20 # MultiLeadingTerm(_m) <-- MultiLeadingCoef(m) * MultiLeadingMono(m); - -MultiVars(MultiNomial(_vars,_terms)) <-- vars; - -20 # MultiLT(multi_IsMulti) - <-- CreateTerm(MultiVars(multi),MultiLeadingTerm(multi)); - -10 # MultiLM(multi_IsMulti) <-- MultiDegree(multi); - -10 # MultiLC(MultiNomial(_vars,{})) <-- 0; -20 # MultiLC(multi_IsMulti) <-- MultiLeadingCoef(multi); - -DropZeroLC(multi_IsMulti) <-- MultiDropLeadingZeroes(multi); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/sparsenomial/sparsenomial.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/sparsenomial/sparsenomial.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/sparsenomial/sparsenomial.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/sparsenomial/sparsenomial.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -%mathpiper,def="" - - -/* Implementation of MultiNomials based on sparse representation - in the sparsetree.mpi code. This is the real driver, using - the sparse trees just for representation. - */ -Use("org/mathpiper/assembledscripts/multivar.rep/sparsetree.mpi"); - -LocalSymbols(NormalMultiNomial) [ - -CreateTerm(_vars,{_coefs,_fact}) - <-- MultiNomial(vars,CreateSparseTree(coefs,fact)); - -/************************************************************ - -Adding and multiplying multivariate polynomials - -************************************************************/ -MultiNomialAdd(MultiNomial(_vars,_x), MultiNomial(_vars,_y)) - <-- MultiNomial(vars,AddSparseTrees(Length(vars),x,y)); -MultiNomialMultiplyAdd(MultiNomial(_vars,_x), MultiNomial(_vars,_y),_coefs,_fact) - <-- MultiNomial(vars,MultiplyAddSparseTrees(Length(vars),x,y,coefs,fact)); -MultiNomialNegate(MultiNomial(_vars,_terms)) - <-- - [ - SparseTreeMap(Hold({{coefs,list},-list}),Length(vars),terms); - MultiNomial(vars,terms); - ]; -MultiNomialMultiply(MultiNomial(_vars,_x),_multi2) - <-- - [ - Local(result); - Set(result,MakeMultiNomial(0,vars)); - SparseTreeScan("muadm",Length(vars),x); - result; - ]; -muadm(_coefs,_fact) <-- -[ - Set(result,MultiNomialMultiplyAdd(result, multi2,coefs,fact)); -]; -UnFence("muadm",2); - - -/* NormalForm: done as an explicit loop in stead of using SparseTreeScan - for speed. This routine is a lot faster! - */ -10 # NormalForm(x_IsMulti/y_IsMulti) <-- NormalForm(x)/NormalForm(y); -20 # NormalForm(MultiNomial(_vars,_list) ) - <-- NormalMultiNomial(vars,list,1); -10 # NormalMultiNomial({},_term,_prefact) <-- prefact*term; -20 # NormalMultiNomial(_vars,_list,_prefact) - <-- - [ - Local(first,rest,result); - Set(first,First(vars)); - Set(rest,Rest(vars)); - Set(result,0); - ForEach(item,list) - [ - Set(result,result+NormalMultiNomial(rest,item[2],prefact*first^(item[1]))); - ]; - result; - ]; - -]; // LocalSymbols - -MultiLeadingTerm(MultiNomial(_vars,_terms)) - <-- - [ - Local(coefs,fact); - Set(coefs,MultiDegreeScanHead(terms,Length(vars))); - {coefs,fact}; - ]; -10 # MultiDegreeScanHead(_tree,0) - <-- - [ - Set(fact,tree); - {}; - ]; -10 # MultiDegreeScanHead(_tree,1) - <-- - [ - Set(fact,tree[1][2]); - {tree[1][1]}; - ]; -20 # MultiDegreeScanHead(_tree,_depth) - <-- - [ - (tree[1][1]):MultiDegreeScanHead(tree[1][2],depth-1); - ]; -UnFence("MultiDegreeScanHead",2); - -ScanMultiNomial(_op,MultiNomial(vars_IsList,_terms)) - <-- SparseTreeScan(op,Length(vars),terms); -UnFence("ScanMultiNomial",2); - - -MultiDropLeadingZeroes(MultiNomial(_vars,_terms)) - <-- - [ - MultiDropScan(terms,Length(vars)); - MultiNomial(vars,terms); - ]; -10 # MultiDropScan(0,0) <-- True; -10 # MultiDropScan({_n,0},0) <-- True; -20 # MultiDropScan(_n,0) - <-- - [ - False; - ]; -30 # MultiDropScan(_tree,_depth) - <-- - [ - Local(i); - For(i:=1,i<=Length(tree),i++) - [ - if (MultiDropScan(tree[i][2],depth-1)) - [ - DestructiveDelete(tree,i); - i--; - ] - else - [ - i:=Length(tree); - ]; - ]; - (tree = {}); - ]; -UnFence("MultiDropScan",2); - - -MultiTermLess({_deg1,_fact1},{_deg2,_fact2}) <-- - [ - Local(deg); - Set(deg, deg1-deg2); - While(deg != {} And First(deg) = 0) [ Set(deg, Rest(deg));]; - - ((deg = {}) And (fact1-fact2 < 0)) Or - ((deg != {}) And (deg[1] < 0)); - ]; - -20 # MultiZero(multi_IsMulti) <-- -[ - CheckMultiZero(DropZeroLC(multi)); -]; -10 # CheckMultiZero(MultiNomial(_vars,{})) <-- True; -20 # CheckMultiZero(MultiNomial(_vars,_terms)) <-- False; - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/sparsetree/sparsetree.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/sparsetree/sparsetree.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/multivar/sparsetree/sparsetree.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/multivar/sparsetree/sparsetree.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,220 +0,0 @@ -%mathpiper,def="CreateSparseTree;SparseTreeMap;SparseTreeScan;AddSparseTrees;MultiplyAddSparseTrees;SparseTreeGet" - -/* def file definitions -CreateSparseTree -SparseTreeMap -SparseTreeScan -AddSparseTrees -MultiplyAddSparseTrees -SparseTreeGet -*/ - -/* Implementation of a sparse tree of Multidimensional matrix elements. -*/ - -10 # SparseTreeGet({},_tree) <-- tree; -20 # SparseTreeGet(_key,_tree) <-- -[ - SparseTreeGet2(Rest(key),Assoc(First(key),tree)); -]; -10 # SparseTreeGet2(_key,Empty) <-- 0; -20 # SparseTreeGet2(_key,_item) <-- SparseTreeGet(key,First(Rest(item))); - -10 # SparseTreeSet({_i},_tree,_newvalue) - <-- -[ - Local(Current,assoc,result); - Set(assoc,Assoc(i,tree)); - if(assoc=Empty) - [ - Set(Current,0); - Set(result,Eval(newvalue)); - AddSparseTrees(1,tree,CreateSparseTree({i},result)); - ] - else - [ - Set(Current,assoc[2]); - Set(result,Eval(newvalue)); - assoc[2] := result; - ]; - result; -]; -20 # SparseTreeSet(_key,_tree,_newvalue) <-- -[ - SparseTreeSet2(Rest(key),Assoc(First(key),tree)); -]; -10 # SparseTreeSet2(_key,Empty) <-- 0; -20 # SparseTreeSet2(_key,_item) - <-- SparseTreeSet(key,First(Rest(item)),newvalue); -UnFence("SparseTreeSet",3); -UnFence("SparseTreeSet2",2); - - -LocalSymbols(SparseTreeMap2,SparseTreeScan2,Muaddterm,MuMuaddterm, - meradd,meraddmap) [ - -10 # CreateSparseTree({},_fact) <-- fact; - -20 # CreateSparseTree(_coefs,_fact) - <-- CreateSparseTree(First(coefs),Rest(coefs),fact); -10 # CreateSparseTree(_first,{},_fact) <-- {{first,fact}}; -20 # CreateSparseTree(_first,_coefs,_fact) - <-- {{first,CreateSparseTree(First(coefs),Rest(coefs),fact)}}; - -10 # SparseTreeMap(_op,_depth,_list) <-- SparseTreeMap2(list,depth,{}); -10 # SparseTreeMap2(_list,1,_coefs) - <-- - ForEach(item,list) - [ - item[2] := ApplyPure(op,{Concat(coefs,{item[1]}),item[2]}); - ]; -20 # SparseTreeMap2(_list,_depth,_coefs) - <-- - ForEach(item,list) - [ - SparseTreeMap2(item[2],AddN(depth,-1),Concat(coefs,{item[1]})); - ]; -UnFence("SparseTreeMap", 3); -[Local(fn);fn:=String(SparseTreeMap2);`UnFence(@fn,3);]; - -10 # SparseTreeScan(_op,_depth,_list) <-- SparseTreeScan2(list,depth,{}); -10 # SparseTreeScan2(_list,0,_coefs) <-- ApplyPure(op,{coefs,list}); -20 # SparseTreeScan2(_list,_depth,_coefs) - <-- - ForEach(item,list) - [ - SparseTreeScan2(item[2],AddN(depth,-1),Concat(coefs,{item[1]})); - ]; -UnFence("SparseTreeScan", 3); -[Local(fn);fn:=String(SparseTreeScan2);`UnFence(@fn,3);]; - - - -5 # AddSparseTrees(0,_x,_y) <-- x+y; -10 # AddSparseTrees(_depth,_x,_y) <-- -[ - Local(i,t1,t2,inspt); - Set(t1,x); - Set(i,1); - Set(t2,y); - Set(inspt,{}); - While(t1 != {} And t2 != {}) - [ - Muaddterm(First(t1),First(t2)); - ]; - While(t2 != {}) - [ - Set(x,DestructiveAppend(x,First(t2))); - Set(t2,Rest(t2)); - ]; - While(inspt != {}) - [ - Set(i,First(inspt)); - Set(x,DestructiveInsert(x,i[2],i[1])); - Set(inspt,Rest(inspt)); - ]; - x; -]; - -10 # Muaddterm({_pow,_list1},{_pow,_list2}) <-- -[ - if(depth=1) - [ t1[1][2] := list1+list2; ] - else - [ t1[1][2] := AddSparseTrees(AddN(depth,-1),list1,list2);]; - Set(t2,Rest(t2)); -]; -20 # Muaddterm(_h1,_h2)_(h1[1] Abs(N(Eval(eps*r)) ) ) ) - [ - r2 := r1; - n++; - r1 := ContFracEval(Take(cflist,n)); - ]; - // now r1 and r2 are some rational numbers. - // decide whether the search was successful. - If( - n=Length(cflist), - {}, // return empty list if not enough precision - If(N(Eval(r-r1))>0, - {r1, r2}, // successive approximations are always bracketing, we only need to decide their order - {r2, r1} - ) - ); -]; - -%/mathpiper - - - -%mathpiper_docs,name="BracketRational",categories="User Functions;Numbers (Operations)" -*CMD BracketRational --- find optimal rational approximations -*STD -*CALL - BracketRational(x, eps) - -*PARMS - -{x} -- a number to be approximated (must be already evaluated to floating-point) - -{eps} -- desired precision - -*DESC - -The function {BracketRational(x,eps)} can be used to find approximations with a given relative precision from above and from below. -This function returns a list of two rational numbers {{r1,r2}} such that $r1 BracketRational(N(Ln(10)), 10^(-8)) - Out> {12381/5377,41062/17833}; - - -*SEE GuessRational, NearRational, ContFrac, ContFracList, Rationalize -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/CharacteristicEquation.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/CharacteristicEquation.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/CharacteristicEquation.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/CharacteristicEquation.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -%mathpiper,def="CharacteristicEquation" - -Function("CharacteristicEquation",{matrix,var}) - SymbolicDeterminant(matrix-var*Identity(Length(matrix))); -HoldArg("CharacteristicEquation",var); - -%/mathpiper - - - -%mathpiper_docs,name="CharacteristicEquation",categories="User Functions;Linear Algebra" -*CMD CharacteristicEquation --- get characteristic polynomial of a matrix -*STD -*CALL - CharacteristicEquation(matrix,var) - -*PARMS - -{matrix} -- a matrix - -{var} -- a free variable - -*DESC - -CharacteristicEquation -returns the characteristic equation of "matrix", using -"var". The zeros of this equation are the eigenvalues -of the matrix, Det(matrix-I*var); - -*E.G. - - In> A:=DiagonalMatrix({a,b,c}) - Out> {{a,0,0},{0,b,0},{0,0,c}}; - In> B:=CharacteristicEquation(A,x) - Out> (a-x)*(b-x)*(c-x); - In> Expand(B,x) - Out> (b+a+c)*x^2-x^3-((b+a)*c+a*b)*x+a*b*c; - -*SEE EigenValues, EigenVectors -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ContFracEval.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ContFracEval.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ContFracEval.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ContFracEval.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="ContFracEval" - -////////////////////////////////////////////////// -/// ContFracEval: evaluate continued fraction from the list of coefficients -////////////////////////////////////////////////// -/// Each coefficient is either a single expression or a list of 2 expressions, giving the term and the numerator of the current level in the fraction. -/// ContFracEval({{a0, b0}, {a1, b1}, ...}) = a0+b0/(a1+b1/(...)) -/// ContFracEval({a0, a1, ...}) = a0+1/(a1+1/(...)) - -10 # ContFracEval({}, _rest) <-- rest; -// finish recursion here -10 # ContFracEval({{_n, _m}}, _rest) <-- n+m+rest; -15 # ContFracEval({_n}, _rest) <-- n+rest; -/// Continued fractions with nontrivial numerators -20 # ContFracEval(list_IsList, _rest)_(IsList(First(list))) <-- First(First(list)) + Rest(First(list)) / ContFracEval(Rest(list), rest); -/// Continued fractions with unit numerators -30 # ContFracEval(list_IsList, _rest) <-- First(list) + 1 / ContFracEval(Rest(list), rest); - -/// evaluate continued fraction: main interface -ContFracEval(list_IsList) <-- ContFracEval(list, 0); - -%/mathpiper - - - -%mathpiper_docs,name="ContFracEval",categories="User Functions;Numbers (Operations)" -*CMD ContFracList --- manipulate continued fractions -*CMD ContFracEval --- manipulate continued fractions -*STD -*CALL - ContFracList(frac) - ContFracList(frac, depth) - ContFracEval(list) - ContFracEval(list, rest) - -*PARMS - -{frac} -- a number to be expanded - -{depth} -- desired number of terms - -{list} -- a list of coefficients - -{rest} -- expression to put at the end of the continued fraction - -*DESC - -The function {ContFracList} computes terms of the continued fraction -representation of a rational number {frac}. It returns a list of terms of length {depth}. If {depth} is not specified, it returns all terms. - -The function {ContFracEval} converts a list of coefficients into a continued fraction expression. The optional parameter {rest} specifies the symbol to put at the end of the expansion. If it is not given, the result is the same as if {rest=0}. - -*E.G. - - In> A:=ContFracList(33/7 + 0.000001) - Out> {4,1,2,1,1,20409,2,1,13,2,1,4,1,1,3,3,2}; - In> ContFracEval(Take(A, 5)) - Out> 33/7; - In> ContFracEval(Take(A,3), remainder) - Out> 1/(1/(remainder+2)+1)+4; - -*SEE ContFrac, GuessRational -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ContFracList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ContFracList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ContFracList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ContFracList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -%mathpiper,def="ContFracList" - -///////////////////////////////////////////////// -/// Continued fractions stuff -///////////////////////////////////////////////// - -/// compute the list of continued fraction coefficients for a given number -/// if order is not given, computes to the end -10 # ContFracList(_n) <-- ContFracList(n, Infinity); -/// compute list of given length -10 # ContFracList(_n, _depth)_(depth <= 0) <-- {}; -20 # ContFracList(n_IsInteger, _depth) <-- {n}; -// prevent infinite loop when in numeric mode -30 # ContFracList(n_IsNumber, _depth) _InNumericMode() <-- NonN(ContFracList(Rationalize(n), depth)); - -40 # ContFracList(n_IsNumber, _depth) <-- ContFracList(Rationalize(n), depth); - -/* n/m = Div(n,m) + 1/( m/Mod(n,m) ) */ -35 # ContFracList((n_IsNegativeInteger) / (m_IsInteger), _depth) <-- Push( ContFracList(m/Mod(n,m), depth-1) , Div(n,m)-1); - -40 # ContFracList((n_IsInteger) / (m_IsInteger), _depth) <-- Push( ContFracList(m/Mod(n,m), depth-1) , Div(n,m)); - -%/mathpiper - - - -%mathpiper_docs,name="ContFracList",categories="User Functions;Numbers (Operations)" -*CMD ContFracList --- manipulate continued fractions -*CMD ContFracEval --- manipulate continued fractions -*STD -*CALL - ContFracList(frac) - ContFracList(frac, depth) - ContFracEval(list) - ContFracEval(list, rest) - -*PARMS - -{frac} -- a number to be expanded - -{depth} -- desired number of terms - -{list} -- a list of coefficients - -{rest} -- expression to put at the end of the continued fraction - -*DESC - -The function {ContFracList} computes terms of the continued fraction -representation of a rational number {frac}. It returns a list of terms of length {depth}. If {depth} is not specified, it returns all terms. - -The function {ContFracEval} converts a list of coefficients into a continued fraction expression. The optional parameter {rest} specifies the symbol to put at the end of the expansion. If it is not given, the result is the same as if {rest=0}. - -*E.G. - - In> A:=ContFracList(33/7 + 0.000001) - Out> {4,1,2,1,1,20409,2,1,13,2,1,4,1,1,3,3,2}; - In> ContFracEval(Take(A, 5)) - Out> 33/7; - In> ContFracEval(Take(A,3), remainder) - Out> 1/(1/(remainder+2)+1)+4; - -*SEE ContFrac, GuessRational -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ContFrac.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ContFrac.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ContFrac.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ContFrac.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -%mathpiper,def="ContFrac" - -////////////////////////////////////////////////// -/// continued fractions for polynomials -////////////////////////////////////////////////// - -/// main interface -10 # ContFrac(_n) <-- ContFrac(n, 6); -50 # ContFrac(_n,_depth) <-- ContFracEval(ContFracList(n, depth), rest); - -40 # ContFrac(n_CanBeUni,_depth)_(Length(VarList(n)) = 1) <-- -[ - ContFracDoPoly(n,depth,VarList(n)[1]); -]; - -5 # ContFracDoPoly(_exp,0,_var) <-- rest; -5 # ContFracDoPoly(0,0,_var) <-- rest; -10 # ContFracDoPoly(_exp,_depth,_var) <-- -[ - Local(content,exp2,first,second); - first:=Coef(exp,var,0); - exp:=exp-first; - content:=Content(exp); - exp2:=DivPoly(1,PrimitivePart(exp),var,5+3*depth)-1; - second:=Coef(exp2,0); - exp2 := exp2 - second; - first+content/((1+second)+ContFracDoPoly(exp2,depth-1,var)); -]; - -%/mathpiper - - - -%mathpiper_docs,name="ContFrac",categories="User Functions;Numbers (Operations)" -*CMD ContFrac --- continued fraction expansion -*STD -*CALL - ContFrac(x) - ContFrac(x, depth) - -*PARMS - -{x} -- number or polynomial to expand in continued fractions - -{depth} -- integer, maximum required depth of result - -*DESC - -This command returns the continued fraction expansion of {x}, which -should be either a floating point number or a polynomial. If -{depth} is not specified, it defaults to 6. The remainder is -denoted by {rest}. - -This is especially useful for polynomials, since series expansions -that converge slowly will typically converge a lot faster if -calculated using a continued fraction expansion. - -*E.G. - - In> PrettyForm(ContFrac(N(Pi))) - - 1 - --------------------------- + 3 - 1 - ----------------------- + 7 - 1 - ------------------ + 15 - 1 - -------------- + 1 - 1 - -------- + 292 - rest + 1 - - Out> True; - In> PrettyForm(ContFrac(x^2+x+1, 3)) - - x - ---------------- + 1 - x - 1 - ------------ - x - -------- + 1 - rest + 1 - - Out> True; - -*SEE PAdicExpand, N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Decimal.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Decimal.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Decimal.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Decimal.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -%mathpiper,def="Decimal" - -10 # Decimal( n_IsInteger ) <-- {n,{0}}; -10 # Decimal( (n_IsPositiveInteger) / (d_IsPositiveInteger) ) <-- -[ - Local(result,rev,first,period,repeat,static); - result:={Div(n,d)}; - Decimal(result,Mod(n,d),d,350); - rev:=DecimalFindPeriod(result); - first:=rev[1]; - period:=rev[2]; - repeat:=result[first .. (first+period-1)]; - static:=result[1 .. (first-1)]; - DestructiveAppend(static,repeat); -]; -20 # Decimal(_n/_m)_((n/m)<0) <-- "-":Decimal(-n/m); - -10 # Decimal(_result , _n , _d,_count ) <-- -[ - While(count>0) - [ - DestructiveAppend(result,Div(10*n,d)); - n:=Mod(10*n,d); - count--; - ]; -]; - -DecimalFindPeriod(_list) <-- -[ - Local(period,nr,reversed,first,i); - reversed:=Rest(DestructiveReverse(FlatCopy(Rest(list)))); - nr:=Length(reversed)>>1; - period:=1; - first:=reversed[1]; - - For(i:=1,i1 And list[first] = list[first+period]) first--; - first++; - - {first,period}; -]; - -DecimalMatches(_reversed,_period) <-- -[ - Local(nr,matches,first); - nr:=0; - matches:=True; - first:=1; - While((nr<100) And matches) - [ - matches := (matches And - (reversed[first .. (first+period-1)] = reversed[(first+period) .. (first+2*period-1)])); - first:=first+period; - nr:=nr+period; - ]; - matches; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Decimal",categories="User Functions;Numbers (Operations)" -*CMD Decimal --- decimal representation of a rational -*STD -*CALL - Decimal(frac) - -*PARMS - -{frac} -- a rational number - -*DESC - -This function returns the infinite decimal representation of a -rational number {frac}. It returns a list, with the first element -being the number before the decimal point and the last element the -sequence of digits that will repeat forever. All the intermediate list -elements are the initial digits before the period sets in. - -*E.G. - - In> Decimal(1/22) - Out> {0,0,{4,5}}; - In> N(1/22,30) - Out> 0.045454545454545454545454545454; - -*SEE N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/EigenValues.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/EigenValues.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/EigenValues.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/EigenValues.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="EigenValues" - -// diagonal matrices will be caught by IsUpperTriangular -10 # EigenValues(matrix_IsUpperTriangular) <-- Diagonal(matrix); -10 # EigenValues(matrix_IsLowerTriangular) <-- Diagonal(matrix); - -20 # EigenValues(matrix_IsMatrix) <-- Roots(CharacteristicEquation(matrix,xx)); - -%/mathpiper - - - -%mathpiper_docs,name="EigenValues",categories="User Functions;Linear Algebra" -*CMD EigenValues --- get eigenvalues of a matrix -*STD -*CALL - EigenValues(matrix) - -*PARMS - -{matrix} -- a square matrix - -*DESC - -EigenValues returns the eigenvalues of a matrix. -The eigenvalues x of a matrix M are the numbers such that -$M*v=x*v$ for some vector. - -It first determines the characteristic equation, and then factorizes this -equation, returning the roots of the characteristic equation -Det(matrix-x*identity). - -*E.G. - - In> M:={{1,2},{2,1}} - Out> {{1,2},{2,1}}; - In> EigenValues(M) - Out> {3,-1}; - -*SEE EigenVectors, CharacteristicEquation -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/EigenVectors.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/EigenVectors.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/EigenVectors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/EigenVectors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -%mathpiper,def="EigenVectors" - -EigenVectors(_matrix,_eigenvalues) <-- -[ - Local(result,n); -/* eigenvalues:=N(Eval(eigenvalues)); */ - n:=Length(eigenvalues); - result:={}; - ForEach(e,eigenvalues) - [ - Local(possible); -/* Echo({"1...",result}); */ - possible:=OldSolve(matrix*MakeVector(k,n)==e*MakeVector(k,n),MakeVector(k,n))[1]; -/* Echo({"2..."}); */ -/* Echo({"2..."}); */ - - If(Not(IsZeroVector(possible)), - DestructiveAppend(result,possible) - ); -/* Echo({"3..."}); */ - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="EigenVectors",categories="User Functions;Linear Algebra" -*CMD EigenVectors --- get eigenvectors of a matrix -*STD -*CALL - EigenVectors(A,eigenvalues) - -*PARMS - -{matrix} -- a square matrix - -{eigenvalues} -- list of eigenvalues as returned by {EigenValues} - -*DESC - -{EigenVectors} returns a list of the eigenvectors of a matrix. -It uses the eigenvalues and the matrix to set up n equations with -n unknowns for each eigenvalue, and then calls {Solve} to determine -the values of each vector. - -*E.G. - - In> M:={{1,2},{2,1}} - Out> {{1,2},{2,1}}; - In> e:=EigenValues(M) - Out> {3,-1}; - In> EigenVectors(M,e) - Out> {{-ki2/ -1,ki2},{-ki2,ki2}}; - -*SEE EigenValues, CharacteristicEquation -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/GuessRational.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/GuessRational.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/GuessRational.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/GuessRational.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -%mathpiper,def="GuessRational" - -/// guess the rational number behind an imprecise number -/// prec parameter is the max number of digits you can have in the denominator -GuessRational(_x) <-- GuessRational(x, Floor(1/2*BuiltinPrecisionGet())); -GuessRational(x_IsRationalOrNumber, prec_IsInteger) <-- [ - Local(denom'estimate, cf, i); - denom'estimate := 1; - cf := ContFracList(x); - For(i:=2, i<=Length(cf) And denom'estimate < 10^prec, i++) - [ // estimate the denominator - denom'estimate := denom'estimate * If( - cf[i] = 1, - If( - i+2<=Length(cf), // have at least two more terms, do a full estimate - RoundTo(N(Eval(cf[i]+1/(cf[i+1]+1/cf[i+2]))), 3), - // have only one more term - RoundTo(N(Eval(cf[i]+1/cf[i+1])), 3) - ), - // term is not 1, use the simple estimate - cf[i] - ); - ]; - If (denom'estimate < 10^prec, - If(InVerboseMode(), Echo({"GuessRational: all ", i, "terms are within limits"})), - i-- // do not use the last term - ); - i--; // loop returns one more number - If(InVerboseMode(), Echo({"GuessRational: using ", i, "terms of the continued fraction"})); - ContFracEval(Take(cf, i)); -]; - -%/mathpiper - - - -%mathpiper_docs,name="GuessRational",categories="User Functions;Numbers (Operations)" -*CMD GuessRational --- find optimal rational approximations -*STD -*CALL - GuessRational(x) - GuessRational(x, digits) - -*PARMS - -{x} -- a number to be approximated (must be already evaluated to floating-point) - -{digits} -- desired number of decimal digits (integer) - -*DESC - -The functions {GuessRational(x)} and {NearRational(x)} attempt to find "optimal" -rational approximations to a given value {x}. The approximations are "optimal" -in the sense of having smallest numerators and denominators among all rational -numbers close to {x}. This is done by computing a continued fraction -representation of {x} and truncating it at a suitably chosen term. Both -functions return a rational number which is an approximation of {x}. - -Unlike the function {Rationalize()} which converts floating-point numbers to -rationals without loss of precision, the functions {GuessRational()} and -{NearRational()} are intended to find the best rational that is approximately -equal to a given value. - -The function {GuessRational()} is useful if you have obtained a -floating-point representation of a rational number and you know -approximately how many digits its exact representation should contain. -This function takes an optional second parameter {digits} which limits -the number of decimal digits in the denominator of the resulting -rational number. If this parameter is not given, it defaults to half -the current precision. This function truncates the continuous fraction -expansion when it encounters an unusually large value (see example). -This procedure does not always give the "correct" rational number; a -rule of thumb is that the floating-point number should have at least as -many digits as the combined number of digits in the numerator and the -denominator of the correct rational number. - -*E.G. - -Start with a rational number and obtain a floating-point approximation: - In> x:=N(956/1013) - Out> 0.9437314906 - In> Rationalize(x) - Out> 4718657453/5000000000; - In> V(GuessRational(x)) - - GuessRational: using 10 terms of the continued fraction - Out> 956/1013; - In> ContFracList(x) - Out> {0,1,16,1,3,2,1,1,1,1,508848,3,1,2,1,2,2}; - -*SEE BracketRational, NearRational, ContFrac, ContFracList, Rationalize -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/InverseTaylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/InverseTaylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/InverseTaylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/InverseTaylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -%mathpiper,def="InverseTaylor" - -/* InverseTaylor : given a function y=f(x), determine the Taylor series - * expansion of the inverse f^-1(y)=x this function around y0=f(x0). - * - */ -Function("InverseTaylor",{var,val,degree,func}) -[ - Local(l1); - l1:=UniTaylor(func,var,val,degree); - val+ReversePoly(l1,var,var,var,degree+1); -]; - -%/mathpiper - - - -%mathpiper_docs,name="InverseTaylor",categories="User Functions;Series" -*CMD InverseTaylor --- Taylor expansion of inverse -*STD -*CALL - InverseTaylor(var, at, order) expr - -*PARMS - -{var} -- variable - -{at} -- point to get inverse Taylor series around - -{order} -- order of approximation - -{expr} -- expression to get inverse Taylor series for - -*DESC - -This function builds the Taylor series expansion of the inverse of the -expression "expr" with respect to the variable "var" around "at" -up to order "order". It uses the function {ReversePoly} to perform the task. - -*E.G. - - In> PrettyPrinter'Set("PrettyForm") - - True - - In> exp1 := Taylor(x,0,7) Sin(x) - - 3 5 7 - x x x - x - -- + --- - ---- - 6 120 5040 - - In> exp2 := InverseTaylor(x,0,7) ArcSin(x) - - 5 7 3 - x x x - --- - ---- - -- + x - 120 5040 6 - - In> Simplify(exp1-exp2) - - 0 - - -*SEE ReversePoly, Taylor, BigOh -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/IsFreeOf.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/IsFreeOf.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/IsFreeOf.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/IsFreeOf.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -%mathpiper,def="IsFreeOf" - -1 # IsFreeOf({},_expr) <-- True; -2 # IsFreeOf(var_IsList, _expr) <-- And(IsFreeOf(First(var),expr), IsFreeOf(Rest(var),expr)); - -4 # IsFreeOf(_var,{}) <-- True; -5 # IsFreeOf(_var,expr_IsList) <-- And(IsFreeOf(var,First(expr)), IsFreeOf(var,Rest(expr))); - -/* Accept any variable. */ -10 # IsFreeOf(_expr,_expr) <-- False; - -/* Otherwise check all leafs of a function. */ -11 # IsFreeOf(_var,expr_IsFunction) <-- IsFreeOf(var,Rest(Listify(expr))); - -/* Else it doesn't depend on any variable. */ -12 # IsFreeOf(_var,_expr) <-- True; - -%/mathpiper - - - -%mathpiper_docs,name="IsFreeOf",categories="User Functions;Predicates" -*CMD IsFreeOf --- test whether expression depends on variable -*STD -*CALL - IsFreeOf(var, expr) - IsFreeOf({var, ...}, expr) - -*PARMS - -{expr} -- expression to test - -{var} -- variable to look for in "expr" - -*DESC - -This function checks whether the expression "expr" (after being -evaluated) depends on the variable "var". It returns {False} if this is the case and {True} -otherwise. - -The second form test whether the expression depends on any of -the variables named in the list. The result is {True} if none of the variables appear in the expression and {False} otherwise. - -*E.G. - - In> IsFreeOf(x, Sin(x)); - Out> False; - In> IsFreeOf(y, Sin(x)); - Out> True; - In> IsFreeOf(x, D(x) a*x+b); - Out> True; - In> IsFreeOf({x,y}, Sin(x)); - Out> False; - -The third command returns {True} because the -expression {D(x) a*x+b} evaluates to {a}, which does not depend on {x}. - -*SEE Contains -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/IsZeroVector.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/IsZeroVector.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/IsZeroVector.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/IsZeroVector.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsZeroVector" - -Function("IsZeroVector",{aList}) aList = ZeroVector(Length(aList)); - -%/mathpiper - - - -%mathpiper_docs,name="IsZeroVector",categories="User Functions;Predicates" -*CMD IsZeroVector --- test whether list contains only zeroes -*STD -*CALL - IsZeroVector(list) - -*PARMS - -{list} -- list to compare against the zero vector - -*DESC - -The only argument given to {IsZeroVector} should be -a list. The result is {True} if the list contains -only zeroes and {False} otherwise. - -*E.G. - - In> IsZeroVector({0, x, 0}); - Out> False; - In> IsZeroVector({x-x, 1 - D(x) x}); - Out> True; - -*SEE IsList, ZeroVector -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/LagrangeInterpolant.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/LagrangeInterpolant.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/LagrangeInterpolant.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/LagrangeInterpolant.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -%mathpiper,def="LagrangeInterpolant" - -LagrangeInt(_var,_list) <-- -[ - Local(nr); - nr:=Length(list); - Product(FillList(var,nr)-list); -]; - -LagrangeInterpolant(list_IsList,_values,_var) <-- -[ - Local(i,nr,sublist); - nr:=Length(list); - result:=0; - For(i:=1,i<=nr,i++) - [ - sublist:=FlatCopy(list); - DestructiveDelete(sublist,i); - result:=result + values[i]*LagrangeInt(var,sublist)/LagrangeInt(list[i],sublist); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="LagrangeInterpolant",categories="User Functions;Series" -*CMD LagrangeInterpolant --- polynomial interpolation -*STD -*CALL - LagrangeInterpolant(xlist, ylist, var) - -*PARMS - -{xlist} -- list of argument values - -{ylist} -- list of function values - -{var} -- free variable for resulting polynomial - -*DESC - -This function returns a polynomial in the variable "var" which -interpolates the points "(xlist, ylist)". Specifically, the value of -the resulting polynomial at "xlist[1]" is "ylist[1]", the value at -"xlist[2]" is "ylist[2]", etc. The degree of the polynomial is not -greater than the length of "xlist". - -The lists "xlist" and "ylist" should be of equal -length. Furthermore, the entries of "xlist" should be all distinct -to ensure that there is one and only one solution. - -This routine uses the Lagrange interpolant formula to build up the -polynomial. - -*E.G. - - In> f := LagrangeInterpolant({0,1,2}, \ - {0,1,1}, x); - Out> (x*(x-1))/2-x*(x-2); - In> Eval(Subst(x,0) f); - Out> 0; - In> Eval(Subst(x,1) f); - Out> 1; - In> Eval(Subst(x,2) f); - Out> 1; - - In> PrettyPrinter'Set("PrettyForm"); - - True - - In> LagrangeInterpolant({x1,x2,x3}, {y1,y2,y3}, x) - - y1 * ( x - x2 ) * ( x - x3 ) - ---------------------------- - ( x1 - x2 ) * ( x1 - x3 ) - - y2 * ( x - x1 ) * ( x - x3 ) - + ---------------------------- - ( x2 - x1 ) * ( x2 - x3 ) - - y3 * ( x - x1 ) * ( x - x2 ) - + ---------------------------- - ( x3 - x1 ) * ( x3 - x2 ) - - -*SEE Subst -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/NearRational.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/NearRational.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/NearRational.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/NearRational.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -%mathpiper,def="NearRational" - -////////////////////////////////////////////////// -/// NearRational, GuessRational -////////////////////////////////////////////////// - -/// find rational number with smallest num./denom. near a given number x -/// See: HAKMEM, MIT AI Memo 239, 02/29/1972, Item 101C -NearRational(_x) <-- NearRational(x, Floor(1/2*BuiltinPrecisionGet())); -NearRational(x_IsRationalOrNumber, prec_IsInteger) <-- [ - Local(x1, x2, i, old'prec); - old'prec := BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec + 8); // 8 guard digits (?) - x1 := ContFracList(N(Eval(x+10^(-prec)))); - x2 := ContFracList(N(Eval(x-10^(-prec)))); - - If(InVerboseMode(), Echo("NearRational: x = ", N(Eval(x )))); - If(InVerboseMode(), Echo("NearRational: xplus = ", N(Eval(x+10^(-prec))))); - If(InVerboseMode(), Echo("NearRational: xmin = ", N(Eval(x-10^(-prec))))); - - If(InVerboseMode(), Echo("NearRational: Length(x1) = ", Length(x1)," ",x1)); - If(InVerboseMode(), Echo("NearRational: Length(x2) = ", Length(x2)," ",x1)); - // find where the continued fractions for "x1" and "x2" differ - // prepare result in "x1" and length of result in "i" - For (i:=1, i<=Length(x1) And i<=Length(x2) And x1[i]=x2[i], i++ ) True; - If( - i>Length(x1), - // "x1" ended but matched, so use "x2" as "x1" - x1:=x2, - If( - i>Length(x2), - // "x2" ended but matched, so use "x1" - True, - // neither "x1" nor "x2" ended and there is a mismatch at "i" - // apply recipe: select the smalest of the differing terms - x1[i]:=Min(x1[i],x2[i]) - ) - ); - // recipe: x1dd 1 to the lx1st term unless it's the lx1st in the originx1l sequence - //Ayal added this line, i could become bigger than Length(x1)! - If(InVerboseMode(), Echo({"NearRational: using ", i, "terms of the continued fraction"})); - If(i>Length(x1),i:=Length(x1)); - x1[i] := x1[i] + If(i=Length(x1), 0, 1); - BuiltinPrecisionSet(old'prec); - ContFracEval(Take(x1, i)); -]; - -%/mathpiper - - - -%mathpiper_docs,name="NearRational",categories="User Functions;Numbers (Operations)" -*CMD NearRational --- find optimal rational approximations -*STD -*CALL - NearRational(x) - NearRational(x, digits) - -*PARMS - -{x} -- a number to be approximated (must be already evaluated to floating-point) - -{digits} -- desired number of decimal digits (integer) - -*DESC - -The functions {GuessRational(x)} and {NearRational(x)} attempt to find "optimal" -rational approximations to a given value {x}. The approximations are "optimal" -in the sense of having smallest numerators and denominators among all rational -numbers close to {x}. This is done by computing a continued fraction -representation of {x} and truncating it at a suitably chosen term. Both -functions return a rational number which is an approximation of {x}. - -Unlike the function {Rationalize()} which converts floating-point numbers to -rationals without loss of precision, the functions {GuessRational()} and -{NearRational()} are intended to find the best rational that is approximately -equal to a given value. - -The function {NearRational(x)} is useful if one needs to -approximate a given value, i.e. to find an "optimal" rational number -that lies in a certain small interval around a certain value {x}. This -function takes an optional second parameter {digits} which has slightly -different meaning: it specifies the number of digits of precision of -the approximation; in other words, the difference between {x} and the -resulting rational number should be at most one digit of that -precision. The parameter {digits} also defaults to half of the current -precision. - -*E.G. - -Start with a rational number and obtain a floating-point approximation: - In> x:=N(956/1013) - Out> 0.9437314906 - In> Rationalize(x) - Out> 4718657453/5000000000; -The first 10 terms of this continued fraction correspond to the correct continued fraction for the original rational number. - In> NearRational(x) - Out> 218/231; -This function found a different rational number closeby because the precision was not high enough. - In> NearRational(x, 10) - Out> 956/1013; - -*SEE BracketRational, GuessRational, ContFrac, ContFracList, Rationalize -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/NewLine.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/NewLine.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/NewLine.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/NewLine.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="NewLine" - -NewLine() := WriteN(Nl(),1); -NewLine(n):= WriteN(Nl(),n); - -%/mathpiper - - - -%mathpiper_docs,name="NewLine",categories="User Functions;Input/Output" -*CMD NewLine --- print one or more newline characters -*STD -*CALL - NewLine() - NewLine(nr) - -*PARMS - -{nr} -- the number of newline characters to print - -*DESC - -The command {NewLine()} prints one newline character -on the current output. The second form prints "nr" newlines on the -current output. The result is always True. - -*E.G. notest - - In> NewLine(); - - Out> True; - -*SEE Echo, Write, Space -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Nl.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Nl.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Nl.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Nl.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="Nl" - -Nl():= -" -"; - -%/mathpiper - - - -%mathpiper_docs,name="Nl",categories="User Functions;Input/Output" -*CMD Nl --- the newline character -*STD -*CALL - Nl() - -*DESC - -This function returns a string with one element in it, namely a newline -character. This may be useful for building strings to send to some -output in the end. - -Note that the second letter in the name of this command is a lower -case {L} (from "line"). - -*E.G. notest - - In> WriteString("First line" : Nl() : "Second line" : Nl()); - First line - Second line - Out> True; - -*SEE NewLine -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Rationalize.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Rationalize.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Rationalize.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Rationalize.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="Rationalize" - -Function("Rationalize",{a'number}) - Substitute(a'number,{{x},IsNumber(x) And Not(IsInteger(x))},"RationalizeNumber"); - -%/mathpiper - - - -%mathpiper_docs,name="Rationalize",categories="User Functions;Numbers (Operations)" -*CMD Rationalize --- convert floating point numbers to fractions -*STD -*CALL - Rationalize(expr) - -*PARMS - -{expr} -- an expression containing real numbers - -*DESC - -This command converts every real number in the expression "expr" -into a rational number. This is useful when a calculation needs to be -done on floating point numbers and the algorithm is unstable. -Converting the floating point numbers to rational numbers will force -calculations to be done with infinite precision (by using rational -numbers as representations). - -It does this by finding the smallest integer $n$ such that multiplying -the number with $10^n$ is an integer. Then it divides by $10^n$ again, -depending on the internal gcd calculation to reduce the resulting -division of integers. - -*E.G. - - In> {1.2,3.123,4.5} - Out> {1.2,3.123,4.5}; - In> Rationalize(%) - Out> {6/5,3123/1000,9/2}; - -*SEE IsRational - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/RationalizeNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/RationalizeNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/RationalizeNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/RationalizeNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="RationalizeNumber" - -Function("RationalizeNumber",{x}) -[ - Check(IsNumber(x),"RationalizeNumber: Error: " : (ToString()Write(x)) :" is not a number"); - Local(n,i); - n:=1; - i:=0; - // We can not take for granted that the internal representation is rounded properly... - While(i<=BuiltinPrecisionGet() And Not(FloatIsInt(x))) - [ - n:=n*10; x:=x*10; - i:=i+1; -//Echo(x,"/",n); - ]; - Floor(x+0.5)/n; //FIXME forced thunking to string representation -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ReversePoly.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ReversePoly.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/ReversePoly.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/ReversePoly.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -%mathpiper,def="ReversePoly" - -/* Lagrangian power series reversion. Copied - from Knuth seminumerical algorithms */ - -ReversePoly(_f,_g,_var,_newvar,_degree) <-- -[ - Local(orig,origg,G,V,W,U,n,initval,firstder,j,k,newsum); - orig:=MakeUni(f,var); - origg:=MakeUni(g,var); - initval:=Coef(orig,0); - firstder:=Coef(orig,1); - V:=Coef(orig,1 .. Degree(orig)); - V:=Concat(V,FillList(0,degree)); - G:=Coef(origg,1 .. Degree(origg)); - G:=Concat(G,FillList(0,degree)); - W:=FillList(0,Length(V)+2); - W[1]:=G[1]/firstder; - U:=FillList(0,Length(V)+2); - U[1]:=1/firstder; - n:=1; - While(n f(x):=Eval(Expand((1+x)^4)) - Out> True; - In> g(x) := x^2 - Out> True; - In> h(y):=Eval(ReversePoly(f(x),g(x),x,y,8)) - Out> True; - In> BigOh(h(f(x)),x,8) - Out> x^2; - In> h(x) - Out> (-2695*(x-1)^7)/131072+(791*(x-1)^6) - /32768 +(-119*(x-1)^5)/4096+(37*(x-1)^4) - /1024+(-3*(x-1)^3)/64+(x-1)^2/16; - -*SEE InverseTaylor, Taylor, BigOh -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Series.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Series.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Series.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Series.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//todo:tk:not implemented. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Space.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Space.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/Space.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/Space.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="Space" - -Space() := WriteN(" ",1); -Space(n):= WriteN(" ",n); - -%/mathpiper - - - -%mathpiper_docs,name="Space",categories="User Functions;Input/Output" -*CMD Space --- print one or more spaces -*STD -*CALL - Space() - Space(nr) - -*PARMS - -{nr} -- the number of spaces to print - -*DESC - -The command {Space()} prints one space on the -current output. The second form prints {nr} spaces on the current -output. The result is always True. - -*E.G. notest - - In> Space(5); - Out> True; - -*SEE Echo, Write, NewLine -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/TRun.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/TRun.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/TRun.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/TRun.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="" - -//todo:tk:this function is completely commented out. - -/* -TRun(_f,_g,_degree)<-- -[ - Local(l2,l3,l4); - l2:=ReversePoly(f,g,t,z,degree); - l3:=Subst(z,f)l2; - l4:=BigOh(l3,t,degree); - Echo({g," == ",l4}); - NewLine(); -]; - -TRun(t+t^2,t,10); -TRun(t/2-t^2,t,10); -TRun(t/2-t^2,3+t+t^2/2,10); -TRun(2+t/2-t^2,t,10); -*/ - -/* -TRun(_f,_degree)<-- -[ - Local(l2,l3,l4); - l2:=InverseTaylor(t,0,degree)f; - l3:=Subst(t,Taylor(t,0,degree)f)l2; - l4:=BigOh(l3,t,degree); - - Echo({t," == ",Simplify(l4)}); - NewLine(); -]; -TRun(Sin(a*t),3); -TRun(a^t,3); -TRun(a^t,3); -TRun(t+t^2,10); -TRun(t/2-t^2,10); -TRun(t/2-t^2,10); -TRun(2+t/2-t^2,10); -*/ - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/UniqueConstant.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/UniqueConstant.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/UniqueConstant.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/UniqueConstant.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="UniqueConstant" - -UniqueConstant() <-- -[ - Local(result); - result := String(LocalSymbols(C)(C)); - Atom(StringMidGet(2,Length(result)-1,result)); -]; - -%/mathpiper - - - -%mathpiper_docs,name="UniqueConstant",categories="User Functions;Variables" -*CMD UniqueConstant --- create a unique identifier -*STD -*CALL - UniqueConstant() - -*DESC - -This function returns a unique constant atom each time you call -it. The atom starts with a C character, and a unique number is -appended to it. - -*E.G. - - In> UniqueConstant() - Out> C9 - In> UniqueConstant() - Out> C10 - -*SEE LocalSymbols - -*CMD LocalSymbols --- create unique local symbols with given prefix -*STD -*CALL - LocalSymbols(var1, var2, ...) body - -*PARMS - -{var1}, {var2}, ... -- atoms, symbols to be made local - -{body} -- expression to execute - -*DESC - -Given the symbols passed as the first arguments to LocalSymbols a set of local -symbols will be created, and creates unique ones for them, typically of the -form {$}, where {symbol} was the symbol entered by the user, -and {number} is a unique number. This scheme was used to ensure that a generated -symbol can not accidentally be entered by a user. - -This is useful in cases where a guaranteed free variable is needed, -for example, in the macro-like functions ({For}, {While}, etc.). - -*E.G. notest - - In> LocalSymbols(a,b)a+b - Out> $a6+ $b6; - -*SEE UniqueConstant -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/WithValue.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/WithValue.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/WithValue.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/WithValue.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="WithValue" - -TemplateFunction("WithValue",{var,val,expr}) -[ - If(IsList(var), - ApplyPure("MacroLocal",var), - MacroLocal(var) - ); - ApplyPure(":=",{var,val}); - Eval(expr); -]; - -%/mathpiper - - - -%mathpiper_docs,name="WithValue",categories="User Functions;Control Flow" -*CMD WithValue --- temporary assignment during an evaluation -*STD -*CALL - WithValue(var, val, expr) - WithValue({var,...}, {val,...}, expr) - -*PARMS - -{var} -- variable to assign to - -{val} -- value to be assigned to "var" - -{expr} -- expression to evaluate with "var" equal to "val" - -*DESC - -First, the expression "val" is assigned to the variable -"var". Then, the expression "expr" is evaluated and -returned. Finally, the assignment is reversed so that the variable -"var" has the same value as it had before {WithValue} was evaluated. - -The second calling sequence assigns the first element in the list of -values to the first element in the list of variables, the second value -to the second variable, etc. - -*E.G. - - In> WithValue(x, 3, x^2+y^2+1); - Out> y^2+10; - In> WithValue({x,y}, {3,2}, x^2+y^2+1); - Out> 14; - -*SEE Subst, /: -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/WriteN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/WriteN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/newly/WriteN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/newly/WriteN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="WriteN" - -WriteN(string,n) := -[ - Local(i); - For(i:=1,i<=n,i++) WriteString(string); - True; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/BellNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/BellNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/BellNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/BellNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="BellNumber" - -10 # BellNumber(n_IsInteger) <-- Sum(k,1,n,StirlingNumber2(n,k)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/CatalanNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/CatalanNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/CatalanNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/CatalanNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="CatalanNumber" - -CatalanNumber(_n) <-- -[ - Check( IsPositiveInteger(n), "CatalanNumber: Error: argument must be positive" ); - BinomialCoefficient(2*n,n)/(n+1); -]; - -%/mathpiper - - - -%mathpiper_docs,name="CatalanNumber",categories="User Functions;Number Theory" -*CMD CatalanNumber --- return the {n}th Catalan Number -*STD -*CALL - CatalanNumber(n) -*PARMS - -{n} -- positive integer - -*DESC - -This function returns the {n}-th Catalan number, defined as $BinomialCoefficient(2*n,n)/(n+1)$. - -*E.G. - - In> CatalanNumber(10) - Out> 16796; - In> CatalanNumber(5) - Out> 42; - -*SEE BinomialCoefficient -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/CheckIntPower.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/CheckIntPower.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/CheckIntPower.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/CheckIntPower.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="CheckIntPower",scope="private" - -/// Check whether n is a power of some integer, assuming that it has no prime factors <= limit. -/// This routine uses only integer arithmetic. -/// Returns {p, s} where s is the smallest prime integer such that n=p^s. (p is not necessarily a prime!) -/// If no powers found, returns {n, 1}. Primality testing of n is not done. -CheckIntPower(n, limit) := -[ - Local(s0, s, root); - If(limit<=1, limit:=2); // guard against too low value of limit - // compute the bound on power s - s0 := IntLog(n, limit); - // loop: check whether n^(1/s) is integer for all prime s up to s0 - root := 0; - s := 0; - While(root = 0 And NextPseudoPrime(s)<=s0) // root=0 while no root is found - [ - s := NextPseudoPrime(s); - root := IntNthRoot(n, s); - If( - root^s = n, // found root - True, - root := 0 - ); - ]; - // return result - If( - root=0, - {n, 1}, - {root, s} - ); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/DigitalRoot.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/DigitalRoot.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/DigitalRoot.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/DigitalRoot.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -%mathpiper,def="DigitalRoot" - -// Digital root of n (repeatedly add digits until reach a single digit). -10 # DigitalRoot(n_IsPositiveInteger) <-- If(n%9=0,9,n%9); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Divisors.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Divisors.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Divisors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Divisors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%mathpiper,def="Divisors" - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 6.2 p112 -5 # Divisors(0) <-- 0; -5 # Divisors(1) <-- 1; -// Unsure about if there should also be a function that returns -// n's divisors, may have to change name in future -10 # Divisors(_n) <-- -[ - Check(IsPositiveInteger(n), - "Divisors: argument must be positive integer"); - Local(len,sum,factors,i); - sum:=1; - factors:=Factors(n); - len:=Length(factors); - For(i:=1,i<=len,i++)[ - sum:=sum*(factors[i][2]+1); - ]; - sum; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Divisors",categories="User Functions;Number Theory" -*CMD Divisors --- number of divisors -*STD -*CALL - Divisors(n) -*PARMS - -{n} -- positive integer - -*DESC - -{Divisors} returns the number of positive divisors of a number. -A number is prime if and only if it has two divisors, 1 and itself. - -*E.G. - In> Divisors(180) - Out> 18; - In> Divisors(37) - Out> 2; - -*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/DivisorsSum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/DivisorsSum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/DivisorsSum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/DivisorsSum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -%mathpiper,def="DivisorsSum" - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 6.2 p112 -5 # DivisorsSum(0) <-- 0; -5 # DivisorsSum(1) <-- 1; -10 # DivisorsSum(_n) <-- -[ - Check(IsPositiveInteger(n), - "DivisorsSum: argument must be positive integer"); - Local(factors,i,sum,len,p,k); - p:=0;k:=0; - factors:={}; - factors:=Factors(n); - len:=Length(factors); - sum:=1; - For(i:=1,i<=len,i++)[ - p:=factors[i][1]; - k:=factors[i][2]; - sum:=sum*(p^(k+1)-1)/(p-1); - ]; - sum; -]; - -%/mathpiper - - - -%mathpiper_docs,name="DivisorsSum",categories="User Functions;Number Theory" -*CMD DivisorsSum --- the sum of divisors -*STD -*CALL - DivisorsSum(n) -*PARMS - -{n} -- positive integer - -*DESC - -{DivisorsSum} returns the sum all numbers that divide it. A number -{n} is prime if and only if the sum of its divisors are {n+1}. - -*E.G. - - In> DivisorsSum(180) - Out> 546; - In> DivisorsSum(37) - Out> 38; - -*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/EulerArray.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/EulerArray.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/EulerArray.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/EulerArray.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -%mathpiper,def="EulerArray" - -/** Compute an array of Euler numbers using recurrence relations. -*/ -10 # EulerArray(n_IsInteger) <-- -[ - Local(E,i,sum,r); - E:=ZeroVector(n+1); - E[1]:=1; - For(i:=1,2*i<=n,i++)[ - sum:=0; - For(r:=0,r<=i-1,r++)[ - sum:=sum+BinomialCoefficient(2*i,2*r)*E[2*r+1]; - ]; - E[2*i+1] := -sum; - ]; - E; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Eulerian.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Eulerian.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Eulerian.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Eulerian.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="Eulerian" - -Eulerian(n_IsInteger,k_IsInteger) <-- Sum(j,0,k+1,(-1)^j*BinomialCoefficient(n+1,j)*(k-j+1)^n); - -%/mathpiper - - - -%mathpiper_docs,name="Eulerian",categories="User Functions;Combinatorics" -*CMD Eulerian --- Eulerian numbers -*STD -*CALL - Eulerian(n,m) - -*PARMS - -{n}, {m} --- integers - -*DESC - -The Eulerian numbers can be viewed as a generalization of the binomial coefficients, -and are given explicitly by $$ Sum(j,0,k+1,(-1)^j*BinomialCoefficient(n+1,j)*(k-j+1)^n) $$ . - -*E.G. - - In> Eulerian(6,2) - Out> 302; - In> Eulerian(10,9) - Out> 1; - -*SEE BinomialCoefficient -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Euler.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Euler.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Euler.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Euler.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="Euler" - -5 # Euler(0) <-- 1; -10 # Euler(n_IsOdd) <-- 0; -10 # Euler(n_IsEven) <-- - Sum(r,0,n/2-1,BinomialCoefficient(n,2*r)*Euler(2*r)); -10 # Euler(n_IsNonNegativeInteger,_x) <-- Sum(i,0,Round(n/2),BinomialCoefficient(n,2*i)*Euler(2*i)*(x-1/2)^(n-2*i)/2^(2*i)); - -%/mathpiper - - - -%mathpiper_docs,name="Euler",categories="User Functions;Special" -*CMD Euler --- Euler numbers and polynomials -*STD -*CALL - Euler(index) - Euler(index,x) - -*PARMS - -{x} -- expression that will be the variable in the polynomial - -{index} -- expression that can be evaluated to an integer - -*DESC - -{Euler(n)} evaluates the $n$-th Euler number. {Euler(n,x)} returns the $n$-th Euler polynomial in the variable $x$. - -*E.G. - - In> Euler(6) - Out> -61; - In> A:=Euler(5,x) - Out> (x-1/2)^5+(-10*(x-1/2)^3)/4+(25*(x-1/2))/16; - In> Simplify(A) - Out> (2*x^5-5*x^4+5*x^2-1)/2; - -*SEE BinomialCoefficient -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/FermatNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/FermatNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/FermatNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/FermatNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="FermatNumber" - -Function("FermatNumber",{n})[ - Check(IsPositiveInteger(n), - "FermatNumber: argument must be a positive integer"); - 2^(2^n)+1; -]; - -%/mathpiper - - - -%mathpiper_docs,name="FermatNumber",categories="User Functions;Number Theory" -*CMD FermatNumber --- return the {n}th Fermat Number -*STD -*CALL - FermatNumber(n) -*PARMS - -{n} -- positive integer - -*DESC - -This function returns the {n}-th Fermat number, which is defined as -$2^(2^n) + 1$. - -*E.G. - - In> FermatNumber(7) - Out> 340282366920938463463374607431768211457; - -*SEE Factor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/AddGaussianFactor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/AddGaussianFactor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/AddGaussianFactor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/AddGaussianFactor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="AddGaussianFactor" - -/* AddGaussianFactor: auxiliary function for Gaussian Factors. -L is a lists of factors of the Gaussian integer z and p is a Gaussian prime -that we want to add to the list. We first find the exponent e of p in the -decomposition of z (into Gaussian primes). If it is not zero, we add {p,e} -to the list */ - -AddGaussianFactor(L_IsList,z_IsGaussianInteger,p_IsGaussianInteger) <-- -[ - Local(e); - e :=0; - While (IsGaussianInteger(z:= z/p)) e++; - If (e != 0, DestructiveAppend(L,{p,e})); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/FactorGaussianInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/FactorGaussianInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/FactorGaussianInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/FactorGaussianInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="FactorGaussianInteger" - -// Algorithm adapted from: Number Theory: A Programmer's Guide -// Mark Herkommer -// Program 8.7.1c, p 264 -// This function needs to be modified to return the factors in -// data structure instead of printing them out - -// THIS FUNCTION IS DEPRECATED NOW! -// Use GaussianFactors instead (Pablo) -// I've leave this here so that you can compare the eficiency of one -// function against the other - -Function("FactorGaussianInteger",{x}) [ - Check( IsGaussianInteger(x), "FactorGaussianInteger: argument must be a Gaussian integer"); - Local(re,im,norm,a,b,d,i,j); - - re:=Re(x);im:=Im(x); - - If(re<0, re:=(-re) ); - If(im<0, im:=(-im) ); - norm:=re^2+im^2; - - if( IsComposite(norm) )[ - For(i:=0, i^2 <= norm, i++ )[ // real part - For(j:=0, i^2 + j^2 <= norm, j++)[ // complex part - if( Not( (i = re And j = im) Or - (i = im And j = re) ) )[ // no associates - d:=i^2+j^2; - if( d > 1 )[ - a := re * i + im * j; - b := im * i - re * j; - While( (Mod(a,d) = 0) And (Mod(b,d) = 0) ) [ - FactorGaussianInteger(Complex(i,j)); - re:= a/d; - im:= b/d; - a := re * i + im * j; - b := im * i - re * j; - norm := re^2 + im^2; - ]; - ]; - ]; - ]; - ]; - If( re != 1 Or im != 0, Echo(Complex(re,im)) ); - ] else [ - Echo(Complex(re,im)); - ]; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactorPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactorPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactorPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactorPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -%mathpiper,def="GaussianFactorPrime" - -/* GaussianFactorPrime(p): auxiliary function for Gaussian factors. -If p is a rational prime of the form 4n+1, we find a factor of p in the -Gaussian Integers. We compute - a = (2n)! -By Wilson's theorem a^2 is -1 (mod p), it follows that - - p| (a+I)(a-I) - -in the Gaussian integers. The desired factor is then the Gaussian GCD of a+i -and p. Note: If the result is Complex(a,b), then p=a^2+b^2 */ - -GaussianFactorPrime(p_IsInteger) <-- [ - Local(a,i); - a := 1; - For (i:=2,i<=(p-1)/2,i++) a := Mod(a*i,p); - GaussianGcd(a+I,p); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactors.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactors.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianFactors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -%mathpiper,def="GaussianFactors" - -Retract("GaussianFactors",*); - -/* -GaussianFactors(n) : returns a list of factors of n, in a similar way to Factors(n). -If n is a rational integer, we factor n in the Gaussian integers, by first -factoring it in the rational integers, and after that factoring each of -its integer prime factors. -*/ - -10 # GaussianFactors(n_IsInteger) <-- -[ - // Chosing to factor this integer as a Gaussian Integer - Local(ifactors,gfactors,p,alpha); - ifactors := FactorizeInt(n); // since we know it is an integer - gfactors := {}; - ForEach(p,ifactors) - [ - If (p[1]=2, [ DestructiveAppend(gfactors,{1+I,p[2]}); - DestructiveAppend(gfactors,{1-I,p[2]}); ]); - If (Mod(p[1],4)=3, DestructiveAppend(gfactors,p)); - If (Mod(p[1],4)=1, [ alpha := GaussianFactorPrime(p[1]); - DestructiveAppend(gfactors,{alpha,p[2]}); - DestructiveAppend(gfactors,{Conjugate(alpha),p[2]}); - ]); - ]; -gfactors; -]; - -/* -If z is is a Gaussian integer, we find its possible Gassian prime factors, -by factoring its norm -*/ - -20 # GaussianFactors(z_IsGaussianInteger) <-- -[ - Local(n,nfactors,gfactors,p); - gfactors :={}; - n := GaussianNorm(z); - nfactors := Factors(n); - ForEach(p,nfactors) - [ - If (p[1]=2, [ AddGaussianFactor(gfactors,z,1+I);]); - If (Mod(p[1],4)=3, AddGaussianFactor(gfactors,z,p[1])); - If (Mod(p[1],4)=1, [ Local(alpha); - alpha := GaussianFactorPrime(p[1]); - AddGaussianFactor(gfactors,z,alpha); - AddGaussianFactor(gfactors,z,Conjugate(alpha)); - ]); - ]; - gfactors; -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - -%mathpiper_docs,name="GaussianFactors",categories="User Functions;Number Theory" -*CMD GaussianFactors --- factorization in Gaussian integers -*STD -*CALL - GaussianFactors(z) - -*PARMS - -{z} -- Gaussian integer - -*DESC - -This function decomposes a Gaussian integer number {z} into a product of -Gaussian prime factors. -A Gaussian integer is a complex number with integer real and imaginary parts. -A Gaussian integer $z$ can be decomposed into Gaussian primes essentially in a -unique way (up to Gaussian units and associated prime factors), i.e. one -can write $z$ as -$$z = u*p[1]^n[1] * ... * p[s]^n[s]$$, -where $u$ is a Gaussian unit and $p[1]$, $p[2]$, ..., $p[s]$ are Gaussian primes. - -The factorization is returned as a list of pairs. The first member of -each pair is the factor (a Gaussian integer) and the second member denotes the power to -which this factor should be raised. So the factorization is returned as -a list, e.g. {{{p1,n1}, {p2,n2}, ...}}. - -*E.G. - - In> GaussianFactors(5) - Out> {{Complex(2,1),1},{Complex(2,-1),1}}; - In> GaussianFactors(3+I) - Out> {{Complex(1,1),1},{Complex(2,-1),1}}; - -*SEE Factors, IsGaussianPrime, IsGaussianUnit -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianGcd.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianGcd.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianGcd.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianGcd.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="GaussianGcd" - -10 # GaussianGcd(n_IsGaussianInteger,m_IsGaussianInteger) <-- -[ - If(N(Abs(m))=0,n, GaussianGcd(m,n - m*Round(n/m) ) ); -]; - -%/mathpiper - - - -%mathpiper_docs,name="GaussianGcd",categories="User Functions;Number Theory" -*CMD GaussianGcd --- greatest common divisor in Gaussian integers -*STD -*CALL - GaussianGcd(z,w) - -*PARMS - -{z}, {w} -- Gaussian integers - -*DESC - -This function returns the greatest common divisor, in the ring of Gaussian -integers, computed using Euclid's algorithm. Note that in the Gaussian -integers, the greatest common divisor is only defined up to a Gaussian unit factor. - -*E.G. - - In> GaussianGcd(2+I,5) - Out> Complex(2,1); -The GCD of two mutually prime Gaussian integers might come out to be equal to some Gaussian unit instead of $1$: - In> GaussianGcd(2+I,3+I) - Out> -1; - -*SEE Gcd, Lcm, IsGaussianUnit -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianMod.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianMod.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianMod.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianMod.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="GaussianMod" - -GaussianMod(z_IsGaussianInteger,w_IsGaussianInteger) <-- z - w * Round(z/w); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianNorm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianNorm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianNorm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/GaussianNorm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -%mathpiper,def="GaussianNorm" - -GaussianNorm(z_IsGaussianInteger) <-- Re(z)^2+Im(z)^2; - -%/mathpiper - - - -%mathpiper_docs,name="GaussianNorm",categories="User Functions;Number Theory" -*CMD GaussianNorm --- norm of a Gaussian integer -*STD -*CALL - GaussianNorm(z) - -*PARMS - -{z} -- Gaussian integer - -*DESC - -This function returns the norm of a Gaussian integer $z=a+b*I$, defined as -$a^2+b^2$. - -*E.G. - - In> GaussianNorm(2+I) - Out> 5; - -*SEE IsGaussianInteger -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="IsGaussianInteger" - -5 # IsGaussianInteger(x_IsList) <-- False; - -// ?????? why is the following rule needed? -// 5 # IsGaussianInteger(ProductPrimesTo257) <-- False; - -10 # IsGaussianInteger(x_IsComplex) <-- (IsInteger(Re(x)) And IsInteger(Im(x))); -// to catch IsGaussianInteger(x+2) from Apart -15 # IsGaussianInteger(_x) <-- False; - -%/mathpiper - - - -%mathpiper_docs,name="IsGaussianInteger",categories="User Functions;Predicates" -*CMD IsGaussianInteger --- test for a Gaussian integer -*STD -*CALL - IsGaussianInteger(z) -*PARMS - -{z} -- a complex or real number - -*DESC - -This function returns {True} if the argument is a Gaussian integer and {False} otherwise. -A Gaussian integer is a generalization -of integers into the complex plane. A complex number $a+b*I$ is a Gaussian -integer if and only if $a$ and $b$ are integers. - -*E.G. - In> IsGaussianInteger(5) - Out> True; - In> IsGaussianInteger(5+6*I) - Out> True; - In> IsGaussianInteger(1+2.5*I) - Out> False; - -*SEE IsGaussianUnit, IsGaussianPrime -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -%mathpiper,def="IsGaussianPrime" - -Function("IsGaussianPrime",{x}) -[ - if( IsGaussianInteger(x) )[ - if( IsZero(Re(x)) )[ - ( Abs(Im(x)) % 4 = 3 And IsPrime(Abs(Im(x))) ); - ] else if ( IsZero(Im(x)) ) [ - ( Abs(Re(x)) % 4 = 3 And IsPrime(Abs(Re(x))) ); - ] else [ - IsPrime(Re(x)^2 + Im(x)^2); - ]; - ] else [ - False; - ]; - -]; - - -/* -10 # IsGaussianPrime(p_IsInteger) <-- IsPrime(p) And Mod(p,3)=1; -20 # IsGaussianPrime(p_IsGaussianInteger) <-- IsPrime(GaussianNorm(p)); -*/ - -%/mathpiper - - - -%mathpiper_docs,name="IsGaussianPrime",categories="User Functions;Number Theory;Predicates" -*CMD IsGaussianPrime --- test for a Gaussian prime -*STD -*CALL - IsGaussianPrime(z) -*PARMS - -{z} -- a complex or real number - -*DESC - -This function returns {True} if the argument -is a Gaussian prime and {False} otherwise. - -A prime element $x$ of a ring is divisible only by the units of -the ring and by associates of $x$. -("Associates" of $x$ are elements of the form $x*u$ where $u$ is -a unit of the ring). - -Gaussian primes are Gaussian integers $z=a+b*I$ that satisfy one of the -following properties: - -* If $Re(z)$ and $Im(z)$ are nonzero then $z$ is a Gaussian prime if and only -if $Re(z)^2 + Im(z)^2$ is an ordinary prime. -* If $Re(z)==0$ then $z$ is a Gaussian prime if and only if $Im(z)$ is an -ordinary prime and $Im(z):=Mod(3,4)$. -* If $Im(z)==0$ then $z$ is a Gaussian prime -if and only if $Re(z)$ is an ordinary prime and $Re(z):=Mod(3,4)$. - -*E.G. - In> IsGaussianPrime(13) - Out> False; - In> IsGaussianPrime(2+2*I) - Out> False; - In> IsGaussianPrime(2+3*I) - Out> True; - In> IsGaussianPrime(3) - Out> True; - -*SEE IsGaussianInteger, GaussianFactors -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianUnit.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianUnit.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianUnit.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/gaussianintegers/IsGaussianUnit.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="IsGaussianUnit" - -IsGaussianUnit(z_IsGaussianInteger) <-- GaussianNorm(z)=1; - -%/mathpiper - - - -%mathpiper_docs,name="IsGaussianUnit",categories="User Functions;Number Theory;Predicates" -*CMD IsGaussianUnit --- test for a Gaussian unit -*STD -*CALL - IsGaussianUnit(z) -*PARMS - -{z} -- a Gaussian integer - -*DESC - -This function returns {True} if the argument is a unit in the Gaussian -integers and {False} otherwise. A unit in a ring is an element that divides -any other element. - -There are four "units" in the ring of Gaussian integers, which are -$1$, $-1$, $I$, and $-I$. - -*E.G. - In> IsGaussianInteger(I) - Out> True; - In> IsGaussianUnit(5+6*I) - Out> False; - -*SEE IsGaussianInteger, IsGaussianPrime, GaussianNorm -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/GetPrimePower.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/GetPrimePower.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/GetPrimePower.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/GetPrimePower.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="GetPrimePower" - -/// Check whether n is a power of some prime integer and return that integer and the power. -/// This routine uses only integer arithmetic. -/// Returns {p, s} where p is a prime and n=p^s. -/// If no powers found, returns {n, 1}. Primality testing of n is not done. -20 # GetPrimePower(n_IsPositiveInteger) <-- -[ - Local(s, factors, new'factors); - // first, separate any small prime factors - factors := TrialFactorize(n, 257); // "factors" = {n1, {p1,s1},{p2,s2},...} or just {n} if no factors found - If( - Length(factors) > 1, // factorized into something - // now we return {n, 1} either if we haven't completely factorized, or if we factorized into more than one prime factor; otherwise we return the information about prime factors - If( - factors[1] = 1 And Length(factors) = 2, // factors = {1, {p, s}}, so we have a prime power n=p^s - factors[2], - {n, 1} - ), - // not factorizable into small prime factors -- use main algorithm - [ - factors := CheckIntPower(n, 257); // now factors = {p, s} with n=p^s - If( - factors[2] > 1, // factorized into something - // now need to check whether p is a prime or a prime power and recalculate "s" - If( - IsPrime(factors[1]), - factors, // ok, prime power, return information - [ // not prime, need to check if it's a prime power - new'factors := GetPrimePower(factors[1]); // recursive call; now new'factors = {p1, s1} where n = (p1^s1)^s; we need to check that s1>1 - If( - new'factors[2] > 1, - {new'factors[1], new'factors[2]*factors[2]}, // recalculate and return prime power information - {n, 1} // not a prime power - ); - ] - ), - // not factorizable -- return {n, 1} - {n, 1} - ); - ] - ); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/HarmonicNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/HarmonicNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/HarmonicNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/HarmonicNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -%mathpiper,def="HarmonicNumber" - -10 # HarmonicNumber(n_IsInteger) <-- HarmonicNumber(n,1); -HarmonicNumber(n_IsInteger,r_IsPositiveInteger) <-- -[ - // small speed up - if( r=1 )[ - Sum(k,1,n,1/k); - ] else [ - Sum(k,1,n,1/k^r); - ]; -]; - -%/mathpiper - - - -%mathpiper_docs,name="HarmonicNumber",categories="User Functions;Number Theory" -*CMD HarmonicNumber --- return the {n}th Harmonic Number -*STD -*CALL - HarmonicNumber(n) - HarmonicNumber(n,r) -*PARMS - -{n}, {r} -- positive integers - -*DESC - -This function returns the {n}-th Harmonic number, which is defined -as $Sum(k,1,n,1/k)$. If given a second argument, the Harmonic number -of order $r$ is returned, which is defined as $Sum(k,1,n,k^(-r))$. - -*E.G. - - In> HarmonicNumber(10) - Out> 7381/2520; - In> HarmonicNumber(15) - Out> 1195757/360360; - In> HarmonicNumber(1) - Out> 1; - In> HarmonicNumber(4,3) - Out> 2035/1728; - - - -*SEE Sum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IntLog.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IntLog.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IntLog.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IntLog.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -%mathpiper,def="IntLog" - -/// Return integer part of the logarithm of x in given base. Use only integer arithmetic. -10 # IntLog(_x, _base) _ (base<=1) <-- Undefined; -/// Use variable steps to speed up operation for large numbers x -20 # IntLog(_x, _base) <-- -[ - Local(result, step, old'step, factor, old'factor); - result := 0; - old'step := step := 1; - old'factor := factor := base; - // first loop: increase step - While (x >= factor) - [ - old'factor := factor; - factor := factor*factor; - old'step := step; - step := step*2; - ]; - If(x >= base, - [ - step := old'step; - result := step; - x := Div(x, old'factor); - ], - step := 0 - ); - // second loop: decrease step - While (step > 0 And x != 1) - [ - step := Div(step,2); // for each step size down to 1, divide by factor if x is up to it - factor := base^step; - If( - x >= factor, - [ - x:=Div(x, factor); - result := result + step; - ] - ); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="IntLog" -*CMD IntLog --- integer part of logarithm -*STD -*CALL - IntLog(n, base) - -*PARMS - -{n}, {base} -- positive integers - -*DESC - -{IntLog} calculates the integer part of the logarithm of {n} in base {base}. The algorithm uses only integer math and may be faster than computing $$Ln(n)/Ln(base)$$ with multiple precision floating-point math and rounding off to get the integer part. - -This function can also be used to quickly count the digits in a given number. - -*E.G. -Count the number of bits: - In> IntLog(257^8, 2) - Out> 64; - -Count the number of decimal digits: - In> IntLog(321^321, 10) - Out> 804; - -*SEE IntNthRoot, Div, Mod, Ln -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IntNthRoot.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IntNthRoot.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IntNthRoot.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IntNthRoot.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -%mathpiper,def="IntNthRoot" - -/// Compute integer part of s-th root of (positive) integer n. -// algorithm using floating-point math -10 # IntNthRoot(_n, 2) <-- Floor(SqrtN(n)); -20 # IntNthRoot(_n, s_IsInteger) <-- -[ - Local(result, k); - GlobalPush(BuiltinPrecisionGet()); - // find integer k such that 2^k <= n^(1/s) < 2^(k+1) - k := Div(IntLog(n, 2), s); - // therefore we need k*Ln(2)/Ln(10) digits for the floating-point calculation - BuiltinPrecisionSet(2+Div(k*3361, 11165)); // 643/2136 < Ln(2)/Ln(10) < 3361/11165 - result := Round(ExpN(DivideN(Internal'LnNum(DivideN(n, 2^(k*s))), s))*2^k); - BuiltinPrecisionSet(GlobalPop()); - // result is rounded and so it may overshoot (we do not use Floor above because numerical calculations may undershoot) - If(result^s>n, result-1, result); -]; - -/* algorithm using only integer arithmetic. -(this is slower than the floating-point algorithm for large numbers because all calculations are with long integers) -IntNthRoot1(_n, s_IsInteger) <-- -[ - Local(x1, x2, x'new, y1); - // initial guess should always undershoot - // x1:= 2 ^ Div(IntLog(n, 2), s); // this is worse than we can make it - x1 := IntLog(n,2); - // select initial interval using (the number of bits in n) mod s - // note that if the answer is 1, the initial guess must also be 1 (not 0) - x2 := Div(x1, s); // save these values for the next If() - x1 := Mod(x1, s)/s; // this is kept as a fraction - // now assign the initial interval, x1 <= root <= x2 - {x1, x2} := If( - x1 >= 263/290, // > Ln(15/8)/Ln(2) - Div({15,16}*2^x2, 8), - If( - x1 >= 373/462, // > Ln(7/4)/Ln(2) - Div({7,8}*2^x2, 4), - If( - x1 >= 179/306, // > Ln(3/2)/Ln(2) - Div({6,7}*2^x2, 4), - If( - x1 >= 113/351, // > Ln(5/4)/Ln(2) - Div({5,6}*2^x2, 4), - Div({4,5}*2^x2, 4) // between x1 and (5/4)*x1 - )))); - // check whether x2 is the root - y1 := x2^s; - If( - y1=n, - x1 := x2, - // x2 is not a root, so continue as before with x1 - y1 := x1^s // henceforth, y1 is always x1^s - ); - // Newton iteration combined with bisection - While(y1 < n) - [ -// Echo({x1, x2}); - x'new := Div(x1*((s-1)*y1+(s+1)*n), (s+1)*y1+(s-1)*n) + 1; // add 1 because the floating-point value undershoots - If( - x'new < Div(x1+x2, 2), - // x'new did not reach the midpoint, need to check progress - If( - Div(x1+x2, 2)^s <= n, - // Newton's iteration is not making good progress, so leave x2 in place and update x1 by bisection - x'new := Div(x1+x2, 2), - // Newton's iteration knows what it is doing. Update x2 by bisection - x2 := Div(x1+x2, 2) - ) - // else, x'new reached the midpoint, good progress, continue - ); - x1 := x'new; - y1 := x1^s; - ]; - If(y1=n, x1, x1-1); // subtract 1 if we overshot -]; -*/ - -%/mathpiper - - - -%mathpiper_docs,name="IntNthRoot" -*CMD IntNthRoot --- integer part of $n$-th root -*STD -*CALL - IntNthRoot(x, n) - -*PARMS - -{x}, {n} -- positive integers - -*DESC - -{IntNthRoot} calculates the integer part of the $n$-th root of $x$. The algorithm uses only integer math and may be faster than computing $x^(1/n)$ with floating-point and rounding. - -This function is used to test numbers for prime powers. - -*E.G. - In> IntNthRoot(65537^111, 37) - Out> 281487861809153; - -*SEE IntLog, MathPower, IsPrimePower -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsAmicablePair.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsAmicablePair.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsAmicablePair.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsAmicablePair.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsAmicablePair" - -IsAmicablePair(m_IsPositiveInteger,n_IsPositiveInteger) <-- ( ProperDivisorsSum(m)=n And ProperDivisorsSum(n)=m ); - -%/mathpiper - - - -%mathpiper_docs,name="IsAmicablePair",categories="User Functions;Number Theory;Predicates" -*CMD IsAmicablePair --- test for a pair of amicable numbers -*STD -*CALL - IsAmicablePair(m,n) - -*PARMS - -{m}, {n} -- positive integers - -*DESC - -This function tests if a pair of numbers are amicable. A pair of -numbers $m$, $n$ has this property if the sum of the proper divisors of $m$ is -$n$ and the sum of the proper divisors of $n$ is $m$. - -*E.G. - - In> IsAmicablePair(200958394875, 209194708485 ) - Out> True; - In> IsAmicablePair(220, 284) - Out> True; - -*SEE ProperDivisorsSum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsCarmichaelNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsCarmichaelNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsCarmichaelNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsCarmichaelNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="IsCarmichaelNumber" - -// Carmichael numbers are odd,squarefree and have at least 3 prime factors -5 # IsCarmichaelNumber(n_IsEven) <-- False; -5 # IsCarmichaelNumber(_n)_(n<561) <-- False; -10 # IsCarmichaelNumber(n_IsPositiveInteger) <-- -[ - Local(i,factors,length,carmichael); - - factors:=Factors(n); - carmichael:=True; - length:=Length(factors); - if( length < 3)[ - carmichael:=False; - ] else [ - For(i:=1,i<=length And carmichael,i++)[ - //Echo( n-1,"%",factors[i][1]-1,"=", Mod(n-1,factors[i][1]-1) ); - If( Mod(n-1,factors[i][1]-1) != 0, carmichael:=False ); - If(factors[i][2]>1,carmichael:=False); // squarefree - ]; - ]; - carmichael; -]; - -IsCarmichaelNumber(n_IsList) <-- MapSingle("IsCarmichaelNumber",n); - -%/mathpiper - - - -%mathpiper_docs,name="IsCarmichaelNumber",categories="User Functions;Number Theory;Predicates" -*CMD IsCarmichaelNumber --- test for a Carmichael number -*STD -*CALL - IsCarmichaelNumber(n) - -*PARMS - -{n} -- positive integer - -*DESC - -This function returns {True} if {n} is a Carmichael number, also called an absolute pseudoprime. -They have the property that $ b^(n-1) % n == 1 $ for all $b$ satisfying $Gcd(b,n)==1$. These numbers -cannot be proved composite by Fermat's little theorem. Because the previous property is extremely -slow to test, the following equivalent property is tested by MathPiper: for all prime factors $p[i]$ of $n$, -$(n-1) % (p[i] - 1) == 0$ and $n$ must be square free. Also, Carmichael numbers must be odd and have -at least three prime factors. Although these numbers are rare (there are only 43 such numbers between $1$ and $10^6$), -it has recently been proven that there are infinitely many of them. - -*E.G. notest - - In> IsCarmichaelNumber(561) - Out> True; - In> EchoTime() Select(IsCarmichaelNumber,1 .. 10000) - 504.19 seconds taken - Out> {561,1105,1729,2465,2821,6601,8911}; - -*SEE IsSquareFree, IsComposite -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsComposite.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsComposite.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsComposite.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsComposite.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="IsComposite" - -5 # IsComposite(1) <-- False; -10 # IsComposite(n_IsPositiveInteger) <-- (Not IsPrime(n)); - -%/mathpiper - - - -%mathpiper_docs,name="IsComposite",categories="User Functions;Number Theory;Predicates" -*CMD IsComposite --- test for a composite number -*STD -*CALL - IsComposite(n) - -*PARMS - -{n} -- positive integer - -*DESC - -This function is the logical negation of {IsPrime}, except for the number 1, which is -neither prime nor composite. - -*E.G. - - In> IsComposite(1) - Out> False; - In> IsComposite(7) - Out> False; - In> IsComposite(8) - Out> True; - In> Select(IsComposite,1 .. 20) - Out> {4,6,8,9,10,12,14,15,16,18,20}; - -*SEE IsPrime -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsCoprime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsCoprime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsCoprime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsCoprime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="IsCoprime" - -5 # IsCoprime(list_IsList) <-- (Lcm(list) = Product(list)); -10 # IsCoprime(n_IsInteger,m_IsInteger) <-- (Gcd(n,m) = 1); - -%/mathpiper - - - -%mathpiper_docs,name="IsCoprime",categories="User Functions;Number Theory;Predicates" -*CMD IsCoprime --- test if integers are coprime -*STD -*CALL - IsCoprime(m,n) - IsCoprime(list) -*PARMS - -{m},{n} -- positive integers - -{list} -- list of positive integers - -*DESC - -This function returns {True} if the given pair or list of integers are coprime, -also called relatively prime. A pair or list of numbers are coprime if they -share no common factors. - -*E.G. - - In> IsCoprime({3,4,5,8}) - Out> False; - In> IsCoprime(15,17) - Out> True; - -*SEE Prime -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsIrregularPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsIrregularPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsIrregularPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsIrregularPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%mathpiper,def="IsIrregularPrime" - -5 # IsIrregularPrime(p_IsComposite) <-- False; -// First irregular prime is 37 -5 # IsIrregularPrime(_p)_(p<37) <-- False; - -// an odd prime p is irregular iff p divides the numerator of a Bernoulli number B(2*n) with -// 2*n+1

    IsIrregularPrime(5) - Out> False; - In> Select(IsIrregularPrime,1 .. 100) - Out> {37,59,67}; - -*SEE IsPrime -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsPerfect.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsPerfect.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsPerfect.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsPerfect.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="IsPerfect" - -IsPerfect(n_IsPositiveInteger) <-- ProperDivisorsSum(n)=n; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="IsPrime",categories="User Functions;Number Theory" - -2 # IsPrime(_n)_(Not IsInteger(n) Or n<=1) <-- False; -3 # IsPrime(n_IsInteger)_(n<=FastIsPrime(0)) <-- IsSmallPrime(n); - -/* Fast pseudoprime testing: if n is a prime, then 24 divides (n^2-1) */ -5 # IsPrime(n_IsPositiveInteger)_(n > 4 And Mod(n^2-1,24)!=0) <-- False; - -/* Determine if a number is prime, using Rabin-Miller primality - testing. Code submitted by Christian Obrecht - */ -10 # IsPrime(n_IsPositiveInteger) <-- RabinMiller(n); - -%/mathpiper - - - -%mathpiper_docs,name="IsPrime",categories="User Functions;Number Theory;Predicates" -*CMD IsPrime --- test for a prime number -*CMD IsSmallPrime --- test for a (small) prime number -*STD -*CALL - IsPrime(n) - IsSmallPrime(n) - -*PARMS - -{n} -- integer to test - -*DESC - -The commands checks whether $n$, which should be a positive integer, -is a prime number. A number $n$ is a prime number if it is only divisible -by 1 and itself. As a special case, 1 is not considered a prime number. -The first prime numbers are 2, 3, 5, ... - -The function {IsShortPrime} only works for numbers $n<=65537$ but it is very fast. - -The function {IsPrime} operates on all numbers and uses different algorithms depending on the magnitude of the number $n$. -For small numbers $n<=65537$, a constant-time table lookup is performed. -(The function {IsShortPrime} is used for that.) -For numbers $n$ between $65537$ and $34155071728321$, the function uses the Rabin-Miller test together with table lookups to guarantee correct results. - -For even larger numbers a version of the probabilistic Rabin-Miller test is executed. -The test can sometimes mistakenly mark a number as prime while it is in fact composite, but a prime number will never be mistakenly declared composite. -The parameters of the test are such that the probability for a false result is less than $10^(-24)$. - -*E.G. - - In> IsPrime(1) - Out> False; - In> IsPrime(2) - Out> True; - In> IsPrime(10) - Out> False; - In> IsPrime(23) - Out> True; - In> Select("IsPrime", 1 .. 100) - Out> {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47, - 53,59,61,67,71,73,79,83,89,97}; - -*SEE IsPrimePower, Factors -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsPrimePower.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsPrimePower.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsPrimePower.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsPrimePower.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="IsPrimePower" - -/* Returns whether n is a prime^m. */ -10 # IsPrimePower(n_IsPrime) <-- True; -10 # IsPrimePower(0) <-- False; -10 # IsPrimePower(1) <-- False; -20 # IsPrimePower(n_IsPositiveInteger) <-- (GetPrimePower(n)[2] > 1); - -%/mathpiper - - - -%mathpiper_docs,name="IsPrimePower",categories="User Functions;Number Theory;Predicates" -*CMD IsPrimePower --- test for a power of a prime number -*STD -*CALL - IsPrimePower(n) - -*PARMS - -{n} -- integer to test - -*DESC - -This command tests whether "n", which should be a positive integer, -is a prime power, that is whether it is of the form $p^m$, with -"p" prime and "m" an integer. - -This function does not try to decompose the number $n$ into factors. -Instead we check for all prime numbers $r=2$, $3$, ... that the $r$-th root of $n$ is an integer, and we find such $r$ and $m$ that $n=m^r$, we check that $m$ is a prime. If it is not a prime, we execute the same function call on $m$. - -*E.G. - - In> IsPrimePower(9) - Out> True; - In> IsPrimePower(10) - Out> False; - In> Select("IsPrimePower", 1 .. 50) - Out> {2,3,4,5,7,8,9,11,13,16,17,19,23,25,27, - 29,31,32,37,41,43,47,49}; - -*SEE IsPrime, Factors -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsQuadraticResidue.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsQuadraticResidue.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsQuadraticResidue.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsQuadraticResidue.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="IsQuadraticResidue" - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 9.1 p187 -10 # IsQuadraticResidue(_a,_p) <-- -[ - Check( IsInteger(a) And IsInteger(p) And p>2 And IsCoprime(a,p) And IsPrime(p), - "IsQuadraticResidue: Invalid arguments"); - If(a^((p-1)/2) % p = 1, True, False); -]; - -%/mathpiper - - - -%mathpiper_docs,name="IsQuadraticResidue",categories="User Functions;Number Theory;Predicates" -*CMD IsQuadraticResidue --- functions related to finite groups -*STD -*CALL - IsQuadraticResidue(m,n) - -*PARMS -{m}, {n} -- integers, $n$ must be odd and positive - -*DESC - -A number $m$ is a "quadratic residue modulo $n$" if there exists a number $k$ such that $k^2:=Mod(m,n)$. - -*E.G. - - In> IsQuadraticResidue(9,13) - Out> True; - -*SEE Gcd, JacobiSymbol, LegendreSymbol -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsSmallPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsSmallPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsSmallPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsSmallPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -%mathpiper,def="IsSmallPrime" - -/* Returns whether n is a small by a lookup table, very fast. -The largest prime number in the table is returned by FastIsPrime(0). */ - -2 # IsSmallPrime(0) <-- False; -3 # IsSmallPrime(n_IsInteger) <-- (FastIsPrime(n)>0); - -%/mathpiper - - - -%mathpiper_docs,name="IsSmallPrime",categories="User Functions;Number Theory;Predicates" -*CMD IsPrime --- test for a prime number -*CMD IsSmallPrime --- test for a (small) prime number -*STD -*CALL - IsPrime(n) - IsSmallPrime(n) - -*PARMS - -{n} -- integer to test - -*DESC - -The commands checks whether $n$, which should be a positive integer, -is a prime number. A number $n$ is a prime number if it is only divisible -by 1 and itself. As a special case, 1 is not considered a prime number. -The first prime numbers are 2, 3, 5, ... - -The function {IsShortPrime} only works for numbers $n<=65537$ but it is very fast. - -The function {IsPrime} operates on all numbers and uses different algorithms depending on the magnitude of the number $n$. -For small numbers $n<=65537$, a constant-time table lookup is performed. -(The function {IsShortPrime} is used for that.) -For numbers $n$ between $65537$ and $34155071728321$, the function uses the Rabin-Miller test together with table lookups to guarantee correct results. - -For even larger numbers a version of the probabilistic Rabin-Miller test is executed. -The test can sometimes mistakenly mark a number as prime while it is in fact composite, but a prime number will never be mistakenly declared composite. -The parameters of the test are such that the probability for a false result is less than $10^(-24)$. - -*E.G. - - In> IsPrime(1) - Out> False; - In> IsPrime(2) - Out> True; - In> IsPrime(10) - Out> False; - In> IsPrime(23) - Out> True; - In> Select("IsPrime", 1 .. 100) - Out> {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47, - 53,59,61,67,71,73,79,83,89,97}; - -*SEE IsPrimePower, Factors -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsSquareFree.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsSquareFree.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsSquareFree.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsSquareFree.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="IsSquareFree" - -IsSquareFree(n_IsInteger) <-- ( Moebius(n) != 0 ); - -%/mathpiper - - - -%mathpiper_docs,name="IsSquareFree",categories="User Functions;Number Theory;Predicates" -*CMD IsSquareFree --- test for a square-free number -*STD -*CALL - IsSquareFree(n) - -*PARMS - -{n} -- positive integer - -*DESC - -This function uses the {Moebius} function to tell if the given number is square-free, which -means it has distinct prime factors. If $Moebius(n)!=0$, then {n} is square free. All prime -numbers are trivially square-free. - -*E.G. - - In> IsSquareFree(37) - Out> True; - In> IsSquareFree(4) - Out> False; - In> IsSquareFree(16) - Out> False; - In> IsSquareFree(18) - Out> False; - -*SEE Moebius, SquareFreeDivisorsList -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsTwinPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsTwinPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/IsTwinPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/IsTwinPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="IsTwinPrime" - -IsTwinPrime(n_IsPositiveInteger) <-- (IsPrime(n) And IsPrime(n+2)); - -%/mathpiper - - - -%mathpiper_docs,name="IsTwinPrime",categories="User Functions;Number Theory;Predicates" -*CMD IsTwinPrime --- test for a twin prime -*STD -*CALL - IsTwinPrime(n) -*PARMS - -{n} -- positive integer - -*DESC - -This function returns {True} if {n} is a twin prime. By definition, a twin -prime is a prime number $n$ such that $n+2$ is also a prime number. - -*E.G. - In> IsTwinPrime(101) - Out> True; - In> IsTwinPrime(7) - Out> False; - In> Select(IsTwinPrime, 1 .. 100) - Out> {3,5,11,17,29,41,59,71}; - -*SEE IsPrime -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/LegendreSymbol.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/LegendreSymbol.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/LegendreSymbol.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/LegendreSymbol.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="LegendreSymbol" - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Definition 9.2 p191 - -10 # LegendreSymbol(_a,_p) <-- -[ - Check( IsInteger(a) And IsInteger(p) And p>2 And IsCoprime(a,p) And IsPrime(p), - "LegendreSymbol: Invalid arguments"); - If(IsQuadraticResidue(a,p), 1, -1 ); -]; - -%/mathpiper - - - -%mathpiper_docs,name="LegendreSymbol",categories="User Functions;Number Theory" -*CMD LegendreSymbol --- functions related to finite groups -*STD -*CALL - LegendreSymbol(m,n) - -*PARMS -{m}, {n} -- integers, $n$ must be odd and positive - -*DESC - -The Legendre symbol ($m$/$n$) is defined as $+1$ if $m$ is a quadratic residue modulo $n$ and $-1$ if it is a non-residue. -The Legendre symbol is equal to $0$ if $m/n$ is an integer. - -*E.G. - - In> IsQuadraticResidue(9,13) - Out> True; - In> LegendreSymbol(15,23) - Out> -1; - In> JacobiSymbol(7,15) - Out> -1; - -*SEE Gcd, JacobiSymbol, IsQuadraticResidue -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Moebius.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Moebius.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Moebius.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Moebius.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="Moebius" - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Definition 6.3 p120 - -5 # Moebius(1) <-- 1; - -10 # Moebius(_n) <-- -[ - Check(IsPositiveInteger(n), - "Moebius: argument must be positive integer"); - Local(factors,i,repeat); - repeat:=0; - factors:=Factors(n); - len:=Length(factors); - For(i:=1,i<=len,i++)[ - If(factors[i][2]>1,repeat:=1); - ]; - If(repeat=0,(-1)^len,0); - -]; - -%/mathpiper - - - -%mathpiper_docs,name="Moebius",categories="User Functions;Number Theory" -*CMD Moebius --- the Moebius function -*STD -*CALL - Moebius(n) -*PARMS - -{n} -- positive integer - -*DESC - -The Moebius function is 0 when a prime factor is repeated (which means it -is not square-free) and is $(-1)^r$ if $n$ has $r$ distinct factors. Also, -$Moebius(1)==1$. - -*E.G. - In> Moebius(10) - Out> 1; - In> Moebius(11) - Out> -1; - In> Moebius(12) - Out> 0; - In> Moebius(13) - Out> -1; - -*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, MoebiusDivisorsList -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/NextPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/NextPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/NextPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/NextPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="NextPrime" - -/// obtain the real next prime number -- use primality testing -1# NextPrime(_i) <-- -[ - Until(IsPrime(i)) i := NextPseudoPrime(i); - i; -]; - -%/mathpiper - - - -%mathpiper_docs,name="NextPrime",categories="User Functions;Number Theory" -*CMD NextPrime --- generate a prime following a number -*STD -*CALL - NextPrime(i) - -*PARMS - -{i} -- integer value - -*DESC - -The function finds the smallest prime number that is greater than the given -integer value. - -The routine generates "candidate numbers" using the formula $n+2*Mod(-n,3)$ -where $n$ is an odd number (this generates the sequence 5, 7, 11, 13, 17, -19, ...) and {IsPrime()} to test whether the next candidate number is in -fact prime. - -*E.G. - In> NextPrime(5) - Out> 7; - -*SEE IsPrime -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/NextPseudoPrime.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/NextPseudoPrime.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/NextPseudoPrime.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/NextPseudoPrime.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -%mathpiper,def="NextPseudoPrime" - -/// obtain next number that has good chances of being prime (not divisible by 2,3) -1# NextPseudoPrime(i_IsInteger)_(i<=1) <-- 2; -2# NextPseudoPrime(2) <-- 3; -//2# NextPseudoPrime(3) <-- 5; -3# NextPseudoPrime(i_IsOdd) <-- -[ - // this sequence generates numbers not divisible by 2 or 3 - i := i+2; - If(Mod(i,3)=0, i:=i+2, i); -/* commented out because it slows things down without a real advantage -// this works only for odd i>=5 - i := If( - Mod(-i,3)=0, - i + 2, - i + 2*Mod(-i, 3) - ); - // now check if divisible by 5 - If( - Mod(i,5)=0, - NextPseudoPrime(i), - i - ); -*/ -]; -// this works only for even i>=4 -4# NextPseudoPrime(i_IsEven) <-- NextPseudoPrime(i-1); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/nthroot/nthroot.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/nthroot/nthroot.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/nthroot/nthroot.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/nthroot/nthroot.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -%mathpiper,def="NthRoot;NthRoot'Calc;NthRoot'List;NthRoot'Save;NthRoot'Restore;NthRoot'Clear" - -/* def file definitions -NthRoot -NthRoot'Calc -NthRoot'List -NthRoot'Save -NthRoot'Restore -NthRoot'Clear - -*/ - -////// -// $Id: nthroot.mpi,v 1.5 2007/05/17 11:56:45 ayalpinkus Exp $ -// calculation/simplifaction of nth roots of nonnegative integers -// NthRoot - interface function -// NthRoot'Calc - actually calculate/simplifies -// NthRoot'List - list table entries for a given n -// NthRoot'Restore - get a root from lookup table -// NthRoot'Save - save a root in lookup table -// NthRoot'Clear - clear lookup table -////// - -// LocalSymbols(m,n,r, -// NthRoot'Table, -// NthRoot'Calc, -// NthRoot'List, -// NthRoot'Restore, -// NthRoot'Save, -// NthRoot'Clear) -LocalSymbols(m,n,r, - NthRoot'Table) -[ - -// interface function for nth root of m -// m>=0, n>1, integers -// m^(1/n) --> f*(r^(1/n)) -NthRoot(m_IsNonNegativeInteger,n_IsInteger)_(n>1) <-- -[ - Local(r); - r:=NthRoot'Restore(m,n); - If(Length(r)=0, - [ - r:=NthRoot'Calc(m,n); - NthRoot'Save(m,n,r); - ]); - r; -]; - -// internal functions -Function("NthRoot'Calc",{m,n}) -[ - Local(i,j,f,r,in); - Set(i,2); - Set(j,Ceil(FastPower(m,N(1.0/n))+1)); - Set(f,1); - Set(r,m); - // for large j (approx >4000) - // using Factors instead of the - // following. would this be - // faster in general? -//Echo("i j ",i," ",j); - While(LessThan(i,j)) - [ - Set(in,PowerN(i,n)); -//Echo("r in mod ",r, " ",in," ",ModN(r,in)); - While(Equals(ModN(r,in),0)) - [ - Set(f,MultiplyN(f,i)); - Set(r,DivN(r,in)); - ]; - While(Equals(ModN(r,i),0)) // - Set(r,DivN(r,i)); // - //Set(i,NextPrime(i)); - Set(i,NextPseudoPrime(i)); - Set(j,Ceil(FastPower(r,N(1.0/n))+1)); - ]; - //List(f,r); - List(f,DivN(m,PowerN(f,n))); // -]; - -// lookup table utilities -Function("NthRoot'List",{n}) -[ - If(Length(NthRoot'Table)>0, - [ - Local(p,xx); - p:=Select({{xx},First(xx)=n},NthRoot'Table); - If(Length(p)=1,Rest(p[1]),List()); - ], - List()); -]; - -Function("NthRoot'Restore",{m,n}) -[ - Local(p); - p:=NthRoot'List(n); - If(Length(p)>0, - [ - Local(r,xx); - r:=Select({{xx},First(xx)=m},p); - If(Length(r)=1,First(Rest(r[1])),List()); - ], - List()); -]; - -Function("NthRoot'Save",{m,n,r}) -[ - Local(p); - p:=NthRoot'List(n); - If(Length(p)=0, - // create power list and save root - DestructiveInsert(NthRoot'Table,1,List(n,List(m,r))), - [ - Local(rr,xx); - rr:=Select({{xx},First(xx)=m},p); - If(Length(rr)=0, - [ - // save root only - DestructiveAppend(p,List(m,r)); - ], - // already saved - False); - ]); -]; - -//TODO why is NthRoot'Table both lazy global and protected with LocalSymbols? -Function("NthRoot'Clear",{}) SetGlobalLazyVariable(NthRoot'Table,List()); - -// create empty table -NthRoot'Clear(); - -]; // LocalSymbols(m,n,r,NthRoot'Table); - -////// -////// - - -%/mathpiper - - - -%mathpiper_docs,name="NthRoot" -*CMD NthRoot --- calculate/simplify nth root of an integer -*STD -*CALL - NthRoot(m,n) - -*PARMS - -{m} -- a non-negative integer ($m>0$) - -{n} -- a positive integer greater than 1 ($n>1$) - -*DESC - -{NthRoot(m,n)} calculates the integer part of the $n$-th root $m^(1/n)$ and -returns a list {{f,r}}. {f} and {r} are both positive integers -that satisfy $f^n*r$=$m$. -In other words, $f$ is the largest integer such that $m$ divides $f^n$ and $r$ is the remaining factor. - -For large {m} and small {n} -{NthRoot} may work quite slowly. Every result {{f,r}} for given -{m}, {n} is saved in a lookup table, thus subsequent calls to -{NthRoot} with the same values {m}, {n} will be executed quite -fast. - -*E.G. - In> NthRoot(12,2) - Out> {2,3}; - In> NthRoot(81,3) - Out> {3,3}; - In> NthRoot(3255552,2) - Out> {144,157}; - In> NthRoot(3255552,3) - Out> {12,1884}; - -*SEE IntNthRoot, Factors, MathPower -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/DivisorsList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/DivisorsList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/DivisorsList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/DivisorsList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%mathpiper,def="DivisorsList" - -/* Implementation of some number theoretical functions for MathPiper */ -/* (C) 2002 Pablo De Napoli under GNU GPL */ - -/* DivisorsList(n) = the list of divisors of n */ - -DivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {1}; - ForEach (f,nFactors) - [ - oldresult := result; - For (k:=1,k<=f[2],k++) - ForEach (x,oldresult) - result:=Append(result,x*f[1]^k); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="DivisorsList",categories="User Functions;Number Theory" -*CMD DivisorsList --- the list of divisors -*STD -*CALL - DivisorsList(n) -*PARMS - -{n} -- positive integer - -*DESC - -{DivisorsList} creates a list of the divisors of $n$. -This is useful for loops like - - ForEach(d,DivisorsList(n)) - -*E.G. - - In> DivisorsList(18) - Out> {1,2,3,6,9,18}; - -*SEE DivisorsSum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/JacobiSymbol.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/JacobiSymbol.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/JacobiSymbol.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/JacobiSymbol.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -%mathpiper,def="JacobiSymbol" - -/* Implementation of some number theoretical functions for MathPiper */ -/* (C) 2002 Pablo De Napoli under GNU GPL */ - -/** Compute the Jacobi symbol JS(m/n) - n must be odd, both positive. -See the Algo book for documentation. - -*/ - -10 # JacobiSymbol(_a, 1) <-- 1; -15 # JacobiSymbol(0, _b) <-- 0; -18 # JacobiSymbol(_a, _b) _ (Gcd(a,b)>1) <-- 0; - -20 # JacobiSymbol(_a, b_IsOdd)_(a>=Abs(b) Or a<0) <-- JacobiSymbol(Mod(a,Abs(b)),Abs(b)); - -30 # JacobiSymbol(a_IsEven, b_IsOdd) <-- -[ - Local(c, s); - // compute c,s where a=c*2^s and c is odd - {c,s}:=FindPrimeFactorSimple(a, 2); // use the "Simple" function because we don't expect a worst case here - If(Mod(s,2)=1 And Abs(Mod(b,8)-4)=1, -1, 1) * JacobiSymbol(c,b); -]; - -40 # JacobiSymbol(a_IsOdd, b_IsOdd) <-- If(Mod(a,4)=3 And Mod(b,4)=3, -1, 1) * JacobiSymbol(b,a); - -%/mathpiper - - - -%mathpiper_docs,name="JacobiSymbol",categories="User Functions;Number Theory" -*CMD JacobiSymbol --- functions related to finite groups -*STD -*CALL - JacobiSymbol(m,n) - -*PARMS -{m}, {n} -- integers, $n$ must be odd and positive - -*DESC - -The Jacobi symbol $[m/n;]$ is defined as the product of the Legendre symbols of the prime factors $f[i]$ of $n=f[1]^p[1]*...*f[s]^p[s]$, -$$ [m/n;] := [m/f[1];]^p[1]*...*[m/f[s];]^p[s] $$. -(Here we used the same notation $[a/b;]$ for the Legendre and the Jacobi symbols; this is confusing but seems to be the current practice.) -The Jacobi symbol is equal to $0$ if $m$, $n$ are not mutually prime (have a common factor). -The Jacobi symbol and the Legendre symbol have values $+1$, $-1$ or $0$. -If $n$ is prime, then the Jacobi symbol is the same as the Legendre symbol. - -The Jacobi symbol can be efficiently computed without knowing the full factorization of the number $n$. - -*E.G. - - In> JacobiSymbol(7,15) - Out> -1; - -*SEE Gcd, LegendreSymbol, IsQuadraticResidue -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/MoebiusDivisorsList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/MoebiusDivisorsList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/MoebiusDivisorsList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/MoebiusDivisorsList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -%mathpiper,def="MoebiusDivisorsList" - -/* Implementation of some number theoretical functions for MathPiper */ -/* (C) 2002 Pablo De Napoli under GNU GPL */ - -/* Returns a list of pairs {d,m} - where d runs through the square free divisors of n - and m=Moebius(m) - This is much more efficient than making a list of all - square-free divisors of n, and then compute Moebius on each of them. - It is useful for computing the Cyclotomic polinomials. - It can be useful in other computations based on - Moebius inversion formula. */ - -MoebiusDivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {{1,1}}; - ForEach (f,nFactors) - [ - oldresult := result; - ForEach (x,oldresult) - result:=Append(result,{x[1]*f[1],-x[2]}); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="MoebiusDivisorsList",categories="User Functions;Number Theory" -*CMD MoebiusDivisorsList --- the list of divisors and Moebius values -*STD -*CALL - MoebiusDivisorsList(n) -*PARMS - -{n} -- positive integer - -*DESC - -Returns a list of pairs of the form {{d,m}}, where {d} runs through the squarefree divisors of $n$ and $m=Moebius(d)$. -This is more efficient than making a list of all -square-free divisors of $n$ and then computing {Moebius} on each of them. -It is useful for computing the cyclotomic polynomials. -It can be useful in other computations based on the Moebius inversion formula. - -*E.G. - - In> MoebiusDivisorsList(18) - Out> {{1,1},{2,-1},{3,-1},{6,1}}; - -*SEE DivisorsList, Moebius -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/RamanujanSum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/RamanujanSum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/RamanujanSum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/RamanujanSum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="RamanujanSum" - -/* Implementation of some number theoretical functions for MathPiper */ -/* (C) 2002 Pablo De Napoli under GNU GPL */ - -/* RamanujanSum(k,n) = the sum of the n-th powers of the -k-th primitive roots of the identity */ - -10 # RamanujanSum(k_IsPositiveInteger,0) <-- Totient(k); - -20 # RamanujanSum(k_IsPositiveInteger,n_IsPositiveInteger) <-- -[ - Local(s,gcd,d); - s:= 0; - gcd := Gcd(n,k); - ForEach (d,DivisorsList(gcd)) - s:=s+d*Moebius(k/d); - s; -]; - -%/mathpiper - - - -%mathpiper_docs,name="RamanujanSum",categories="User Functions;Number Theory" -*CMD RamanujanSum --- compute the "Ramanujan sum" -*STD -*CALL - RamanujanSum(k,n) - -*PARMS - -{k}, {n} -- positive integers - -*DESC -This function computes the Ramanujan sum, i.e. the sum of the $n$-th powers of -the $k$-th primitive roots of the unit: - -$$ Sum(l,1,k, Exp(2*Pi*I*(l*n)/k)) $$ - -where $l$ runs thought the integers between $1$ and $k-1$ that are coprime to $l$. - -The computation is done by using the formula in T. M. Apostol, -Introduction to Analytic Theory (Springer-Verlag), Theorem 8.6. -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/SquareFreeDivisorsList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/SquareFreeDivisorsList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/SquareFreeDivisorsList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/SquareFreeDivisorsList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="SquareFreeDivisorsList" - -/* Implementation of some number theoretical functions for MathPiper */ -/* (C) 2002 Pablo De Napoli under GNU GPL */ - -/* Returns a list of the square-free divisors of n */ -SquareFreeDivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {1}; - ForEach (f,nFactors) - [ - oldresult := result; - ForEach (x,oldresult) - result:=Append(result,x*f[1]); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="SquareFreeDivisorsList",categories="User Functions;Number Theory" -*CMD SquareFreeDivisorsList --- the list of square-free divisors -*STD -*CALL - SquareFreeDivisorsList(n) -*PARMS - -{n} -- positive integer - -*DESC - -{SquareFreeDivisorsList} creates a list of the square-free divisors of $n$. -Square-free numbers are numbers that have only simple prime factors (no prime powers). -For example, $18=2*3*3$ is not square-free because it contains a square of $3$ as a factor. - -*E.G. - - In> SquareFreeDivisorsList(18) - Out> {1,2,3,6}; - -*SEE DivisorsList -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/SumForDivisors.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/SumForDivisors.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/numbertheory/SumForDivisors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/numbertheory/SumForDivisors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -%mathpiper,def="SumForDivisors" - -/* Implementation of some number theoretical functions for MathPiper */ -/* (C) 2002 Pablo De Napoli under GNU GPL */ - -/* This function performs a sum where sumvar runs through - the divisors of n - For example SumForDivisors(d,10,d^2) - sums d^2 with d walking through the divisors of 10 - LocalSymbols is needed since we use Eval() inside - Look at Programming in MathPiper: Evaluating Variables in the Wrong - Scope */ - -Function ("SumForDivisors",{sumvar,n,sumbody}) LocalSymbols(s,d) -[ - Local(s,d); - s:=0; - ForEach (d,DivisorsList(n)) - [ - MacroLocal(sumvar); - MacroSet(sumvar,d); - s:=s+Eval(sumbody); - ]; - s; -]; -UnFence("SumForDivisors",3); -HoldArg("SumForDivisors",sumvar); -HoldArg("SumForDivisors",sumbody); - -%/mathpiper - - - -%mathpiper_docs,name="SumForDivisors",categories="User Functions;Number Theory" -*CMD SumForDivisors --- loop over divisors -*STD -*CALL - SumForDivisors(var,n,expr) -*PARMS - -{var} -- atom, variable name - -{n} -- positive integer - -{expr} -- expression depending on {var} - -*DESC - -This function performs the sum of the values of the expression {expr} while the variable {var} runs through -the divisors of {n}. -For example, {SumForDivisors(d, 10, d^2)} sums $d^2$ where $d$ runs -through the divisors of $10$. -This kind of computation is frequently used in number theory. - -*SEE DivisorsList -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -OMDef( "BellNumber", mathpiper,"BellNumber" ); -OMDef( "CatalanNumber", mathpiper,"CatalanNumber" ); -OMDef( "DigitalRoot", mathpiper,"DigitalRoot" ); -OMDef( "Divisors", mathpiper,"Divisors" ); -OMDef( "DivisorsSum", mathpiper,"DivisorsSum" ); -OMDef( "Euler", mathpiper,"Euler" ); -OMDef( "EulerArray", mathpiper,"EulerArray" ); -OMDef( "Eulerian", mathpiper,"Eulerian" ); -OMDef( "FermatNumber", mathpiper,"FermatNumber" ); -OMDef( "GetPrimePower", mathpiper,"GetPrimePower" ); -OMDef( "HarmonicNumber", mathpiper,"HarmonicNumber" ); -OMDef( "IntLog", mathpiper,"IntLog" ); -OMDef( "IntNthRoot", mathpiper,"IntNthRoot" ); -OMDef( "IsAmicablePair", mathpiper,"IsAmicablePair" ); -OMDef( "IsCarmichaelNumber", mathpiper,"IsCarmichaelNumber" ); -OMDef( "IsComposite", mathpiper,"IsComposite" ); -OMDef( "IsCoprime", mathpiper,"IsCoprime" ); -OMDef( "IsIrregularPrime", mathpiper,"IsIrregularPrime" ); -OMDef( "IsPerfect", mathpiper,"IsPerfect" ); -OMDef( "IsPrime", mathpiper,"IsPrime" ); -OMDef( "IsPrimePower", mathpiper,"IsPrimePower" ); -OMDef( "IsQuadraticResidue", mathpiper,"IsQuadraticResidue" ); -OMDef( "IsSmallPrime", mathpiper,"IsSmallPrime" ); -OMDef( "IsSquareFree", mathpiper,"IsSquareFree" ); -OMDef( "IsTwinPrime", mathpiper,"IsTwinPrime" ); -OMDef( "LegendreSymbol", mathpiper,"LegendreSymbol" ); -OMDef( "Moebius", mathpiper,"Moebius" ); -OMDef( "NextPrime", mathpiper,"NextPrime" ); -OMDef( "NextPseudoPrime", mathpiper,"NextPseudoPrime" ); -OMDef( "PartitionsP", mathpiper,"PartitionsP" ); -OMDef( "ProductPrimesTo257", mathpiper,"ProductPrimesTo257" ); -OMDef( "ProperDivisors", mathpiper,"ProperDivisors" ); -OMDef( "ProperDivisorsSum", mathpiper,"ProperDivisorsSum" ); -OMDef( "Repunit", mathpiper,"Repunit" ); -OMDef( "StirlingNumber1", mathpiper,"StirlingNumber1" ); -OMDef( "StirlingNumber2", mathpiper,"StirlingNumber2" ); -OMDef( "Totient", mathpiper,"Totient" ); - -// From GaussianIntegers.mpi.def -OMDef( "IsGaussianUnit", mathpiper,"IsGaussianUnit" ); -OMDef( "IsGaussianInteger", mathpiper,"IsGaussianInteger" ); -OMDef( "IsGaussianPrime", mathpiper,"IsGaussianPrime" ); -OMDef( "GaussianFactorPrime", mathpiper,"GaussianFactorPrime" ); -OMDef( "GaussianNorm", mathpiper,"GaussianNorm" ); -OMDef( "GaussianMod", mathpiper,"GaussianMod" ); -OMDef( "GaussianFactors", mathpiper,"GaussianFactors" ); -OMDef( "AddGaussianFactor", mathpiper,"AddGaussianFactor" ); -OMDef( "FactorGaussianInteger", mathpiper,"FactorGaussianInteger" ); -OMDef( "GaussianGcd", mathpiper,"GaussianGcd" ); - -// From nthroot.mpi.def -OMDef( "NthRoot", mathpiper,"NthRoot" ); -OMDef( "NthRoot'Calc", mathpiper,"NthRoot'Calc" ); -OMDef( "NthRoot'List", mathpiper,"NthRoot'List" ); -OMDef( "NthRoot'Save", mathpiper,"NthRoot'Save" ); -OMDef( "NthRoot'Restore", mathpiper,"NthRoot'Restore" ); -OMDef( "NthRoot'Clear", mathpiper,"NthRoot'Clear" ); - -// From NumberTheory.mpi.def -OMDef( "DivisorsList", mathpiper,"DivisorsList" ); -OMDef( "SquareFreeDivisorsList", mathpiper,"SquareFreeDivisorsList" ); -OMDef( "MoebiusDivisorsList", mathpiper,"MoebiusDivisorsList" ); -OMDef( "SumForDivisors", mathpiper,"SumForDivisors" ); -OMDef( "RamanujanSum", mathpiper,"RamanujanSum" ); -OMDef( "JacobiSymbol", mathpiper,"JacobiSymbol" ); - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/PartitionsP.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/PartitionsP.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/PartitionsP.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/PartitionsP.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -%mathpiper,def="PartitionsP" - -/// the restricted partition function -/// partitions of length k - -5 # PartitionsP(n_IsInteger,0) <-- 0; -5 # PartitionsP(n_IsInteger,n_IsInteger) <-- 1; -5 # PartitionsP(n_IsInteger,1) <-- 1; -5 # PartitionsP(n_IsInteger,2) <-- Floor(n/2); -5 # PartitionsP(n_IsInteger,3) <-- Round(n^2/12); -6 # PartitionsP(n_IsInteger,k_IsInteger)_(k>n) <-- 0; -10 # PartitionsP(n_IsInteger,k_IsInteger) <-- PartitionsP(n-1,k-1)+PartitionsP(n-k,k); - -/// the number of additive partitions of an integer -5 # PartitionsP(0) <-- 1; -5 # PartitionsP(1) <-- 1; -// decide which algorithm to use -10 # PartitionsP(n_IsInteger)_(n<250) <-- PartitionsP'recur(n); -20 # PartitionsP(n_IsInteger) <-- PartitionsP'HR(n); - -/// Calculation using the Hardy-Ramanujan series. -10 # PartitionsP'HR(n_IsPositiveInteger) <-- -[ - Local(P0, A, lambda, mu, mu'k, result, term, j, k, l, prec, epsilon); - result:=0; - term:=1; // initial value must be nonzero - GlobalPush(BuiltinPrecisionGet()); - // precision must be at least Pi/Ln(10)*Sqrt(2*n/3)-Ln(4*n*Sqrt(3))/Ln(10) - // here Pi/Ln(10) < 161/118, and Ln(4*Sqrt(3))/Ln(10) <1 so it is disregarded. Add 2 guard digits and compensate for round-off errors by not subtracting Ln(n)/Ln(10) now - prec := 2+Div(IntNthRoot(Div(2*n+2,3),2)*161+117,118); - BuiltinPrecisionSet(prec); // compensate for round-off errors - epsilon := PowerN(10,-prec)*n*10; // stop when term < epsilon - - // get the leading term approximation P0 - compute once at high precision - lambda := N(Sqrt(n - 1/24)); - mu := N(Pi*lambda*Sqrt(2/3)); - // the hoops with DivideN are needed to avoid roundoff error at large n due to fixed precision: - // Exp(mu)/(n) must be computed by dividing by n, not by multiplying by 1/n - P0 := N(1-1/mu)*DivideN(ExpN(mu),(n-DivideN(1,24))*4*SqrtN(3)); - /* - the series is now equal to - P0*Sum(k,1,Infinity, - ( - Exp(mu*(1/k-1))*(1/k-1/mu) + Exp(-mu*(1/k+1))*(1/k+1/mu) - ) * A(k,n) * Sqrt(k) - ) - */ - - A := 0; // this is also used as a flag - // this is a heuristic, because the next term error is expensive - // to calculate and the theoretic bounds have arbitrary constants - // use at most 5+Sqrt(n)/2 terms, stop when the term is nonzero and result stops to change at precision prec - For(k:=1, k<=5+Div(IntNthRoot(n,2),2) And (A=0 Or Abs(term)>epsilon), k++) - [ - // compute A(k,n) - A:=0; - For(l:=1,l<=k,l++) - [ - If( - Gcd(l,k)=1, - A := A + Cos(Pi* - ( // replace Exp(I*Pi*...) by Cos(Pi*...) since the imaginary part always cancels - Sum(j,1,k-1, j*(Mod(l*j,k)/k-1/2)) - 2*l*n - // replace (x/y - Floor(x/y)) by Mod(x,y)/y for integer x,y - )/k) - ); - A:=N(A); // avoid accumulating symbolic Cos() expressions - ]; - - term := If( - A=0, // avoid long calculations if the term is 0 - 0, - N( A*Sqrt(k)*( - [ - mu'k := mu/k; // save time, compute mu/k once - Exp(mu'k-mu)*(mu'k-1) + Exp(-mu'k-mu)*(mu'k+1); - ] - )/(mu-1) ) - ); -// Echo("k=", k, "term=", term); - result := result + term; -// Echo("result", new'result* P0); - ]; - result := result * P0; - BuiltinPrecisionSet(GlobalPop()); - Round(result); -]; - -// old code for comparison - -10 # PartitionsP1(n_IsPositiveInteger) <-- - [ - Local(C,A,lambda,m,pa,k,h,term); - GlobalPush(BuiltinPrecisionGet()); - // this is an overshoot, but seems to work up to at least n=4096 - BuiltinPrecisionSet(10 + Floor(N(Sqrt(n))) ); - pa:=0; - C:=Pi*Sqrt(2/3)/k; - lambda:=Sqrt(m - 1/24); - term:=1; - // this is a heuristic, because the next term error is expensive - // to calculate and the theoretic bounds have arbitrary constants - For(k:=1,k<=5+Floor(SqrtN(n)*0.5) And ( term=0 Or Abs(term)>0.1) ,k++)[ - A:=0; - For(h:=1,h<=k,h++)[ - if( Gcd(h,k)=1 )[ - A:=A+Exp(I*Pi*Sum(j,1,k-1,(j/k)*((h*j)/k - Floor((h*j)/k) -1/2)) -- 2*Pi*I*h*n/k ); - ]; - ]; - If(A!=0, term:= N(A*Sqrt(k)*(Deriv(m) Sinh(C*lambda)/lambda) Where m==n ),term:=0 ); -// Echo("Term ",k,"is ",N(term/(Pi*Sqrt(2)))); - pa:=pa+term; -// Echo("result", N(pa/(Pi*Sqrt(2)))); - ]; - pa:=N(pa/(Pi*Sqrt(2))); - BuiltinPrecisionSet(GlobalPop()); - Round(pa); - ]; - -/// integer partitions by recurrence relation P(n) = Sum(k,1,n, (-1)^(k+1)*( P(n-k*(3*k-1)/2)+P(n-k*(3*k+1)/2) ) ) = P(n-1)+P(n-2)-P(n-5)-P(n-7)+... -/// where 1, 2, 5, 7, ... is the "generalized pentagonal sequence" -/// this method is faster with internal math for number<300 or so. -PartitionsP'recur(number_IsPositiveInteger) <-- -[ - // need storage of n values PartitionsP(k) for k=1,...,n - Local(sign, cache, n, k, pentagonal, P); - cache:=ArrayCreate(number+1,1); // cache[n] = PartitionsP(n-1) - n := 1; - While(n ProperDivisors(180) - Out> 17; - In> ProperDivisors(37) - Out> 1; - -*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/ProperDivisorsSum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/ProperDivisorsSum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/ProperDivisorsSum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/ProperDivisorsSum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="ProperDivisorsSum" - -10 # ProperDivisorsSum(_n) <-- -[ - Check(IsPositiveInteger(n), - "ProperDivisorsSum: argument must be positive integer"); - DivisorsSum(n)-n; -]; - -%/mathpiper - - - -%mathpiper_docs,name="ProperDivisorsSum",categories="User Functions;Number Theory" -*CMD ProperDivisorsSum --- the sum of proper divisors -*STD -*CALL - ProperDivisorsSum(n) -*PARMS - -{n} -- positive integer - -*DESC - -{ProperDivisorsSum} returns the sum of proper divisors, i.e. {ProperDivisors(n)-n}, -since {n} is not counted. -{n} is prime if and only if {ProperDivisorsSum(n)==1}. - -*E.G. - In> ProperDivisorsSum(180) - Out> 366; - In> ProperDivisorsSum(37) - Out> 1; - - -*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Repunit.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Repunit.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Repunit.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Repunit.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="Repunit" - -10 # Repunit(0) <-- 0; -// Number consisting of n 1's -Repunit(n_IsPositiveInteger) <-- -[ - (10^n-1)/9; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/StirlingNumber1.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/StirlingNumber1.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/StirlingNumber1.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/StirlingNumber1.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -%mathpiper,def="StirlingNumber1" - -10 # StirlingNumber1(n_IsInteger,0) <-- If(n=0,1,0); -10 # StirlingNumber1(n_IsInteger,1) <-- (-1)^(n-1)*(n-1)!; -10 # StirlingNumber1(n_IsInteger,2) <-- (-1)^n*(n-1)! * HarmonicNumber(n-1); -10 # StirlingNumber1(n_IsInteger,n-1) <-- -BinomialCoefficient(n,2); -10 # StirlingNumber1(n_IsInteger,3) <-- (-1)^(n-1)*(n-1)! * (HarmonicNumber(n-1)^2 - HarmonicNumber(n-1,2))/2; -20 # StirlingNumber1(n_IsInteger,m_IsInteger) <-- - Sum(k,0,n-m,(-1)^k*BinomialCoefficient(k+n-1,k+n-m)*BinomialCoefficient(2*n-m,n-k-m)*StirlingNumber2(k-m+n,k)); - -%/mathpiper - - - -%mathpiper_docs,name="StirlingNumber1",categories="User Functions;Number Theory" -*CMD StirlingNumber1 --- return the {n m}th Stirling Number of the first kind -*STD -*CALL - StirlingNumber1(n,m) -*PARMS - -{n}, {m} -- positive integers - -*DESC - -This function returns the signed Stirling Number of the first kind. -All Stirling Numbers are integers. If $ m > n $, then {StirlingNumber1} returns -$0$. - -*E.G. - - In> StirlingNumber1(10,5) - Out> -269325; - In> StirlingNumber1(3,6) - Out> 0; - -*SEE StirlingNumber2 -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/StirlingNumber2.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/StirlingNumber2.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/StirlingNumber2.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/StirlingNumber2.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="StirlingNumber2" - -10 # StirlingNumber2(n_IsInteger,0) <-- If(n=0,1,0); -20 # StirlingNumber2(n_IsInteger,k_IsInteger) <-- Sum(i,0,k-1,(-1)^i*BinomialCoefficient(k,i)*(k-i)^n)/ k! ; - -%/mathpiper - - - -%mathpiper_docs,name="StirlingNumber2",categories="User Functions;Number Theory" -*CMD StirlingNumber2 --- return the {n m}th Stirling Number of the second kind -*STD -*CALL - StirlingNumber1(n,m) -*PARMS - -{n}, {m} -- positive integers - -*DESC - -This function returns the Stirling Number of the second kind. -All Stirling Numbers are positive integers. If $ m > n $, then {StirlingNumber2} returns -$0$. - -*E.G. - - In> StirlingNumber2(3,6) - Out> 0; - In> StirlingNumber2(10,4) - Out> 34105; - -*SEE StirlingNumber1 -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Totient.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Totient.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/numbers/Totient.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/numbers/Totient.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -%mathpiper,def="Totient" - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 7.3 p139 - -10 # Totient(_n) <-- -[ - Check(IsPositiveInteger(n), - "Totient: argument must be positive integer"); - Local(i,sum,factors,len); - sum:=n; - factors:=Factors(n); - len:=Length(factors); - For(i:=1,i<=len,i++)[ - sum:=sum*(1-1/factors[i][1]); - ]; - sum; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/odesolver/odesolver.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/odesolver/odesolver.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/odesolver/odesolver.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/odesolver/odesolver.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,382 +0,0 @@ -%mathpiper,def="OdeSolve;OdeTest;OdeOrder" - -/* def file definitions -OdeSolve -OdeTest -OdeOrder -*/ - -/* - 1) implement more sub-solvers - 2) test code - 3) Done: documentation for OdeSolve and OdeTest - */ - -10 # OdeLeftHandSideEq(_l == _r) <-- (l-r); -20 # OdeLeftHandSideEq(_e) <-- e; - -10 # OdeNormChange(y(n_IsInteger)) <-- UnList({yyy,n}); -20 # OdeNormChange(y) <-- yyy(0); -25 # OdeNormChange(y') <-- yyy(1); -25 # OdeNormChange(y'') <-- yyy(2); -30 # OdeNormChange(_e) <-- e; -OdeNormPred(_e) <-- (e != OdeNormChange(e)); - - -OdeNormalForm(_e) <-- -[ - e := Substitute(OdeLeftHandSideEq(e),"OdeNormPred","OdeNormChange"); -]; - -/*TODO better OdeNormalForm? -OdeNormalForm(_e) <-- -[ - OdeLeftHandSideEq(e) /: - { - y <- yyy(0), - y' <- yyy(1), - y'' <- yyy(2), - y(_n) <- yyy(n) - }; -]; -*/ - -10 # OdeChange(yyy(n_IsInteger)) <-- Apply(yn,{n}); -30 # OdeChange(_e) <-- e; -OdePred(_e) <-- (e != OdeChange(e)); -UnFence("OdeChange",1); -UnFence("OdePred",1); -OdeSubstitute(_e,_yn) <-- -[ - Substitute(e,"OdePred","OdeChange"); -]; -UnFence("OdeSubstitute",2); - -OdeConstantList(n_IsInteger) <-- -[ - Local(result,i); - result:=ZeroVector(n); - For (i:=1,i<=n,i++) result[i]:=UniqueConstant(); - result; -]; - - -RuleBase("OdeTerm",{px,list}); - -/*5 # OdeFlatTerm(_x)_[Echo({x});False;] <-- True; */ - -10# OdeFlatTerm(OdeTerm(_a0,_b0)+OdeTerm(_a1,_b1)) <-- OdeTerm(a0+a1,b0+b1); -10# OdeFlatTerm(OdeTerm(_a0,_b0)-OdeTerm(_a1,_b1)) <-- OdeTerm(a0-a1,b0-b1); -10# OdeFlatTerm(-OdeTerm(_a1,_b1)) <-- OdeTerm(-a1,-b1); -10# OdeFlatTerm(OdeTerm(_a0,_b0)*OdeTerm(_a1,_b1))_ - (IsZeroVector(b0) Or IsZeroVector(b1)) <-- -[ - OdeTerm(a0*a1,a1*b0+a0*b1); -]; - -10# OdeFlatTerm(OdeTerm(_a0,_b0)/OdeTerm(_a1,_b1))_ - (IsZeroVector(b1)) <-- - OdeTerm(a0/a1,b0/a1); - -10# OdeFlatTerm(OdeTerm(_a0,b0_IsZeroVector)^OdeTerm(_a1,b1_IsZeroVector)) <-- - OdeTerm(a0^a1,b0); -15 # OdeFlatTerm(OdeTerm(_a,_b)) <-- OdeTerm(a,b); - -15# OdeFlatTerm(OdeTerm(_a0,_b0)*OdeTerm(_a1,_b1)) <-- OdeTermFail(); -15# OdeFlatTerm(OdeTerm(_a0,b0)^OdeTerm(_a1,b1)) <-- OdeTermFail(); -15# OdeFlatTerm(OdeTerm(_a0,b0)/OdeTerm(_a1,b1)) <-- OdeTermFail(); -20 # OdeFlatTerm(a_IsAtom) <-- OdeTermFail(); - -20 # OdeFlatTerm(_a+_b) <-- OdeFlatTerm(OdeFlatTerm(a) + OdeFlatTerm(b)); -20 # OdeFlatTerm(_a-_b) <-- OdeFlatTerm(OdeFlatTerm(a) - OdeFlatTerm(b)); -20 # OdeFlatTerm(_a*_b) <-- OdeFlatTerm(OdeFlatTerm(a) * OdeFlatTerm(b)); -20 # OdeFlatTerm(_a^_b) <-- OdeFlatTerm(OdeFlatTerm(a) ^ OdeFlatTerm(b)); -20 # OdeFlatTerm(_a/_b) <-- OdeFlatTerm(OdeFlatTerm(a) / OdeFlatTerm(b)); - -OdeMakeTerm(xx_IsAtom) <-- OdeTerm(xx,FillList(0,10)); -OdeMakeTerm(yyy(_n)) <-- OdeTerm(0,BaseVector(n+1,10)); - - -20 # OdeMakeTerm(_xx) <-- OdeTerm(xx,FillList(0,10)); -10 # OdeMakeTermPred(_x+_y) <-- False; -10 # OdeMakeTermPred(_x-_y) <-- False; -10 # OdeMakeTermPred( -_y) <-- False; -10 # OdeMakeTermPred(_x*_y) <-- False; -10 # OdeMakeTermPred(_x/_y) <-- False; -10 # OdeMakeTermPred(_x^_y) <-- False; -20 # OdeMakeTermPred(_rest) <-- True; - - -OdeCoefList(_e) <-- -[ - Substitute(e,"OdeMakeTermPred","OdeMakeTerm"); -]; -OdeTermFail() <-- OdeTerm(Error,FillList(Error,10)); - -// should check if it is linear... -OdeAuxiliaryEquation(_e) <-- -[ - // extra conversion that should be optimized away later - e:=OdeNormalForm(e); - e:=OdeSubstitute(e,{{n},aaa^n*Exp(aaa*x)}); - e:=Subst(Exp(aaa*x),1)e; - Simplify(Subst(aaa,x)e); -]; - -/* Solving a Homogeneous linear differential equation - with real constant coefficients */ -OdeSolveLinearHomogeneousConstantCoefficients(_e) <-- -[ - Local(roots,consts,auxeqn); - - /* Try solution Exp(aaa*x), and divide by Exp(aaa*x), which - * should yield a polynomial in aaa. - e:=OdeSubstitute(e,{{n},aaa^n*Exp(aaa*x)}); - e:=Subst(Exp(aaa*x),1)e; - auxeqn:=Simplify(Subst(aaa,x)e); - e:=auxeqn; - */ - e:=OdeAuxiliaryEquation(e); - auxeqn:=e; - - If(InVerboseMode(), Echo("OdeSolve: Auxiliary Eqn ",auxeqn) ); - - - /* Solve the resulting polynomial */ - e := Apply("RootsWithMultiples",{e}); - e := RemoveDuplicates(e); - - /* Generate dummy constants */ - if( Length(e) > 0 )[ - roots:=Transpose(e); - consts:= MapSingle(Hold({{nn},Add(OdeConstantList(nn)*(x^(0 .. (nn-1))))}),roots[2]); - roots:=roots[1]; - - /* Return results */ - //Sum(consts * Exp(roots*x)); - Add( consts * Exp(roots*x) ); - ] else if ( Degree(auxeqn,x) = 2 ) [ - // we can solve second order equations without RootsWithMultiples - Local(a,b,c,roots); - roots:=ZeroVector(2); - - // this should probably be incorporated into RootsWithMultiples - {c,b,a} := Coef(auxeqn,x,0 .. 2); - - - roots := PSolve(a*x^2+b*x+c,x); - If(InVerboseMode(),Echo("OdeSolve: Roots of quadratic:",roots) ); - - // assuming real coefficients, the roots must come in a complex - // conjugate pair, so we don't have to check both - // also, we don't need to check to repeated root case, because - // RootsWithMultiples (hopefully) catches those, except for - // the case b,c=0 - - if( b=0 And c=0 )[ - Add(OdeConstantList(2)*{1,x}); - ] else if( IsNumber(N(roots[1])) )[ - If(InVerboseMode(),Echo("OdeSolve: Real roots")); - Add(OdeConstantList(2)*{Exp(roots[1]*x),Exp(roots[2]*x)}); - ] else [ - If(InVerboseMode(),Echo("OdeSolve: Complex conjugate pair roots")); - Local(alpha,beta); - alpha:=Re(roots[1]); - beta:=Im(roots[1]); - Exp(alpha*x)*Add( OdeConstantList(2)*{Sin(beta*x),Cos(beta*x)} ); - ]; - - ] else [ - Echo("OdeSolve: Could not find roots of auxilliary equation"); - ]; -]; - -// this croaks on Sin(x)*y'' because OdeMakeTerm does -10 # OdeOrder(_e) <-- [ - Local(h,i,coefs); - - coefs:=ZeroVector(10); //ugly - e:=OdeNormalForm(e); - - If(InVerboseMode(),Echo("OdeSolve: Normal form is",e)); - h:=OdeFlatTerm(OdeCoefList(e)); - If(InVerboseMode(),Echo("OdeSolve: Flatterm is",h)); - - // get the list of coefficients of the derivatives - // in decreasing order - coefs:=Reverse(Listify(h)[3]); - While( First(coefs) = 0 )[ - coefs:=Rest(coefs); - ]; - Length(coefs)-1; -]; - - -10 # OdeSolve(_expr)_(OdeOrder(expr)=0) <-- Echo("OdeSolve: Not a differential equation"); - -// Solve the ever lovable seperable equation - -10 # OdeSolve(y'+_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr-a); -10 # OdeSolve(y'-_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr+a); -10 # OdeSolve(y'/_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr*a); -10 # OdeSolve(_a*y'==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr/a); -10 # OdeSolve(y'*_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr/a); -10 # OdeSolve(_a/y'==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==a/expr); - -// only works for low order equations -10 # OdeSolve(y'==_expr)_(IsFreeOf({y,y',y''},expr)) <-- -[ - If(InVerboseMode(),Echo("OdeSolve: Integral in disguise!")); - If(InVerboseMode(),Echo("OdeSolve: Attempting to integrate ",expr)); - - (Integrate(x) expr)+UniqueConstant(); -]; - -50 # OdeSolve(_e) <-- -[ - Local(h); - e:=OdeNormalForm(e); - If(InVerboseMode(),Echo("OdeSolve: Normal form is",e)); - h:=OdeFlatTerm(OdeCoefList(e)); - If(InVerboseMode(),Echo("OdeSolve: Flatterm is",h)); - if (IsFreeOf(Error,h)) - [ - OdeSolveLinear(e,h); - ] - else - OdeUnsolved(e); -]; - -10 # OdeSolveLinear(_e,OdeTerm(0,_list))_(Length(VarList(list)) = 0) <-- -[ - OdeSolveLinearHomogeneousConstantCoefficients(OdeNormalForm(e)); -]; - -100 # OdeSolveLinear(_e,_ode) <-- OdeUnsolved(e); - -OdeUnsolved(_e) <-- Subst(yyy,y)e; - - - -/* -FT3(_e) <-- -[ - e:=OdeNormalForm(e); -Echo({e}); - e:=OdeCoefList(e); -Echo({e}); - e:=OdeFlatTerm(e); -Echo({e}); - e; -]; -OdeBoundaries(_solution,bounds_IsList) <-- -[ -]; -*/ - -OdeTest(_e,_solution) <-- -[ - Local(s); - s:= `Lambda({n},if (n>0)(D(x,n)(@solution)) else (@solution)); - e:=OdeNormalForm(e); - e:=Apply("OdeSubstitute",{e,s}); - e:=Simplify(e); - e; -]; - -%/mathpiper - - - -%mathpiper_docs,name="OdeSolve",categories="User Functions;Differential Equations" -*CMD OdeSolve --- general ODE solver -*STD -*CALL - OdeSolve(expr1==expr2) -*PARMS - -{expr1,expr2} -- expressions containing a function to solve for - -*DESC - -This function currently can solve second order homogeneous linear real constant -coefficient equations. The solution is returned with unique constants -generated by {UniqueConstant}. The roots of the auxiliary equation are -used as the arguments of exponentials. If the roots are complex conjugate -pairs, then the solution returned is in the form of exponentials, sines -and cosines. - -First and second derivatives are entered as {y',y''}. Higher order derivatives -may be entered as {y(n)}, where {n} is any integer. - - -*E.G. - - In> OdeSolve( y'' + y == 0 ) - Out> C42*Sin(x)+C43*Cos(x); - In> OdeSolve( 2*y'' + 3*y' + 5*y == 0 ) - Out> Exp(((-3)*x)/4)*(C78*Sin(Sqrt(31/16)*x)+C79*Cos(Sqrt(31/16)*x)); - In> OdeSolve( y'' - 4*y == 0 ) - Out> C132*Exp((-2)*x)+C136*Exp(2*x); - In> OdeSolve( y'' +2*y' + y == 0 ) - Out> (C183+C184*x)*Exp(-x); - -*SEE Solve, RootsWithMultiples -%/mathpiper_docs - - - -%mathpiper_docs,name="OdeTest",categories="User Functions;Differential Equations" -*CMD OdeTest --- test the solution of an ODE -*STD -*CALL - OdeTest(eqn,testsol) -*PARMS - -{eqn} -- equation to test - -{testsol} -- test solution - -*DESC - -This function automates the verification of the solution of an ODE. -It can also be used to quickly see how a particular equation operates -on a function. - -*E.G. - - In> OdeTest(y''+y,Sin(x)+Cos(x)) - Out> 0; - In> OdeTest(y''+2*y,Sin(x)+Cos(x)) - Out> Sin(x)+Cos(x); - -*SEE OdeSolve -%/mathpiper_docs - - - -%mathpiper_docs,name="OdeOrder",categories="User Functions;Differential Equations" -*CMD OdeOrder --- return order of an ODE -*STD -*CALL - OdeOrder(eqn) -*PARMS - -{eqn} -- equation - -*DESC - -This function returns the order of the differential equation, which is -order of the highest derivative. If no derivatives appear, zero is returned. - -*E.G. - - In> OdeOrder(y'' + 2*y' == 0) - Out> 2; - In> OdeOrder(Sin(x)*y(5) + 2*y' == 0) - Out> 5; - In> OdeOrder(2*y + Sin(y) == 0) - Out> 0; - -*SEE OdeSolve -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/openmath/openmath.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/openmath/openmath.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/openmath/openmath.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/openmath/openmath.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,937 +0,0 @@ -%mathpiper,def="OMREP;OMDef;OMForm;OMRead;OMParse;OMEcho;OMEchoEscape" - -/* def file definitions -OMREP -OMDef -OMForm -OMRead -OMParse -OMEcho -OMEchoEscape -*/ - -//////////////////////// -// Written by Alberto González Palomo and Ayal Pinkus. -//////////////////////// - -/* The read-eval-print loop */ -/* It can take one parameter, that is the evaluation count. If it is greater - than zero, only that number of iterations will be performed before - exiting. This is particularly useful when connecting to MathPiper via pipes. -*/ -RuleBase("OMREP",{}); -Rule("OMREP",0,1,True) -[ - OMREP(0);// 0 means keep repeating, as usual. -]; -RuleBase("OMREP",{count}); -LocalSymbols(input,stringOut,result) -Rule("OMREP",1,1,True) -[ - Local(input,stringOut,result); - While(Not(IsExitRequested())) - [ - Set(errorObject, ""); - TrapError(Set(input, FromString(ConcatStrings(ReadCmdLineString("")," "))OMRead()),Set(errorObject,OMGetCoreError())); - If(Not(errorObject = ""), errorObject); - If (Not(IsExitRequested()) And errorObject="", - [ - Set(stringOut,""); - Set(result,False); - TrapError(Set(stringOut,ToString()[Secure(Set(result,Eval(input)));]),Set(errorObject,OMGetCoreError())); - If(Not(errorObject = ""), errorObject); - If(Not(stringOut = ""), WriteString(stringOut)); - SetGlobalLazyVariable(%,result); - If(PrettyPrinter'Get()="", - [ - Apply("OMForm",{result}); - ], - Apply(PrettyPrinter'Get(),{result})); - If(count > 0 And (count:=count-1) = 0, Exit()); - ]); - ]; -]; - - -LocalSymbols(omindent) [ - // Function definitions - OMIndent() := [omindent := omindent + 2;]; - OMUndent() := [omindent := omindent - 2;]; - OMClearIndent() := [omindent := 0;]; - OMIndentSpace() := Space(omindent); - - // Initialization of indentation - OMClearIndent(); -]; // LocalSymbols(omindent) - -/////////////////////////////////////////////////////////////////////// -// Output - -10 # OMForm(_expression) - <-- - [ - OMClearIndent(); - OMEcho(""); - OMIndent(); - If(IsAtom(expression), - If(expression = Atom("%"), - Secure(expression := Eval(expression)) - ) - ); - OMFormExpression(expression); - OMUndent(); - OMEcho(""); - ]; - -10 # OMFormExpression(i_IsString) <-- OMEcho("":i:""); -11 # OMFormExpression(i_IsInteger) <-- OMEcho("":String(i):""); -12 # OMFormExpression(i_IsNumber) <-- OMEcho(""); -13 # OMFormExpression(i_IsConstant)_(OMSymbol()[ String(i) ] != Empty) - <-- OMEcho("" - ); -14 # OMFormExpression(i_IsConstant)// Should we rather evaluate it? - <-- OMEcho(""); -15 # OMFormExpression(i_IsVariable)_(OMSymbol()[ String(i) ] != Empty) - <-- OMEcho("" - ); -16 # OMFormExpression(i_IsVariable) - <-- OMEcho(""); -16 # OMFormExpression(i_IsVariable)_(i = Empty) - <-- False; // This is useful for void expressions. - -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMError") - <-- - [ - Local(cd, name); - If(IsList(function[1]), - [ cd := function[1][1]; name := function[1][2]; ], - [ cd := "error"; name := function[1]; ]); - OMEcho(""); - OMIndent(); - OMEcho(""); - ForEach(i, Rest(function)) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OME") - <-- - [ - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMS") - <-- OMEcho(""); -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMBIND") - <-- - [ - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMBVAR") - <-- - [ - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMA") - <-- - [ - // This is not the same as the next rule: this is OMA(a,b,c,...), - // which is used for building OMA constructs in the mapping to OM. - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -11 # OMFormExpression(function_IsFunction) - <-- - [ - OMEcho(""); - OMIndent(); - OMFormFunction(function); - OMUndent(); - OMEcho(""); - ]; - -11 # OMFormFunction(function_IsFunction) - <-- - [ - Local(arity); - arity := Length(function); - OMEcho(""); - If(arity > 0, ForEach(arg, function) OMFormExpression(arg)); - ]; -10 # OMFormFunction(function_IsFunction)_(OMSymbol()[ Type(function) ] != Empty) - <-- - [ - Local(symbolDef); - // [20051016 AGP] The "signature" feature is an old attempt at pattern - // matching, but now that we have real predicates in the mappings it's - // probably obsolete. I'll think about removing it. - symbolDef := OMSymbol()[ OMSignature(function) ]; - If(symbolDef = Empty, symbolDef := OMSymbol()[ Type(function) ] ); - If(symbolDef = Empty Or Length(symbolDef) < 3 Or symbolDef[3] = {}, - [ - OMEcho(""); - ForEach(arg, function) OMFormExpression(arg); - ], - [ - Local(result); - result := OMApplyMapping(function, symbolDef[3]); - //Check(IsList(result), ToString()Echo("Mapping result is not a list: ", result)); - If(IsList(result), - [ - result := UnList(Subst($, function[0]) result); - OMFormExpression(result[0]); - ForEach(i, result) OMFormExpression(i); - ], - If(result = Empty, - Echo("No rule matched ", function, symbolDef[3]), - Echo("Unexpected result value from OMApplyMapping(): ", result) - ) - ); - ] - ); - ]; - - -OMWrite(_expression) <-- -[ - Write(expression); -]; - -OMEcho(_expression) <-- -[ - OMIndentSpace(); - Write(expression); - NewLine(); -]; -OMEcho(expression_IsString) <-- -[ - OMIndentSpace(); - WriteString(expression); - NewLine(); -]; -OMEcho(expression_IsList) <-- -[ - ForEach(arg, expression) - [ - If (IsString(arg), WriteString(arg), Write(arg)); - ]; - NewLine(); -]; - -OMEscape(_expression) <-- -[ - ""; -]; -OMEscapeString(_expression_IsString) <-- -[ - ""; -]; -OMWriteEscape(_expression) <-- -[ - WriteString(OMEscape(expression)); -]; -OMWriteStringEscape(expression_IsString) <-- -[ - WriteString(OMEscapeString(expression)); -]; -OMEchoEscape(_expression) <-- -[ - OMWriteEscape(expression); - NewLine(); -]; -OMEchoEscape(expression_IsString) <-- -[ - OMWriteStringEscape(expression); - NewLine(); -]; -OMEchoEscape(expression_IsList) <-- -[ - WriteString(""); - NewLine(); -]; - - -HoldArgNr("OMForm",1,1); -//HoldArgNr("OMFormExpression",1,1); -//HoldArgNr("OMFormFunction",1,1); - - -OMSignature(_function) <-- ""; -OMSignature(function_IsFunction) <-- -[ - Local(makeSig); - makeSig := {ConcatStrings, Type(function), "_"}; - Local(type); - type := "";// If "function" doesn't have parameters, the signature is "f_". - ForEach(arg, function) - [ - If(Type(arg) = "List", - type := "L", - If(IsFunction(arg), - type := "F", - If(IsInteger(arg), - type := "I", - type := "V" - ) - ) - ); - DestructiveAppend(makeSig, type); - ]; - Secure(Eval(UnList(makeSig))); -]; -HoldArgNr("OMSignature", 1, 1); - - - -/////////////////////////////////////////////////////////////////////// -// Input - -// Troubleshooting guide: -// "encodingError:unexpected closing brace": this happens in the ReadOMOBJ -// rules. It means that you forgot to call OMNextToken() from your rule. - -LocalSymbols(omtoken) [ - OMNextToken() := - [ - omtoken := XmlExplodeTag(String(ReadToken())); - ]; - OMToken() := omtoken; -]; // LocalSymbols(omtoken) - -OMRead():= -[ - Local(result); - TrapError( - [ - XmlTokenizer(); - OMNextToken(); - result := MatchOMOBJ(OMToken()); - DefaultTokenizer(); - ], - [ - result := OMGetCoreError(); - DefaultTokenizer(); - ]); - result; -]; - - -OMDump(str):= -FromString(str:" EndOfFile") -[ - Local(result); - XmlTokenizer(); - OMNextToken(); - While(OMToken() != "EndOfFile") - [ - Echo("Exploded ",OMToken()); - OMNextToken(); - ]; - DefaultTokenizer(); - True; -]; - - - -10 # MatchClose(_x)_(x = OMToken()) <-- [OMNextToken();True;]; -20 # MatchClose(_x) <-- Check(False,ToString()Echo("encodingError:unexpected closing brace")); //@@@ TODO better error reporting - -10 # MatchOMOBJ(XmlTag("OMOBJ",_attributes,"Open")) <-- -[ - // Any attributes are ignored. - Local(result); - OMNextToken(); - result := ReadOMOBJ(OMToken()); - MatchClose(XmlTag("OMOBJ",{},"Close")); - result; -]; -10 # MatchOMOBJ(XmlTag("OMOBJ",_attributes,"OpenClose")) <-- -[ - OMNextToken(); - // Any attributes are ignored. - // This is a void expression, of the form "". - Empty; -]; -20 # MatchOMOBJ(_rest) <-- Check(False,ToString()Echo("encodingError:not an OMOBJ :",rest)); - -10 # ReadOMOBJ(XmlTag("OMOBJ",_attributes,"Close")) <-- -[ - // This is a void expression, of the form "". - Empty; -]; - -10 # ReadOMOBJ(XmlTag("OMI",{},"Open")) <-- -[ - Local(result); - OMNextToken(); - result := Atom(OMToken()); - OMNextToken(); - MatchClose(XmlTag("OMI",{},"Close")); - result; -]; - -10 # ReadOMOBJ(XmlTag("OMV",{{"NAME",_name}},"OpenClose")) <-- -[ - OMNextToken(); - Atom(name); -]; - -10 # ReadOMOBJ(XmlTag("OMF",{{"DEC",_dec}},"OpenClose")) <-- -[ - OMNextToken(); - Atom(dec); -]; - -10 # ReadOMOBJ(XmlTag("OMSTR",{},"Open")) <-- -[ - Local(result); - OMNextToken(); - If(IsString(OMToken()), [result := OMToken(); OMNextToken();], result := ""); - MatchClose(XmlTag("OMSTR",{},"Close")); - result; -]; -10 # ReadOMOBJ(XmlTag("OMSTR",{},"OpenClose")) <-- -[ - OMNextToken(); - ""; -]; - -10 # ReadOMOBJ(XmlTag("OMA",{},"Open")) <-- -[ - Local(result, new); - result:={}; - OMNextToken(); - While (OMToken() != XmlTag("OMA",{},"Close")) - [ - new:=ReadOMOBJ(OMToken()); - DestructiveAppend(result,new); - ]; - MatchClose(XmlTag("OMA",{},"Close")); - OMApplyReverseMapping(UnList(result)); -]; - -10 # ReadOMOBJ(XmlTag("OMBIND",{},"Open")) <-- -[ - Local(result, new); - result:={}; - OMNextToken(); - While (OMToken() != XmlTag("OMBIND",{},"Close")) - [ - new:=ReadOMOBJ(OMToken()); - DestructiveAppend(result,new); - ]; - MatchClose(XmlTag("OMBIND",{},"Close")); - result; -]; -10 # ReadOMOBJ(XmlTag("OMBVAR",{},"Open")) <-- -[ - Local(result, new); - result:={}; - OMNextToken(); - While (OMToken() != XmlTag("OMBVAR",{},"Close")) - [ - new:=ReadOMOBJ(OMToken()); - DestructiveAppend(result,new); - ]; - MatchClose(XmlTag("OMBVAR",{},"Close")); - result; -]; - -10 # OMApplyReverseMapping(piperExp_IsFunction) <-- piperExp; -10 # OMApplyReverseMapping(piperExp_IsFunction)_(OMSymbol()[ Type(piperExp) ] != Empty) - <-- - [ - Local(symbolDef, result); - symbolDef := OMSymbol()[ Type(piperExp) ]; - If(symbolDef[4] = {}, - result := piperExp, - [ - result := OMApplyMapping(piperExp, symbolDef[4]); - result := Subst($, piperExp[0]) result; - If(IsList(result), result := UnList(result)); - ] - ); - result; - ]; - -10 # OMApplyMapping(_function, _mapping) <-- -[ - Local(expandRules, result); - expandRules := { _(_path) <- OMPathSelect(path, function) }; - expandRules[1][2][2] := function;// the "function" variable is not expanded above. - - mapping := (mapping /: expandRules);// "/:" has lower precedence than ":=". - - Local(ruleMatched); - ruleMatched := False; - If(Type(mapping) = "|", - [ - mapping := Flatten(mapping, "|"); - ForEach(rule, mapping) - If(Not ruleMatched, - [ - If(Type(rule) = "_", - If( Eval(rule[2]), [ result := rule[1]; ruleMatched := True; ] ), - [ result := rule; ruleMatched := True; ] - ); - ] - ); - ], - [ - If(Type(mapping) = "_", - If(Eval(mapping[2]), - result := mapping[1], - result := Listify(function) - ), - result := mapping - ); - ruleMatched := True; - ] - ); - - If(ruleMatched, - If(Type(result) = ":", - If(Length(result) = 2, - result[1]:result[2], - result),// Perhaps we should give a warning here. - result), - Empty); -]; - -11 # OMPathSelect(path_IsNumber, _expression) <-- -[ - If(path >= 0 And path <= Length(expression), - expression[path], - Undefined); -]; -11 # OMPathSelect(path_IsList, _expression) <-- -[ - ForEach(i, path) - If(IsFunction(expression) And i >= 0 And i <= Length(expression), - expression := expression[i], - Undefined); - expression; -]; -HoldArgNr("OMPathSelect", 2, 2); - -// Previously, any unknown symbols where reported as errors. -// Now, we just store them as OMS(cd, name) since MathPiper is perfectly happy -// with such unknown symbols, and will handle them right: When -// producing an OpenMath result from them, they will be output back -// unmodified, forming a valid OpenMath expression. -// This way we don't have to bother defining bogus symbols for concepts that -// MathPiper does not handle. -100 # ReadOMOBJ(XmlTag("OMS", _attributes, "OpenClose")) <-- -[ - OMNextToken(); - Local(omcd, omname); - omcd := attributes["CD"]; - omname := attributes["NAME"]; - If(omcd = Empty Or omname = Empty, - OMCheck(False,OMError({"moreerrors", "encodingError"}, ToString()Echo("missing \"cd\" or \"name\" attribute: ",attributes))), - [ - Local(cdTable, piperform); - cdTable := OMSymbolReverse()[ omcd ]; - If(cdTable != Empty, piperform := cdTable[ omname ]); - // We can not optimize here by checking first whether the CD is mathpiper - // and avoiding the table lookup then, because for some symbols the - // OM name have to be different from the MathPiper name (e.g. "/@"). - If(piperform = Empty, - If(cd = mathpiper, Atom(omname), OMS(omcd, omname)), - If(IsString(piperform), Atom(piperform), piperform)); - ] - ); -]; - -101 # ReadOMOBJ(_rest) <-- OMCheck(False,OMError({"moreerrors", "encodingError"}, ToString()Echo("unhandled tag: ",rest))); - - - -/////////////////////////////////////////////////////////////////////// -// Error reporting - -Macro(OMCheck,{predicate,error}) -[ - If(Not(@predicate), - [ - Assert("omErrorObject", @error) False; - Check(False,"omErrorObject"); - ] - , - True); -]; -OMGetCoreError():= -[ - Local(result); - result := GetCoreError(); - If(result != "", - If( IsError("omErrorObject"), - [result := GetError("omErrorObject"); ], - [result := OMError({"moreerrors", "unexpected"}, result); ]) - ); - result; -]; - - - -/////////////////////////////////////////////////////////////////////// -// Symbol mapping tables - -LocalSymbols(omsymbol, omsymbolreverse) [ - // Initialization of the openmath symbol dictionaries - omsymbol := {}; - omsymbolreverse := {}; - - // Access to the dictionaries - OMSymbol() := omsymbol; - OMSymbolReverse() := omsymbolreverse; - -]; // LocalSymbols(omsymbol, omsymbolreverse) - -OMDef(_piperform, omcd_IsString, omname_IsString, _directMapping, _reverseMapping) <-- -[ - Local(cdTable); - If(IsString(piperform), - OMSymbol()[ piperform ] := {omcd, omname, directMapping, reverseMapping} - ); - cdTable := OMSymbolReverse()[ omcd ]; - If(cdTable = Empty, - OMSymbolReverse()[ omcd ] := {{omname, piperform}}, - [ - Local(oldMathPiperform); - oldMathPiperform := cdTable[ omname ]; - If(oldMathPiperform = Empty, - cdTable[ omname ] := piperform, - [ - If(oldMathPiperform != piperform, - [ - cdTable[ omname ] := piperform; - Echo("Warning: the mapping for ", omcd, ":", omname, - " was already defined as ", oldMathPiperform, - ", but is redefined now as ", piperform - ); - ] - ); - ] - ); - ] - ); - True; -]; - -OMDef(_piperform, omcd_IsString, omname_IsString) -<-- OMDef(piperform, omcd, omname, {}, {}); - -OMDef(piperalias_IsString, pipername_IsString) <-- -[ - OMSymbol()[ piperalias ] := OMSymbol()[ pipername ]; -]; -HoldArgNr("OMDef", 5, 4); -HoldArgNr("OMDef", 5, 5); - -// Many objects, such as matrices and sets, do not have a specific -// encoding in MathPiper, but are represented as lists. -OMDef( {}, "set1","emptyset" ); -OMDef( "List", "set1","set" ); -OMDef( "List", "linalg2","matrix" ); -OMDef( "List", "linalg2","matrixrow" ); -OMDef( "List", "linalg2","vector" ); -OMDef( "List", "list1","list" ); - -// [20010916 AGP] I couldn't find these symbols in the def files: -// "E" , "nums1", "e" -// "Gamma" , "nums1", "gamma" -OMDef( "Infinity" , "nums1", "infinity" ); -OMDef( "Undefined", "nums1", "NaN" ); -// [20010916 AGP] From org/mathpiper/assembledscripts/initialization.rep/stdopers.mpi: -OMDef( "And" , "logic1", "and" ); -OMDef( "==" , "logic1", "equivalent" ); -OMDef( "!==" , "logic1", "not", - { "", - 1, - 2, - "" - } - ); -OMDef( "False", "logic1", "false" ); -OMDef( "Or" , "logic1", "or" ); -OMDef( "True" , "logic1", "true" ); -//[20010916 AGP ] Xor is not available in MathPiper. -// "Xor" , "logic1", "xor" ); -OMDef( "&" , mathpiper, "bitwise_and" ); -OMDef( "|" , mathpiper, "bitwise_or" ); -OMDef( "%" , mathpiper, "bitwise_xor" ); -OMDef( "/" , "arith1", "divide");// This definition is for OM arith1:divide to MathPiper. In all other cases, the next one will be used. -OMDef( "/" , "nums1", "rational", {$, _1, _2}_(IsRational(_1/_2)) | {OMS("arith1", "divide"), _1, _2}, {/, _1, _2}); -OMDef( "-" , "arith1", "unary_minus"); -OMDef( "-" , "arith1", "minus" );// We need a way of testing the arity. -OMDef( "+" , "arith1", "plus" ); -OMDef( "^" , "arith1", "power" ); -OMDef( "*" , "arith1", "times" ); - - -Use("org/mathpiper/assembledscripts/constants.rep/om.mpi"); -Use("org/mathpiper/assembledscripts/stdfuncs.rep/om.mpi"); -Use("org/mathpiper/assembledscripts/stubs.rep/om.mpi"); -Use("org/mathpiper/assembledscripts/logic.rep/om.mpi"); -Use("org/mathpiper/assembledscripts/complex.rep/om.mpi"); -Use("org/mathpiper/assembledscripts/integrate.rep/om.mpi"); -Use("org/mathpiper/assembledscripts/sums.rep/om.mpi"); -Use("org/mathpiper/assembledscripts/limit.rep/om.mpi"); -//Use("org/mathpiper/assembledscripts/numbers.rep/om.mpi");// Sqrt is loaded before (stubs.rep) than IntNthRoot. -Use("org/mathpiper/assembledscripts/functional.rep/om.mpi"); - - -%/mathpiper - - - -%mathpiper_docs,name="OMForm;OMRead",categories="User Functions;Input/Output" -*CMD OMForm --- convert MathPiper expression to OpenMath -*CMD OMRead --- convert expression from OpenMath to MathPiper expression -*STD -*CALL - OMForm(expression) - OMRead() - -*PARMS - -{expression} -- expression to convert - -*DESC - -{OMForm} prints an OpenMath representation of the input parameter {expression} -to standard output. {OMRead} reads an OpenMath expression from standard -input and returns a normal MathPiper expression that matches the input OpenMath -expression. - -If a MathPiper symbol does not have a mapping defined by {OMDef}, it is translated -to and from OpenMath as the OpenMath symbol in the CD "mathpiper" with the same -name as it has in MathPiper. - -*E.G. notest - - In> str:=ToString()OMForm(2+Sin(a*3)) - Out> " - - - 2 - - - - - - 3 - - - - - "; - In> FromString(str)OMRead() - Out> 2+Sin(a*3); - - In> OMForm(NotDefinedInOpenMath(2+3)) - - - - - - 2 - 3 - - - - Out> True - -*SEE XmlTokenizer, XmlExplodeTag, OMDef -%/mathpiper_docs - - - -%mathpiper_docs,name="OMDef",categories="User Functions;Input/Output" -*CMD OMDef --- define translations from MathPiper to OpenMath and vice-versa. -*STD -*CALL - OMDef(mathpiperForm, cd, name) - OMDef(mathpiperForm, cd, name, mathpiperToOM) - OMDef(mathpiperForm, cd, name, mathpiperToOM, omToMathPiper) - -*PARMS - -{mathpiperForm} -- string with the name of a MathPiper symbol, or a MathPiper expression - -{cd} -- OpenMath Content Dictionary for the symbol - -{name} -- OpenMath name for the symbol - -{mathpiperToOM} -- rule for translating an application of that symbol in MathPiper into an OpenMath expression - -{omToMathPiper} -- rule for translating an OpenMath expression into an application of this symbol in MathPiper - -*DESC - -{OMDef} defines the translation rules for symbols between the MathPiper -representation and {OpenMath}. -The first parameter, {mathpiperForm}, can be a string or an expression. The -difference is that when giving an expression only the {omToMathPiper} translation -is defined, and it uses the exact expression given. This is used for {OpenMath} -symbols that must be translated into a whole subexpression in MathPiper, such -as {set1:emptyset} which gets translated to an empty list as follows: - In> OMDef( {}, "set1","emptyset" ) - Out> True - In> FromString(" ")OMRead() - Out> {} - In> IsList(%) - Out> True -Otherwise, a symbol that is not inside an application (OMA) gets translated to -the MathPiper atom with the given name: - In> OMDef( "EmptySet", "set1","emptyset" ) - Warning: the mapping for set1:emptyset was already defined as {} , but is redefined now as EmptySet - Out> True - In> FromString(" ")OMRead() - Out> EmptySet - -The definitions for the symbols in the MathPiper -library are in the {*.rep} script subdirectories. In those modules for which -the mappings are defined, there is a file called {om.ys} that contains the -{OMDef} calls. Those files are loaded in {openmath.rep/om.ys}, so any new -file must be added to the list there, at the end of the file. - -A rule is represented as a list of expressions. Since both OM and -MathPiper expressions are actually lists, the syntax is the same in both -directions. There are two template forms that are expanded before the -translation: - -* {$}: this symbol stands for the translation of the symbol applied -in the original expression. - -* {_path}: a path into the original expression (list) to extract an -element, written as an underscore applied to an integer or a list of integers. - Those integers are indexes into expressions, and integers in a list are - applied recursively starting at the original expression. - For example, {_2} means the second parameter of the expression, while - {_{3,2,1}} means the first parameter of the second parameter of the third - parameter of the original expression. - -They can appear anywhere in the rule as expressions or subexpressions. - -Finally, several alternative rules can be specified by joining them with -the {|} symbol, and each of them can be annotated with a post-predicate -applied with the underscore {_} symbol, in the style of MathPiper' simplification -rules. Only the first alternative rule that matches is applied, so the more -specific rules must be written first. - -There are special symbols recognized by {OMForm} to output {OpenMath} -constructs that have no specific parallel in MathPiper, such as an OpenMath -symbol having a {CD} and {name}: MathPiper symbols have only a name. -Those special symbols are: - -* {OMS(cd, name)}: {} -* {OMA(f x y ...)}: {f x y ...} -* {OMBIND(binderSymbol, bvars, expression)}: {binderSymbol bvars expression}, where {bvars} must be produced by using {OMBVAR(...)}. -* {OMBVAR(x y ...)}: {x y ...} -* {OME(...)}: {...} - -When translating from OpenMath to MathPiper, we just store unknown symbols as -{OMS("cd", "name")}. This way we don't have to bother defining bogus symbols -for concepts that MathPiper does not handle, and we can evaluate expressions that -contain them. - -*E.G. notest - - In> OMDef( "Sqrt" , "arith1", "root", { $, _1, 2 }, $(_1)_(_2=2) | (_1^(1/_2)) ); - Out> True - In> OMForm(Sqrt(3)) - - - - 3 - 2 - - - Out> True - In> FromString("162 ")OMRead() - Out> Sqrt(16) - In> FromString("163 ")OMRead() - Out> 16^(1/3) - - In> OMDef("Limit", "limit1", "limit", \ - { $, _2, OMS("limit1", "under"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) \ - |{ $, _2, OMS("limit1", "above"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) \ - |{ $, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, \ - { $, _{3,2,1}, _1, Left, _{3,3}}_(_2=OMS("limit1", "below")) \ - |{$, _{3,2,1}, _1, Right, _{3,3}}_(_2=OMS("limit1", "above")) \ - |{$, _{3,2,1}, _1, _{3,3}} \ - ); - In> OMForm(Limit(x,0) Sin(x)/x) - - - - 0 - - - - - - - - - - - - - - - - - - Out> True - In> OMForm(Limit(x,0,Right) 1/x) - - - - 0 - - - - - - - - - 1 - - - - - - Out> True - In> FromString(ToString()OMForm(Limit(x,0,Right) 1/x))OMRead() - Out> Limit(x,0,Right)1/x - In> % - Out> Infinity - -*SEE OMForm, OMRead -%/mathpiper_docs - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/orthopoly/orthopoly.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/orthopoly/orthopoly.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/orthopoly/orthopoly.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/orthopoly/orthopoly.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,941 +0,0 @@ -%mathpiper,def="OrthoP;OrthoG;OrthoH;OrthoL;OrthoT;OrthoU;OrthoPSum;OrthoGSum;OrthoHSum;OrthoLSum;OrthoTSum;OrthoUSum;EvaluateHornerScheme" - -/* def file definitions -OrthoP -OrthoG -OrthoH -OrthoL -OrthoT -OrthoU -OrthoPSum -OrthoGSum -OrthoHSum -OrthoLSum -OrthoTSum -OrthoUSum -EvaluateHornerScheme -*/ - -/* -Orthogonal polynomials -version 1.2 -(Serge Winitzki) - -Polynomials are found from direct recurrence relations. Sums of series of polynomials are found using the Clenshaw-Smith recurrence scheme. - -Reference: Yudell L. Luke. Mathematical functions and their approximations. Academic Press, N. Y., 1975. - -Usage: - The polynomials are evaluated by functions named Ortho*, where * is one of P, G, H, L, T, U. The first argument of these functions is an integer. The series of polynomials are evaluated by functions named Ortho*Sum. The first argument of these functions is a list of coefficients. The last argument is the value x at which the polynomials are to be computed; if x is numerical, a faster routine is used. - - If n is an integer, n>=0, then: - OrthoP(n, x) gives the n-th Legendre polynomial, evaluated on x - OrthoP(n, a, b, x) gives the n-th Jacobi polynomial with parameters a, b, evaluated on x - OrthoG(n, a, x) gives the n-th Gegenbauer polynomial - OrthoH(n, x) gives the n-th Hermite polynomial - OrthoL(n, a, x) gives the n-th Laguerre polynomial - OrthoT(n, x) gives the n-th Tschebyscheff polynomial of the 1st kind - OrthoU(n, x) gives the n-th Tschebyscheff polynomial of the 2nd kind - - If c is a list of coefficients c[1], c[2], ..., c[N], then Ortho*Sum(c, ...) where * is one of P, G, H, L, T, U, computes the sum of a series c[1]*P_0+c[2]*P_1+...+c[N]*P_N, where P_k is the relevant polynomial of k-th order. (For polynomials taking parameters: the parameters must remain constant throughout the summation.) Note that the intermediate polynomials are not evaluated and the recurrence relations are different for this computation, so there may be a numerical difference between Ortho*(c, ...) and computing the sum of the series directly. - - Internal functions that may be useful: - OrthoPolyCoeffs(name_IsString, n_IsInteger, parameters_IsList) returns a list of coefficients of the polynomial. Here "name" must be one of the predefined names: "Jacobi", "Gegenbauer", "Hermite", "Laguerre", "Tscheb1", "Tscheb2"; and "parameters" is a list of extra parameters for the given family of polynomials, e.g. {a,b} for the Jacobi, {a} for Laguerre and {} for Hermite polynomials. - OrthoPolySumCoeffs(name_IsString, c_IsList, parameters_IsList) returns a list of coefficients of the polynomial which is a sum of series with coefficients c. - EvaluateHornerScheme(coefficients, x) returns the Horner-evaluated polynomial on x. The "coefficients" is a list that starts at the lowest power. For example, EvaluateHornerScheme({a,b,c}, x) should return (a+x*(b+x*c)) -*/ - -10 # EvaluateHornerScheme({}, _x) <-- 0; -/* Strictly speaking, the following rule is not needed, but it doesn't hurt */ -10 # EvaluateHornerScheme({_coeffs}, _x) <-- coeffs; -20 # EvaluateHornerScheme(coeffs_IsList, _x) <-- First(coeffs)+x*EvaluateHornerScheme(Rest(coeffs), x); - -/* Plain polynomials */ -// some are computed by general routines, and some are replaced by more efficient routines below -OrthoP(n_IsInteger, _x)_(n>=0) <-- OrthoP(n, 0, 0, x); -OrthoP(n_IsInteger, a_IsRationalOrNumber, b_IsRationalOrNumber, _x)_(n>=0 And a> -1 And b> -1) <-- OrthoPoly("Jacobi", n, {a, b}, x); - -OrthoG(n_IsInteger, a_IsRationalOrNumber, _x)_(n>=0 And a> -1/2) <-- OrthoPoly("Gegenbauer", n, {a}, x); - -OrthoH(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Hermite", n, {}, x); - -OrthoL(n_IsInteger, a_IsRationalOrNumber, _x)_(n>=0 And a> -1) <-- OrthoPoly("Laguerre", n, {a}, x); - -OrthoT(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Tscheb1", n, {}, x); -OrthoU(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Tscheb2", n, {}, x); - -/* Sums of series of orthogonal polynomials */ - -OrthoPSum(c_IsList, _x) <-- OrthoP(c, 0, 0, x); -OrthoPSum(c_IsList, a_IsRationalOrNumber, b_IsRationalOrNumber, _x)_(a> -1 And b> -1) <-- OrthoPolySum("Jacobi", c, {a, b}, x); - -OrthoGSum(c_IsList, a_IsRationalOrNumber, _x)_(a> -1/2) <-- OrthoPolySum("Gegenbauer", c, {a}, x); - -OrthoHSum(c_IsList, _x) <-- OrthoPolySum("Hermite", c, {}, x); - -OrthoLSum(c_IsList, a_IsRationalOrNumber, _x)_(a> -1) <-- OrthoPolySum("Laguerre", c, {a}, x); - -OrthoTSum(c_IsList, _x) <-- OrthoPolySum("Tscheb1", c, {}, x); -OrthoUSum(c_IsList, _x) <-- OrthoPolySum("Tscheb2", c, {}, x); - -/* -Orthogonal polynomials are evaluated using a general routine OrthoPolyCoeffs that generates their coefficients recursively. - -The recurrence relations start with n=0 and n=1 (the n=0 polynomial is always identically 1) and continue for n>=2. Note that the n=1 polynomial is not always given by the n=1 recurrence formula if we assume P_{-1}=0, so the recurrence should be considered undefined at n=1. - - For Legendre/Jacobi polynomials: (a>-1, b>-1) -P(0,a,b,x):=1 -P(1,a,b,x):=(a-b)/2+x*(1+(a+b)/2) -P(n,a,b,x):=(2*n+a+b-1)*(a^2-b^2+x*(2*n+a+b-2)*(2*n+a+b))/(2*n*(n+a+b)*(2*n+a+b-2))*P(n-1,a,b,x)-(n+a-1)*(n+b-1)*(2*n+a+b)/(n*(n+a+b)*(2*n+a+b-2))*P(n-2,a,b,x) - - For Hermite polynomials: -H(0,x):=1 -H(1,x):=2*x -H(n,x):=2*x*H(n-1,x)-2*(n-1)*H(n-2,x) - - For Gegenbauer polynomials: (a>-1/2) -G(0,a,x):=1 -G(1,a,x):=2*a*x -G(n,a,x):=2*(1+(a-1)/n)*x*G(n-1,a,x)-(1+2*(a-2)/n)*G(n-2,a,x) - - For Laguerre polynomials: (a>-1) -L(0,a,x):=1 -L(1,a,x):=a+1-x -L(n,a,x):=(2+(a-1-x)/n)*L(n-1,a,x)-(1+(a-1)/n)*L(n-2,a,x) - - For Tschebycheff polynomials of the first kind: -T(0,x):=1 -T(1,x):=x -T(n,x):=2*x*T(n-1,x)-T(n-2,x) - - For Tschebycheff polynomials of the second kind: -U(0,x):=1 -U(1,x):=2*x -U(n,x):=2*x*U(n-1,x)-U(n-2,x) - -The database "KnownOrthoPoly" contains closures that return coefficients for the recurrence relations of each family of polynomials. KnownOrthoPoly["name"] is a closure that takes two arguments: the order (n) and the extra parameters (p), and returns a list of two lists: the first list contains the coefficients {A,B} of the n=1 polynomial, i.e. "A+B*x"; the second list contains the coefficients {A,B,C} in the recurrence relation, i.e. "P_n = (A+B*x)*P_{n-1}+C*P_{n-2}". (So far there are only 3 coefficients in the second list, i.e. no "C+D*x", but we don't want to be limited.) - -*/ - -LocalSymbols(knownOrthoPoly) [ - knownOrthoPoly := Hold({ - {"Jacobi", {{n, p}, {{(p[1]-p[2])/2, 1+(p[1]+p[2])/2}, {(2*n+p[1]+p[2]-1)*((p[1])^2-(p[2])^2)/(2*n*(n+p[1]+p[2])*(2*n+p[1]+p[2]-2)), (2*n+p[1]+p[2]-1)*(2*n+p[1]+p[2])/(2*n*(n+p[1]+p[2])), -(n+p[1]-1)*(n+p[2]-1)*(2*n+p[1]+p[2])/(n*(n+p[1]+p[2])*(2*n+p[1]+p[2]-2))}}}}, - {"Gegenbauer", {{n, p}, {{0, 2*p[1]}, {0, 2+2*(p[1]-1)/n, -1-2*(p[1]-1)/n}}}}, - {"Laguerre", {{n, p}, {{p[1]+1, -1}, {2+(p[1]-1)/n, -1/n, -1-(p[1]-1)/n}}}}, - {"Hermite", {{n, p}, {{0,2}, {0, 2, -2*(n-1)}}}}, - {"Tscheb1", {{n, p}, {{0,1}, {0,2,-1}}}}, - {"Tscheb2", {{n, p}, {{0,2}, {0,2,-1}}}} - }); - KnownOrthoPoly() := knownOrthoPoly; - -]; // LocalSymbols(knownOrthoPoly) - -/* -For efficiency, polynomials are represented by lists of coefficients rather than by MathPiper expressions. Polynomials are evaluated using the explicit Horner scheme. On numerical arguments, the polynomial coefficients are not computed, only the resulting value. -*/ - -/* -Sums of series of orthogonal polynomials are found using the Clenshaw-Smith recurrence scheme: - If $P_n$ satisfy $P_n = A_n p_{n-1} + B_n p_{n-2}$, $n>=2$, and if $A_1$ is defined so that $P_1 = A_1 P_0$, then $\sum _{n=0}^N c_n P_n = X_0 P_0$, where $X_n$ are found from the following backward recurrence: $X_{N+1} = X_{N+2} = 0$, $X_n = c_n + A_{n+1} X_{n+1} + B_{n+2} X_{n+2}$, $n=N, N-1, ..., 0$. -*/ - -/* Numeric arguments are processed by a faster routine */ - -10 # OrthoPoly(name_IsString, _n, p_IsList, x_IsRationalOrNumber) _ (KnownOrthoPoly()[name] != Empty) <-- OrthoPolyNumeric(name, n, p, x); -20 # OrthoPoly(name_IsString, _n, p_IsList, _x) _ (KnownOrthoPoly()[name] != Empty) <-- EvaluateHornerScheme(OrthoPolyCoeffs(name, n, p), x); - -10 # OrthoPolySum(name_IsString, c_IsList, p_IsList, x_IsRationalOrNumber) _ (KnownOrthoPoly()[name] != Empty) <-- OrthoPolySumNumeric(name, c, p, x); -20 # OrthoPolySum(name_IsString, c_IsList, p_IsList, _x) _ (KnownOrthoPoly()[name] != Empty) <-- EvaluateHornerScheme(OrthoPolySumCoeffs(name, c, p), x); - -/* -OrthoPolyNumeric computes the value of the polynomial from recurrence relations directly. Do not use with non-numeric arguments, except for testing! -*/ -OrthoPolyNumeric(name_IsString, n_IsInteger, p_IsList, _x) <-- [ - Local(value1, value2, value3, ruleCoeffs, index); - value1 := 1; - ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[1]; - value2 := ruleCoeffs[1] + x*ruleCoeffs[2]; - index := 1; - /* value1, value2, value3 is the same as P_{n-2}, P_{n-1}, P_n where n = index */ - While(index=1) [ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[2]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; - value3 := (ruleCoeffs[1] + x*ruleCoeffs[2])*value2 + ruleCoeffs1[3]*value1 + c[index+1]; - value1 := value2; - value2 := value3; - index := index - 1; - ]; - /* Last iteration by hand: works correctly also if c has only 1 element */ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {1, p})[1]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {2, p})[2]; - value2 := (ruleCoeffs[1] + x*ruleCoeffs[2])*value2 + ruleCoeffs1[3]*value1 + c[1]; - value2; -]; - -/* -OrthoPolyCoeffs(name, n, p) returns the list of coefficients for orthogonal polynomials, starting with the lowest powers. -*/ - -10 # OrthoPolyCoeffs(name_IsString, 0, p_IsList) <-- {1}; -10 # OrthoPolyCoeffs(name_IsString, 1, p_IsList) <-- Apply(KnownOrthoPoly()[name], {1, p})[1]; - -/* Simple implementation, very slow, for testing only: recursive rule matches, no loops -20 # OrthoPolyCoeffs(name_IsString, n_IsInteger, p_IsList)_(n>1) <-- [ - Local(ruleCoeffs, newCoeffs); - ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[2]; - newCoeffs := OrthoPolyCoeffs(name, n-1, p); - Concat(newCoeffs,{0})*ruleCoeffs[1] + Concat(OrthoPolyCoeffs(name, n-2, p),{0,0})*ruleCoeffs[3] + Concat({0}, newCoeffs)*ruleCoeffs[2]; -]; -*/ - -/* A fast implementation that works directly with lists and saves memory. Same recurrence as in OrthoPolyNumeric() */ -/* note: here we pass "name" instead of "KnownOrthoPoly()[name]" for efficiency, but strictly speaking we don't need to use this global constant */ - -20 # OrthoPolyCoeffs(name_IsString, n_IsInteger, p_IsList)_(n>1) <-- [ - Local(ruleCoeffs, tmpCoeffs, newCoeffs, prevCoeffs, index, jndex, tmptmpCoeffs, prevCoeffsA, newCoeffsA, tmpCoeffsA); - /* For speed, allocate all lists now. Length is n+1 */ - prevCoeffsA := ZeroVector(n+1); - newCoeffsA := ZeroVector(n+1); - tmpCoeffsA := ZeroVector(n+1); - /* pointers to arrays */ - prevCoeffs := prevCoeffsA; - newCoeffs := newCoeffsA; - tmpCoeffs := tmpCoeffsA; - /* Initialize: n=0 and n=1 */ - prevCoeffs[1] := 1; - ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[1]; - newCoeffs[1] := ruleCoeffs[1]; - newCoeffs[2] := ruleCoeffs[2]; - /* Invariant: answer ready in "newCoeffs" at value of index */ - index := 1; - /* main loop */ - While(index < n) [ - index := index + 1; - /* Echo({"index ", index}); */ /* in case this is slow */ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index, p})[2]; - tmpCoeffs[1] := ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs[3]*prevCoeffs[1]; - /* The polynomial tmpCoeffs must have (index+1) coefficients now */ - For(jndex:=2, jndex <= index, jndex:=jndex+1) [ - tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; - ]; - tmpCoeffs[index+1] := ruleCoeffs[2]*newCoeffs[index]; -/* - prevCoeffs := FlatCopy(newCoeffs); - newCoeffs := FlatCopy(tmpCoeffs); -*/ -/* juggle pointers instead of copying lists */ - tmptmpCoeffs := prevCoeffs; - prevCoeffs := newCoeffs; - newCoeffs := tmpCoeffs; - tmpCoeffs := tmptmpCoeffs; - ]; - newCoeffs; -]; - -/* -OrthoPolySumCoeffs(name, c, p) returns the list of coefficients for the sum of a series of orthogonal polynomials. Same recurrence as in OrthoPolySumNumeric() -*/ - -OrthoPolySumCoeffs(name_IsString, c_IsList, p_IsList) <-- [ - Local(n, ruleCoeffs, ruleCoeffs1, tmpCoeffs, newCoeffs, prevCoeffs, index, jndex, tmptmpCoeffs, prevCoeffsA, newCoeffsA, tmpCoeffsA); - /* n is the max polynomial order we need */ - n := Length(c) - 1; - /* For speed, allocate all lists now. Length is n+1 */ - prevCoeffsA := ZeroVector(n+1); - newCoeffsA := ZeroVector(n+1); - tmpCoeffsA := ZeroVector(n+1); - /* pointers to arrays */ - prevCoeffs := prevCoeffsA; - newCoeffs := newCoeffsA; - tmpCoeffs := tmpCoeffsA; - /* Invariant: answer ready in "newCoeffs" at value of index */ - /* main loop */ - For(index:=n, index >= 1, index:=index-1) [ - /* Echo({"index ", index}); */ /* in case this is slow */ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[2]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; - tmpCoeffs[1] := c[index+1] + ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs1[3]*prevCoeffs[1]; - /* The polynomial tmpCoeffs must have (n-index+1) coefficients now */ - For(jndex:=2, jndex <= n-index, jndex:=jndex+1) [ - tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs1[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; - ]; - If(n-index>0, tmpCoeffs[n-index+1] := ruleCoeffs[2]*newCoeffs[n-index]); -/* - prevCoeffs := FlatCopy(newCoeffs); - newCoeffs := FlatCopy(tmpCoeffs); -*/ -/* juggle pointers instead of copying lists */ - tmptmpCoeffs := prevCoeffs; - prevCoeffs := newCoeffs; - newCoeffs := tmpCoeffs; - tmpCoeffs := tmptmpCoeffs; - ]; - /* Last iteration by hand: works correctly also if c has only 1 element */ - index:=0; - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[1]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; - tmpCoeffs[1] := c[index+1] + ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs1[3]*prevCoeffs[1]; - /* The polynomial tmpCoeffs must have (n-index+1) coefficients now */ - For(jndex:=2, jndex <= n-index, jndex:=jndex+1) [ - tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs1[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; - ]; - tmpCoeffs[n-index+1] := ruleCoeffs[2]*newCoeffs[n-index]; - tmpCoeffs; -]; - -////////////////////////////////////////////////// -/// Very fast computation of Chebyshev polynomials -////////////////////////////////////////////////// -/// (This is not used now because of numerical instability, until I figure out how much to increase the working precision to get P correct digits.) -/// See: W. Koepf. Efficient computation of Chebyshev polynomials in computer algebra (unpublished preprint). Contrary to Koepf's claim (unsupported by any calculation in his paper) that the method is numerically stable, I found unsatisfactory numerical behavior for very large orders. -/// Koepf suggests to use M. Bronstein's algorithm for finding rational solutions of linear ODEs for all other orthogonal polynomials (may be faster than recursion if we want to find the analytic form of the polynomial, but still slower if an explicit formula is available). -////////////////////////////////////////////////// -/// Main formulae: T(2*n,x) = 2*T(n,x)^2-1; T(2*n+1,x) = 2*T(n+1,x)*T(n,x)-x; -/// U(2*n,x) = 2*T(n,x)*U(n,x)-1; T(2*n+1,x) = 2*T(n+1,x)*U(n,x); -/// We avoid recursive calls and build the sequence of bits of n to determine the minimal sequence of n[i] for which T(n[i], x) and U(n[i], x) need to be computed -////////////////////////////////////////////////// -/* -/// This function will return the list of binary bits, e.g. BitList(10) returns {1,0,1,0}. -BitList(n) := BitList(n, {}); -/// This will not be called on very large numbers so it's okay to use recursion -1# BitList(0, _bits) <-- bits; -2# BitList(_n, _bits) <-- BitList(Div(n,2), Push(bits, Mod(n,2))); - -// Tchebyshev polynomials of 1st kind -1 # FastOrthoT(0, _x) <-- 1; -1 # FastOrthoT(1, _x) <-- x; -// Tchebyshev polynomials of 2nd kind -1 # FastOrthoU(0, _x) <-- 1; -1 # FastOrthoU(1, _x) <-- 2*x; - -// guard against user errors -2 # FastOrthoT(_n, _x) _ (IsInteger(n) And n<0) <-- Undefined; -2 # FastOrthoU(_n, _x) _ (IsInteger(n) And n<0) <-- Undefined; - -// make T(), U() of even order more efficient: delegate gruntwork to odd order -2 # FastOrthoT(n_IsEven, _x) <-- 2*FastOrthoT(Div(n,2), x)^2-1; -2 # FastOrthoU(n_IsEven, _x) <-- 2*FastOrthoT(Div(n,2), x)*FastOrthoU(Div(n,2), x)-1; - -// FastOrthoT() of odd order -3 # FastOrthoT(n_IsOdd, _x) <-- -[ - Local(T1, T2, i); - // first bit in the list is always 1, so initialize the pair - T1 := FastOrthoT(1, x); - T2 := FastOrthoT(2, x); - ForEach(i, Rest(BitList(n))) // skip first bit - [ - // if the current bit is 1, we need to double the second index, else double the first index. - // Invariant: n[i+1] = 2*n[i] + BitList[i] and we need to have FastOrthoT(n[i]), FastOrthoT(1+n[i]) as T1, T2. Initially n[1]=1 and after the cycle n[i]=n. - {T1, T2} := If - ( - i=1, - {2*T1*T2-x, 2*T2^2-1}, - {2*T1^2-1, 2*T1*T2-x} - ); - ]; - T1; -]; - -// FastOrthoU() of any order -3 # FastOrthoU(_n, _x) <-- -[ - Local(U1, T1, T2, i); - // first bit in the list is always 1, so initialize the pair - U1 := FastOrthoU(1, x); - T1 := FastOrthoT(1, x); - T2 := FastOrthoT(2, x); - ForEach(i, Rest(BitList(n))) // skip first bit - [ - // if the current bit is 1, we need to double the second index, else double the first index - // Invariant: n[i+1] = 2*n[i] + BitList[i] and we need to have U(n[i]), T(n[i]), T(1+n[i]) as U1, T1, T2. Initially n[1]=1 and after the cycle n[i]=n. - {U1, T1, T2} := If - ( - i=1, - {2*U1*T2, 2*T1*T2-x, 2*T2^2-1}, - {2*U1*T1-1, 2*T1^2-1, 2*T1*T2-x} - ); - ]; - U1; -]; -*/ -////////////////////////////////////////////////// -/// Fast symbolic computation of some polynomials -////////////////////////////////////////////////// - - -////////////////////////////////////////////////// -/// Fast symbolic computation of Legendre polynomials -////////////////////////////////////////////////// - -8# OrthoPolyCoeffs("Jacobi", n_IsInteger, {0,0}) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := (2*n-1)!! /n!; // coefficient at x^n - i := 1; - While(2*i<=n) - [ // prepare coefficient at x^(n-2*i) now - result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+1)*(n-2*i+2)) / ((2*n-2*i+1)*2*i); - i++; - ]; - result; -]; - -////////////////////////////////////////////////// -/// Fast symbolic computation of Hermite polynomials -////////////////////////////////////////////////// - -OrthoPolyCoeffs("Hermite", n_IsInteger, {}) <-- HermiteCoeffs(n); - -/// Return the list of coefficiets of Hermite polynomials. -HermiteCoeffs(n_IsEven)_(n>0) <-- -[ - Local(i, k, result); - k := Div(n,2); - result := ZeroVector(n+1); - result[1] := (-2)^k*(n-1)!!; // coefficient at x^0 - For(i:=1,i<=k,i++) // prepare coefficient at x^(2*i) now - result[2*i+1] := Div(-2*result[2*i-1] * (k-i+1), (2*i-1)*i); // this division is always integer but faster with Div() - result; -]; -HermiteCoeffs(n_IsOdd)_(n>0) <-- -[ - Local(i, k, result); - k := Div(n,2); - result := ZeroVector(n+1); - result[2] := 2*(-2)^k*(n!!); // coefficient at x^1 - For(i:=1,i<=k,i++) // prepare coefficient at x^(2*i+1) now - result[2*i+2] := Div(-2*result[2*i] * (k-i+1), i*(2*i+1)); // this division is always integer but faster with Div() - result; -]; - -////////////////////////////////////////////////// -/// Fast symbolic computation of Laguerre polynomials -////////////////////////////////////////////////// - -/// Return the list of coefficients of Laguerre polynomials. -OrthoPolyCoeffs("Laguerre", n_IsInteger, {_k}) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := (-1)^n/n!; // coefficient at x^n - For(i:=n,i>=1,i--) // prepare coefficient at x^(i-1) now - result[i] := -(result[i+1]*i*(k+i))/(n-i+1); - result; -]; - - -////////////////////////////////////////////////// -/// Fast symbolic computation of Chebyshev polynomials -////////////////////////////////////////////////// - -OrthoPolyCoeffs("Tscheb1", n_IsInteger, {}) <-- ChebTCoeffs(n); -OrthoPolyCoeffs("Tscheb2", n_IsInteger, {}) <-- ChebUCoeffs(n); - -1 # ChebTCoeffs(0) <-- {1}; -2 # ChebTCoeffs(n_IsInteger) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := 2^(n-1); // coefficient at x^n - i := 1; - While(2*i<=n) - [ // prepare coefficient at x^(n-2*i) now - result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+2)*(n-2*i+1)) / ((n-i)*4*i); - i++; - ]; - result; -]; - -1 # ChebUCoeffs(0) <-- {1}; -2 # ChebUCoeffs(n_IsInteger) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := 2^n; // coefficient at x^n - i := 1; - While(2*i<=n) - [ // prepare coefficient at x^(n-2*i) now - result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+2)*(n-2*i+1)) / ((n-i+1)*4*i); - i++; - ]; - result; -]; - - -%/mathpiper - - - -%mathpiper_docs,name="EvaluateHornerScheme",categories="User Functions;Polynomials (Operations)" -*CMD EvaluateHornerScheme --- fast evaluation of polynomials -*STD -*CALL - EvaluateHornerScheme(coeffs,x) - -*PARMS - -{coeffs} -- a list of coefficients - -{x} -- expression - -*DESC - -This function evaluates a polynomial given as a list of its coefficients, using -the Horner scheme. The list of coefficients starts with the $0$-th power. - -*E.G. - - In> EvaluateHornerScheme({a,b,c,d},x) - Out> a+x*(b+x*(c+x*d)); - -*SEE Horner -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoP",categories="User Functions;Polynomials (Special)" -*CMD OrthoP --- Legendre and Jacobi orthogonal polynomials -*STD -*CALL - OrthoP(n, x); - OrthoP(n, a, b, x); - -*PARMS - -{n} -- degree of polynomial - -{x} -- point to evaluate polynomial at - -{a}, {b} -- parameters for Jacobi polynomial - -*DESC - -The first calling format with two arguments evaluates the Legendre polynomial -of degree {n} at the point {x}. The second form does the same for the Jacobi -polynomial with parameters {a} and {b}, which should be both greater than -1. - -The Jacobi polynomials are orthogonal with respect to the weight -function $(1-x)^a *(1+x)^b$ on the interval [-1,1]. They satisfy the -recurrence relation -$$P(n,a,b,x) = (2*n+a+b-1)/(2*n+a+b-2) $$* -$$ ((a^2-b^2+x*(2*n+a+b-2)*(n+a+b))/(2*n*(n+a+b))) * P(n-1,a,b,x)$$ -$$ - ((n+a-1)*(n+b-1)*(2*n+a+b))/(n*(n+a+b)*(2*n+a+b-2))*P(n-2,a,b,x)$$ -for $n > 1$, with -$P(0,a,b,x) = 1$, -$$P(1,a,b,x) = (a-b)/2+x*(1+(a+b)/2)$$. - -*REM (old versions of the equations:) -// P(0,a,b,x) = 1, -// -// a - b / a + b \ -// P(1,a,b,x) = ----- + x | 1 + ----- | , -// 2 \ 2 / -// -// -// -// P(n,a,b,x) = (2n + a + b - 1) * -// -// -// 2 2 -// a - b + x (2n+a+b-2) (n+a+b) -// ---------------------------- P(n-1,a,b,x) -// 2n (2n+a+b-2) (n+a+b) -// -// (n+a-1) (n+b-1) (2n+a+b) -// - ------------------------ P(n-2,a,b,x) -// n (n+a+b) (2n+a+b-2) - -Legendre polynomials are a special case of Jacobi polynomials with the -specific parameter values $a = b = 0$. So they form an orthogonal system -with respect to the weight function identically equal to 1 on the -interval [-1,1], and they satisfy the recurrence relation -$$ P(n,x)=((2*n-1)*x/(2*n))*P(n-1,x)-(n-1)/n*P(n-2,x) $$ -for $n > 1$, with -$ P(0,x)=1 $, -$ P(1,x)=x $. - -*REM -// P(0,x) = 1 -// -// P(1,x) = x -// -// (2n - 1) x n - 1 -// P(n,x) = ---------- P(n-1,x) - ----- P(n-2,x), -// 2n n - -Most of the work is performed by the internal function {OrthoPoly}. - -*E.G. - - In> PrettyPrinter'Set("PrettyForm"); - - True - - In> OrthoP(3, x); - - / 2 \ - | 5 * x 3 | - x * | ------ - - | - \ 2 2 / - - In> OrthoP(3, 1, 2, x); - - 1 / / 21 * x 7 \ 7 \ - - + x * | x * | ------ - - | - - | - 2 \ \ 2 2 / 2 / - - In> Expand(%) - - 3 2 - 21 * x - 7 * x - 7 * x + 1 - ---------------------------- - 2 - - In> OrthoP(3, 1, 2, 0.5); - - -0.8124999999 - - -*SEE OrthoPSum, OrthoG, OrthoPoly -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoH",categories="User Functions;Polynomials (Special)" -*CMD OrthoH --- Hermite orthogonal polynomials -*STD -*CALL - OrthoH(n, x); - -*PARMS - -{n} -- degree of polynomial - -{x} -- point to evaluate polynomial at - -*DESC - -This function evaluates the Hermite polynomial of degree {n} at the -point {x}. - -The Hermite polynomials are orthogonal with respect to the weight -function $Exp(-x^2/2)$ on the entire real axis. They satisfy the -recurrence relation -$$ H(n,x) = 2*x*H(n-1,x) - 2*(n-1)*H(n-2,x) $$ -for $n > 1$, with -$H(0,x) = 1$, -$H(1,x) = 2*x$. - -Most of the work is performed by the internal function {OrthoPoly}. - -*E.G. - - In> OrthoH(3, x); - Out> x*(8*x^2-12); - In> OrthoH(6, 0.5); - Out> 31; - -*SEE OrthoHSum, OrthoPoly -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoG",categories="User Functions;Polynomials (Special)" -*CMD OrthoG --- Gegenbauer orthogonal polynomials -*STD -*CALL - OrthoG(n, a, x); - -*PARMS - -{n} -- degree of polynomial - -{a} -- parameter - -{x} -- point to evaluate polynomial at - -*DESC - -This function evaluates the Gegenbauer (or ultraspherical) polynomial -with parameter {a} and degree {n} at the point {x}. The -parameter {a} should be greater than -1/2. - -The Gegenbauer polynomials are orthogonal with respect to the weight -function $(1-x^2)^(a-1/2)$ on the interval [-1,1]. Hence they are -connected to the Jacobi polynomials via -$$ G(n, a, x) = P(n, a-1/2, a-1/2, x) $$. -They satisfy the recurrence relation -$$ G(n,a,x) = 2*(1+(a-1)/n)*x*G(n-1,a,x) $$ -$$ -(1+2*(a-2)/n)*G(n-2,a,x) $$ -for $n>1$, with -$G(0,a,x) = 1$, -$G(1,a,x) = 2*x$. - -*REM -// / a - 1 \ -// G(n,a,x) = 2 | 1 + ----- | x G(n-1,a,x) -// \ n / -// -// / 2 (a-2) \ -// - | 1 + ------- | G(n-2,a,x), -// \ n / - -Most of the work is performed by the internal function {OrthoPoly}. - -*E.G. - - In> OrthoG(5, 1, x); - Out> x*((32*x^2-32)*x^2+6); - In> OrthoG(5, 2, -0.5); - Out> 2; - -*SEE OrthoP, OrthoT, OrthoU, OrthoGSum, OrthoPoly -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoL",categories="User Functions;Polynomials (Special)" -*CMD OrthoL --- Laguerre orthogonal polynomials -*STD -*CALL - OrthoL(n, a, x); - -*PARMS - -{n} -- degree of polynomial - -{a} -- parameter - -{x} -- point to evaluate polynomial at - -*DESC - -This function evaluates the Laguerre polynomial with parameter {a} -and degree {n} at the point {x}. The parameter {a} should be -greater than -1. - -The Laguerre polynomials are orthogonal with respect to the weight -function $x^a * Exp(-x)$ on the positive real axis. They satisfy the -recurrence relation -$$ L(n,a,x) = (2+(a-1-x)/n)* L(n-1,a,x) $$ -$$ -(1-(a-1)/n)*L(n-2,a,x) $$ -for $n>1$, with -$L(0,a,x) = 1$, -$L(1,a,x) = a + 1 - x$. - -*REM -// / a - 1 - x \ -// L(n,a,x) = | 2 + --------- | L(n-1,a,x) - -// \ n / -// -// / a - 1 \ -// | 1 + ----- | L(n-2,a,x), -// \ n / - - -Most of the work is performed by the internal function {OrthoPoly}. - -*E.G. - - In> OrthoL(3, 1, x); - Out> x*(x*(2-x/6)-6)+4; - In> OrthoL(3, 1/2, 0.25); - Out> 1.2005208334; - -*SEE OrthoLSum, OrthoPoly -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoT;OrthoU",categories="User Functions;Polynomials (Special)" -*CMD OrthoT --- Chebyshev polynomials -*CMD OrthoU --- Chebyshev polynomials -*STD -*CALL - OrthoT(n, x); - OrthoU(n, x); - -*PARMS - -{n} -- degree of polynomial - -{x} -- point to evaluate polynomial at - -*DESC - -These functions evaluate the Chebyshev polynomials of the first kind -$T(n,x)$ and of the second kind $U(n,x)$, of degree "n" at the point "x". (The -name of this Russian mathematician is also sometimes spelled "Tschebyscheff".) - -The Chebyshev polynomials are orthogonal with respect to the weight -function $(1-x^2)^(-1/2)$. Hence they are a special case of the Gegenbauer -polynomials $G(n,a,x)$, with $a=0$. They satisfy the recurrence relations -$$ T(n,x) = 2* x* T(n-1,x) - T(n-2,x) $$, -$$ U(n,x) = 2* x* U(n-1,x) - U(n-2,x) $$ -for $n > 1$, with -$T(0,x) = 1$, -$T(1,x) = x$, -$U(0,x) = 1$, -$U(1,x) = 2*x$. - - -*E.G. - - In> OrthoT(3, x); - Out> 2*x*(2*x^2-1)-x; - In> OrthoT(10, 0.9); - Out> -0.2007474688; - In> OrthoU(3, x); - Out> 4*x*(2*x^2-1); - In> OrthoU(10, 0.9); - Out> -2.2234571776; - - -*SEE OrthoG, OrthoTSum, OrthoUSum, OrthoPoly -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoPSum;OrthoHSum;OrthoLSum;OrthoGSum;OrthoTSum;OrthoUSum",categories="User Functions;Polynomials (Special)" -*CMD OrthoPSum --- sums of series of orthogonal polynomials -*CMD OrthoHSum --- sums of series of orthogonal polynomials -*CMD OrthoLSum --- sums of series of orthogonal polynomials -*CMD OrthoGSum --- sums of series of orthogonal polynomials -*CMD OrthoTSum --- sums of series of orthogonal polynomials -*CMD OrthoUSum --- sums of series of orthogonal polynomials -*STD -*CALL - OrthoPSum(c, x); - OrthoPSum(c, a, b, x); - OrthoHSum(c, x); - OrthoLSum(c, a, x); - OrthoGSum(c, a, x); - OrthoTSum(c, x); - OrthoUSum(c, x); - -*PARMS - -{c} -- list of coefficients - -{a}, {b} -- parameters of specific polynomials - -{x} -- point to evaluate polynomial at - -*DESC - -These functions evaluate the sum of series of orthogonal polynomials at the point {x}, with given list of coefficients {c} of the series and fixed polynomial parameters {a}, {b} (if applicable). - -The list of coefficients starts with the lowest order, so that for example -OrthoLSum(c, a, x) = c[1] L[0](a,x) + c[2] L[1](a,x) + ... + c[N] L[N-1](a,x). - -See pages for specific orthogonal polynomials for more details on the parameters of the polynomials. - -Most of the work is performed by the internal function {OrthoPolySum}. The individual polynomials entering the series are not computed, only the sum of the series. - -*E.G. - - In> Expand(OrthoPSum({1,0,0,1/7,1/8}, 3/2, \ - 2/3, x)); - Out> (7068985*x^4)/3981312+(1648577*x^3)/995328+ - (-3502049*x^2)/4644864+(-4372969*x)/6967296 - +28292143/27869184; - -*SEE OrthoP, OrthoG, OrthoH, OrthoL, OrthoT, OrthoU, OrthoPolySum -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoPoly",categories="User Functions;Polynomials (Special)" -*CMD OrthoPoly --- internal function for constructing orthogonal polynomials -*STD -*CALL - OrthoPoly(name, n, par, x) - -*PARMS - -{name} -- string containing name of orthogonal family - -{n} -- degree of the polynomial - -{par} -- list of values for the parameters - -{x} -- point to evaluate at - -*DESC - -This function is used internally to construct orthogonal -polynomials. It returns the {n}-th polynomial from the family -{name} with parameters {par} at the point {x}. - -All known families are stored in the association list returned by the function {KnownOrthoPoly()}. The name serves as key. At the moment -the following names are known to MathPiper: {"Jacobi"}, {"Gegenbauer"}, {"Laguerre"}, {"Hermite"}, {"Tscheb1"}, -and {"Tscheb2"}. The value associated to the key -is a pure function that takes two arguments: the order {n} and the -extra parameters {p}, and returns a list of two lists: the first list -contains the coefficients {A,B} of the n=1 polynomial, i.e. $A+B*x$; -the second list contains the coefficients {A,B,C} in the recurrence -relation, i.e. $P[n] = (A+B*x)*P[n-1]+C*P[n-2]$. (There are -only 3 coefficients in the second list, because none of the polynomials use $C+D*x$ instead of $C$ in the recurrence relation. This is assumed in the implementation!) - -If the argument {x} is numerical, the function {OrthoPolyNumeric} is called. Otherwise, the function {OrthoPolyCoeffs} computes a list of coefficients, and -{EvaluateHornerScheme} converts this list into a -polynomial expression. - -*SEE OrthoP, OrthoG, OrthoH, OrthoL, OrthoT, OrthoU, OrthoPolySum -%/mathpiper_docs - - - -%mathpiper_docs,name="OrthoPolySum",categories="User Functions;Polynomials (Special)" -*CMD OrthoPolySum --- internal function for computing series of orthogonal polynomials -*STD -*CALL - OrthoPolySum(name, c, par, x) - -*PARMS - -{name} -- string containing name of orthogonal family - -{c} -- list of coefficients - -{par} -- list of values for the parameters - -{x} -- point to evaluate at - -*DESC - -This function is used internally to compute series of orthogonal polynomials. -It is similar to the function {OrthoPoly} and returns the result of the -summation of series of polynomials from the family {name} with parameters {par} -at the point {x}, where {c} is the list of coefficients of the series. - -The algorithm used to compute the series without first computing the individual polynomials is the Clenshaw-Smith recurrence scheme. -(See the algorithms book for explanations.) - -If the argument {x} is numerical, the function {OrthoPolySumNumeric} is called. -Otherwise, the function {OrthoPolySumCoeffs} computes the list of coefficients -of the resulting polynomial, and {EvaluateHornerScheme} converts this list into -a polynomial expression. - -*SEE OrthoPSum, OrthoGSum, OrthoHSum, OrthoLSum, OrthoTSum, OrthoUSum, OrthoPoly -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/Apart.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/Apart.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/Apart.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/Apart.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -%mathpiper,def="Apart" - -Apart(_f) <-- Apart(f,x); - -Apart(_f,_var) <-- -[ - Local(rat); - rat:=RationalForm(f,var); - If(Degree(rat[1],var) = 0 And Degree(rat[2],var) = 0, - [ - rat:={Coef(rat[1],var,0),Coef(rat[2],var,0)}; - Local(summed,add); - summed := Eval(PartFracExpand(Rem(rat[1],rat[2]),rat[2])); - add:=(rat[1]/rat[2] - summed); - add + summed; - ] - , - [ - /*TODO check this one! Do we have to do the same as with the - * integers? - */ - Expand(Div(rat[1],rat[2])) + PartFracExpand(Rem(rat[1],rat[2]),rat[2]); - ] - ); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ChineseRemainderInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ChineseRemainderInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ChineseRemainderInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ChineseRemainderInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="ChineseRemainderInteger" - -/* Chinese Remaindering algorithm, as described in "Modern Computer Algebra". - */ -ChineseRemainderInteger(mlist_IsList,vlist_IsList) <-- -[ - Local(m,i,nr,result,msub,euclid,clist); - clist:={}; - m:=Product(mlist); - result:=0; - - nr:=Length(mlist); - For(i:=1,i<=nr,i++) - [ - msub:=Div(m,mlist[i]); - euclid := ExtendedEuclidean(msub,mlist[i]); - Local(c); - c:=vlist[i] * euclid[2]; - c:=Rem(c, mlist[i]); - DestructiveAppend(clist,c); - result:=result + msub * c; - ]; - {result,clist}; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ChineseRemainderPoly.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ChineseRemainderPoly.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ChineseRemainderPoly.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ChineseRemainderPoly.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="ChineseRemainderPoly" - -ChineseRemainderPoly(mlist_IsList,vlist_IsList) <-- -[ - Local(m,i,nr,result,msub,euclid,clist); - clist:={}; - m:=Product(mlist); - result:=0; - -/* Echo({mlist,m}); */ - - - nr:=Length(mlist); - For(i:=1,i<=nr,i++) - [ - msub:=Div(m,mlist[i]); - -/* Echo({Factor(msub)}); */ - - euclid := ExtendedEuclideanMonic(msub,mlist[i]); - Local(c); - - c:=vlist[i] * euclid[2]; - - c:=Mod(c, mlist[i]); - - DestructiveAppend(clist,c); - result:=result + msub * c; - ]; - {Expand(result),clist}; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ExtendedEuclideanMonic.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ExtendedEuclideanMonic.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ExtendedEuclideanMonic.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ExtendedEuclideanMonic.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="ExtendedEuclideanMonic" - -ExtendedEuclideanMonic(_f,_g) <-- -[ - Local(rho,r,s,t,i); - -/* -Echo({f,g}); -Echo({}); -*/ - - /* Initialize the loop */ - rho:={LeadingCoef(f),LeadingCoef(g)}; - r:={Monic(f),Monic(g)}; - s:={1/(rho[1]),0}; - t:={0,1/(rho[2])}; - i:=1; - - Local(q,newr,news,newt,newrho); - newr:=r[2]; - While(newr != 0) - [ - q :=Div(r[i],r[i+1]); - newr:=Mod(r[i],r[i+1]); - newrho:=LeadingCoef(newr); - - - If (newr != 0, newr:=Monic(newr)); - news :=(s[i]-q*s[i+1]); - newt :=(t[i]-q*t[i+1]); - If(newrho != 0, - [ - news:=news/newrho; - newt:=newt/newrho; - ]); - DestructiveAppend(rho,newrho); - DestructiveAppend(r ,newr); - DestructiveAppend(s,news); - DestructiveAppend(t,newt); - i++; - ]; - -/* -TableForm({i,r,s,t}); -Echo({}); -*/ - - {r[i],s[i],t[i]}; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ExtendedEuclidean.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ExtendedEuclidean.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/ExtendedEuclidean.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/ExtendedEuclidean.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="ExtendedEuclidean" - -/* Extended Euclidean algorithm. Algorithm taken from - * "Modern Computer Algebra". It does a Gcd calculation, but - * returns the intermediate results also. - * - * Returns {l,r,s,t} - * where - * - l the number of steps required - * - r[i] the i-th remainder - * - s[i] and t[i] the i-th bezout coefficients of f and g: - s[i]*f + t[i]*g = r[i] . - * The gcd is r[l]. - * - * This is a slightly modified version from the one described in - * "Modern Computer Algebra", where the elements in list r are not - * monic. If needed this can be done afterwards. As a consequence - * this version works on integers as well as on polynomials. - */ - -ExtendedEuclidean(_f,_g) <-- -[ - Local(r,s,t,i); - - /* Initialize the loop */ - r:={f,g}; - s:={1,0}; - t:={0,1}; - i:=1; - - Local(q,newr,news,newt); - newr:=1; - While(newr != 0) - [ - newr:=Rem(r[i],r[i+1]); - q :=Div(r[i],r[i+1]); - news :=(s[i]-q*s[i+1]); - newt :=(t[i]-q*t[i+1]); - DestructiveAppend(r ,newr); - DestructiveAppend(s,news); - DestructiveAppend(t,newt); - i++; - ]; - {r[i],s[i],t[i]}; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/GcdReduce.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/GcdReduce.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/GcdReduce.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/GcdReduce.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -%mathpiper,def="GcdReduce" - -/* Reduce rational function by dividing gcd away */ -GcdReduce(_f,_var)<-- -[ - Local(rat,gcd); - rat:=RationalForm(f,var); - gcd:=Gcd(rat[1],rat[2]); -/* gcd:=gcd*Gcd(Content(rat[1]),Content(rat[2]));*/ - - Local(numer,denom,lc); - numer:=Div(rat[1],gcd); - denom:=Div(rat[2],gcd); - lc:=LeadingCoef(numer,var); - numer:=numer/lc; - denom:=denom/lc; - Expand(numer)/Expand(denom); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/PAdicExpandInternal.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/PAdicExpandInternal.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/PAdicExpandInternal.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/PAdicExpandInternal.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -%mathpiper,def="PAdicExpandInternal" - -10 # PAdicExpandInternal(0,_y) <-- {}; -20 # PAdicExpandInternal(_x,_y) <-- -[ - Mod(x,y) : PAdicExpandInternal(Div(x,y),y); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/PAdicExpand.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/PAdicExpand.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/PAdicExpand.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/PAdicExpand.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -%mathpiper,def="PAdicExpand" - -/* - TODO: - - - - - - example: - 20 # f(_x) <-- Sin(x); - 10 # f(Eval(_x)) <-- Sin(Eval(x)); - HoldArgNr("f",1,1); - - Out( 0 ) = True; - In( 1 ) = f(2+3) - Out( 1 ) = Sin(2+3); - In( 2 ) = f(Eval(2+3)) - Out( 2 ) = Sin(5); - - Alternative: - f(x):= - [ - UnHoldable(x); - Sin(x); - ]; - - this is if you don't want to use patterns. - - - Mini-module padic. This module creates a p-adic expansion of - an expression: - - expression = a0 + a1*p + a2 * p^2 + ... etc. - - PAdicExpand and PAdicExpandInternal can be called with integer - or univariate polynomial arguments. - */ - - -Expand(x); /* TODO no idea why this is needed! Mod/Div/UniVariate thing :-( */ - -10 # PAdicExpand(_x,_y) <-- -[ - Local(coefs); - coefs:=PAdicExpandInternal(x,y); - Subst(p,y)Add(coefs*(p^(0 .. Length(coefs)))); -]; - -%/mathpiper - - - -%mathpiper_docs,name="PAdicExpand",categories="User Functions;Number Theory" -*CMD PAdicExpand --- p-adic expansion -*STD -*CALL - PAdicExpand(n, p) - -*PARMS - -{n} -- number or polynomial to expand - -{p} -- base to expand in - -*DESC - -This command computes the $p$-adic expansion of $n$. In other words, -$n$ is expanded in powers of $p$. The argument $n$ can be either -an integer or a univariate polynomial. The base $p$ should be of the -same type. - -*E.G. - - In> PrettyForm(PAdicExpand(1234, 10)); - - 2 3 - 3 * 10 + 2 * 10 + 10 + 4 - - Out> True; - In> PrettyForm(PAdicExpand(x^3, x-1)); - - 2 3 - 3 * ( x - 1 ) + 3 * ( x - 1 ) + ( x - 1 ) + 1 - - Out> True; - -*SEE Mod, ContFrac, FromBase, ToBase -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/PartFracExpand.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/PartFracExpand.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/padic/PartFracExpand.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/padic/PartFracExpand.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="PartFracExpand",scope="private" - -/* Partial fraction expansion of g/f with Degree(g) MakeVector(a,3) - Out> {a1,a2,a3}; - -*SEE RandomIntegerVector, ZeroVector -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/patterns/pound_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/patterns/pound_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/patterns/pound_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/patterns/pound_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not defined in the scripts. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_2d/backends.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_2d/backends.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_2d/backends.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_2d/backends.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,166 +0,0 @@ -%mathpiper,def="Plot2DOutputs" - -////////////////////////////////////////////////// -/// Backends for 2D plotting -////////////////////////////////////////////////// - - -/// List of all defined backends and their symbolic labels. -/// Add any new backends here - -LocalSymbols(options) -[ - options := { - {"default", "data"}, - {"data", "Plot2DData"}, - {"java", "Plot2DJava"}, - {"geogebra", "Plot2DGeoGebra"}, - {"jfreechart", "Plot2DJFreeChart"}, -}; - - -Plot2DOutputs() := options; - -]; - -/* - How backends work: - Plot2D'(values, optionsHash) - optionsHash is a hash that contains all plotting options: - ["xrange"] - a list of {x1, x2}, ["xname"] - name of the variable to plot, ["yname"] - array of string representations of the function(s), and perhaps other options relevant to the particular backend. - {values} is a list of lists of pairs of the form {{{x1, y1}, {x2, y2}, ...}, {{x1, z1}, {x2, z2}, ...}, ...} corresponding to the functions y(x), z(x), ... to be plotted. The abscissa points x[i] are not the same for all functions. - The backend should prepare the graph of the function(s). The "datafile" backend Plot2D'datafile(values, optionsHash) may be used to output all data to file(s), in which case the file name should be given by the value optionsHash["filename"]. Multiple files are created with names obtained by appending numbers to the filename. - Note that the "data" backend does not do anything and simply returns the data. - The backend Plot2D'datafile takes care not to write "Infinity" or "Undefined" data points (it just ignores them). Custom backends should either use Plot2D'datafile or take care of this themselves. -*/ - -/// trivial backend: return data list (do not confuse with Plot2D'get'data() defined in the main code which is the middle-level plotting routine) -Plot2DData(values_IsList, _optionsHash) <-- values; - -/// The Java back-end generates a call-list that the Java graph plotter can handle -Plot2DJava(values_IsList, _optionsHash) <-- -[ - Local(result,count); - count := 0; - result:="$plot2d:"; - - result := result:" pensize 2.0 "; - ForEach(function,values) - [ - result := result:ColorForGraphNr(count); - count++; - result:=result:" lines2d ":String(Length(function)); - - function:=Select(Lambda({item},item[2] != Undefined),function); - - ForEach(item,function) - [ - result := result:" ":String(item[1]):" ":String(item[2]):" "; - ]; - ]; - WriteString(result:"$"); - True; -]; - -10 # ColorForGraphNr(0) <-- " pencolor 64 64 128 "; -10 # ColorForGraphNr(1) <-- " pencolor 128 64 64 "; -10 # ColorForGraphNr(2) <-- " pencolor 64 128 64 "; -20 # ColorForGraphNr(_count) <-- ColorForGraphNr(Mod(count,3)); - - - - -//GeoGebra backend. -Plot2DGeogebra(values_IsList, _optionsHash) <-- -[ - Local(result,count); - count := 0; - result:=""; - - - ForEach(function,values) - [ - - function:=Select(Lambda({item},item[2] != Undefined),function); - - ForEach(item,function) - [ - result := result:"(":String(item[1]):",":String(item[2]):")":Nl(); - ]; - ]; - WriteString(result); - True; -]; - - - - -//JFreeChart backend. -Retract("Plot2DJFreeChart", *); -Plot2DJFreeChart(values_IsList, _optionsHash) <-- -[ - Local(rangeList, domainList, function, allProcessedFunctionData, lineChartCallListForm); - - - - //Remove Plot2D's options so that they don't get passed through to LineChart(); - ForEach(name, {"xrange", "xname", "yname", "output", "precision", "points", "depth"}) - [ - AssocDelete(optionsHash, name); - ]; - - - - //Convert {x,y} pairs into {x,x,x,...} {y,y,y,...} form. - allProcessedFunctionData := {}; - - ForEach(function,values) - [ - rangeList := {}; - - domainList := {}; - - function := Select(Lambda({item},item[2] != Undefined),function); - - ForEach(item,function) - [ - rangeList := Append(rangeList, item[1]); - - domainList := Append(domainList, item[2]); - ]; - - allProcessedFunctionData := Append(allProcessedFunctionData, rangeList); - allProcessedFunctionData := Append(allProcessedFunctionData, domainList); - - ]; - - - - //Put LineChart() function call into list form so it can be manipulated. - lineChartCallListForm := {LineChart, allProcessedFunctionData }; - - - - //Add any options to the list. - ForEach(key, AssocIndices(optionsHash)) - [ - lineChartCallListForm := Append(lineChartCallListForm, Apply("->", {key, optionsHash[key]})); - ]; - - - - //Call the LineChart() function. - Eval(UnList(lineChartCallListForm)); - - -]; - - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_2d/plot2d.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_2d/plot2d.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_2d/plot2d.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_2d/plot2d.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,332 +0,0 @@ -%mathpiper,def="Plot2D" - -Retract("Plot2D", *); - -////////////////////////////////////////////////// -/// Plot2D --- adaptive two-dimensional plotting -////////////////////////////////////////////////// - -/// definitions of backends -//Use("org/mathpiper/assembledscripts/plots.rep/backends_2d.mpi"); - -/* - Plot2D is an interface for various backends (Plot2D'...). It calls -Plot2D'get'data to obtain the list of points and values, and then it calls -Plot2D' on that data. - - Algorithm for Plot2D'get'data: - 1) Split the given interval into Div(points+3, 4) subintervals, and split each subinterval into 4 parts. - 2) For each of the parts: evaluate function values and call Plot2D'adaptive - 3) concatenate resulting lists and return -*/ - -LocalSymbols(var, func, range, option, options'list, delta, options'hash, c, fc, all'values, dummy) -[ - -// declaration of Plot2D with variable number of arguments -Function() Plot2D(func); -Function() Plot2D(func, range); -Function() Plot2D(func, range, options, ...); - -/// interface routines -1 # Plot2D(_func) <-- ("Plot2D" @ {func, -5:5}); -2 # Plot2D(_func, _range) <-- ("Plot2D" @ {func, range, {}}); -3 # Plot2D(_func, _range, option_IsFunction) _ (Type(option) = "->" ) <-- ("Plot2D" @ {func, range, {option}}); - -/// Plot a single function -5 # Plot2D(_func, _range, options'list_IsList)_(Not IsList(func)) <-- ("Plot2D" @ {{func}, range, options'list}); - -/// Top-level 2D plotting routine: -/// plot several functions sharing the same xrange and other options -4 # Plot2D(func'list_IsList, _range, options'list_IsList) <-- -[ - Local(var, func, delta, options'hash, c, fc, all'values, dummy); - all'values := {}; - options'hash := "OptionsListToHash" @ {options'list}; - - - // this will be a string - name of independent variable - options'hash["xname"] := ""; - // this will be a list of strings - printed forms of functions being plotted - options'hash["yname"] := {}; - // parse range - If ( - Type(range) = "->", // variable also specified -- ignore for now, store in options - [ - // store alternative variable name - options'hash["xname"] := String(range[1]); - range := range[2]; - ] - ); - If( - Type(range) = ":", // simple range - range := N(Eval({range[1], range[2]})) - ); - // set default option values - If( - options'hash["points"] = Empty, - options'hash["points"] := 23 - ); - If( - options'hash["depth"] = Empty, - options'hash["depth"] := 5 - ); - If( - options'hash["precision"] = Empty, - options'hash["precision"] := 0.0001 - ); - If( - options'hash["output"] = Empty Or IsString(options'hash["output"]) And Plot2DOutputs()[options'hash["output"]] = Empty, - options'hash["output"] := Plot2DOutputs()["default"] - ); - // a "filename" parameter is required when using data file - If( - options'hash["output"] = "datafile" And options'hash["filename"] = Empty, - options'hash["filename"] := "output.data" - ); - - // we will divide each subinterval in 4 parts, so divide number of points by 4 now - options'hash["points"] := N(Eval(Div(options'hash["points"]+3, 4))); - - // in case it is not a simple number but an unevaluated expression - options'hash["precision"] := N(Eval(options'hash["precision"])); - - // store range in options - options'hash["xrange"] := {range[1], range[2]}; - - // compute the separation between grid points - delta := N(Eval( (range[2] - range[1]) / (options'hash["points"]) )); - - // check that the input parameters are valid (all numbers) - Check(IsNumber(range[1]) And IsNumber(range[2]) And IsNumber(options'hash["points"]) And IsNumber(options'hash["precision"]), - "Plot2D: Error: plotting range '" - :(ToString()Write(range)) - :"' and/or the number of points '" - :(ToString()Write(options'hash["points"])) - :"' and/or precision '" - :(ToString()Write(options'hash["precision"])) - :"' is not numeric" - ); - // loop over functions in the list - ForEach(func, func'list) - [ - // obtain name of variable - var := VarList(func); // variable name in a one-element list - Check(Length(var)<=1, - "Plot2D: Error: expression is not a function of one variable: " - :(ToString()Write(func)) - ); - // Allow plotting of constant functions - If(Length(var)=0, var:={dummy}); - // store variable name if not already done so - If( - options'hash["xname"] = "", - options'hash["xname"] := String(VarList(var)[1]) - ); - // store function name in options - DestructiveAppend(options'hash["yname"], ToString()Write(func)); - // compute the first point to see if it's okay - c := range[1]; - fc := N(Eval(Apply({var, func}, {c}))); - Check(IsNumber(fc) Or fc=Infinity Or fc= -Infinity Or fc=Undefined, - "Plot2D: Error: cannot evaluate function '" - :(ToString()Write(func)) - :"' at point '" - :(ToString()Write(c)) - :"' to a number, instead got '" - :(ToString()Write(fc)) - :"'" - ); - // compute all other data points - DestructiveAppend(all'values, Plot2D'get'data(func, var, c, fc, delta, options'hash) ); - - If(InVerboseMode(), Echo({"Plot2D: using ", Length(all'values[Length(all'values)]), " points for function ", func}), True); - ]; - - // call the specified output backend - Plot2DOutputs()[options'hash["output"]] @ {all'values, options'hash}; -]; - -//HoldArg("Plot2D", range); -//HoldArg("Plot2D", options); -HoldArgNr("Plot2D", 2, 2); -HoldArgNr("Plot2D", 3, 2); -HoldArgNr("Plot2D", 3, 3); - - - -Retract("Plot2D'get'data", *); -/// this is the middle-level plotting routine; it generates the initial -/// grid, calls the adaptive routine, and gathers data points. -/// func must be just one function (not a list) -Plot2D'get'data(_func, _var, _x'init, _y'init, _delta'x, _options'hash) <-- -[ - Local(i, a, fa, b, fb, c, fc, result); - // initialize list by first points (later will always use Rest() to exclude first points of subintervals) - result := { {c,fc} := {x'init, y'init} }; - For(i:=0, i value) - Plot2D(f(x), a:b, option -> value, ...) - Plot2D(list, ...) - -*PARMS - -{f(x)} -- unevaluated expression containing one variables (function to be plotted) - -{list} -- list of functions to plot - -{a}, {b} -- numbers, plotting range in the $x$ coordinate - -{option} -- atom, option name - -{value} -- atom, number or string (value of option) - -*DESC -The routine {Plot2D} performs adaptive plotting of one or several functions -of one variable in the specified range. -The result is presented as a line given by the equation $y=f(x)$. -Several functions can be plotted at once. -Various plotting options can be specified. -Output can be directed to a plotting program (the default is to use -{data}) to a list of values. - -The function parameter {f(x)} must evaluate to a MathPiper expression containing -at most one variable. (The variable does not have to be called {x}.) -Also, {N(f(x))} must evaluate to a real (not complex) numerical value when given a numerical value of the argument {x}. -If the function {f(x)} does not satisfy these requirements, an error is raised. - -Several functions may be specified as a list and they do not have to depend on the same variable, for example, {{f(x), g(y)}}. -The functions will be plotted on the same graph using the same coordinate ranges. - -If you have defined a function which accepts a number but does not -accept an undefined variable, {Plot2D} will fail to plot it. -Use {NFunction} to overcome this difficulty. - -Data files are created in a temporary directory {/tmp/plot.tmp/} unless otherwise requested. -File names -and other information is printed if {InVerboseMode()} returns {True} on using {V()}. - -The current algorithm uses Newton-Cotes quadratures and some heuristics for error estimation (see <*mathpiperdoc://Algo/3/1/*>). -The initial grid of {points+1} points is refined between any grid points $a$, $b$ if the integral -$Integrate(x,a,b)f(x)$ is not approximated to the given precision by -the existing grid. - -Default plotting range is {-5:5}. Range can also be specified as {x= -5:5} (note the mandatory space separating "{=}" and "{-}"); -currently the variable name {x} is ignored in this case. - -Options are of the form {option -> value}. Currently supported option names -are: "points", "precision", "depth", "output", "filename", "yrange". Option values -are either numbers or special unevaluated atoms such as {data}. -If you need to use the names of these atoms -in your script, strings can be used. Several option/value pairs may be specified (the function {Plot2D} has a variable number of arguments). - -* {yrange}: the range of ordinates to use for plotting, e.g. -{yrange=0:20}. If no range is specified, the default is usually to -leave the choice to the plotting backend. -* {points}: initial number of points (default 23) -- at least that -many points will be plotted. The initial grid of this many points will be -adaptively refined. -* {precision}: graphing precision (default $10^(-6)$). This is interpreted as the relative precision of computing the integral of $f(x)-Min(f(x))$ using the grid points. For a smooth, non-oscillating function this value should be roughly 1/(number of screen pixels in the plot). -* {depth}: max. refinement depth, logarithmic (default 5) -- means there will be at most $2^depth$ extra points per initial grid point. -* {output}: name of the plotting backend. Supported names: {data} (default). -The {data} backend will return the data as a list of pairs such as {{{x1,y1}, {x2,y2}, ...}}. -* {filename}: specify name of the created data file. For example: {filename="data1.txt"}. -The default is the name {"output.data"}. -Note that if several functions are plotted, the data files will have a number appended to the given name, for example {data.txt1}, {data.txt2}. - -Other options may be supported in the future. - -The current implementation can deal with a singularity within the plotting range only if the function {f(x)} returns {Infinity}, {-Infinity} or -{Undefined} at the singularity. -If the function {f(x)} generates a numerical error and fails at a -singularity, {Plot2D} will fail if one of the grid points falls on the -singularity. -(All grid points are generated by bisection so in principle the -endpoints and the {points} parameter could be chosen to avoid numerical -singularities.) - -*WIN32 - - - -*SEE V, NFunction, Plot3DS -%/mathpiper_docs - - %output,preserve="false" - -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_3d/backends.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_3d/backends.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_3d/backends.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_3d/backends.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="" - -////////////////////////////////////////////////// -/// Backends for 3D plotting -////////////////////////////////////////////////// - -/// List of all defined backends and their symbolic labels. -/// Add any new backends here -Plot3DS'outputs() := { - {"default", "data"}, - {"data", "Plot3DS'data"}, -}; - -/* - How backends work: - Plot3DS'(values, options'hash) - options'hash is a hash that contains all plotting options: - ["xrange"] - a list of {x1, x2}, ["xname"] - name of the variable to plot, same for "yrange"; - ["zname"] - array of string representations of the function(s), and perhaps other options relevant to the particular backend. - {values} is a list of lists of triples of the form {{{x1, y1, z1}, {x2, y2, z2}, ...}, {{x1, y1, t1}, {x2, y2, t2}, ...}, ...} corresponding to the functions z(x,y), t(x,y), ... to be plotted. The points x[i], y[i] are not necessarily the same for all functions. - The backend should prepare the graph of the function(s). The "datafile" backend Plot3DS'datafile(values, options'hash) may be used to output all data to file(s), in which case the file name should be given by the value options'hash["filename"]. Multiple files are created with names obtained by appending numbers to the filename. - Note that the "data" backend does not do anything and simply returns the data. - The backend Plot3DS'datafile takes care not to write "Infinity" or "Undefined" data points (it just ignores them). Custom backends should either use Plot3DS'datafile to prepare a file, or take care of this themselves. -*/ - -/// trivial backend: return data list (do not confuse with Plot3DS'get'data() defined in the main code which is the middle-level plotting routine) -Plot3DS'data(values_IsList, _options'hash) <-- values; - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_3d/plot3ds.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_3d/plot3ds.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/_3d/plot3ds.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/_3d/plot3ds.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,415 +0,0 @@ -%mathpiper,def="Plot3DS" - -////////////////////////////////////////////////// -/// Plot3DS --- adaptive three-dimensional surface plotting -////////////////////////////////////////////////// - -/// definitions of backends -//Use("org/mathpiper/assembledscripts/plots.rep/backends_3d.mpi"); - -/* - Plot3DS is an interface for various backends (Plot3DS'...). It calls -Plot3DS'get'data to obtain the list of points and values, and then it calls -Plot3DS' on that data. - - Algorithm for Plot3DS'get'data: - 1) Split the given square into Div(Sqrt(points)+1, 2) subsquares, and split each subsquare into 4 parts. - 2) For each of the parts: evaluate function values and call Plot3DS'adaptive - 3) concatenate resulting lists and return -*/ - - LocalSymbols(var, func, xrange, yrange, option, options'list, xdelta, ydelta, options'hash, cx, cy, fc, all'values, dummy) -[ - -// declaration of Plot3DS with variable number of arguments -Function() Plot3DS(func); -Function() Plot3DS(func, xrange, yrange); -Function() Plot3DS(func, xrange, yrange, options, ...); - - -/// interface routines -1 # Plot3DS(_func) <-- ("Plot3DS" @ {func, -5:5, -5:5}); -2 # Plot3DS(_func, _xrange, _yrange) <-- ("Plot3DS" @ {func, xrange, yrange, {}}); -3 # Plot3DS(_func, _xrange, _yrange, option_IsFunction) _ (Type(option) = "->" ) <-- ("Plot3DS" @ {func, xrange, yrange, {option}}); - -/// Plot a single function -5 # Plot3DS(_func, _xrange, _yrange, options'list_IsList)_(Not IsList(func)) <-- ("Plot3DS" @ {{func}, xrange, yrange, options'list}); - -/// Top-level 3D plotting routine: -/// plot several functions sharing the same ranges and other options -4 # Plot3DS(func'list_IsList, _xrange, _yrange, options'list_IsList) <-- -[ - Local(var, func, xdelta, ydelta, options'hash, cx, cy, fc, all'values, dummy); - // this will be a list of all computed values - all'values := {}; - options'hash := "OptionsListToHash" @ {options'list}; - // this will be a string - name of independent variable - options'hash["xname"] := ""; - options'hash["yname"] := ""; - // this will be a list of strings - printed forms of functions being plotted - options'hash["zname"] := {}; - // parse range - If ( - Type(xrange) = "->", // variable also specified -- ignore for now, store in options - [ - // store alternative variable name - options'hash["xname"] := String(xrange[1]); - xrange := xrange[2]; - ] - ); - If ( - Type(yrange) = "->" , // variable also specified -- ignore for now, store in options - [ - // store alternative variable name - options'hash["yname"] := String(yrange[1]); - yrange := yrange[2]; - ] - ); - If( - Type(xrange) = ":", // simple range - xrange := N(Eval({xrange[1], xrange[2]})) - ); - If( - Type(yrange) = ":", // simple range - yrange := N(Eval({yrange[1], yrange[2]})) - ); - // set default option values - If( - options'hash["points"] = Empty, - options'hash["points"] := 10 // default # of points along each axis - ); - If( - options'hash["xpoints"] = Empty, - options'hash["xpoints"] := options'hash["points"] - ); - If( - options'hash["ypoints"] = Empty, - options'hash["ypoints"] := options'hash["points"] - ); - - If( - options'hash["depth"] = Empty, - options'hash["depth"] := 2 - ); - If( - options'hash["precision"] = Empty, - options'hash["precision"] := 0.0001 - ); - If( - options'hash["hidden"] = Empty Or Not IsBoolean(options'hash["hidden"]), - options'hash["hidden"] := True - ); - If( - options'hash["output"] = Empty Or IsString(options'hash["output"]) And Plot3DS'outputs()[options'hash["output"]] = Empty, - options'hash["output"] := Plot3DS'outputs()["default"] - ); - // a "filename" parameter is required when using data file - If( - options'hash["output"] = "datafile" And options'hash["filename"] = Empty, - options'hash["filename"] := "output.data" - ); - options'hash["used depth"] := options'hash["depth"]; - // we will divide each subsquare in 4 parts, so divide number of points by 2 now - options'hash["xpoints"] := N(Eval(Div(options'hash["xpoints"]+1, 2))); - options'hash["ypoints"] := N(Eval(Div(options'hash["ypoints"]+1, 2))); - // in case it is not a simple number but an unevaluated expression - options'hash["precision"] := N(Eval(options'hash["precision"])); - // store range in options - options'hash["xrange"] := {xrange[1], xrange[2]}; - options'hash["yrange"] := {yrange[1], yrange[2]}; - // compute the separation between grid points - xdelta := N(Eval( (xrange[2] - xrange[1]) / (options'hash["xpoints"]) ) ); - ydelta := N(Eval( (yrange[2] - yrange[1]) / (options'hash["ypoints"]) ) ); - // check that the input parameters are valid (all numbers) - Check(IsNumericList({xrange[1], xrange[2], options'hash["xpoints"], options'hash["ypoints"], options'hash["precision"]}), - "Plot3DS: Error: plotting ranges '" - :(ToString()Write(xrange, yrange)) - :"' and/or the number of points '" - :(ToString()Write(options'hash["xpoints"], options'hash["ypoints"])) - :"' and/or precision '" - :(ToString()Write(options'hash["precision"])) - :"' is not numeric" - ); - // loop over functions in the list - ForEach(func, func'list) - [ - // obtain name of variable - var := VarList(func); // variable names in a list - Check(Length(var)<=2, - "Plot3DS: Error: expression is not a function of at most two variables: " - :(ToString()Write(func)) - ); - // Allow plotting of constant functions - If(Length(var)=0, var:={dummy, dummy}); - If(Length(var)=1, var:={var[1], dummy}); - // store variable name if not already done so - If( - options'hash["xname"] = "", - options'hash["xname"] := String(var[1]) - ); - If( - options'hash["yname"] = "", - options'hash["yname"] := String(var[2]) - ); - // store function name in options - DestructiveAppend(options'hash["zname"], ToString()Write(func)); - // compute the first point to see if it's okay - cx := xrange[1]; cy := yrange[1]; - fc := N(Eval(Apply({var, func}, {cx, cy}))); - Check(IsNumber(fc) Or fc=Infinity Or fc= -Infinity Or fc=Undefined, - "Plot3DS: Error: cannot evaluate function '" - :(ToString()Write(func)) - :"' at point '" - :(ToString()Write(cx, cy)) - :"' to a number, instead got '" - :(ToString()Write(fc)) - :"'" - ); - // compute all other data points - DestructiveAppend(all'values, RemoveRepeated(HeapSort( Plot3DS'get'data(func, var, {cx, cy, fc}, {xdelta, ydelta}, options'hash), Hold({{x,y},x[1]value) - Plot3DS(f(x,y), a:b, c:d, option->value, ...) - Plot3DS(list, ...) - -*PARMS - -{f(x,y)} -- unevaluated expression containing two variables (function to be plotted) - -{list} -- list of functions to plot - -{a}, {b}, {c}, {d} -- numbers, plotting ranges in the $x$ and $y$ coordinates - -{option} -- atom, option name - -{value} -- atom, number or string (value of option) - -*DESC -The routine {Plot3DS} performs adaptive plotting of a function -of two variables in the specified ranges. -The result is presented as a surface given by the equation $z=f(x,y)$. -Several functions can be plotted at once, by giving a list of functions. -Various plotting options can be specified. -Output can be directed to a plotting program (the default is to use -{data}), to a list of values. - -The function parameter {f(x,y)} must evaluate to a MathPiper expression containing -at most two variables. (The variables do not have to be called {x} and {y}.) -Also, {N(f(x,y))} must evaluate to a real (not complex) numerical value when given numerical values of the arguments {x}, {y}. -If the function {f(x,y)} does not satisfy these requirements, an error is raised. - -Several functions may be specified as a list but they have to depend on the same symbolic variables, for example, {{f(x,y), g(y,x)}}, but not {{f(x,y), g(a,b)}}. -The functions will be plotted on the same graph using the same coordinate ranges. - -If you have defined a function which accepts a number but does not -accept an undefined variable, {Plot3DS} will fail to plot it. -Use {NFunction} to overcome this difficulty. - -Data files are created in a temporary directory {/tmp/plot.tmp/} unless otherwise requested. -File names -and other information is printed if {InVerboseMode()} returns {True} on using {V()}. - -The current algorithm uses Newton-Cotes cubatures and some heuristics for error estimation (see <*mathpiperdoc://Algo/3/1/*>). -The initial rectangular grid of {xpoints+1}*{ypoints+1} points is refined within any rectangle where the integral -of $f(x,y)$ is not approximated to the given precision by -the existing grid. - -Default plotting range is {-5:5} in both coordinates. -A range can also be specified with a variable name, e.g. {x= -5:5} (note the mandatory space separating "{=}" and "{-}"). -The variable name {x} should be the same as that used in the function {f(x,y)}. -If ranges are not given with variable names, the first variable encountered in the function {f(x,y)} is associated with the first of the two ranges. - -Options are of the form {option->value}. Currently supported option names -are "points", "xpoints", "ypoints", "precision", "depth", "output", "filename", "xrange", "yrange", "zrange". Option values -are either numbers or special unevaluated atoms such as {data}. -If you need to use the names of these atoms -in your script, strings can be used (e.g. {output="data"}). Several option/value pairs may be specified (the function {Plot3DS} has a variable number of arguments). - -* {xrange}, {yrange}: optionally override coordinate ranges. Note that {xrange} is always the first variable and {yrange} the second variable, regardless of the actual variable names. -* {zrange}: the range of the $z$ axis to use for plotting, e.g. -{zrange=0:20}. If no range is specified, the default is usually to -leave the choice to the plotting backend. Automatic choice based on actual values may -give visually inadequate plots if the function has a singularity. -* {points}, {xpoints}, {ypoints}: initial number of points (default 10 each) -- at least that -many points will be plotted in each coordinate. -The initial grid of this many points will be -adaptively refined. -If {points} is specified, it serves as a default for both {xpoints} and {ypoints}; this value may be overridden by {xpoints} and {ypoints} values. -* {precision}: graphing precision (default $0.01$). This is interpreted as the relative precision of computing the integral of $f(x,y)-Min(f(x,y))$ using the grid points. For a smooth, non-oscillating function this value should be roughly 1/(number of screen pixels in the plot). -* {depth}: max. refinement depth, logarithmic (default 3) -- means there will be at most $2^depth$ extra points per initial grid point (in each coordinate). -* {output}: name of the plotting backend. Supported names: {data} (default). -The {data} backend will return the data as a list of triples such as {{{x1, y1, z1}, {x2, y2, z2}, ...}}. - -Other options may be supported in the future. - -The current implementation can deal with a singularity within the plotting range only if the function {f(x,y)} returns {Infinity}, {-Infinity} or -{Undefined} at the singularity. -If the function {f(x,y)} generates a numerical error and fails at a -singularity, {Plot3DS} will fail only if one of the grid points falls on the -singularity. -(All grid points are generated by bisection so in principle the -endpoints and the {xpoints}, {ypoints} parameters could be chosen to avoid numerical -singularities.) - -The {filename} option is optional if using graphical backends, but can be used to specify the location of the created data file. - -*WIN32 - -Same limitations as {Plot2D}. - -*E.G. notest - In> Plot3DS(a*b^2) - Out> True; - In> V(Plot3DS(Sin(x)*Cos(y),x->0:20, y->0:20,depth->3)) - CachedConstant: Info: constant Pi is being - recalculated at precision 10 - CachedConstant: Info: constant Pi is being - recalculated at precision 11 - Plot3DS: using 1699 points for function Sin(x)*Cos(y) - Plot3DS: max. used 8 subdivisions for Sin(x)*Cos(y) - Plot3DS'datafile: created file '/tmp/plot.tmp/data1' - Out> True; - - -*SEE V, NFunction, Plot2D -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/OptionsListToHash.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/OptionsListToHash.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/OptionsListToHash.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/OptionsListToHash.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="OptionsListToHash" - -/// utility function: convert options lists of the form -/// "{key=value, key=value}" into a hash of the same form. -/// The argument list is kept unevaluated using "HoldArgNr()". -/// Note that symbolic values of type atom are automatically converted to strings, e.g. ListToHash({a -> b}) returns {{"a", "b"}} -OptionsListToHash(list) := -[ - Local(item, result); - result := {}; - ForEach(item, list) - If( - IsFunction(item) And (Type(item) = "->" ) And IsAtom(item[1]), - result[String(item[1])] := If( - IsAtom(item[2]) And Not IsNumber(item[2]) And Not IsString(item[2]), - String(item[2]), - item[2] - ), - Echo({"OptionsListToHash: Error: item ", item, " is not of the format a -> b."}) - ); - - result; -]; - -HoldArgNr("OptionsListToHash", 1, 1); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/RemoveRepeated.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/RemoveRepeated.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/RemoveRepeated.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/RemoveRepeated.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="RemoveRepeated" - -10 # RemoveRepeated({}) <-- {}; -10 # RemoveRepeated({_x}) <-- {x}; -20 # RemoveRepeated(list_IsList) <-- [ - Local(i, done); - done := False; - For(i:=0, Not done, i++) - [ - While(iy And yz - ) -, 0, 1); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/WriteDataItem.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/WriteDataItem.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/plots/WriteDataItem.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/plots/WriteDataItem.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="WriteDataItem" - -/// service function. WriteDataItem({1,2,3}, {}) will output "1 2 3" on a separate line. -/// Writes data points to the current output stream, omits non-numeric values. -WriteDataItem(tuple_IsList, _options'hash) <-- -[ - Local(item); - If( // do not write anything if one of the items is not a number - IsNumericList(tuple), - ForEach(item,tuple) - [ - Write(item); - Space(); - ] - ); - NewLine(); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/AllSatisfy.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/AllSatisfy.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/AllSatisfy.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/AllSatisfy.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="AllSatisfy" - -10 # AllSatisfy(pred_IsString,lst_IsList) <-- Apply("And",(MapSingle(pred,lst))); - -20 # AllSatisfy(_pred,_lst) <-- False; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - -%mathpiper_docs,name="AllSatisfy",categories="User Functions;Predicates" - - -*CMD AllSatisfy --- Check if all elements of list {lst} satisfy predicate {pred} - -*STD -*CALL - AllSatisfy(pred,lst) - -*PARMS - -{pred} -- the name of the predicate (as string, with quotes) to be tested - -{lst} -- a list - - -*DESC - -The command {AllSatisfy} returns {True} if every element of the list {lst} satisfies the predicate {pred}. -It returns {False} otherwise. -It also returns {False} if {lst} is not a list, or if {pred} is not a predicate. - -*E.G. - - In> AllSatisfy("IsInteger",{1,0,-5}) - Result> True - In> AllSatisfy("IsPositiveInteger",{1,0,-5}) - Result> False - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/FloatIsInt.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/FloatIsInt.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/FloatIsInt.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/FloatIsInt.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="FloatIsInt" - -/// TODO FIXME document this: FloatIsInt returns True if the argument is integer after removing potential trailing -/// zeroes after the decimal point -// but in fact this should be a call to BigNumber::IsIntValue() -FloatIsInt(_x) <-- - [ - x:=N(Eval(x)); - Local(prec,result,n); - Set(prec,BuiltinPrecisionGet()); - If(IsZero(x),Set(n,2), - If(x>0, - Set(n,2+FloorN(N(FastLog(x)/FastLog(10)))), - Set(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) - )); - BuiltinPrecisionSet(n+prec); - Set(result,IsZero(RoundTo(x-Floor(x),prec)) Or IsZero(RoundTo(x-Ceil(x),prec))); - BuiltinPrecisionSet(prec); - result; - ]; -// - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasExprArith.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasExprArith.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasExprArith.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasExprArith.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="HasExprArith" - -/// Analyse arithmetic expressions - -HasExprArith(expr, atom) := HasExprSome(expr, atom, {Atom("+"), Atom("-"), *, /}); - - -%/mathpiper - - - -%mathpiper_docs,name="HasExprArith",categories="User Functions;Predicates" -*CMD HasExprArith --- check for expression containing a subexpression -*STD -*CALL - HasExprArith(expr, x) - -*PARMS - -{expr} -- an expression - -{x} -- a subexpression to be found - -*DESC - -{HasExprArith} is defined through {HasExprSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> HasExprArith(x+y*Cos(Ln(x)/x), z) - Out> False; - -*SEE HasExpr, HasExprSome, FuncList, VarList, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasExpr.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasExpr.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasExpr.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasExpr.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="HasExpr" - -/// HasExpr --- test for an expression containing a subexpression -/// for checking dependence on variables, this may be faster than using VarList or IsFreeOf and this also can be used on non-variables, e.g. strings or numbers or other atoms or even on non-atoms -// an expression contains itself -- check early -10 # HasExpr(_expr, _atom) _ Equals(expr, atom) <-- True; -// an atom contains itself -15 # HasExpr(expr_IsAtom, _atom) <-- Equals(expr, atom); -// a list contains an atom if one element contains it -// we test for lists now because lists are also functions -// first take care of the empty list: -19 # HasExpr({}, _atom) <-- False; -20 # HasExpr(expr_IsList, _atom) <-- HasExpr(First(expr), atom) Or HasExpr(Rest(expr), atom); -// a function contains an atom if one of its arguments contains it -30 # HasExpr(expr_IsFunction, _atom) <-- HasExpr(Rest(Listify(expr)), atom); - -%/mathpiper - - - -%mathpiper_docs,name="HasExpr",categories="User Functions;Predicates" -*CMD HasExpr --- check for expression containing a subexpression -*STD -*CALL - HasExpr(expr, x) - -*PARMS - -{expr} -- an expression - -{x} -- a subexpression to be found - - - -*DESC - -The command {HasExpr} returns {True} if the expression {expr} contains a literal subexpression {x}. The expression is recursively traversed. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> HasExpr(x+y*Cos(Ln(z)/z), z) - Out> True; - In> HasExpr(x+y*Cos(Ln(z)/z), Ln(z)) - Out> True; - In> HasExpr(x+y*Cos(Ln(z)/z), z/Ln(z)) - Out> False; - -*SEE HasExprArith, HasExprSome, FuncList, VarList, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasExprSome.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasExprSome.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasExprSome.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasExprSome.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -%mathpiper,def="HasExprSome" - -/// Same except only look at function arguments for functions in a given list -HasExprSome(_expr, _atom, _look'list) _ Equals(expr, atom) <-- True; -// an atom contains itself -15 # HasExprSome(expr_IsAtom, _atom, _look'list) <-- Equals(expr, atom); -// a list contains an atom if one element contains it -// we test for lists now because lists are also functions -// first take care of the empty list: -19 # HasExprSome({}, _atom, _look'list) <-- False; -20 # HasExprSome(expr_IsList, _atom, _look'list) <-- HasExprSome(First(expr), atom, look'list) Or HasExprSome(Rest(expr), atom, look'list); -// a function contains an atom if one of its arguments contains it -// first deal with functions that do not belong to the list: return False since we have already checked it at #15 -25 # HasExprSome(expr_IsFunction, _atom, _look'list)_(Not Contains(look'list, Atom(Type(expr)))) <-- False; -// a function contains an atom if one of its arguments contains it -30 # HasExprSome(expr_IsFunction, _atom, _look'list) <-- HasExprSome(Rest(Listify(expr)), atom, look'list); - -%/mathpiper - - - -%mathpiper_docs,name="HasExprSome",categories="User Functions;Predicates" -*CMD HasExprSome --- check for expression containing a subexpression -*STD -*CALL - HasExprSome(expr, x, list) - -*PARMS - -{expr} -- an expression - -{x} -- a subexpression to be found - -{list} -- list of function atoms to be considered "transparent" - -*DESC - -The command {HasExprSome} does the same as {HasExpr}, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain anything). - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> HasExprSome({a+b*2,c/d},c/d,{List}) - Out> True; - In> HasExprSome({a+b*2,c/d},c,{List}) - Out> False; - -*SEE HasExpr, HasExprArith, FuncList, VarList, HasFunc -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasFuncArith.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasFuncArith.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasFuncArith.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasFuncArith.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="HasFuncArith" - -/// Analyse arithmetic expressions - -HasFuncArith(expr, atom) := HasFuncSome(expr, atom, {Atom("+"), Atom("-"), *, /}); - -%/mathpiper - - - -%mathpiper_docs,name="HasFuncArith",categories="User Functions;Predicates" -*CMD HasFuncArith --- check for expression containing a function -*STD -*CALL - HasFuncArith(expr, func) - -*PARMS - -{expr} -- an expression - -{func} -- a function atom to be found - -*DESC - -{HasFuncArith} is defined through {HasFuncSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> HasFuncArith(x+y*Cos(Ln(x)/x), Cos) - Out> True; - In> HasFuncArith(x+y*Cos(Ln(x)/x), Ln) - Out> False; - -*SEE HasFunc, HasFuncSome, FuncList, VarList, HasExpr -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasFunc.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasFunc.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasFunc.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasFunc.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="HasFunc" - -/// HasFunc --- test for an expression containing a function -/// function name given as string. -10 # HasFunc(_expr, string_IsString) <-- HasFunc(expr, Atom(string)); -/// function given as atom. -// atom contains no functions -10 # HasFunc(expr_IsAtom, atom_IsAtom) <-- False; -// a list contains the function List so we test it together with functions -// a function contains itself, or maybe an argument contains it -20 # HasFunc(expr_IsFunction, atom_IsAtom) <-- Equals(First(Listify(expr)), atom) Or ListHasFunc(Rest(Listify(expr)), atom); - -%/mathpiper - - - -%mathpiper_docs,name="HasFunc",categories="User Functions;Predicates" -*CMD HasFunc --- check for expression containing a function -*STD -*CALL - HasFunc(expr, func) - -*PARMS - -{expr} -- an expression - -{func} -- a function atom to be found - -*DESC - -The command {HasFunc} returns {True} if the expression {expr} contains a function {func}. The expression is recursively traversed. - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> HasFunc(x+y*Cos(Ln(z)/z), Ln) - Out> True; - In> HasFunc(x+y*Cos(Ln(z)/z), Sin) - Out> False; - -*SEE HasFuncArith, HasFuncSome, FuncList, VarList, HasExpr -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasFuncSome.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasFuncSome.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/HasFuncSome.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/HasFuncSome.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -%mathpiper,def="HasFuncSome" - -/// function name given as string. -10 # HasFuncSome(_expr, string_IsString, _look'list) <-- HasFuncSome(expr, Atom(string), look'list); -/// function given as atom. -// atom contains no functions -10 # HasFuncSome(expr_IsAtom, atom_IsAtom, _look'list) <-- False; -// a list contains the function List so we test it together with functions -// a function contains itself, or maybe an argument contains it - -// first deal with functions that do not belong to the list: return top level function -15 # HasFuncSome(expr_IsFunction, atom_IsAtom, _look'list)_(Not Contains(look'list, Atom(Type(expr)))) <-- Equals(First(Listify(expr)), atom); -// function belongs to the list - check its arguments -20 # HasFuncSome(expr_IsFunction, atom_IsAtom, _look'list) <-- Equals(First(Listify(expr)), atom) Or ListHasFuncSome(Rest(Listify(expr)), atom, look'list); - -%/mathpiper - - - -%mathpiper_docs,name="HasFuncSome",categories="User Functions;Predicates" -*CMD HasFuncSome --- check for expression containing a function -*STD -*CALL - HasFuncSome(expr, func, list) - -*PARMS - -{expr} -- an expression - -{func} -- a function atom to be found - -{list} -- list of function atoms to be considered "transparent" - -*DESC - -The command {HasFuncSome} does the same thing as {HasFunc}, except it only looks at arguments of a given {list} of functions. Arguments of all other functions become "opaque" (as if they do not contain anything). - -Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {Atom("+")} to obtain the unevaluated atom "{+}". - -*E.G. - - In> HasFuncSome({a+b*2,c/d},/,{List}) - Out> True; - In> HasFuncSome({a+b*2,c/d},*,{List}) - Out> False; - -*SEE HasFunc, HasFuncArith, FuncList, VarList, HasExpr -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsBoolean.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsBoolean.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsBoolean.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsBoolean.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="IsBoolean" - -Function ("IsBoolean", {x}) - (x=True) Or (x=False) Or IsFunction(x) And Contains({"=", ">", "<", ">=", "<=", "!=", "And", "Not", "Or"}, Type(x)); - -%/mathpiper - - - -%mathpiper_docs,name="IsBoolean",categories="User Functions;Predicates" -*CMD IsBoolean --- test for a Boolean value -*STD -*CALL - IsBoolean(expression) - -*PARMS - -{expression} -- an expression - -*DESC - -IsBoolean returns True if the argument is of a boolean type. -This means it has to be either True, False, or an expression involving -functions that return a boolean result, e.g. -{=}, {>}, {<}, {>=}, {<=}, {!=}, {And}, {Not}, {Or}. - -*E.G. - - In> IsBoolean(a) - Out> False; - In> IsBoolean(True) - Out> True; - In> IsBoolean(a And b) - Out> True; - -*SEE True, False -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsBoolType.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsBoolType.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsBoolType.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsBoolType.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="IsBoolType" - -0 # IsBoolType(True) <-- True; -0 # IsBoolType(False) <-- True; -1 # IsBoolType(_anythingelse) <-- False; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsConstant.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsConstant.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsConstant.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsConstant.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="IsConstant" - -IsConstant(_n) <-- (VarList(n) = {}); - -%/mathpiper - - - -%mathpiper_docs,name="IsConstant",categories="User Functions;Predicates" -*CMD IsConstant --- test for a constant -*STD -*CALL - IsConstant(expr) - -*PARMS - -{expr} -- some expression - -*DESC - -{IsConstant} returns {True} if the -expression is some constant or a function with constant arguments. It -does this by checking that no variables are referenced in the -expression. {Pi} is considered a constant. - -*E.G. - - In> IsConstant(Cos(x)) - Out> False; - In> IsConstant(Cos(2)) - Out> True; - In> IsConstant(Cos(2+x)) - Out> False; - -*SEE IsNumber, IsInteger, VarList -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsDiagonal.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsDiagonal.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsDiagonal.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsDiagonal.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="IsDiagonal" - -IsDiagonal(A_IsMatrix) <-- -[ - Local(i,j,m,n,result); - m:=Length(A); - n:=Length(A[1]); - i:=2; - result:=(m=n); - While(i<=m And result) - [ - j:=1; - While(j<=n And result) - [ - result:= (i=j Or A[i][j] = 0); - j++; - ]; - i++; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="IsDiagonal",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsDiagonal --- test for a diagonal matrix -*STD -*CALL - IsDiagonal(A) - -*PARMS - -{A} -- a matrix - -*DESC - -{IsDiagonal(A)} returns {True} if {A} is a diagonal square matrix and {False} otherwise. - -*E.G. - In> IsDiagonal(Identity(5)) - Out> True; - In> IsDiagonal(HilbertMatrix(5)) - Out> False; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsEquation.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsEquation.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsEquation.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsEquation.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="IsEquation" - -Retract("IsEquation",*); - -10 # IsEquation(expr_IsAtom) <-- False; - -12 # IsEquation(_expr) <-- Listify(expr)[1] = == ; - -%/mathpiper - - - - -%mathpiper_docs,name="IsEquation",categories="User Functions;Predicates" - -*CMD IsEquation --- Return true if {expr} is an Equation, False otherwise - -*STD -*CALL - IsEquation(expr) - -*PARMS - -{expr} -- mathematical expression - -*DESC - -This function returns {True} if MathPiper can determine that the expression is an equation. -Otherwise, {False}. -Equations are defined by the property that they are of the form {a==b}. - -*E.G. - -In> IsEquation(x^2==4) - -Result: True - -In> IsEquation(x^2-4) - -Result: False - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsEvenFunction.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsEvenFunction.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsEvenFunction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsEvenFunction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -%mathpiper,def="IsEvenFunction" - -IsEvenFunction(f,x):= (f = Eval(Subst(x,-x)f)); - -%/mathpiper - - - -%mathpiper_docs,name="IsEvenFunction",categories="User Functions;Predicates" -*CMD IsEvenFunction --- Return true if function is an even function (False otherwise) - -*STD -*CALL - IsEvenFunction(expression,variable) - -*PARMS - -{expression} -- mathematical expression -{variable} -- variable - -*DESC - -This function returns True if MathPiper can determine that the -function is even. Even functions are -defined to be functions that have the property: - -$$ f(x) = f(-x) $$ - -{Cos(x)} is an example of an even function. - -As a side note, one can decompose a function into an -even and an odd part: - -$$ f(x) = f_even(x) + f_odd(x) $$ - -Where - -$$ f_even(x) = (f(x)+f(-x))/2 $$ - -and - -$$ f_odd(x) = (f(x)-f(-x))/2 $$ - -*E.G. - - In> IsEvenFunction(Cos(b*x),x) - Out> True - In> IsEvenFunction(Sin(b*x),x) - Out> False - In> IsEvenFunction(1/x^2,x) - Out> True - In> IsEvenFunction(1/x,x) - Out> False - -*SEE IsOddFunction, Sin, Cos -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsEven.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsEven.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsEven.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsEven.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsEven" - -IsEven(n) := IsInteger(n) And ( BitAnd(n,1) = 0 ); - -%/mathpiper - - - -%mathpiper_docs,name="IsEven",categories="User Functions;Predicates" -*CMD IsEven --- test for an even integer -*STD -*CALL - IsEven(n) - -*PARMS - -{n} -- integer to test - -*DESC - -This function tests whether the integer "n" is even. An integer is -even if it is divisible by two. Hence the even numbers are 0, 2, 4, 6, -8, 10, etc., and -2, -4, -6, -8, -10, etc. - -*E.G. - - In> IsEven(4); - Out> True; - In> IsEven(-1); - Out> False; - -*SEE IsOdd, IsInteger -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsHermitian.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsHermitian.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsHermitian.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsHermitian.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsHermitian" - -IsHermitian(A_IsMatrix) <-- (Conjugate(Transpose(A))=A); - -%/mathpiper - - - -%mathpiper_docs,name="IsHermitian",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsHermitian --- test for a Hermitian matrix -*STD -*CALL - IsHermitian(A) - -*PARMS - -{A} -- a square matrix - -*DESC - -IsHermitian(A) returns {True} if {A} is Hermitian and {False} -otherwise. $A$ is a Hermitian matrix iff Conjugate( Transpose $A$ )=$A$. -If $A$ is a real matrix, it must be symmetric to be Hermitian. - -*E.G. - - In> IsHermitian({{0,I},{-I,0}}) - Out> True; - In> IsHermitian({{0,I},{2,0}}) - Out> False; - -*SEE IsUnitary -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsIdempotent.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsIdempotent.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsIdempotent.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsIdempotent.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="IsIdempotent" - -IsIdempotent(A_IsMatrix) <-- (A^2 = A); - -%/mathpiper - - - -%mathpiper_docs,name="IsIdempotent",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsIdempotent --- test for an idempotent matrix -*STD -*CALL - IsIdempotent(A) - -*PARMS - -{A} -- a square matrix - -*DESC - -{IsIdempotent(A)} returns {True} if {A} is idempotent and {False} otherwise. -$A$ is idempotent iff $A^2=A$. Note that this also implies that $A$ raised -to any power is also equal to $A$. - -*E.G. - - In> IsIdempotent(ZeroMatrix(10,10)); - Out> True; - In> IsIdempotent(Identity(20)) - Out> True; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsInfinity.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsInfinity.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsInfinity.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsInfinity.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="IsInfinity" - -10 # IsInfinity(Infinity) <-- True; -10 # IsInfinity(-(_x)) <-- IsInfinity(x); - -// This is just one example, we probably need to extend this further to include all -// cases for f*Infinity where f can be guaranteed to not be zero -11 # IsInfinity(Sign(_x)*y_IsInfinity) <-- True; - -60000 # IsInfinity(_x) <-- False; - -%/mathpiper - - - -%mathpiper_docs,name="IsInfinity",categories="User Functions;Predicates" -*CMD IsInfinity --- test for an infinity -*STD -*CALL - IsInfinity(expr) - -*PARMS - -{expr} -- expression to test - -*DESC - -This function tests whether {expr} is an infinity. This is only the -case if {expr} is either {Infinity} or {-Infinity}. - -*E.G. - - In> IsInfinity(10^1000); - Out> False; - In> IsInfinity(-Infinity); - Out> True; - -*SEE Integer -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsLowerTriangular.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsLowerTriangular.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsLowerTriangular.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsLowerTriangular.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="IsLowerTriangular" - -IsLowerTriangular(A_IsMatrix) <-- (IsUpperTriangular(Transpose(A))); - -%/mathpiper - - - -%mathpiper_docs,name="IsLowerTriangular",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsLowerTriangular --- test for a lower triangular matrix -*STD -*CALL - IsLowerTriangular(A) - -*PARMS - -{A} -- a matrix - -*DESC - -A lower triangular matrix is a square matrix which has all zero entries below the diagonal. - -{IsLowerTriangular(A)} returns {True} if {A} is a lower triangular matrix and {False} otherwise. - -*E.G. - In> IsLowerTriangular(Identity(5)) - Out> True; - In> IsLowerTriangular({{1,2},{0,1}}) - Out> False; - -A non-square matrix cannot be triangular: - In> IsLowerTriangular({{1,2,3},{0,1,2}}) - Out> False; - -*SEE IsUpperTriangle, IsDiagonal -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNegativeInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNegativeInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNegativeInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNegativeInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsNegativeInteger" - -IsNegativeInteger(x):= IsInteger(x) And x < 0; - -%/mathpiper - - - -%mathpiper_docs,name="IsNegativeInteger",categories="User Functions;Predicates" -*CMD IsNegativeInteger --- test for a negative integer -*STD -*CALL - IsNegativeInteger(n) - -*PARMS - -{n} -- integer to test - -*DESC - -This function tests whether the integer {n} is (strictly) -negative. The negative integers are -1, -2, -3, -4, -5, etc. If -{n} is not a integer, the function returns {False}. - -*E.G. - - In> IsNegativeInteger(31); - Out> False; - In> IsNegativeInteger(-2); - Out> True; - -*SEE IsPositiveInteger, IsNonZeroInteger, IsNegativeNumber -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNegativeNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNegativeNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNegativeNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNegativeNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="IsNegativeNumber" - -IsNegativeNumber(x):= IsNumber(x) And x < 0; - -%/mathpiper - - - -%mathpiper_docs,name="IsNegativeNumber",categories="User Functions;Predicates" -*CMD IsNegativeNumber --- test for a negative number -*STD -*CALL - IsNegativeNumber(n) - -*PARMS - -{n} -- number to test - -*DESC - -{IsNegativeNumber(n)} evaluates to {True} if $n$ is (strictly) negative, i.e. -if $n<0$. If {n} is not a number, the functions return {False}. - -*E.G. - - In> IsNegativeNumber(6); - Out> False; - In> IsNegativeNumber(-2.5); - Out> True; - -*SEE IsNumber, IsPositiveNumber, IsNotZero, IsNegativeInteger, IsNegativeReal -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNegativeReal.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNegativeReal.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNegativeReal.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNegativeReal.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="IsNegativeReal" - -/* See if a number, when evaluated, would be a positive real value */ - -IsNegativeReal(_r) <-- -[ - r:=N(Eval(r)); - (IsNumber(r) And r <= 0); -]; - -%/mathpiper - - - -%mathpiper_docs,name="IsNegativeReal",categories="User Functions;Predicates" -*CMD IsNegativeReal --- test for a numerically negative value -*STD -*CALL - IsNegativeReal(expr) - -*PARMS - -{expr} -- expression to test - -*DESC - -This function tries to approximate {expr} numerically. It returns {True} if this approximation is negative. In case no -approximation can be found, the function returns {False}. Note that round-off errors may cause incorrect -results. - -*E.G. - - In> IsNegativeReal(Sin(1)-3/4); - Out> False; - In> IsNegativeReal(Sin(1)-6/7); - Out> True; - In> IsNegativeReal(Exp(x)); - Out> False; - -The last result is because {Exp(x)} cannot be -numerically approximated if {x} is not known. Hence -MathPiper can not determine the sign of this expression. - -*SEE IsPositiveReal, IsNegativeNumber, N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNonNegativeInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNonNegativeInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNonNegativeInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNonNegativeInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="IsNonNegativeInteger" - -IsNonNegativeInteger(x):= IsInteger(x) And x >= 0; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNonNegativeNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNonNegativeNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNonNegativeNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNonNegativeNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="IsNonNegativeNumber" - -IsNonNegativeNumber(x):= IsNumber(x) And x >= 0; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNonZeroInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNonZeroInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNonZeroInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNonZeroInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="IsNonZeroInteger" - -IsNonZeroInteger(x) := (IsInteger(x) And x != 0); - -%/mathpiper - - - -%mathpiper_docs,name="IsNonZeroInteger",categories="User Functions;Predicates" -*CMD IsNonZeroInteger --- test for a nonzero integer -*STD -*CALL - IsNonZeroInteger(n) - -*PARMS - -{n} -- integer to test - -*DESC - -This function tests whether the integer {n} is not zero. If {n} is -not an integer, the result is {False}. - -*E.G. - - In> IsNonZeroInteger(0) - Out> False; - In> IsNonZeroInteger(-2) - Out> True; - -*SEE IsPositiveInteger, IsNegativeInteger, IsNotZero -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNotZero.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNotZero.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNotZero.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNotZero.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="IsNotZero" - -/* -10 # IsNotZero(x_IsNumber) <-- ( RoundTo(x,BuiltinPrecisionGet()) != 0); -*/ - - -10 # IsNotZero(x_IsNumber) <-- ( AbsN(x) >= PowerN(10, -BuiltinPrecisionGet())); -10 # IsNotZero(x_IsInfinity) <-- True; -60000 # IsNotZero(_x) <-- False; - -%/mathpiper - - - -%mathpiper_docs,name="IsNotZero",categories="User Functions;Predicates" -*CMD IsNotZero --- test for a nonzero number -*STD -*CALL - IsNotZero(n) - -*PARMS - -{n} -- number to test - -*DESC - -{IsNotZero(n)} evaluates to {True} if {n} is not zero. In case {n} is not a -number, the function returns {False}. - -*E.G. - - In> IsNotZero(3.25); - Out> True; - In> IsNotZero(0); - Out> False; - -*SEE IsNumber, IsPositiveNumber, IsNegativeNumber, IsNonZeroInteger -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNumericList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNumericList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsNumericList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsNumericList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="IsNumericList" - -// check that all items in the list are numbers -IsNumericList(_arg'list) <-- IsList(arg'list) And - ("And" @ (MapSingle(Hold({{x},IsNumber(N(Eval(x)))}), arg'list))); - -%/mathpiper - - - -%mathpiper_docs,name="IsNumericList",categories="User Functions;Predicates" -*CMD IsNumericList --- test for a list of numbers -*STD -*CALL - IsNumericList({list}) - -*PARMS - -{{list}} -- a list - -*DESC -Returns {True} when called on a list of numbers or expressions that evaluate to numbers using {N()}. Returns {False} otherwise. - -*SEE N, IsNumber -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOddFunction.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOddFunction.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOddFunction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOddFunction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper,def="IsOddFunction" - -IsOddFunction(f,x):= (f = Eval(-Subst(x,-x)f)); - -%/mathpiper - - - -%mathpiper_docs,name="IsOddFunction",categories="User Functions;Predicates" -*CMD IsOddFunction --- Return true if function is an odd function (False otherwise) - -*STD -*CALL - IsOddFunction(expression,variable) - -*PARMS - -{expression} -- mathematical expression -{variable} -- variable - -*DESC - -This function returns True if MathPiper can determine that the -function is odd. Odd functions have the property: - -$$ f(x) = -f(-x) $$ - -{Sin(x)} is an example of an odd function. - -As a side note, one can decompose a function into an -even and an odd part: - -$$ f(x) = f_even(x) + f_odd(x) $$ - -Where - -$$ f_even(x) = (f(x)+f(-x))/2 $$ - -and - -$$ f_odd(x) = (f(x)-f(-x))/2 $$ - -*E.G. - - In> IsOddFunction(Cos(b*x),x) - Out> False - In> IsOddFunction(Sin(b*x),x) - Out> True - In> IsOddFunction(1/x,x) - Out> True - In> IsOddFunction(1/x^2,x) - Out> False - -*SEE IsEvenFunction, Sin, Cos -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOdd.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOdd.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOdd.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOdd.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsOdd" - -IsOdd(n) := IsInteger(n) And ( BitAnd(n,1) = 1 ); - -%/mathpiper - - - -%mathpiper_docs,name="IsOdd",categories="User Functions;Predicates" -*CMD IsOdd --- test for an odd integer -*STD -*CALL - IsOdd(n) - -*PARMS - -{n} -- integer to test - -*DESC - -This function tests whether the integer "n" is odd. An integer is -odd if it is not divisible by two. Hence the odd numbers are 1, 3, 5, -7, 9, etc., and -1, -3, -5, -7, -9, etc. - -*E.G. - - In> IsOdd(4); - Out> False; - In> IsOdd(-1); - Out> True; - -*SEE IsEven, IsInteger -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOne.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOne.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOne.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOne.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="IsOne",private="true" - -// why do we need this? Why doesn't x=1 not work? -10 # IsOne(x_IsNumber) <-- IsZero(SubtractN(x,1)); -60000 # IsOne(_x) <-- False; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOrthogonal.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOrthogonal.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsOrthogonal.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsOrthogonal.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="IsOrthogonal" - -IsOrthogonal(A_IsMatrix) <-- (Transpose(A)*A=Identity(Length(A))); - -%/mathpiper - - - -%mathpiper_docs,name="IsOrthogonal",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsOrthogonal --- test for an orthogonal matrix -*STD -*CALL - IsOrthogonal(A) - -*PARMS - -{A} -- square matrix - -*DESC - -{IsOrthogonal(A)} returns {True} if {A} is orthogonal and {False} -otherwise. $A$ is orthogonal iff $A$*Transpose($A$) = Identity, or -equivalently Inverse($A$) = Transpose($A$). - -*E.G. - - In> A := {{1,2,2},{2,1,-2},{-2,2,-1}}; - Out> {{1,2,2},{2,1,-2},{-2,2,-1}}; - In> PrettyForm(A/3) - - / \ - | / 1 \ / 2 \ / 2 \ | - | | - | | - | | - | | - | \ 3 / \ 3 / \ 3 / | - | | - | / 2 \ / 1 \ / -2 \ | - | | - | | - | | -- | | - | \ 3 / \ 3 / \ 3 / | - | | - | / -2 \ / 2 \ / -1 \ | - | | -- | | - | | -- | | - | \ 3 / \ 3 / \ 3 / | - \ / - Out> True; - In> IsOrthogonal(A/3) - Out> True; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPolynomialOverIntegers.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPolynomialOverIntegers.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPolynomialOverIntegers.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPolynomialOverIntegers.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -%mathpiper,def="IsPolynomialOverIntegers" - -Retract("IsPolynomialOverIntegers",*); - -10 # IsPolynomialOverIntegers(expr_IsFunction) <-- -[ - Local(x); - x := VarList(expr)[1]; - IsPolynomialOverIntegers(expr,x); -]; - -15 # IsPolynomialOverIntegers(_expr) <-- False; - - -10 # IsPolynomialOverIntegers(_expr,_var)_(CanBeUni(var,expr)) <-- -[ - If( AllSatisfy("IsInteger",Coef(expr,var,0 .. Degree(expr,var))), - True, - False - ); -]; - -15 # IsPolynomialOverIntegers(_expr,_var) <-- False; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - -%mathpiper_docs,name="IsPolynomialOverIntegers",categories="User Functions;Predicates" - -*CMD IsPolynomialOverIntegers --- Check if {expr} is a polynomial in variable {var} all of whose coefficients are integers - -*STD -*CALL - IsPolynomialOverIntegers(expr,var) - -*PARMS - -{expr} -- an algebraic expression which may be a polynomial - -{var} -- a variable name which might be used in {expr} - -*DESC - -The command {IsPolynomialOverIntegers} returns {True} if {expr} is a polynomial in {var} and all of its coefficients are integers. -It returns {False} if {expr} is not a polynomial in {var} or if any of its coefficients are not integers. - -This can be important, since many factoring theorems are applicable to such polynomials but not others. - -*E.G. - -In> IsPolynomialOverIntegers(2*x^3-3*x^2+5*x-14,x) -Result: True - -In> IsPolynomialOverIntegers(2.0*x^3-3*x^2+5*x-14,x) -Result: False - -In> IsPolynomialOverIntegers(y^2-4) -Result: True - NOTE: if variable name is omitted, a reasonable default is taken. - -In> IsPolynomialOverIntegers(x^2-a^2) -Result: False - NOTE: the unbound variable 'a' need not be an integer. - -%/mathpiper_docs - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPositiveInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPositiveInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPositiveInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPositiveInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="IsPositiveInteger" - -IsPositiveInteger(x):= IsInteger(x) And x > 0; - -%/mathpiper - - - -%mathpiper_docs,name="IsPositiveInteger",categories="User Functions;Predicates" -*CMD IsPositiveInteger --- test for a positive integer -*STD -*CALL - IsPositiveInteger(n) - -*PARMS - -{n} -- integer to test - -*DESC - -This function tests whether the integer {n} is (strictly) positive. The -positive integers are 1, 2, 3, 4, 5, etc. If {n} is not a integer, the -function returns {False}. - -*E.G. - - In> IsPositiveInteger(31); - Out> True; - In> IsPositiveInteger(-2); - Out> False; - -*SEE IsNegativeInteger, IsNonZeroInteger, IsPositiveNumber -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPositiveNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPositiveNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPositiveNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPositiveNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="IsPositiveNumber" - -IsPositiveNumber(x):= IsNumber(x) And x > 0; - -%/mathpiper - - - -%mathpiper_docs,name="IsPositiveNumber",categories="User Functions;Predicates" -*CMD IsPositiveNumber --- test for a positive number -*STD -*CALL - IsPositiveNumber(n) - -*PARMS - -{n} -- number to test - -*DESC - -{IsPositiveNumber(n)} evaluates to {True} if $n$ is (strictly) positive, i.e. -if $n>0$. If {n} is not a number the function returns {False}. - -*E.G. - - In> IsPositiveNumber(6); - Out> True; - In> IsPositiveNumber(-2.5); - Out> False; - -*SEE IsNumber, IsNegativeNumber, IsNotZero, IsPositiveInteger, IsPositiveReal -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPositiveReal.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPositiveReal.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsPositiveReal.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsPositiveReal.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="IsPositiveReal" - -/* See if a number, when evaluated, would be a positive real value */ -IsPositiveReal(_r) <-- -[ - r:=N(Eval(r)); - (IsNumber(r) And r >= 0); -]; - -%/mathpiper - - - -%mathpiper_docs,name="IsPositiveReal",categories="User Functions;Predicates" -*CMD IsPositiveReal --- test for a numerically positive value -*STD -*CALL - IsPositiveReal(expr) - -*PARMS - -{expr} -- expression to test - -*DESC - -This function tries to approximate "expr" numerically. It returns {True} if this approximation is positive. In case no -approximation can be found, the function returns {False}. Note that round-off errors may cause incorrect -results. - -*E.G. - - In> IsPositiveReal(Sin(1)-3/4); - Out> True; - In> IsPositiveReal(Sin(1)-6/7); - Out> False; - In> IsPositiveReal(Exp(x)); - Out> False; - -The last result is because {Exp(x)} cannot be -numerically approximated if {x} is not known. Hence -MathPiper can not determine the sign of this expression. - -*SEE IsNegativeReal, IsPositiveNumber, N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsRationalFunction.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsRationalFunction.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsRationalFunction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsRationalFunction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -%mathpiper,def="IsRationalFunction",scope="private" - -Retract("IsRationalFunction",*); - -10 # IsRationalFunction(_expr)_(Length(VarList(expr))=0) <-- False; - -15 # IsRationalFunction(_expr) <-- IsRationalFunction(expr,VarList(expr)[1]); - -10 # IsRationalFunction(expr_IsRationalOrNumber,_x) <-- False; - -15 # IsRationalFunction(_expr,_x)_(Type(expr)="/") <-- -[ - If( Contains(VarList(Numerator(expr)),x) Or Contains(VarList(Denominator(expr)),x), - True, - False - ); -]; - -60000 # IsRationalFunction(_expr,_x) <-- False; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - -%mathpiper_docs,name="IsRationalFunction",categories="Private Functions;Predicates" - -*CMD IsRationalFunction --- test for a Rational Function -*STD -*CALL - IsRationalFunction(expr) - IsRationalFunction(expr,var) - -*PARMS - -{expr} -- expression to test -{var} -- (optional) variable - -*DESC - -This function tests whether the expression {expr} is (strictly) a -Rational Function of the variable {var}. If {var} is omitted, the -test is made w.r.t. the first variable (if any) in VarList(expr). - -The strict definition of a"rational function" used here requires that -(a) the {expr} has Type(expr) = "/", and -(b) either the numerator or the denominator of {expr} contains {var}. - -Note that this definition neither requires nor implies that the -numerator and denominator be polynomials. - -*E.G. - - In> IsRationalFunction(3,x) - Out> False - In> IsRationalFunction(3) - Out> False; - In> IsRationalFunction(3.5,x) - Out> False - In> IsRationalFunction(3.5) - Out> False - In> IsRationalFunction(3/5,x) - Out> False - In> IsRationalFunction(3/5) - Out> False - In> IsRationalFunction(x,y) - Out> False - In> IsRationalFunction(x) - Out> False - In> IsRationalFunction(x/y,x) - Out> True - In> IsRationalFunction(x/y) - Out> True - In> IsRationalFunction(x/5,x) - Out> True - In> IsRationalFunction(x/5) - Out> True - In> IsRationalFunction(5/x,x) - Out> True - In> IsRationalFunction(5/x) - Out> True - In> IsRationalFunction(5/y,x) - Out> False - In> IsRationalFunction(5/y) - Out> True - In> IsRationalFunction(1-1/x,x) - Out> False - In> IsRationalFunction(1-1/x) - Out> False - -%/mathpiper_docs - - -%mathpiper,scope="nobuild",subtype="manual_test" - -Tell(1,IsRationalFunction(3,x)); -Tell(2,IsRationalFunction(3.5,x)); -Tell(3,IsRationalFunction(3/5,x)); -Tell(4,IsRationalFunction(x,y)); -Tell(5,IsRationalFunction(x/y,x)); -Tell(6,IsRationalFunction(x/5,x)); -Tell(7,IsRationalFunction(5/x,x)); -Tell(8,IsRationalFunction(5/y,x)); -Tell(9,IsRationalFunction(1-1/x,x)); -Tell(11,IsRationalFunction(3)); -Tell(12,IsRationalFunction(3.5)); -Tell(13,IsRationalFunction(3/5)); -Tell(14,IsRationalFunction(x)); -Tell(15,IsRationalFunction(x/y)); -Tell(16,IsRationalFunction(x/5)); -Tell(17,IsRationalFunction(5/x)); -Tell(18,IsRationalFunction(5/y)); -Tell(19,IsRationalFunction(1-1/x)); - -%/mathpiper - - - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsRational.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsRational.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsRational.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsRational.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -%mathpiper,def="IsRational" - -/* changed definition of IsRational, Nobbi 030529 -Function("IsRational",{aLeft}) Type(aLeft) = "/"; - -Function("IsRationalNumeric",{aLeft}) - Type(aLeft) = "/" And - IsNumber(aLeft[1]) And - IsNumber(aLeft[2]); - -IsRationalOrNumber(_x) <-- (IsNumber(x) Or IsRationalNumeric(x)); - -10 # IsRationalOrInteger(x_IsInteger) <-- True; -10 # IsRationalOrInteger(x_IsInteger / y_IsInteger) <-- True; -20 # IsRationalOrInteger(_x) <-- False; - -*/ - -10 # IsRational(x_IsInteger) <-- True; -10 # IsRational(x_IsInteger / y_IsInteger) <-- True; -10 # IsRational(-(x_IsInteger / y_IsInteger)) <-- True; -60000 # IsRational(_x) <-- False; - -%/mathpiper - - - -%mathpiper_docs,name="IsRational",categories="User Functions;Numbers (Predicates);Predicates" -*CMD IsRational --- test whether argument is a rational -*STD -*CALL - IsRational(expr) - -*PARMS - -{expr} -- expression to test - -*DESC - -This commands tests whether the expression "expr" is a rational -number, i.e. an integer or a fraction of integers. - -*E.G. - - In> IsRational(5) - Out> True; - In> IsRational(2/7) - Out> True; - In> IsRational(0.5) - Out> False; - In> IsRational(a/b) - Out> False; - In> IsRational(x + 1/x) - Out> False; - -*SEE Numerator, Denominator -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsRationalOrNumber.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsRationalOrNumber.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsRationalOrNumber.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsRationalOrNumber.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -%mathpiper,def="IsRationalOrNumber" - -10 # IsRationalOrNumber(x_IsNumber) <-- True; -10 # IsRationalOrNumber(x_IsNumber / y_IsNumber) <-- True; -10 # IsRationalOrNumber(-(x_IsNumber / y_IsNumber)) <-- True; -60000 # IsRationalOrNumber(_x) <-- False; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsSkewSymmetric.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsSkewSymmetric.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsSkewSymmetric.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsSkewSymmetric.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -%mathpiper,def="IsSkewSymmetric" - -IsSkewSymmetric(A_IsMatrix) <-- (Transpose(A)=(-1*A)); - -%/mathpiper - - - -%mathpiper_docs,name="IsSkewSymmetric",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsSkewSymmetric --- test for a skew-symmetric matrix -*STD -*CALL - IsSkewSymmetric(A) - -*PARMS - -{A} -- a square matrix - -*DESC - -{IsSkewSymmetric(A)} returns {True} if {A} is skew symmetric and {False} otherwise. -$A$ is skew symmetric iff $Transpose(A)$ =$-A$. - -*E.G. - - In> A := {{0,-1},{1,0}} - Out> {{0,-1},{1,0}}; - In> PrettyForm(%) - - / \ - | ( 0 ) ( -1 ) | - | | - | ( 1 ) ( 0 ) | - \ / - Out> True; - In> IsSkewSymmetric(A); - Out> True; - -*SEE IsSymmetric, IsHermitian -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsSumOfTerms.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsSumOfTerms.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsSumOfTerms.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsSumOfTerms.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -%mathpiper,def="IsSumOfTerms" - -// an expression free of the variable -- obviously not a sum of terms in it -10 # IsSumOfTerms(_var,expr_IsFreeOf(var)) <-- False; - -// an Atom cannot be a sum of terms -12 # IsSumOfTerms(_var,expr_IsAtom()) <-- False; - -// after being "Listified", expr is a sum of terms if headed by "+" or "-" -14 # IsSumOfTerms(_var,expr_IsList())_(expr[1]=Atom("+") Or expr[1]=Atom("-")) <-- True; - -// after being "Listified", an expr headed by "*" is not considered a sum -// of terms unless one or the other operand is free of the variable -16 # IsSumOfTerms(_var,expr_IsList())_(expr[1]=Atom("*")) <-- Or(IsFreeOf(var,expr[2]),IsFreeOf(var,expr[3])); - -// after being "Listified", an expr headed by "/" is not considered a sum -// of terms unless the denominator (only) is free of the variable -18 # IsSumOfTerms(_var,expr_IsList())_(expr[1]=Atom("/")) <-- IsFreeOf(var,expr[3]); - -// after being "Listified", any other expression is not a sum of terms -20 # IsSumOfTerms(_var,expr_IsList()) <-- False; - -// if we get to this point, Listify the expression and try again -22 # IsSumOfTerms(_var,_expr) <-- IsSumOfTerms(var,Listify(expr)); - -%/mathpiper - -%mathpiper_docs,name="IsSumOfTerms" -*CMD IsSumOfTerms --- check for expression being a sum of terms in variable - -*STD -*CALL - IsSumOfTerms(var,expr) - -*PARMS - -{var} -- a variable name - -{expr} -- an expression to be tested - -*DESC - -The command {IsSumOfTerms} returns {True} if the expression {expr} can be -considered to be a "sum of terms" in the given variable {var}. The criteria -are reasonable but somewhat arbitrary. The criteria were selected after -a lot of experimentation, specifically to aid the logic used in Integration. - -The criteria for {expr} to be a sum of terms in {var} are: - o {expr} is a function of variable {var} - o {expr} can best be described as a sum (or difference) of two or more - functions of {var} OR - {expr} is a monomial in {var} (this latter is to simplify the logic) - o {expr} is not better described as a product of functions of {var} - o {expr} is not better described as a quotient of functions of {var} - (i.e., is a rational function) - -Note that the last three criteria are somewhat subjective! - -*E.G. - - In> IsSumOfTerms(x,23) - Result> False - In> IsSumOfTerms(x,23*x) - Result> True - In> IsSumOfTerms(x,5*y) - Result> False - In> IsSumOfTerms(x,a*x^2-b*x-c/x) - Result> True - In> IsSumOfTerms(x,Sin(x)) - Result> False - In> IsSumOfTerms(x,Sin(x)+Exp(x)) - Result> True - In> IsSumOfTerms(x,d*(x^2-1)) - Result> True - In> IsSumOfTerms(x,(x^2-1)*d) - Result> True - In> IsSumOfTerms(x,(x^2-1)/d) - Result> True - In> IsSumOfTerms(x,d/(x^2-1)) - Result> False - In> IsSumOfTerms(x,(x^2-1)*(x^2+1)) - Result> False - In> IsSumOfTerms(x,(x^2-1)/(x^2+1)) - Result> False - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsSymmetric.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsSymmetric.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsSymmetric.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsSymmetric.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="IsSymmetric" - -IsSymmetric(A_IsMatrix) <-- (Transpose(A)=A); - -%/mathpiper - - - -%mathpiper_docs,name="IsSymmetric",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsSymmetric --- test for a symmetric matrix -*STD -*CALL - IsSymmetric(A) - -*PARMS - -{A} -- a matrix - -*DESC - -{IsSymmetric(A)} returns {True} if {A} is symmetric and {False} otherwise. -$A$ is symmetric iff Transpose ($A$) =$A$. - -*E.G. - - In> A := {{1,0,0,0,1},{0,2,0,0,0},{0,0,3,0,0}, - {0,0,0,4,0},{1,0,0,0,5}}; - In> PrettyForm(A) - - / \ - | ( 1 ) ( 0 ) ( 0 ) ( 0 ) ( 1 ) | - | | - | ( 0 ) ( 2 ) ( 0 ) ( 0 ) ( 0 ) | - | | - | ( 0 ) ( 0 ) ( 3 ) ( 0 ) ( 0 ) | - | | - | ( 0 ) ( 0 ) ( 0 ) ( 4 ) ( 0 ) | - | | - | ( 1 ) ( 0 ) ( 0 ) ( 0 ) ( 5 ) | - \ / - Out> True; - In> IsSymmetric(A) - Out> True; - - -*SEE IsHermitian, IsSkewSymmetric -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsUnitary.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsUnitary.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsUnitary.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsUnitary.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="IsUnitary" - -IsUnitary(A_IsMatrix) <-- (Transpose(Conjugate(A))*A = Identity(Length(A))); - -%/mathpiper - - - -%mathpiper_docs,name="IsUnitary",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsUnitary --- test for a unitary matrix -*STD -*CALL - IsUnitary(A) - -*PARMS - -{A} -- a square matrix - -*DESC - -This function tries to find out if A is unitary. - -A matrix $A$ is orthogonal iff $A^(-1)$ = Transpose( Conjugate($A$) ). This is -equivalent to the fact that the columns of $A$ build an orthonormal system -(with respect to the scalar product defined by {InProduct}). - -*E.G. - - In> IsUnitary({{0,I},{-I,0}}) - Out> True; - In> IsUnitary({{0,I},{2,0}}) - Out> False; - -*SEE IsHermitian, IsSymmetric -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsUpperTriangular.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsUpperTriangular.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsUpperTriangular.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsUpperTriangular.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="IsUpperTriangular" - -IsUpperTriangular(A_IsMatrix) <-- -[ - Local(i,j,m,n,result); - m:=Length(A); - n:=Length(A[1]); - i:=2; - result:=(m=n); - While(i<=m And result) - [ - j:=1; - While(j<=n And result) - [ - result:= (i<=j Or A[i][j] = 0); - j++; - ]; - i++; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="IsUpperTriangular",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsUpperTriangular --- test for an upper triangular matrix -*STD -*CALL - IsUpperTriangular(A) - -*PARMS - -{A} -- a matrix - -*DESC - -An upper triangular matrix is a square matrix which has all zero entries above the diagonal. - -{IsUpperTriangular(A)} returns {True} if {A} is an upper triangular matrix and {False} otherwise. - -*E.G. - In> IsUpperTriangular(Identity(5)) - Out> True; - In> IsUpperTriangular({{1,2},{0,1}}) - Out> True; - -A non-square matrix cannot be triangular: - In> IsUpperTriangular({{1,2,3},{0,1,2}}) - Out> False; - -*SEE IsLowerTriangle, IsDiagonal -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsVariable.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsVariable.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsVariable.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsVariable.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="IsVariable" - -IsVariable(_expr) <-- (IsAtom(expr) And Not(expr=Infinity) And Not(expr= -Infinity) And Not(expr=Undefined) And Not(IsNumber(N(Eval(expr))))); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsZero.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsZero.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/IsZero.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/IsZero.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="IsZero" - -//10 # IsZero(x_IsNumber) <-- (DivideN( Round( MultiplyN(x, 10^BuiltinPrecisionGet()) ), 10^BuiltinPrecisionGet() ) = 0); - -// these should be calls to MathSign() and the math library should do this. Or it should be just MathEquals(x,0). -// for now, avoid underflow and avoid IsZero(10^(-BuiltinPrecisionGet())) returning True. -10 # IsZero(x_IsNumber) <-- ( MathSign(x) = 0 Or AbsN(x) < PowerN(10, -BuiltinPrecisionGet())); -60000 # IsZero(_x) <-- False; - -//Note:tk:moved here from univariate.rep. -20 # IsZero(UniVariate(_var,_first,_coefs)) <-- IsZeroVector(coefs); - -%/mathpiper - - - -%mathpiper_docs,name="IsZero",categories="User Functions;Numbers (Predicates);Predicates" -*CMD IsZero --- test whether argument is zero -*STD -*CALL - IsZero(n) - -*PARMS - -{n} -- number to test - -*DESC - -{IsZero(n)} evaluates to {True} if -"n" is zero. In case "n" is not a number, the function returns -{False}. - -*E.G. - - In> IsZero(3.25) - Out> False; - In> IsZero(0) - Out> True; - In> IsZero(x) - Out> False; - -*SEE IsNumber, IsNotZero -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/ListHasFunc.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/ListHasFunc.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/ListHasFunc.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/ListHasFunc.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -%mathpiper,def="ListHasFunc" - -/// ListHasFunc --- test for one of the elements of a list to contain a function -/// this is mainly useful to test whether a list has nested lists, i.e. ListHasFunc({1,2,3}, List)=False and ListHasFunc({1,2,{3}}, List)=True. -// need to exclude the List atom itself, so don't use Listify -19 # ListHasFunc({}, _atom) <-- False; -20 # ListHasFunc(expr_IsList, atom_IsAtom) <-- HasFunc(First(expr), atom) Or ListHasFunc(Rest(expr), atom); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/ListHasFuncSome.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/ListHasFuncSome.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/ListHasFuncSome.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/ListHasFuncSome.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -%mathpiper,def="ListHasFuncSome",scope="private" - -19 # ListHasFuncSome({}, _atom, _look'list) <-- False; -20 # ListHasFuncSome(expr_IsList, atom_IsAtom, _look'list) <-- HasFuncSome(First(expr), atom, look'list) Or ListHasFuncSome(Rest(expr), atom, look'list); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/matrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/matrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/matrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/matrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,240 +0,0 @@ -%mathpiper,def="IsScalar;IsMatrix;IsVector;IsSquareMatrix" - -/* def file definitions -IsScalar -IsMatrix -IsVector -IsSquareMatrix -*/ - -LocalSymbols(p,x) -[ -// test for a scalar -Function("IsScalar",{x}) Not(IsList(x)); - - - -// test for a vector -Function("IsVector",{x}) - If(IsList(x), - Length(Select(IsList,x))=0, - False); - -// test for a vector w/ element test p -Function("IsVector",{p,x}) -[ - If(IsList(x), - [ - Local(i,n,result); - n:=Length(x); - i:=1; - result:=True; - While(i<=n And result) - [ - result:=Apply(p,{x[i]}); - i++; - ]; - result; - ], - False); -]; - -// test for a matrix (dr) -Function("IsMatrix",{x}) -If(IsList(x) And Length(x)>0, -[ - Local(n); - n:=Length(x); - If(Length(Select(IsVector,x))=n, - MapSingle(Length,x)=Length(x[1])+ZeroVector(n), - False); -], -False); - -// test for a matrix w/ element test p (dr) -Function("IsMatrix",{p,x}) -If(IsMatrix(x), -[ - Local(i,j,m,n,result); - m:=Length(x); - n:=Length(x[1]); - i:=1; - result:=True; - While(i<=m And result) - [ - j:=1; - While(j<=n And result) - [ - result:=Apply(p,{x[i][j]}); - j++; - ]; - i++; - ]; - result; -], -False); - -/* remove? (dr) -IsSquareMatrix(_x) <-- -[ - Local(d); - d:=Dimensions(x); - Length(d)=2 And d[1]=d[2]; -]; -*/ - -// test for a square matrix (dr) -Function("IsSquareMatrix",{x}) IsMatrix(x) And Length(x)=Length(x[1]); -// test for a square matrix w/ element test p (dr) -Function("IsSquareMatrix",{p,x}) IsMatrix(p,x) And Length(x)=Length(x[1]); - -]; // LocalSymbols(p,x) - -%/mathpiper - - - -%mathpiper_docs,name="IsScalar",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsScalar --- test for a scalar -*STD -*CALL - - IsScalar(expr) - -*PARMS - -{expr} -- a mathematical object - -*DESC - -{IsScalar} returns {True} if {expr} is a scalar, {False} otherwise. -Something is considered to be a scalar if it's not a list. - -*E.G. - In> IsScalar(7) - Out> True; - In> IsScalar(Sin(x)+x) - Out> True; - In> IsScalar({x,y}) - Out> False; - -*SEE IsList, IsVector, IsMatrix -%/mathpiper_docs - - - -%mathpiper_docs,name="IsVector",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsVector --- test for a vector -*STD -*CALL - - IsVector(expr) - - IsVector(pred,expr) - -*PARMS - -{expr} -- expression to test - -{pred} -- predicate test (e.g. IsNumber, IsInteger, ...) - -*DESC - -{IsVector(expr)} returns {True} if {expr} is a vector, {False} otherwise. -Something is considered to be a vector if it's a list of scalars. -{IsVector(pred,expr)} returns {True} if {expr} is a vector and if the -predicate test {pred} returns {True} when applied to every element of -the vector {expr}, {False} otherwise. - -*E.G. - In> IsVector({a,b,c}) - Out> True; - In> IsVector({a,{b},c}) - Out> False; - In> IsVector(IsInteger,{1,2,3}) - Out> True; - In> IsVector(IsInteger,{1,2.5,3}) - Out> False; - -*SEE IsList, IsScalar, IsMatrix -%/mathpiper_docs - - - -%mathpiper_docs,name="IsMatrix",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsMatrix --- test for a matrix -*STD -*CALL - IsMatrix(expr) - - IsMatrix(pred,expr) - -*PARMS - -{expr} -- expression to test - -{pred} -- predicate test (e.g. IsNumber, IsInteger, ...) - -*DESC - -{IsMatrix(expr)} returns {True} if {expr} is a matrix, {False} otherwise. -Something is considered to be a matrix if it's a list of vectors of equal -length. -{IsMatrix(pred,expr)} returns {True} if {expr} is a matrix and if the -predicate test {pred} returns {True} when applied to every element of -the matrix {expr}, {False} otherwise. - -*E.G. - - In> IsMatrix(1) - Out> False; - In> IsMatrix({1,2}) - Out> False; - In> IsMatrix({{1,2},{3,4}}) - Out> True; - In> IsMatrix(IsRational,{{1,2},{3,4}}) - Out> False; - In> IsMatrix(IsRational,{{1/2,2/3},{3/4,4/5}}) - Out> True; - -*SEE IsList, IsVector -%/mathpiper_docs - - - -%mathpiper_docs,name="IsSquareMatrix",categories="User Functions;Matrices (Predicates);Predicates" -*CMD IsSquareMatrix --- test for a square matrix -*STD -*CALL - IsSquareMatrix(expr) - - IsSquareMatrix(pred,expr) - -*PARMS - -{expr} -- expression to test - -{pred} -- predicate test (e.g. IsNumber, IsInteger, ...) - -*DESC - -{IsSquareMatrix(expr)} returns {True} if {expr} is a square matrix, -{False} otherwise. Something is considered to be a square matrix if -it's a matrix having the same number of rows and columns. -{IsMatrix(pred,expr)} returns {True} if {expr} is a square matrix and -if the predicate test {pred} returns {True} when applied to every -element of the matrix {expr}, {False} otherwise. - -*E.G. - - In> IsSquareMatrix({{1,2},{3,4}}); - Out> True; - In> IsSquareMatrix({{1,2,3},{4,5,6}}); - Out> False; - In> IsSquareMatrix(IsBoolean,{{1,2},{3,4}}); - Out> False; - In> IsSquareMatrix(IsBoolean,{{True,False},{False,True}}); - Out> True; - -*SEE IsMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/NoneSatisfy.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/NoneSatisfy.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/predicates/NoneSatisfy.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/predicates/NoneSatisfy.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -%mathpiper,def="NoneSatisfy" - -10 # NoneSatisfy(pred_IsString,lst_IsList) <-- Not Apply("Or",(MapSingle(pred,lst))); - -20 # NoneSatisfy(_pred,_lst) <-- True; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - -%mathpiper_docs,name="NoneSatisfy",categories="User Functions;Predicates" - -*CMD NoneSatisfy --- Check if NO element of list {lst} satisfies predicate {pred} - -*STD -*CALL - NoneSatisfy(pred,lst) - -*PARMS - -{pred} -- the name of the predicate (as string, with quotes) to be tested - -{lst} -- a list - -*DESC - -The command {NoneSatisfy} returns {True} if NO element of the list {lst} satisfies the predicate {pred}. -It returns {False} if at least one element of the list satisfies the predicate. -It also returns {True} if {lst} is not a list, or if {pred} is not a predicate. - -*E.G. - - In> NoneSatisfy("IsNegativeInteger",{1,0,5}) - Result: True - In> NoneSatisfy("IsPositiveInteger",{-1,0,5}) - Result: False - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/probability/CumulativeDistributionFunction.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/probability/CumulativeDistributionFunction.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/probability/CumulativeDistributionFunction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/probability/CumulativeDistributionFunction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -%mathpiper,def="CumulativeDistributionFunction" - -/* Evaluates distribution dst at point x - known distributions are: - 1. Discrete distributions - -- BernoulliDistribution(p) - -- BinomialDistribution(p,n) - -- DiscreteUniformDistribution(a,b) - -- PoissonDistribution(l) - -- HypergeometricDistribution(N, M) - 2. Continuous distributions - -- ExponentialDistribution(l) - -- NormalDistrobution(a,s) - -- ContinuousUniformDistribution(a,b) - -- tDistribution(m) - -- GammaDistribution(m) - -- ChiSquareDistribution(m) - - DiscreteDistribution(domain,probabilities) represent arbitrary - distribution with finite number of possible values; domain list - contains possible values such that - Pr(X=domain[i])=probabilities[i]. - TODO: Should domain contain numbers only? -*/ - - -/* Evaluates Cumulative probability function CumulativeDistributionFunction(x)=Pr(X0 And x<=1, p,1)); -11 # CumulativeDistributionFunction(BernoulliDistribution(_p), _x) <-- Hold(If(x<=0,0,If(x>0 And x<=1, p,1))); - -10 # CumulativeDistributionFunction(BinomialDistribution(_p,_n),m_IsNumber)_(m<0) <-- 0; -10 # CumulativeDistributionFunction(BinomialDistribution(_p,n_IsInteger),m_IsNumber)_(m>n) <-- 1; -10 # CumulativeDistributionFunction(BinomialDistribution(_p,_n),_m) <-- Sum @ { i, 0, Floor(m), ProbabilityDensityFunction(BinomialDistribution(p,n),i)}; - -10 # CumulativeDistributionFunction(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(x<=a) <-- 0; -10 # CumulativeDistributionFunction(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(x>b) <-- 1; -10 # CumulativeDistributionFunction(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(ab, 0 ,1/(b-a+1)); -11 # ProbabilityDensityFunction(DiscreteUniformDistribution(_a,_b), _x) <-- Hold(If(xb, 0 ,1/(b-a+1))); - -10 # ProbabilityDensityFunction(PoissonDistribution(_l), n_IsNumber) <-- If(n<0,0,Exp(-l)*l^n/n!); -11 # ProbabilityDensityFunction(PoissonDistribution(_l),_n) <-- Exp(-l)*l^n/n!; - -10 # ProbabilityDensityFunction(GeometricDistribution(_p),_n) <--If(n<0,0,p*(1-p)^n); - -10 # ProbabilityDensityFunction(ExponentialDistribution(_l), _x) <-- If(x<0,0,l*Exp(-l*x)); - -10 # ProbabilityDensityFunction(NormalDistribution(_m,_s),_x) <-- Exp(-(x-m)^2/(2*s))/Sqrt(2*Pi*s); - -10 # ProbabilityDensityFunction(ContinuousUniformDistribution(_a,_b),x)_(ab,0,1/(b-a)); - -10 # ProbabilityDensityFunction(DiscreteDistribution( dom_IsList, prob_IsList), _x)_( Length(dom)=Length(prob) And Simplify(Add(prob))=1) <-- - [ - Local(i); - i:=Find(dom,x); - If(i = -1,0,prob[i]); - ]; -10 # ProbabilityDensityFunction( ChiSquareDistribution( _m),x_IsRationalOrNumber)_(x<=0) <-- 0; -20 # ProbabilityDensityFunction( ChiSquareDistribution( _m),_x) <-- x^(m/2-1)*Exp(-x/2)/2^(m/2)/Gamma(m/2); - -10 # ProbabilityDensityFunction(tDistribution(_m),x) <-- Gamma((m+1)/2)*(1+x^2/m)^(-(m+1)/2)/Gamma(m/2)/Sqrt(Pi*m); - -10 # ProbabilityDensityFunction(HypergeometricDistribution( N_IsNumber, M_IsNumber, n_IsNumber), x_IsNumber)_(M <= N And n <= N) <-- (BinomialCoefficient(M,x) * BinomialCoefficient(N-M, n-x))/BinomialCoefficient(N,n); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - -%mathpiper_docs,name="ProbabilityDensityFunction",categories="User Functions;Statistics & Probability" -*CMD ProbabilityDensityFunction --- probability density function -*STD -*CALL - ProbabilityDensityFunction(dist,x) - -*PARMS -{dist} -- a distribution type - -{x} -- a value of random variable - -*DESC -If {dist} is a discrete distribution, then {ProbabilityDensityFunction} returns the -probability for a random variable with distribution {dist} to take a -value of {x}. If {dist} is a continuous distribution, then {ProbabilityDensityFunction} -returns the density function at point $x$. - -*SEE CumulativeDistributionFunction, Expectation -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/equations/ManipEquations.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/equations/ManipEquations.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/equations/ManipEquations.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/equations/ManipEquations.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,189 +0,0 @@ -%mathpiper - -Use("org/mathpiper/assembledscripts/proposed.rep/equations.mpi"); - -Retract("IsEquation",*); - -Retract("*==",*); -Retract("/==",*); -Retract("+==",*); -Retract("-==",*); -Retract("==+",*); -Retract("==-",*); - -10 # IsEquation(expr_IsAtom) <-- False; -12 # IsEquation(_expr) <-- -[ - Local(EL,res); - EL := Listify(expr); - res := (EL[1] = == ); -]; - -10 # *==(_num,eqn_IsEquation) <-- -[ - Local(EL,LHS,RHS); - EL := Listify(eqn); - LHS := Expand(Simplify( num * EL[2] )); - RHS := Expand(Simplify( num * EL[3] )); - LHS == RHS; -]; - -10 # *==(eqn_IsEquation,_num) <-- -[ - Local(EL,LHS,RHS); - EL := Listify(eqn); - LHS := Expand(Simplify( num * EL[2] )); - RHS := Expand(Simplify( num * EL[3] )); - LHS == RHS; -]; - -10 # /==(eqn_IsEquation,_num) <-- -[ - Local(EL,LHS,RHS); - EL := Listify(eqn); - LHS := Expand(Simplify( EL[2] / num )); - RHS := Expand(Simplify( EL[3] / num )); - LHS == RHS; -]; - -10 # +==(_num,eqn_IsEquation) <-- -[ - Local(EL,LHS,RHS); - EL := Listify(eqn); - LHS := Expand(Simplify( EL[2] + num )); - RHS := Expand(Simplify( EL[3] + num )); - LHS == RHS; -]; - -10 # +==(eqn_IsEquation,_num) <-- -[ - Local(EL,LHS,RHS); - EL := Listify(eqn); - LHS := Expand(Simplify( EL[2] + num )); - RHS := Expand(Simplify( EL[3] + num )); - LHS == RHS; -]; - -10 # -==(eqn_IsEquation,_num) <-- -[ - Local(EL,LHS,RHS); - EL := Listify(eqn); - LHS := Expand(Simplify( EL[2] - num )); - RHS := Expand(Simplify( EL[3] - num )); - LHS == RHS; -]; - -10 # -==(_num,eqn_IsEquation) <-- -[ - Local(EL,LHS,RHS); - EL := Listify(eqn); - LHS := Expand(Simplify( num - EL[2] )); - RHS := Expand(Simplify( num - EL[3] )); - LHS == RHS; -]; - -12 # ==+(eqn1_IsEquation,eqn2_IsEquation) <-- -[ - Local(EL1,LHS,RHS,EL2); - EL1 := Listify(eqn1); - EL2 := Listify(eqn2); - LHS := Expand(Simplify( EL1[2] + EL2[2] )); - RHS := Expand(Simplify( EL1[3] + EL2[3] )); - LHS == RHS; -]; - -12 # ==-(eqn1_IsEquation,eqn2_IsEquation) <-- -[ - Local(EL1,LHS,RHS,EL2); - EL1 := Listify(eqn1); - EL2 := Listify(eqn2); - LHS := Expand(Simplify( EL1[2] - EL2[2] )); - RHS := Expand(Simplify( EL1[3] - EL2[3] )); - LHS == RHS; -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - -/////////////////////////////////////////////////////////////////////////////// - -%mathpiper,scope="nobuild",subtype="manual_test" - -Clear(eqns,eq1,eq2,eq3,eq5,eq6,eq7,X,Y,solution); - -/* Wade & Taylor, page 222, Example 2 */ -// Solve the pair of equations -// 2*x + 3*y == 7 -// 3*x - 2*y == 4 - -eqns := { 2*x+3*y==7, 3*x-2*y==4 }; -Tell(0,eqns); -NewLine(); - -// multiply each side of eqns[1] by 2: -eq1 := *==(2,eqns[1]); -// multiply each side of eqns[2] by 3: -eq2 := *==(3,eqns[2]); -Tell(1,eq1); -Tell(2,eq2); -NewLine(); -// add the two equations together -eq3 := ==+(eq1,eq2); -Tell(Eq2+Eq3,eq3); -// solve eq3 for x -X := Solve(eq3,x); -Tell(4,X); -NewLine(); - -// now multiply each side of eqns[1] by 3: -eq5 := *==(3,eqns[1]); -// multiply each side of eqns[2] by 2: -eq6 := *==(2,eqns[2]); -Tell(5,eq5); -Tell(6,eq6); -NewLine(); -// subtract eq6 from eq5 -eq7 := ==-(eq5,eq6); -Tell(Eq5-Eq6,eq7); -// solve eq7 for y -Y := Solve(eq7,y); -Tell(8,Y); -NewLine(); - -solution := {X,Y}; -Tell(9,solution); - - -%/mathpiper - - %output,preserve="false" - Result: True - - Side effects: - << 0 >> eqns {2*x+3*y==7,3*x-2*y==4} - - << 1 >> eq1 4*x+6*y==14 - << 2 >> eq2 9*x-6*y==12 - - << Eq2+Eq3 >> eq3 13*x==26 - << 4 >> X {x==2} - - << 5 >> eq5 6*x+9*y==21 - << 6 >> eq6 6*x-4*y==8 - - << Eq5-Eq6 >> eq7 13*y==13 - << 8 >> Y {y==1} - - << 9 >> solution {{x==2},{y==1}} -. %/output - - - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/equations/Manipulate.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/equations/Manipulate.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/equations/Manipulate.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/equations/Manipulate.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper - -Use("org/mathpiper/assembledscripts/proposed.rep/equations.mpi"); - -Retract("Manipulate",*); - -RuleBase("Manipulate",{symbolicEquation}); -HoldArg("Manipulate",symbolicEquation); -10 # Manipulate(_symbolicEquation)_HasFunc(Eval(symbolicEquation), "==") <-- -[ - Local(listForm, operator, operand, left, right, leftManipulated, rightManipulated, operandIndex, equationIndex, leftOrder, rightOrder); - - listForm := Listify(symbolicEquation); - - operator := listForm[1]; - - If(HasFunc(Eval(listForm[2]),"==" ), [operandIndex := 3; equationIndex := 2; ], [ operandIndex := 2; equationIndex := 3;]); - - operand := listForm[operandIndex]; - equation := Eval(listForm[equationIndex]); - left := EquLeft(equation); - right := EquRight(equation); - - If(operandIndex = 3, [ leftOrder := `({left,operand});rightOrder := `({right,operand});], [leftOrder := `({operand,left}); rightOrder := `({operand,right});]); - - - leftManipulated := ExpandBrackets(Simplify(Apply(String(operator), leftOrder))); - rightManipulated := ExpandBrackets(Simplify(Apply(String(operator), rightOrder))); - - leftManipulated == rightManipulated; - -]; - -%/mathpiper - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -Clear(equ,a); - -equ := y == m*x+b; -Tell(1, Manipulate(2*equ)); -Tell(2, Manipulate(equ*2)); -Tell(3, Manipulate(2/equ)); -Tell(4, Manipulate(equ/2)); -Tell(5, Manipulate(equ^2)); - -equ := Sqrt(a) == 3; -Tell(6, Manipulate(equ^2)); - -%/mathpiper - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/equations/SolveSetEqns.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/equations/SolveSetEqns.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/equations/SolveSetEqns.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/equations/SolveSetEqns.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,186 +0,0 @@ -%mathpiper - -Use("org/mathpiper/assembledscripts/proposed.rep/equations.mpi"); - -Retract("SolveLinearSysViaMatrix",*); - -Retract("SolveLinearSystemViaGauss",*); - -Retract("CheckEquationSolution",*); - - - -10 # SolveLinearSysViaMatrix( eqns_IsList, vars_IsList ) <-- -[ - /*** NOTE: This function appears to be fully functional, and */ - /*** gives correct answers, but */ - /*** needs some more work to get answers into desired form */ - - Local(LE,LV,E,LHS,X,M,RHS,LL,eqn,row,ans,Det); - If(InVerboseMode(),Tell(SolveLinearSysViaMatrix,{eqns,vars})); - LE := Length(eqns); - LV := Length(vars); - E := Assert() LE=LV; - Check(E,"Number of equations != Number of variables"); - - LHS := {}; - RHS := {}; - X := vars; - M := FillList(1,LE); - ForEach(eqn,eqns) - [ - E := Listify(eqn); - LL := E[2]; - RHS := E[3]:RHS; - row := Map("Coef",{FillList(LL,LE),X,M}); - LHS := row:LHS; - ]; - LHS := DestructiveReverse(LHS); - RHS := DestructiveReverse(RHS); - Det := Determinant(LHS); - //Tell(det,Det); - - ans :=MatrixSolve(LHS,RHS); -]; - -12 # SolveLinearSysViaMatrix( _eqns, _vars ) <-- False; - - - - -10 # SolveLinearSystemViaGauss( eqns_IsList, vars_IsList ) <-- -[ - /***** WARNING: This version is valid for TWO equations only *****/ - - Local(LE,LV,E,E2,s,s1,s2,s3,ans); - If(InVerboseMode(),Tell(SolveLinearSysViaGauss,{eqns,vars})); - LE := Length(eqns); - LV := Length(vars); - E := Assert() LE=LV; - Check(E,"Number of equations != Number of variables"); - - If(InVerboseMode(),Tell(0,{LE,LV,E})); - s := Solve( eqns, vars )[1]; - If(InVerboseMode(),Tell(1,s)); - s1 := s[1]; - s2 := s[2]; - s3 := s[3]; - E2 := Listify(s3); - s2 := (s2 Where s3); - s1 := (s1 Where s2 And s3); - If( E2[2]=E2[3], ans:=Inconsistent-Set, ans:=List(s1,s2,s3)); - ans; -]; - -12 # SolveLinearSystemViaGauss( _eqns, _vars ) <-- False; - - - - -10 # CheckEquationSolution( eqn_IsEquation, soln_IsList ) <-- -[ - Local(EL,LHS,RHS,L,svar,sval); - If(InVerboseMode(),Tell(CheckOneEq,{eqn,soln})); - EL := Listify(eqn); - LHS := Expand(Simplify( EL[2] )); - RHS := Expand(Simplify( EL[3] )); - L := Listify(soln[1]); - svar := L[2]; - sval := L[3]; - If( InVerboseMode(), [Tell(2,{LHS,RHS}); Tell(3,{svar,sval});]); - V := Eliminate(svar,sval,LHS); - If(InVerboseMode(),Tell(4,V)); - V = RHS; -]; - -12 # CheckEquationSolution( eqns_IsList, solns_IsList ) <-- -[ - Tell(CheckSetOfEqns,{eqns,solns}); - Check(False,"Not implemented yet"); -]; - -14 # CheckEquationSolution( _eq, _soln ) <-- -[ - Tell(CheckEqnLeftovers,{eq,soln}); - False; -]; - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - -/////////////////////////////////////////////////////////////////////////////// - -%mathpiper,scope="nobuild",subtype="manual_test" - -Clear(eqns1,eqns2,eqns3,eqns4,eqns5,solution); - -// --- Test the new solver for sets of linear equations --- - -NewLine(); - -eqns1 := {2*x-2*y+z==(-7),3*x+y+2*z==(-2),5*x+3*y-3*z==(-7)}; // 3 eqns, 3 unknowns -Tell(Independent,eqns1); -solution := SolveLinearSysViaMatrix(eqns1,{x,y,z}); -Tell(11,solution); -NewLine(); - -eqns2 := {3*x-2*y+z==1,x-y-z==2,6*x-4*y+2*z==3}; // 3 eqns, 3 unks, inconsistent -Tell(Inconsistent,eqns2); -solution := SolveLinearSysViaMatrix(eqns2,{x,y,z}); -Tell(13,solution); -NewLine(); - -eqns3 := {2*x+3*y==12,3*x+2*y==12}; // 2 eqns, 2 unknown, independent -Tell(Independent,eqns3); -solution := SolveLinearSysViaMatrix(eqns3,{x,y}); -Tell(15,solution); -NewLine(); - -eqns4 := {2*x+3*y==6,4*x+6*y==12}; // 2 eqns, 2 unknowns, dependent -Tell(Dependent,eqns4); -solution := SolveLinearSysViaMatrix(eqns4,{x,y}); -Tell(17,solution); -NewLine(); - -eqns5 := {2*x+3*y==6,2*x+3*y==8}; // 2 eqns, 2 unknowns, parallel (inconsistent) -Tell(Inconsistent,eqns5); -solution := SolveLinearSysViaMatrix(eqns5,{x,y}); -Tell(19,solution); -NewLine(); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side effects: - << Independent >> eqns1 {2*x-2*y+z==(-7),3*x+y+2*z==(-2),5*x+3*y-3*z==(-7)} - << det >> Det -52 - << 11 >> solution {-2,2,1} - - << Inconsistent >> eqns2 {3*x-2*y+z==1,x-y-z==2,6*x-4*y+2*z==3} - << det >> Det 0 - << 13 >> solution {Undefined,Infinity,Infinity} - - << Independent >> eqns3 {2*x+3*y==12,3*x+2*y==12} - << det >> Det -5 - << 15 >> solution {12/5,12/5} - - << Dependent >> eqns4 {2*x+3*y==6,4*x+6*y==12} - << det >> Det 0 - << 17 >> solution {Undefined,Undefined} - - << Inconsistent >> eqns5 {2*x+3*y==6,2*x+3*y==8} - << det >> Det 0 - << 19 >> solution {Infinity,Infinity} -. %/output - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraHistogram.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraHistogram.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraHistogram.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraHistogram.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -%mathpiper - -GeoGebraHistogram(classBoundaries, data) := -[ - Local(command); - //todo:tk: a check must be made to make sure that all data items fit into the class boundaries. - // If they don't, GeoGebra will not accept them. - - command := PatchString("Histogram[,]"); - JavaCall(geogebra, "evalCommand", command); -]; - - - - -GeoGebraHistogram(data) := -[ - Local(command, classBoundaries, noDuplicatesSorted, largestValue, smallestValue, x, numberOfUniqueValues); - - noDuplicatesSorted := HeapSort(RemoveDuplicates(data), "<" ); - - smallestValue := Floor(noDuplicatesSorted[1]); - - numberOfUniqueValues := Length(noDuplicatesSorted); - - largestValue := Ceil(noDuplicatesSorted[Length(noDuplicatesSorted)]); - - classBoundaries := N(Table(x,x,smallestValue-.5,largestValue+.5,1)); - - command := PatchString("Histogram[,]"); - JavaCall(geogebra, "evalCommand", command); -]; - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -GeoGebraHistogram({1, 2, 3, 4}, {1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}); - -%/mathpiper - - %output,preserve="false" - Result: java.lang.Boolean -. %/output - - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -GeoGebraHistogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}); - -%/mathpiper - - %output,preserve="false" - Result: java.lang.Boolean -. %/output - - -%mathpiper,scope="nobuild",subtype="manual_test" - -GeoGebraHistogram(N({16+3/8, 16+3/8, 17+1/8, 16, 14+3/8, 17+1/4, 16+5/8, 16, 17, 17+1/4, 17, 15+7/8, 16+5/8, 16+1/8, 17+1/8, 16+7/8, 16+3/8, 16+3/8, 16+7/8, 17+1/8, 17, 16+3/4, 17+1/4, 17+1/8, 15+3/8})); - -%/mathpiper - - %output,preserve="false" - Result: true -. %/output - - - -%mathpiper,scope="nobuild",subtype="manual_test" -classBoundaries := N(Table(x,x,14,20,1/4)); - -E := N({16+3/8, 16+3/8, 17+1/8, 16, 14+3/8, 17+1/4, 16+5/8, 16, 17, 17+1/4, 17, 15+7/8, 16+5/8, 16+1/8, 17+1/8, 16+7/8, 16+3/8, 16+3/8, 16+7/8, 17+1/8, 17, 16+3/4, 17+1/4, 17+1/8, 15+3/8}); - -D := N({18+1/4, 19+1/4, 18+1/4, 15+5/8, 17+5/8, 17+1/2, 17+1/8, 17+1/8, 17+1/2, 14+1/2, 17+3/8, 16+7/8, 17+3/4, 18+7/8, 14+7/8, 19+1/4, 18+1/8, 16+1/4, 16+1/8, 16+3/4, 17+1/4, 17+3/8, 17+1/8, 17+1/2, 16+5/8}); - -GeoGebraHistogram(classBoundaries,Concat(D,E)); - -%/mathpiper - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebra.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebra.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebra.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebra.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="GeoGebra",scope="private" - -Retract("GeoGebra",*); - -LocalSymbols(options) -[ - options := {}; - - Local(updateObjects); - - updateObjects := ""; - - options["updateObjects"] := updateObjects; - - - -GeoGebra() := options; - - -GeoGebra(list) := (options := list); - - - -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -Use("org/mathpiper/assembledscripts/proposed.rep/geogebra.mpi"); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPlot.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPlot.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPlot.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPlot.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -%mathpiper,def="GeoGebraPlot",scope="private" -Retract("GeoGebraPlot",*); - -RuleBaseListed("GeoGebraPlot",{arg1,arg2}); - - - -5 # GeoGebraPlot(_arg1) <-- GeoGebraPlot(arg1,{}); //Handle single argument call. - - -20 # GeoGebraPlot(function_IsFunction, options_IsList)_(Not IsList(function)) <-- -[ - Local(command); - - function := (Subst(==,=) function); - - command := ConcatStrings(ToString()Write(function)); - - JavaCall(geogebra,"evalCommand",command); -]; - - - - -10 # GeoGebraPlot(list_IsList, _options)_(IsEven(Length(list)And IsNumericList(list)) ) <-- -[ - If(IsList(options), options := OptionListToAssociativeList(options), options := OptionListToAssociativeList({options})); - - Local(length, index, labelIndex, pointTemplate, segmentCommandTemplate, segmentElementTemplate, command, code, x, y); - - length := Length(list); - - index := 1; - - labelIndex := 1; - - pointTemplate := "\"> \" y=\"\" z=\"1.0\"/> "; - segmentCommandTemplate := ""; - segmentElementTemplate := "\">"; - - - //todo:tk: this does not seem to be working JavaCall(geogebra, "setRepaintingActive", "false"); - - While(index < length+1) - [ - x := list[index]; - index++; - y := list[index]; - index++; - - - code := PatchString(pointTemplate); - JavaCall(geogebra,"evalXML",code); - - If(options["lines"] = "True" And labelIndex > 1, - [ - - command := PatchString("a = Segment[A,A]"); - JavaCall(geogebra, "evalCommand", command); - - - code := PatchString(segmentElementTemplate); - JavaCall(geogebra,"evalXML",code); - ] - ); - - labelIndex++; - ]; //end while. - - //todo:tk: this does not seem to be working JavaCall(geogebra, "setRepaintingActive", "true"); - -]; - - -5 # GeoGebraPlot(list_IsList, _options)_(IsMatrix(IsInteger,list)) <-- -[ - Local(flatList); - - flatList := {}; - - ForEach(subList,list) - [ - DestructiveAppend(flatList,subList[1]); - DestructiveAppend(flatList, subList[2]); - ]; - - GeoGebraPlot(flatList, options); - -]; - -//HoldArg("GeoGebraPlot",arg2); - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - - -%mathpiper,title="",scope="nobuild",subtype="manual_test" - -GeoGebraPlot({1,1,2,2,3,3,4,4,5,5,6,6}, lines -> True); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - -%mathpiper,title="",scope="nobuild",subtype="manual_test" - -GeoGebraPlot({{0,0}, {0,-1},{0,-2},{1,-2},{1,-1},{2,-1},{3,-1},{4,-1},{4,-2},{5,-2},{6,-2},{6,-1},{6,-2},{7,-2},{7,-1},{8,-1},{8,0},{8,-1},{9,-1},{8,-1},{7,-1}},lines -> True, labels -> False); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - - - -%mathpiper,title="",scope="nobuild",subtype="manual_test" -GeoGebraPlot(Hold(f(x) = x^2)); - -GeoGebraPlot(x^3); - -%/mathpiper - - %output,preserve="false" - Result: true -. %/output - - - - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPoint.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPoint.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPoint.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/GeoGebraPoint.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -%mathpiper,def="GeoGebraPoint",scope="private" -Retract("GeoGebraPoint",*); - -10 # GeoGebraPoint(name_IsString, x_IsNumber, y_IsNumber) <-- -[ - Local(command); - - command := PatchString("=(,)"); - - JavaCall(geogebra,"evalCommand",command); -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/OptionsToAssociativeList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/OptionsToAssociativeList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geogebra/OptionsToAssociativeList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geogebra/OptionsToAssociativeList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="OptionListToAssociativeList",scope="private" -OptionListToAssociativeList(optionList) := -[ - Local(associativeList, key, value); - - associativeList := {}; - - ForEach(option, optionList) - [ - If(option[0] = ->, - [ - If(IsString(option[1]), key := option[1], key := String(option[1])); - If(IsString(option[2]), value := option[2], value := String(option[2])); - - associativeList := {key, value} : associativeList; - - ]); - - ]; - associativeList; -]; - -%/mathpiper - - - - -%mathpiper,title="",scope="nobuild",subtype="manual_test" - -OptionListToAssociativeList({ lines -> True, labels -> False }); - -%/mathpiper - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Distance.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Distance.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Distance.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Distance.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="" - -Distance(PointA_IsPoint,PointB_IsPoint) <-- -[ - Local(x1,x2,y1,y2,distance); - - x1 := PointA[1]; - x2 := PointB[1]; - y1 := PointA[2]; - y2 := PointB[2]; - - distance := Sqrt((x2 - x1)^2 + (y2 - y1)^2); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Distance" -*CMD Distance --- returns the distance between two points -*STD -*CALL - Distance(p1, p2) -*PARMS - -{p1} -- the first point - -{p2} -- the second point - -*DESC - -This function calculates the distance between two points using the -distance formula. - -*E.G. - - In> PointA := Point(2,3) - Result> {2,3} - - In> PointB := Point(6,8) - Result> {6,8} - - In> Distance(PointA, PointB) - Result> Sqrt(41) - -*SEE IsPoint, Point, Midpoint, Slope, Segment -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/IsPoint.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/IsPoint.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/IsPoint.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/IsPoint.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="" - -IsPoint(p) := If(IsList(p) And (Length(p) = 2 Or Length(p) = 3),True,False); - -%/mathpiper - - - -%mathpiper_docs,name="IsPoint" -*CMD IsPoint --- test for a point -*STD -*CALL - IsPoint(p) -*PARMS - -{p} -- point to test - - -*DESC - -Tests if a value is a point. - -*E.G. - - In> p := Point(2,3) - Result> {2,3} - - In> IsPoint(p) - Result> True - - In> IsPoint(4) - Result> False - -*SEE Point, Midpoint, Distance, Slope, Segment -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/IsSegment.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/IsSegment.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/IsSegment.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/IsSegment.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="" - -IsSegment(list_IsList) <-- -[ - If(IsList(list[1]) And Length(list[1])=2 And IsList(list[2]) And Length(list[2])=2,True,False); - -]; - -%/mathpiper - - - -%mathpiper_docs,name="IsSegment" -*CMD IsSegment --- test for a segment -*STD -*CALL - IsSegment(s) -*PARMS - -{s} -- segment to test - - -*DESC - -Tests if a value is a segment. - -*E.G. - - In> IsSegment(Segment(Point(0,0), Point(3,4))) - Result> True - - In> IsSegment({3,4}) - Result> False - -*SEE Point, Midpoint, Distance, Slope, Segment -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Midpoint.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Midpoint.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Midpoint.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Midpoint.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -%mathpiper,def="" - -Midpoint(PointA_IsPoint,PointB_IsPoint) <-- -[ - Local(x1,x2,y1,y2,midpointX,midpointY); - - x1 := PointA[1]; - x2 := PointB[1]; - y1 := PointA[2]; - y2 := PointB[2]; - - midpointX := (x1 + x2)/2; - midpointY := (y1 + y2)/2; - - {midpointX,midpointY}; - -]; - - - -Midpoint(segment_IsSegment) <-- -[ - Local(x1,x2,y1,y2,midpointX,midpointY); - - x1 := segment[1][1]; - x2 := segment[2][1]; - y1 := segment[1][2]; - y2 := segment[2][2]; - - midpointX := (x1 + x2)/2; - midpointY := (y1 + y2)/2; - - {midpointX,midpointY}; - -]; - -%/mathpiper - - - -%mathpiper_docs,name="Midpoint" -*CMD Midpoint --- returns a Point which represents the midpoint between two points -*STD -*CALL - Midpoint(p1, p2) - Midpoint(s) -*PARMS - -{p1} -- the first point - -{p2} -- the second point - -{s} -- a segment - -*DESC - -This function calculates the midpoint between two points using the -midpoint formula. - -*E.G. - - In> PointA := Point(2,3) - Result> {2,3} - - In> PointB := Point(6,8) - Result> {6,8} - - In> Midpoint(PointA, PointB) - Result> {4,11/2} - - In> Midpoint(Segment(Point(0,0), Point(3,4))) - Result> {3/2,2} - -*SEE IsPoint, Point, Distance, Slope, Segment -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Point.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Point.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Point.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Point.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="" - -Point(x,y) := List(x,y); - -Point(x,y,z) := List(x,y,z); - -%/mathpiper - - - -%mathpiper_docs,name="Point" -*CMD Point --- return a list which contains a point -*STD -*CALL - Point(x, y) - Point(x, y, z) -*PARMS - -{x} -- x coordinate of the point - -{y} -- y coordinatte of the point - -{z} -- z coordinate of the point - -*DESC - -Creates either a 2D point or a 3D point. - -*E.G. - - In> Point(5,2) - Result> {5,2} - -*SEE IsPoint, Midpoint, Distance, Slope, Segment -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Segment.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Segment.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Segment.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Segment.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="" - -Segment(PointA_IsPoint,PointB_IsPoint) <-- -[ - Local(x1,x2,y1,y2); - - x1 := PointA[1]; - x2 := PointB[1]; - y1 := PointA[2]; - y2 := PointB[2]; - - {{x1,y1},{x2,y2}}; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Segment" -*CMD Segment --- returns a list which contains the endpoints of a segment -*STD -*CALL - Segment(p1, p2) -*PARMS - -{p1} -- the first endpoint - -{p2} -- the second endpoint - -*DESC - -This function returns a list which represents a segment by its endpoints. - -*E.G. - - In> PointA := Point(2,3) - Result> {2,3} - - In> PointB := Point(6,8) - Result> {6,8} - - In> Segment(PointA,PointB) - Result> {{2,3},{6,8}} - -*SEE IsPoint, Point, Distance, Slope -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Slope.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Slope.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/geometry/Slope.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/geometry/Slope.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -%mathpiper,def="" - -10 # Slope(PointA_IsPoint,PointB_IsPoint) <-- -[ - Local(x1,x2,y1,y2,slope); - - x1 := PointA[1]; - x2 := PointB[1]; - y1 := PointA[2]; - y2 := PointB[2]; - - slope := (y2 - y1)/(x2 - x1); -]; - - - -10 # Slope(segment_IsList)_(Length(segment) = 2 And Length(segment[1]) = 2 And Length(segment[2]) = 2) <-- -[ - Local(x1,x2,y1,y2,slope); - - x1 := segment[1][1]; //PointA[1]; - x2 := segment[2][1]; //PointB[1]; - - - y1 := segment[1][2]; //PointA[2]; - y2 := segment[2][2]; //PointB[2]; - - slope := (y2 - y1)/(x2 - x1); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Slope" -*CMD Slope --- returns the slope of a line which is represented by two points -*STD -*CALL - Slope(p1, p2) - Slope(Segment(p1, p2)) -*PARMS - -{p1} -- the first point - -{p2} -- the second point - -*DESC - -This function calculates the slope between two points or of a -segment using the slope formula. - -*E.G. - - In> PointA := Point(2,3) - Result> {2,3} - - In> PointB := Point(6,8) - Result> {6,8} - - In> Slope(PointA,PointB) - Result> 5/4 - - In> s := Segment(PointA,PointB) - Result: {{2,3},{6,8}} - - In> Slope(s) - Result: 5/4 - -*SEE IsPoint, Point, Distance, Midpoint, Segment -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/highschool/HighschoolForm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/highschool/HighschoolForm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/highschool/HighschoolForm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/highschool/HighschoolForm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -%mathpiper,def="" - -Retract("HighschoolForm",*); - -HighschoolForm(expression) := -[ - //Note: since := is at a higher precedence than :/, parentheses are needed. - expression := (expression /: { (x_IsNegativeNumber) / _y <- [Echo(x,/,y);]}); - - expression := (expression /: {_z^((x_IsNegativeInteger)/y_IsNumber) <- {z,x,y}}); - -]; - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/jfreechart/JFreeChartHistogram.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/jfreechart/JFreeChartHistogram.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/jfreechart/JFreeChartHistogram.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/jfreechart/JFreeChartHistogram.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ - %mathpiper,title="" - - Retract("JFreeChartHistogram",*); - - JFreeChartHistogram(data) := - [ - histogramDataset := JavaNew("org.jfree.data.statistics.HistogramDataset"); - doubleArray := JavaCall("java.lang.reflect.Array","newInstance","java.lang.Double",String(Length(data)) ); - x := 0; - While(x < Length(data)) - [ - JavaCall("java.lang.reflect.Array","setDouble",doubleArray, x, data[x+1] ); - ]; - - ]; - - - %/mathpiper - - %output,preserve="false" - Result: True JavaCall( JavaNew("java.lang.String","Hello"),"toUpperCase") JavaCall("javax.swing.JOptionPane","showMessageDialog","null","hello") -. %/output - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -JFreeChartHistogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}); - -%/mathpiper - - %output,preserve="false" - Result: [Ljava.lang.Double; -. %/output - -Histogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0},line -> True, title -> "Test histogram"); - -JavaCall("java.lang.reflect.Array","setDouble",doubleArray, 0, 33.2); - -JavaCall("java.lang.reflect.Array","newInstance","java.lang.Double","3"); - - private static IntervalXYDataset createDataset() { - HistogramDataset dataset = new HistogramDataset(); - String samplesString = "16.375,16.375,17.125,16,14.375,17.25,16.625,16,17,17.25,17,15.875,16.625,16.125,17.125,16.875,16.375,16.375,16.875,17.125,17,16.75,17.25,17.125,15.375"; - String[] samples = samplesString.split(","); - double[] values = new double[samples.length]; - int i = 0; - for (String sample:samples) { - values[i] = Float.parseFloat(sample); - i++; - } - dataset.addSeries("Pile E", values, 20, 14.0, 20.0); - - - - import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.xy.StandardXYBarPainter; -import org.jfree.chart.renderer.xy.XYBarRenderer; -import org.jfree.data.statistics.HistogramDataset; -import org.jfree.data.xy.IntervalXYDataset; - - - - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/ListToString.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/ListToString.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/ListToString.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/ListToString.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -%mathpiper,def="ListToString",scope="private" - - -Retract("ListToString", *); - - -10 # ListToString(list_IsList)_(Length(list) = 0) <-- ""; - - - -20 # ListToString(list_IsList) <-- -[ - Local(resultString, character); - - resultString := ""; - - ForEach(element, list) - [ - If(IsString(element), character := element, character := String(element)); - - resultString := resultString : character; - ]; - - resultString; - -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/NumberLinePrintZoom.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/NumberLinePrintZoom.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/NumberLinePrintZoom.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/NumberLinePrintZoom.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -%mathpiper,def="NumberLinePrintZoom",scope="private" - -Retract("NumberLineZoom", *); - -Retract("ZoomInOnce", *); - -LocalSymbols(ZoomInOnce) -[ - - 10 # NumberLinePrintZoom(_lowValue, _highValue, divisions_IsPositiveInteger, depth_IsPositiveInteger)_(lowValue < highValue) <-- - [ - - Local(numbers, stepAmount, zoomIndexes, nextZoomIndex, outputWidth, numbersString, output, randomStep, randomZoomNumber, iteration); - - iteration := 1; - - While(iteration <= depth) - [ - {numbers, stepAmount} := ZoomInOnce(lowValue, highValue, divisions); - - zoomIndexes := {}; - - outputWidth := 0; - - numbersString := ""; - - ForEach(number, numbers) - [ - output := ToString() Write(number); - - zoomIndexes := Append(zoomIndexes, Length(output)); - - numbersString := numbersString : output : ToString() Space(3); - - outputWidth := outputWidth + Length(output) + 3; - - ]; - - randomStep := RandomInteger(divisions); - - randomZoomNumber := Sum(Take(zoomIndexes, randomStep)); - - If(randomStep = 1, nextZoomIndex := randomZoomNumber + 1, nextZoomIndex := 3*(randomStep-1) + randomZoomNumber + 1); - - If(iteration > 1, Echo(ListToString(FillList("-", outputWidth-3)))); - - Echo(numbersString); - - If(iteration != depth,[Space(nextZoomIndex);Echo("|");]); - - lowValue := numbers[randomStep]; - - highValue := numbers[randomStep+1]; - - iteration++; - - ]; - - ]; - - - - - ZoomInOnce(_lowValue, _highValue, divisions_IsPositiveInteger)_(lowValue < highValue) <-- - [ - Local(stepAmount, x, numbers); - - stepAmount := If(IsDecimal(lowValue) Or IsDecimal(highValue), N((highValue-lowValue)/divisions), (highValue-lowValue)/divisions); - - x := lowValue; - - numbers := {}; - - While(x <= highValue) - [ - - numbers := Append(numbers, x); - - x := x + stepAmount; - - ]; - - {numbers, stepAmount}; - - ]; - - -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - - - -%mathpiper,subtype="manual_test" - -N(NumberLineZoom(0,1,8,5), 50); - -%/mathpiper - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/PadLeft.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/PadLeft.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/PadLeft.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/PadLeft.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="PadLeft",scope="private" - -Retract("PadLeft", *); - -10 # PadLeft(number_IsInteger, totalDigits_IsInteger) <-- -[ - Local(integerString, padAmount, resultString); - - integerString := String(number); - - padAmount := totalDigits - Length(integerString); - - If(padAmount > 0, - resultString := ListToString(FillList(0, padAmount)) : integerString, - resultString := integerString ); -]; - -%/mathpiper - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/StringToList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/StringToList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/miscellaneous/StringToList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/miscellaneous/StringToList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="StringToList",scope="private" - -Retract("StringToList", *); - -10 # StringToList(string_IsString)_(Length(string) = 0) <-- {}; - - -20 # StringToList(string_IsString) <-- -[ - Local(resultList); - - resultList := {}; - - ForEach(character, string) - [ - resultList := Append(resultList, character); - ]; - - resultList; - -]; - - - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/BinomialProbability.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/BinomialProbability.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/BinomialProbability.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/BinomialProbability.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="BinomialProbability",scope="private" - -BinomialProbability(r, n, p) := (n! / ((n - r)! * r!)) * p^r * (1-p)^(n-r); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/CombinationationsList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/CombinationationsList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/CombinationationsList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/CombinationationsList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="",scope="private" - - -%/mathpiper - - - -%mathpiper_docs,name="CombinationsList",categories="User Functions;Combinatorics" -*CMD CombinationsList --- get all combinations of a list -*STD -*CALL - CombinationsList(list) - -*PARMS - -{list} -- a list of elements - -*DESC - -CombinationsList returns a list with all the combinations of -the original list. - - -*SEE Permutations, Combinations, PermutationsList, LeviCivita -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/IsSubset.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/IsSubset.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/IsSubset.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/IsSubset.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="IsSubset",scope="private" - -Retract("IsSubset",*); - -IsSubset(bigList, littleList) := -[ - Local(result); - result := True; - - ForEach(element, littleList) - [ - If(Not Contains(bigList,element), result := False); - ]; - - result; -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Mode.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Mode.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Mode.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Mode.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -%mathpiper,def="Mode",scope="private" - -Mode(list) := -[ - - Local(mostFrequent, highestFrequency, currentElementCount); - - highestFrequency := 0; - - noDuplicatesList := RemoveDuplicates(list); - - ForEach(element, noDuplicatesList) - [ - If( (currentElementCount := Count(list, element)) > highestFrequency,[ mostFrequent := element; highestFrequency := currentElementCount;] ); - ]; - - mostFrequent; - -]; - -%/mathpiper - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Permutations.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Permutations.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Permutations.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Permutations.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -%mathpiper,def="Permutations",scope="private" - -Retract("Permutations", *); - -Permutations(n) := -[ - Check(IsInteger(n), "Argument must be an integer"); - - n!; -]; - - -Permutations(n, r) := -[ - Check(IsInteger(n), "Argument 1 must be an integer"); - - Check(IsInteger(r), "Argument 2 must be an integer"); - - n! /(n-r)!; -]; - -%/mathpiper - - - - - -%mathpiper_docs,name="Permutations",categories="User Functions;Combinatorics" -*CMD Permutations --- number of permutations -*STD -*CALL - Permutations(n) - Permutations(n, r) - -*PARMS - -{n} -- integer - total number of objects -{r} -- integer - number of objects chosen - -*DESC - -In combinatorics, this function is thought of as being the number of ways -to choose "r" objects out of a total of "n" objects if order is taken into account. - -The single parameter version of the function is a convenience function for -calculating the number of ways to choose "n" objects out of "n" objects. - -*E.G. -In> Permutations(5) -Result> 120 - -In> Permutations(10,3) -Result> 720 - -*SEE PermutationsAll, Combinations, CombinationaAll, LeviCivita -%/mathpiper_docs - - - - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -Permutations(4); - -%/mathpiper - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/ProbabilityMassFunction.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/ProbabilityMassFunction.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/ProbabilityMassFunction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/ProbabilityMassFunction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,title="" - -ProbabilityMassFunction(sampleSize, numberOfSuccesses, probabilityOfSuccess) := -[ - N(Combinations(sampleSize, numberOfSuccesses) * probabilityOfSuccess^numberOfSuccesses * (1-probabilityOfSuccess)^(sampleSize - numberOfSuccesses)); -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - -%mathpiper,title="",scope="nobuild",subtype="manual_test" - -a := ProbabilityMassFunction(25,1,.01); - -%/mathpiper - - %output,preserve="false" - Result: 0.1964195352 -. %/output diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Quartile.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Quartile.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Quartile.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Quartile.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="Quartile",scope="private" - -Retract("Quartile",*); - -Quartile(list) := -[ - sortedList := HeapSort(list,"<"); - - secondQuartile := Median(sortedList); - - If(IsOdd(Length(sortedList)), - [ - secondQuartileIndex := Find(sortedList, secondQuartile); - - leftList := Take(sortedList, secondQuartileIndex-1); - rightList := Take(sortedList, -(Length(sortedList) - (secondQuartileIndex) ) ); - ], - [ - - leftList := Take(sortedList, Length(sortedList)/2); - rightList := Take(sortedList, -Length(sortedList)/2); - ] - ); - - firstQuartile := Median(leftList); - - thirdQuartile := Median(rightList); - - interquartileRange := thirdQuartile - firstQuartile; - - {firstQuartile, secondQuartile, thirdQuartile, interquartileRange}; - -]; - -%/mathpiper - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/RandomPick.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/RandomPick.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/RandomPick.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/RandomPick.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -%mathpiper,def="RandomPick",scope="private" - -Retract("RandomPick",*); - - -RandomPick(list) := -[ - Check(IsList(list), "Argument must be a list."); - - Check(Length(list) > 0, "The number of elements in the list must be greater than 0."); - - Local(pickPosition); - - pickPosition := RandomInteger(Length(list)); - - list[pickPosition]; -]; - -%/mathpiper - - - - - - - -%mathpiper_docs,name="RandomPick",categories="User Functions;Statistics & Probability" -*CMD RandomPick --- randomly pick an element from a list -*STD -*CALL - RandomPick(list) - -*PARMS - -{list} -- a list which contains - -*DESC -Randomly picks an element from the given list. - -*E.G. -In> RandomPick({HEADS, TAILS}) -Result: HEADS - -In> RandomPick({DOOR1, DOOR2, DOOR3}) -Result: DOOR2 - -In> RandomPick({DOG, CAT, BIRD, MOUSE, TURTLE}) -Result: BIRD - -In> RandomPick({23,56,87,92,15}) -Result: 56 - -*SEE RandomPickWeighted, RandomPickVector -%/mathpiper_docs - - - - - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -RandomPick({A,B,C}); - -%/mathpiper - - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/RandomPickVector.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/RandomPickVector.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/RandomPickVector.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/RandomPickVector.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -%mathpiper,def="RandomPickVector",scope="private" - -Retract("RandomPickVector", *); - -RandomPickVector(list, count) := -[ - Check(IsList(list), "Argument 1 must be a list."); - - Check(IsInteger(count), "Argument 2 must be an integer."); - - Table(RandomPick(list),x,1,count,1); -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - - - - -%mathpiper_docs,name="RandomPickVector",categories="User Functions;Statistics & Probability" -*CMD RandomPickVector --- returns a given number of randomly picked elements from a given list -*STD -*CALL - RandomPickVector(list,count) - -*PARMS - -{list} -- a list which contains elements - -{count} -- an integer which indicates how many elements to return - -*DESC -Randomly picks {count} elements from the given list. - -*E.G. -In> RandomPickVector({ONE,TWO,THREE},7); -Result: {THREE,ONE,THREE,THREE,ONE,TWO,TWO} - -*SEE RandomPick, RandomPickWeighted -%/mathpiper_docs - - %output,preserve="false" - -. %/output - - - - - - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -RandomPickVector({ONE,TWO,THREE},7); - -%/mathpiper - - %output,preserve="false" - Result: {TWO,THREE,ONE,THREE,THREE,TWO,THREE} -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/RandomPickWeighted.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/RandomPickWeighted.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/RandomPickWeighted.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/RandomPickWeighted.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -%mathpiper,def="RandomPickWeighted",scope="private" - -Retract("RandomPickWeighted",*); - -RandomPickWeighted(list) := -[ - - Check(IsList(list), "Argument must be a list."); - - Local(element, probabilities, items, lastWeight, randomNumber, result); - - probabilities := 0; - - items := {}; - - lastWeight := 0; - - - - //Make sure that the probabilities sum to 1. - ForEach(element,list) - [ - probability := element[2]; - - probabilities := probabilities + probability; - ]; - - Check(probabilities = 1, "The probabilities must sum to 1."); - - - - //Place items in a list and associate it with a subrange in the range between 0 and 1. - ForEach(element,list) - [ - probability := element[2]; - - item := element[1]; - - items := Append(items, {item, {lastWeight, lastWeight := lastWeight + N(probability)}} ); - ]; - - - - //Pick the item which is in the randomly determined range. - randomNumber := Random(); - - ForEach(itemData,items) - [ - If(randomNumber >= itemData[2][1] And randomNumber <= itemData[2][2], result := itemData[1] ); - ]; - - - - result; - -]; - -%/mathpiper - - - - - - - - -%mathpiper_docs,name="RandomPickWeighted",categories="User Functions;Statistics & Probability" -*CMD RandomPickWeighted --- randomly pick an element from a list using a given weight -*STD -*CALL - RandomPickWeighted(list) - -*PARMS - -{list} -- a list which contains elements and their respective weights - -*DESC -Randomly picks an element from the given list with a probability which is determined by the element's weight. - -*E.G. -In> RandomPickWeighted({{HEADS,1/2},{TAILS,1/2}}); -Result: HEADS - -In> RandomPickWeighted({{HEADS,1/2},{TAILS,1/2}}); -Result: HEADS - -In> RandomPickWeighted({{HEADS,.5},{TAILS,.5}}); -Result: TAILS - -In> RandomPickWeighted({{DOOR1,2/8}, {DOOR2,1/8}, {DOOR3,5/8}}) -Result: DOOR1 - -In> RandomPickWeighted({{DOG,.2}, {CAT,.3}, {BIRD,.1}, {MOUSE,.15}, {TURTLE,.25}}) -Result: TURTLE - -In> RandomPickWeighted({{23,5/32},{56,10/32},{87,8/32},{92,6/32},{15,3/32}}) -Result: 15 - -*SEE RandomPick, RandomPickVector -%/mathpiper_docs - - - - - - - - -%mathpiper,scope="nobuild",subtype="manual_test" - -RandomPickWeighted({{HEADS,1/2},{TAILS,1/2}}); - -%/mathpiper - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Repeat.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Repeat.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Repeat.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Repeat.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -%mathpiper,def="Repeat",scope="private" - - - -Retract("Repeat",*); - - -/* - These variables need to be declared as local symbols because - body is unfenced and expressions in the body could see them - otherwise. -*/ -LocalSymbols(count, iterations, body)[ - - -RuleBase("Repeat",{iterations,body}); - -/* - A Rule function needed to be used here because 10 # xxx <-- - notation did not work if Bodied was executed before the - function was defined. Bodied is evaluated in stdopers.mrw - because it needs to be evaluated for the parser to parse - Retract correctly. -*/ - -Rule("Repeat",2,10,IsInteger(iterations) And iterations > 0) -[ - Local(count); - - count := 0; - - While (iterations > 0) - [ - Eval(body); - iterations--; - count++; - ]; - - count; - -]; - - - - - -RuleBase("Repeat",{body}); - - -Rule("Repeat",1,20,True) -[ - Local(count); - - count := 0; - While (True) - [ - Eval(body); - count++; - ]; - - count; -]; - -];//end LocalSymbols - -UnFence("Repeat",2); -HoldArgNr("Repeat",2,2); -UnFence("Repeat",1); -HoldArgNr("Repeat",1,1); - - - -%/mathpiper - - - - - -%mathpiper_docs,name="Repeat",categories="User Functions;Control Flow" -*CMD Repeat --- loop a specified number of times or loop indefinitely -*STD -*CALL - Repeat(count) body - Repeat() body - -*PARMS - -{count} -- a positive integer, the number of times to loop - -{body} -- expression to loop over - -*DESC - -The first version of Repeat executes {body} the number of times -which are specified by {count}. The second version -executes {body} indefinitely and the only way to exit the loop -is to execute the Break function inside of {body}. - -Repeat returns the number of times it looped as a result. - -*E.G. -/%mathpiper - -Repeat(4) -[ - Echo("Hello"); -]; - -/%/mathpiper - - /%output,preserve="false" - Result: 4 - - Side Effects: - Hello - Hello - Hello - Hello -. /%/output - - - -/%mathpiper - -x := 1; - -loopCount := Repeat() -[ - Echo(x); - - If(x = 3, Break()); - - x := x + 1; -]; - -Echo("Loop count: ", loopCount); - -/%/mathpiper - - /%output,preserve="false" - Result: True - - Side Effects: - 1 - 2 - 3 - Loop count: 2 -. /%/output - -*SEE While, For, ForEach, Break, Continue -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Sample.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Sample.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Sample.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Sample.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -%mathpiper,def="Sample",scope="private" - -Retract("Sample",*); - - -10 # Sample(list_IsList, amount_IsInteger) <-- -[ - Local(result); - list := Shuffle(list); - - result := Take(list, amount); -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/ShuffledDeckNoSuits.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/ShuffledDeckNoSuits.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/ShuffledDeckNoSuits.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/ShuffledDeckNoSuits.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="ShuffledDeckNoSuits",scope="private" - -Retract("ShuffledDeckNoSuits",*); - - -ShuffledDeckNoSuits() := -[ - Shuffle(Concat(1 .. 13, 1 .. 13, 1 .. 13, 1 .. 13)); -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Shuffle.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Shuffle.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/Shuffle.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/Shuffle.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="Shuffle",scope="private" - -Retract("Shuffle",*); - - -10 # Shuffle(list_IsList) <-- -[ - Local(index, randomIndex, temporary); - - index := Length(list); - - While(index > 1) - [ - randomIndex := RandomInteger(1,index); - temporary := list[randomIndex]; - list[randomIndex] := list[index]; - list[index] := temporary; - index--; - ]; - - list; -]; - -%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/StemAndLeaf.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/StemAndLeaf.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/StemAndLeaf.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/StemAndLeaf.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,1020 +0,0 @@ - -%mathpiper,scope="private" -//Obtained from http://math.uc.edu/~pelikan/probandstat/stem.htm - - -trunc(x):= [ - - If(x < 0, s := -1, s := 1); -s* Floor(Abs(x)); -]; - - - - -intlabels(y1,y2,tnumint) := [ - diff :=y2-y1; - x := intervals(diff,tnumint); - bot := trunc(y1/x)*x; - yy = bot; - L = []; - //i = 0; - xx = 0; - breakLoop := False; - While (yy-x < y2 Or breakLoop = True) [ - L := Append(L, yy); - yy := yy + x; - //i++; - xx++; - If (xx > 100, breakLoop := True); - ]; - L[i] = yy; - L; -]; - - - - -intervals(diff, NumCats) := [ - t4 := trunc(N(Ln(diff))) * 0.4342945; - t4 = Power(10,t4); - T := []; - T := N(t4/10 : t4/5 : t4/2 : t4 : T); - - - A := []; - - For (i := 0,i < 4, i++) [ - A := Append(A,trunc(diff/T[i]) +1); - ]; - - D := AbsN(10 - A[0]); - - index := 1; - For (i := 1, i < 4, i++) - [ - if (A[i] <= 25) [ - if (A[i] > 2) [ - XX := AbsN(NumCats - A[i]); - if (XX < D) [ - D := XX; - index = i+1; - ]; - ]; - ]; - ]; - T[index-1]; -]; - - - - - -stemandleaf(x) := -[ - Echo("Stem and Leaf Display"); - didzero := False; - N := x.length; - - if (N<20) - [ - tNumInt := 5; - ] - else - [ - if (N < 100) - [ - tNumInt := 10; - ] - else - [ - if (N < 150) - [ - tNumInt := 15; - ] - else - [ - tNumInt := 20; - ]; - ]; - ]; - theMax := x[N-1]; - theMin := x[0]; - alldone := False; - if (theMax - theMin < 10) - [ - ratio := 1000/(theMax - theMin); - ratio := Math.max(ratio,1000); - ratio := trunc(Math.log(ratio) * 0.4342945); - ratio := Math.pow(10,ratio); - For ( i := 0, i < N , i++) - [ - x[i] := x[i] * ratio; - ]; - ] - else - [ - ratio := 1; - ]; - zcount := 0; - theMin := x[0]; - abMin := Math.abs(theMin); - theMax := x[N-1]; - Y := intervals(theMax-theMin,tNumInt); - indexA := index +0; - if (indexA= 2) - [ - Y := Y * 5; - ncats :=5 ; - newz := 1; - ] - else - [ - if(indexA=3) - [ - Y := Y * 2; - ncats := 2; - ] - else - [ - ncats := 1; - newz := 0; - ]; - ]; - - cutoffs := intlabels(x[0], x[N-1], tNumInt); - theMax := ratio * Round(theMax); - nc := cutoffs.length; - xx8:=0; - While (cutoffs[nc-2] > theMax) - [ - nc--; - ]; - theMax := cutoffs[nc-2]; - if (Y > AbsN(theMax)) - [ - nc++; - While(Y > AbsN(theMax)) - [ - xx8++; - if(xx8>100)[break;]; - if (nc > Length(cutoffs)) - [ - temp := cutoffs[nc-2] - cutoffs[nc - 3]; - temp := temp + cutoffs[nc-2]; - cutoffs[nc-1] := temp; - ]; - theMax := cutoffs[nc-1]; - nc++; - ]; - ]; - base := trunc(theMax/Y); - leftover := Round(theMax - base * Y); - While (AbsN(leftover) > 10) - [ - leftover := AbsN(Round(leftover/10)); - ]; - theMax2 := Max(theMax,abMin); - t4 := trunc(theMax2/base); - t4 := trunc(N(Ln(t4) * .4342945)); - t4 := Power(10,t4); - t3 := t4/10; - if (indexA = 2) - [ - if (leftover >= 8) - [ - newz := 1; - ] - else - [ - if (leftover >= 6) - [ - newz := 0; - ] - else - [ - if (leftover >= 4) - [ - newz := 4; - ] - else - [ - if (leftover >= 2) - [ - newz := 3; - ] - else - [ - newz := 2; - ]; - ]; - ]; - ]; - ] - else - [ - if (indexA = 3) - [ - if (leftover >=5) - [ - newz := 1; - ] - else - [ - newz := 0; - ]; - ]; - ]; - start := False; - LN := 1; - LN2 := 0; - nn := N; - cur := cutoffs[nc-2]; - count := nc-2; - base2 :=base; - newline := True; - stems := {base2}; - leaves := {""}; - - - For ( i := nn-1, i >= 0 , i--) - [ - it := x[i]; - dd := Round(it/t3) * t3; - b := trunc(dd/t4); - L := dd-t4*b; - leftover := AbsN(Round(L/t3)); - While (leftover >= 10) - [ - leftover := Round(leftover/10); - ]; - if (it >=0) - [ - tt := t3; - ] - else - [ - tt := -t3; - ]; - - xz := b * t4 + leftover * tt; - - if (it<0) - [ - if (xz > 0 ) - [ - xz := xz * -1; - ]; - xz := xz - .00001; - ]; - - if (xz=6)) Or ((indexA = 3) And (zcount >=3)) Or ((indexA = 1) And (zcount >1)) Or ((indexA = 4) And (zcount >1))) - [ - stems := Append(stems,"-" : String(base2)); - ] - else - [ - stems := Append(stems, String(base2)); - ]; - ] - else - [ - stems := Append(stems, String(base2)); - ]; - - ];//end While. - - - ];//end if - - start := True; - leftover := String(leftover); - - if (it>=0) - [ - - leaves[LN2] := leftover : "" : leaves[LN2]; - - ] - else - [ - leaves[LN2] := leaves[LN2] : "" : leftover; - ]; - ]; - - For ( i := 0, i < N , i++) [ - x[i] := x[i] / ratio; - ]; - - - Echo("Stems Leaves"); - For (i:=0, i - - - Stem and Leaf Plot - - - - - - - - -

    Stem and Leaf Plot

    - -

    This page contains JavaScript that will make a Stem-and-Leaf plot of the data you -paste or type into the text area below. Separate the different values by spaces, commas, or newlines - as you enter them. Then hit the "Compute" button and your browser will open a new window and display the plot. When you are done looking at the new window minimize it or close it with controls from its pull-down menus.

    - -

    Note that Microsoft has implemented a different version of scripting language in their Internet Explorer browser. Very likely, the JavaScript program on this page will not work in Microsoft's browser. To the best of my knowledge, the script does work in Netscape's internet browser 3.0.

    - -
    -
    - - -
    -

    - The code in this page for the "hard" part of making the plot was borrowed from Lane's Hyperstat. All I've done is parsed the imput data differently. -

    -
    If you find errors in this program please send email: -
    Stephan Pelikan
    - - - -Last modified: Tue Sep 30 17:09:00 EDT 1997 - - - - - - - - - - - - - - - - - -%html - -Minitab - -



    -

    -Section 2.6. http://www.math.binghamton.edu/arcones/327/2.6.html

    - -

    - -First we use the yarn strength data. We find the boxplot of these data -MTB > Retrieve 'A:\YARNSTRG.MTW'. -Retrieving worksheet from file: A:\YARNSTRG.MTW -************************************** -A boxplot consists of a box, whiskers, and outliers. A line is drawn across -the box at the median. By default, the bottom of the box is at the first -quartile (Q1), and the top is at the third quartile (Q3) value. The whiskers -are the lines that extend from the top and bottom of the box to the adjacent -values. The adjacent values are the lowest and highest observations that are -still inside the region defined by the following limits: - - Lower Limit: Q1 - 1.5 (Q3 - Q1) - Upper Limit: Q3 + 1.5 (Q3 - Q1) - -Outliers are points outside of the lower and upper limits and are plotted -with asterisks (*). -************************************** -MTB > boxplot c1 - -

    -Using that -MTB > desc c1 - N MEAN MEDIAN TRMEAN STDEV SEMEAN -Ln_YarnS 100 2.9238 2.8331 2.8982 0.9378 0.0938 - - MIN MAX Q1 Q3 -Ln_YarnS 1.1514 5.7978 2.2789 3.5732 -We have that -Minimum=1.1514; Q1=2.2789; median=2.8331; Q3=3.5732; maximum=5.7978 -In this case -Lower Limit: Q1 - 1.5 (Q3 - Q1)= 2.2789-1.5(3.5732-2.2789)=0.8903 -Upper Limit: Q3 + 1.5 (Q3 - Q1)= 3.5732+1.5(3.5732-2.2789)=5.5146 -The minimum is not an outlier, but the maximum is. -So, the lower whisker goes to the minimum. The upper whisker goes to -the biggest value in the data small than 5.5146. This value is 5.0904 -Observe that -MTB > sort c1 c2 -MTB > print c2 - - -C2 - 1.1514 1.1535 1.3436 1.4328 1.4570 1.5059 1.5219 1.5305 - 1.6438 1.6787 1.7261 1.7837 1.7902 1.8926 1.8952 2.0813 - 2.0968 2.1232 2.1306 2.1381 2.1771 2.2163 2.2364 2.2671 - 2.2762 2.2872 2.3018 2.3459 2.3483 2.4016 2.4064 2.4190 - 2.4240 2.4822 2.5000 2.5238 2.5264 2.5326 2.5364 2.5453 - 2.5654 2.5724 2.5800 2.5813 2.6266 2.6537 2.6745 2.7243 - 2.7317 2.8243 2.8418 2.8732 2.9382 2.9394 2.9908 3.0027 - 3.0164 3.0693 3.0722 3.1166 3.1412 3.1860 3.1860 3.2108 - 3.2177 3.2217 3.3077 3.3770 3.4002 3.4217 3.4603 3.4743 - 3.4866 3.5017 3.5272 3.5886 3.6152 3.6162 3.6394 3.6398 - 3.6561 3.7043 3.7071 3.7782 3.8849 3.9821 4.0017 4.0022 - 4.0126 4.1251 4.3215 4.3389 4.4382 4.4563 4.5234 4.6315 - 4.6426 4.8444 5.0904 5.7978 - -Next, we draw the quantile graph in page 37: -MTB > set c2 -DATA> 1:100 -DATA> end -MTB > let c2=c2/101 -MTB > sort c1 c3 -MTB > Plot C3*C2; -SUBC> Symbol; -SUBC> Type 5. - -

    - -Next, we get the stem-and leaf- for the strength yard data -****************************************************************** -A stem-and-leaf display shows the distribution of a variable in much the -same way as a histogram. However, the initial digits of each value are -used to construct the display, so individual values can be read from the -display. A stem-and-leaf display has three parts: - - The first column shows a cumulative count of the number of values on that -line or on lines toward the nearer edge. (The line that contains the median -shows a count of values on that line instead, enclosed in parentheses.) - - The second column of numbers holds the stems. - - The right-hand portion of the display holds the leaves. Each leaf digit -represents an individual value. The initial digits of that value are the -stem digits. This is followed by the leaf digit. Thus, a stem of 46 and a -leaf of 2 could represent the number 462, or 46.2, or .00462. The position -of the decimal point is indicated by the UNIT of the leaf digit printed at -the top of the display. -************************************************** - -MTB > stemandleaf c1 - -Stem-and-leaf of Ln_YarnS N = 100 -Leaf Unit = 0.10 - - - 5 1 11344 - 15 1 5556677788 - 34 2 0011112222233344444 - (21) 2 555555555566677888999 - 45 3 000011112223344444 - 27 3 5556666677789 - 14 4 00013344 - 6 4 5668 - 2 5 0 - 1 5 7 -Next, we find robust statistics for location and dispersion. -To find the 5 % trimmed mean we do: -MTB > descr c1 - - N MEAN MEDIAN TRMEAN STDEV SEMEAN -Ln_YarnS 100 2.9238 2.8331 2.8982 0.9378 0.0938 - - MIN MAX Q1 Q3 -Ln_YarnS 1.1514 5.7978 2.2789 3.5732 -The trimmed mean is 2.8982 -Alternatively, we could do: -MTB > sort c1 c2 -MTB > delete 1,2,3,4,5,96,97,98,99,100 c2 -MTB > mean c2 - MEAN = 2.8982 -In this way, we can also find the 5 % trimmed standard deviation: -MTB > stdev c2 - ST.DEV. = 0.75951 - - - - - - -%/html - - %output,preserve="false" - -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/WeightedMean.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/WeightedMean.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/proposed/statistics/WeightedMean.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/proposed/statistics/WeightedMean.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="WeightedMean",scope="private" - -Retract("WeightedMean", *); - -10 # WeightedMean(values_IsList, weights_IsList)_(Length(values) = Length(weights)) <-- -[ - - N(Sum(values * weights)/Sum(weights)); - -]; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - -%mathpiper_docs,name="WeightedMean",categories="User Functions;Statistics & Probability" -*CMD WeightedMean --- weighted mean -*STD -*CALL - WeightedMean(values, weights) - -*PARMS - -{values} -- list, the values. -{weights} -- list, the respective weights to associate with the values. - -*DESC -This function allows more weight to be associated to certain values and -less weight to others when calculating their mean. - -*E.G. -In> WeightedMean({92, 87, 76}, {50, 40, 10}) -Result: 88.4 - -*SEE Mean, Mode, GeometricMean -%/mathpiper_docs - - %output,preserve="false" - -. %/output - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/pslq/Pslq.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/pslq/Pslq.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/pslq/Pslq.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/pslq/Pslq.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,368 +0,0 @@ -%mathpiper,def="Pslq" - -/*********************************************************************************************# -# The PSLQ Integer Relation Algorithm # -# # -# Aut.: Helaman R.P. Ferguson and David Bailey "A Polynomial Time, Numerically Stable # -# Integer Relation Algorithm" (RNR Technical Report RNR-92-032) helaman@super.org # -# Ref.: David Bailey and Simon Plouffe "Recognizing Numerical Constants" dbailey@nas.nasa.gov # -# Cod.: Raymond Manzoni raymman@club-internet.fr # -#*********************************************************************************************# -# Creation:97/11 # -# New termination criteria:97/12/15 # -# this code is free... # - -Ported to MathPiper 2000 Ayal Pinkus. - -Given a list of constants x find coefficients sol[i] such that - sum(sol[i]*x[i], i=1..n) = 0 (where n=Length(x)) - - x is the list of real expressions - N(x[i]) must evaluate to floating point numbers! - precision is the number of digits needed for completion; - must be greater or equal to log10(max(sol[i]))*n - returns the list of solutions with initial precision - and the confidence (the lower the better) - - Example: - - In> Pslq({2*Pi-4*Exp(1),Pi,Exp(1)},20) - Out> {1,-2,4}; - -*/ - -Pslq(x, precision) := -[ - Local (ndigits, gam, A, B, H, n, i, j, k, s, y, tmp, t, m, maxi, gami, - t0, t1, t2, t3, t4, mini, Confidence, norme,result); - n:=Length(x); - ndigits:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(precision+10); // 10 is chosen arbitrarily, but should always be enough. Perhaps we can optimize by lowering this number - Confidence:=10^(-FloorN(N(Eval(precision/3)))); -//Echo("Confidence is ",Confidence); - - gam:=N(Sqrt(4/3)); - For (i:=1, i<=n,i++) x[i]:=N(Eval(x[i])); - -//Echo("1..."); - - A:=Identity(n); /*A and B are of Integer type*/ - B:=Identity(n); /*but this doesn't speed up*/ - s:=ZeroVector(n); - y:=ZeroVector(n); - -//Echo("2..."); - - For(k:=1,k<=n,k++) - [ - tmp:=0; - For (j:=k,j<=n,j++) tmp:=tmp + N(x[j]^2); -//tmp:=DivideN(tmp,1.0); -//Echo("tmp is ",tmp); -//MathDebugInfo(tmp); -/*If(Not IsPositiveNumber(tmp), - Echo("******** not a positive number: ",tmp) -); -If(Not IsNumber(tmp), - Echo("******** not a number: ",tmp) -); -If(LessThan(tmp,0), -[ - Echo("******** not positive: ",tmp); -] -);*/ - - s[k]:=SqrtN(tmp); - - -/*If(Not IsNumber(tmp), -[ -Echo("************** tmp = ",tmp); -]); -If(Not IsNumber(s[k]), -[ -Echo("************** s[k] = ",s[k]); -]);*/ - - ]; - -//Echo("3..."); - - tmp:=N(Eval(s[1])); -/*If(Not IsNumber(tmp), -[ -Echo("************** tmp = ",tmp); -]);*/ - - For (k:= 1,k<= n,k++) - [ - y[k]:=N(Eval(x[k]/tmp)); - s[k]:=N(Eval(s[k]/tmp)); - -//Echo("1..."," ",y[k]," ",s[k]); -/*If(Not IsNumber(y[k]), -[ -Echo("************** y[k] = ",y[k]); -]); -If(Not IsNumber(s[k]), -[ -Echo("************** s[k] = ",s[k]); -]);*/ - - ]; - H:=ZeroMatrix(n, n-1); - -//Echo("4...",n); - For (i:=1,i<= n,i++) - [ - - if (i <= n-1) [ H[i][i]:=N(s[i + 1]/s[i]); ]; - -//Echo("4.1..."); - For (j:= 1,j<=i-1,j++) - [ -//Echo("4.2..."); - H[i][j]:= N(-(y[i]*y[j])/(s[j]*s[j + 1])); -//Echo("4.3..."); - -/*If(Not IsNumber(H[i][j]), -[ -Echo("************** H[i][j] = ",H[i][j]); -] -);*/ - - ]; - ]; - -//Echo("5..."); - - For (i:=2,i<=n,i++) - [ - For (j:=i-1,j>= 1,j--) - [ -//Echo("5.1..."); - t:=Round(H[i][j]/H[j][j]); -//Echo("5.2..."); - y[j]:=y[j] + t*y[i]; -//Echo("2..."," ",y[j]); - For (k:=1,k<=j,k++) [ H[i][k]:=H[i][k]-t*H[j][k]; ]; - For (k:=1,k<=n,k++) - [ - A[i][k]:=A[i][k]-t*A[j][k]; - B[k][j]:=B[k][j] + t*B[k][i]; - ]; - ]; - ]; - Local(found); - found:=False; - -//Echo("Enter loop"); - - While (Not(found)) - [ - m:=1; -//Echo("maxi 1...",maxi); - maxi:=N(gam*Abs(H[1][1])); -//Echo("maxi 2...",maxi); - gami:=gam; -//Echo("3..."); - For (i:= 2,i<= n-1,i++) - [ - gami:=gami*gam; - tmp:=N(gami*Abs(H[i][i])); - if (maxi < tmp) - [ - maxi:=tmp; -//Echo("maxi 3...",maxi); - m:=i; - ]; - ]; -//Echo("4...",maxi); - tmp:=y[m + 1]; - y[m + 1]:=y[m]; - y[m]:=tmp; -//Echo("3..."," ",y[m]); -//Echo("5..."); - For (i:= 1,i<=n,i++) - [ - tmp:=A[m + 1][ i]; - A[m + 1][ i]:=A[m][ i]; - A[m][ i]:=tmp; - tmp:=B[i][ m + 1]; - B[i][ m + 1]:=B[i][ m]; - B[i][ m]:=tmp; - ]; - For (i:=1,i<=n-1,i++) - [ - tmp:=H[m + 1][ i]; - - H[m + 1][ i]:=H[m][ i]; - H[m][ i]:=tmp; - ]; -//Echo("7..."); - if (m < n-1) - [ - t0:=N(Eval(Sqrt(H[m][ m]^2 + H[m][ m + 1]^2))); - - t1:=H[m][ m]/t0; - t2:=H[m][ m + 1]/t0; - -// If(IsZero(t0),t0:=N(Confidence)); -//Echo(""); -//Echo("H[m][ m] = ",N(H[m][ m])); -//Echo("H[m][ m+1] = ",N(H[m][ m+1])); - -//If(IsZero(t0),[t1:=Infinity;t2:=Infinity;]); -//Echo("t0=",N(t0)); -//Echo("t1=",N(t1)); -//Echo("t2=",N(t2)); - - For (i:=m,i<=n,i++) - [ - t3:=H[i][ m]; - t4:=H[i][ m + 1]; -//Echo(" t1 = ",t1); -//Echo(" t2 = ",t2); -//Echo(" t3 = ",t3); -//Echo(" t4 = ",t4); - H[i][ m]:=t1*t3 + t2*t4; -//Echo("7.1... ",H[i][ m]); - H[i][ m + 1]:= -t2*t3 + t1*t4; -//Echo("7.2... ",H[i][ m+1]); - ]; - ]; -//Echo("8..."); - For (i:= 1,i<= n,i++) - [ - For (j := Min(i-1, m + 1),j>= 1,j--) - [ - t:=Round(H[i][ j]/H[j][ j]); -//Echo("MATRIX",H[i][ j]," ",H[j][ j]); -//Echo("5... before"," ",y[j]," ",t," ",y[i]); - y[j]:=y[j] + t*y[i]; -//Echo("5... after"," ",y[j]); - For (k:=1,k<=j,k++) H[i][ k]:=H[i][ k]-t*H[j][ k]; - For (k:= 1,k<=n,k++) - [ - A[i][ k]:=A[i][ k]-t*A[j][ k]; - B[k][ j]:=B[k][ j] + t*B[k][ i]; - ]; - ]; - ]; -//Echo("9...",N(H[1],10)); - - /* BuiltinPrecisionSet(10);*/ /*low precision*/ -// maxi := N(H[1] . H[1],10); - maxi := N(H[1] . H[1]); -//Echo("H[1] = ",H[1]); -//Echo("N(H[1]) = ",N(H[1])); -//Echo("N(H[1] . H[1]) = ",N(H[1] . H[1])); -//Echo("maxi 4...",maxi); - -//Echo("9... maxi = ",maxi); - - For (j:=2,j<=n,j++) - [ -//Echo("9.1..."); - tmp:=N(H[j] . H[j],10); -//Echo("9.2..."); - if (maxi < tmp) [ maxi:=tmp; ]; -//Echo("maxi 5...",maxi); -//Echo("9.3..."); - ]; -//Echo("10..."); - norme:=N(Eval(1/Sqrt(maxi))); - m:=1; - mini:=N(Eval(Abs(y[1]))); -//Echo("y[1] = ",y[1]," mini = ",mini); - maxi:=mini; - -//Echo("maxi 6...",maxi); -//Echo("11..."); - For (j:=2,j<=n,j++) - [ - tmp:=N(Eval(Abs(y[j]))); - if (tmp < mini) - [ - mini:=tmp; - m:=j; - ]; - if (tmp > maxi) [ maxi:=tmp; ]; -//Echo("maxi 7...",maxi); - ]; - /* following line may be commented */ -//Echo({"Norm bound:",norme," Min=",mini," Conf=",mini/maxi," required ",Confidence}); - if ((mini/maxi) < Confidence) /*prefered to : if mini < 10^(- precision) then*/ - [ - /* following line may be commented */ -/* Echo({"Found with Confidence ",mini/maxi}); */ - BuiltinPrecisionSet(ndigits); - result:=Transpose(B)[m]; - found:=True; - ] - else - [ - maxi:=Abs(A[1][ 1]); - For (i:=1,i<=n,i++) - [ -//Echo("i = ",i," n = ",n); - For (j:=1,j<=n,j++) - [ -//Echo("j = ",j," n = ",n); - tmp:=Abs(A[i][ j]); - if (maxi < tmp) [ maxi:=tmp;]; - ]; - ]; -//Echo("maxi = ",maxi); - if (maxi > 10^(precision)) - [ - BuiltinPrecisionSet(ndigits); - result:=Fail; - found:=True; - ]; - BuiltinPrecisionSet(precision+2); -//Echo("CLOSE"); - ]; - ]; - result; -]; - -/* end of file */ - -%/mathpiper - - - -%mathpiper_docs,name="Pslq",categories="User Functions;Numbers (Operations)" -*CMD Pslq --- search for integer relations between reals -*STD -*CALL - Pslq(xlist,precision) - -*PARMS - -{xlist} -- list of numbers - -{precision} -- required number of digits precision of calculation - -*DESC - -This function is an integer relation detection algorithm. This means -that, given the numbers $x[i]$ in the list "xlist", it tries -to find integer coefficients $a[i]$ such that -$a[1]*x[1]$ + ... + $a[n]*x[n] = 0$. -The list of integer coefficients is returned. - -The numbers in "xlist" must evaluate to floating point numbers if -the {N} operator is applied on them. - -*E.G. - - In> Pslq({ 2*Pi+3*Exp(1), Pi, Exp(1) },20) - Out> {1,-2,-3}; - -Note: in this example the system detects correctly that -$1 * (2*Pi+3*e) + (-2) * Pi + (-3) * e = 0$. - -*SEE N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/rabinmiller/RabinMiller.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/rabinmiller/RabinMiller.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/rabinmiller/RabinMiller.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/rabinmiller/RabinMiller.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,180 +0,0 @@ -%mathpiper,def="RabinMiller" - -/* - * File `rabinmiller.mpi' is an implementation of the - * Rabin-Miller primality test. - */ - - -/* - * FastModularPower(a, b, n) computes a^b (mod n) efficiently. - * This function is called by IsStronglyProbablyPrime. - */ - -FastModularPower(a_IsPositiveInteger, b_IsPositiveInteger, n_IsPositiveInteger) <-- -[ - Local(p, j, r); - p := a; - j := b; - r := 1; - - While (j > 0) - [ - If (IsOdd(j), r := ModN(r*p, n)); - p := ModN(p*p, n); - j := ShiftRight(j, 1); - ]; - r; -]; - - -/* - * An integer n is `strongly-probably-prime' for base b if - * - * b^q = 1 (mod n) or - * b^(q*2^i) = -1 (mod n) for some i such that 0 <= i < r - * - * where q and r are such that n-1 = q*2^r and q is odd. - * - * If an integer is not strongly-probably-prime for a given - * base b, then it is composed. The reciprocal is false. - * Composed strongly-probably-prime numbers for base b - * are called `strong pseudoprimes' for base b. - */ -// this will return a pair {root, True/False} -IsStronglyProbablyPrime(b_IsPositiveInteger, n_IsPositiveInteger) <-- -[ - Local(m, q, r, a, flag, i, root); - m := n-1; - q := m; - r := 0; - root := 0; // will be the default return value of the "root" - While (IsEven(q)) - [ - q := ShiftRight(q, 1); - r++; - ]; - - a := FastModularPower(b, q, n); - flag := (a = 1 Or a = m); - i := 1; - - While (Not(flag) And (i < r)) - [ - root := a; // this is the value of the root if flag becomes true now - a := ModN(a*a, n); - flag := (a = m); - i++; - ]; - - {root, flag}; // return a root of -1 (or 0 if not found) -]; - - -/* - * For numbers less than 3.4e14, exhaustive computations have - * shown that there is no strong pseudoprime simultaneously for - * bases 2, 3, 5, 7, 11, 13 and 17. - * Function RabinMillerSmall is based on the results of these - * computations. - */ - -10 # RabinMillerSmall(1) <-- False; - -10 # RabinMillerSmall(2) <-- True; - -20 # RabinMillerSmall(n_IsEven) <-- False; - -20 # RabinMillerSmall(3) <-- True; - -30 # RabinMillerSmall(n_IsPositiveInteger) <-- -[ - Local(continue, prime, i, primetable, pseudotable, root); - continue := True; - prime := True; - i := 1; - primetable := {2, 3, 5, 7, 11, 13, 17}; - pseudotable := {2047, 1373653, 25326001, 3215031751, 2152302898747, - 3474749660383, 34155071728321}; - // if n is strongly probably prime for all bases up to and including primetable[i], then n is actually prime unless it is >= pseudotable[i]. - While (continue And prime And (i < 8)) - [ // we do not really need to collect the information about roots of -1 here, so we do not do anything with root - {root, prime} := IsStronglyProbablyPrime(primetable[i], n); - If(InVerboseMode() And prime, Echo("RabinMiller: Info: ", n, "is spp base", primetable[i])); - continue := (n >= pseudotable[i]); - i++; - ]; - // the function returns "Overflow" when we failed to check (i.e. the number n was too large) - If (continue And (i = 8), Overflow, prime); -]; - - -/* - * RabinMillerProbabilistic(n, p) tells whether n is prime. - * If n is actually prime, the result will always be `True'. - * If n is composed the probability to obtain the wrong - * result is less than 4^(-p). - */ -// these 4 rules are not really used now because RabinMillerProbabilistic is only called for large enough n -10 # RabinMillerProbabilistic(1, _p) <-- False; - -10 # RabinMillerProbabilistic(2, _p) <-- True; - -20 # RabinMillerProbabilistic(n_IsEven, _p) <-- False; - -20 # RabinMillerProbabilistic(3, _p) <-- True; - -30 # RabinMillerProbabilistic(n_IsPositiveInteger, p_IsPositiveInteger) <-- -[ - Local(k, prime, b, roots'of'minus1, root); - k := 1+IntLog(IntLog(n,2),4)+p; // find k such that Ln(n)*4^(-k) < 4^(-p) - b := 1; - prime := True; - roots'of'minus1 := {0}; // accumulate the set of roots of -1 modulo n - While (prime And k>0) - [ - b := NextPseudoPrime(b); // use only prime bases, as suggested by Davenport; weak pseudo-primes are good enough - {root, prime} := IsStronglyProbablyPrime(b, n); - If(prime, roots'of'minus1 := Union(roots'of'minus1, {root})); - If(Length(roots'of'minus1)>3, prime := False); - If(InVerboseMode() And prime, Echo("RabinMiller: Info: ", n, "is spp base", b)); - If( // this whole If() clause is only working when InVerboseMode() is in effect and the test is terminated in the unusual way - InVerboseMode() And Length(roots'of'minus1)>3, - [ // we can actually find a factor of n now - Local(factor); - roots'of'minus1 := Difference(roots'of'minus1,{0}); - Echo("RabinMiller: Info: ", n, "is composite via roots of -1 ; ", roots'of'minus1); - factor := Gcd(n, If( - roots'of'minus1[1]+roots'of'minus1[2]=n, - roots'of'minus1[1]+roots'of'minus1[3], - roots'of'minus1[1]+roots'of'minus1[2] - )); - Echo(n, " = ", factor, " * ", n/factor); - ] - ); - k--; - ]; - prime; -]; - - -/* - * This is the frontend function, which uses RabinMillerSmall for - * ``small'' numbers and RabinMillerProbabilistic for bigger ones. - * - * The probability to err is set to 1e-25, hopping this is less - * than the one to step on a rattlesnake in northern Groenland. :-) - */ - -RabinMiller(n_IsPositiveInteger) <-- -[ - If(InVerboseMode(), Echo("RabinMiller: Info: Testing ", n)); - If( - n < 34155071728321, - RabinMillerSmall(n), - RabinMillerProbabilistic(n, 40) // 4^(-40) - ); -]; - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/radsimp/RadSimp.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/radsimp/RadSimp.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/radsimp/RadSimp.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/radsimp/RadSimp.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,120 +0,0 @@ -%mathpiper,def="RadSimp" - - -/* Simplification of nested radicals. -*/ - -RadSimp(_n) <-- -[ - Local(max, result); - Set(max, CeilN(N(Eval(n^2)))); - Set(result,0); - Set(result,RadSimpTry(n,0,1,max)); - -//Echo("result is ",result); - if (CheckRadicals(n,result)) - result - else - n; -]; - -/*Echo({"Try ",test}); */ - -CheckRadicals(_n,_test) <-- Abs(N(Eval(n-test),20)) < 0.000001; - -10 # ClampRadicals(_r)_(N(Eval(Abs(r)), 20)<0.000001) <-- 0; -20 # ClampRadicals(_r) <-- r; - - - -RadSimpTry(_n,_result,_current,_max)<-- -[ -//Echo(result," ",n," ",current); - if (LessThan(N(Eval(result-n)), 0)) - [ - Local(i); - - // First, look for perfect match - i:=BSearch(max,Hold({{try},ClampRadicals(N(Eval((result+Sqrt(try))-n),20))})); - If(i>0, - [ - Set(result,result+Sqrt(i)); - Set(i,AddN(max,1)); - Set(current,AddN(max,1)); - ]); - - // Otherwise, search for another solution - if (LessThan(N(Eval(result-n)), 0)) - [ - For (Set(i,current),i<=max,Set(i,AddN(i,1))) - [ - Local(new, test); - Set(test,result+Sqrt(i)); - -/* Echo({"Full-try ",test}); */ - - Set(new,RadSimpTry(n,test,i,max)); - if (CheckRadicals(n,new)) - [ - Set(result,new); - Set(i,AddN(max,1)); - ]; - ]; - ]; - ]; - result; -]; - - -%/mathpiper - - - -%mathpiper_docs,name="RadSimp",categories="User Functions;Expression Simplification" -*CMD RadSimp --- simplify expression with nested radicals -*STD -*CALL - RadSimp(expr) - -*PARMS - -{expr} -- an expression containing nested radicals - -*DESC - -This function tries to write the expression "expr" as a sum of roots -of integers: $Sqrt(e1) + Sqrt(e2) + ...$, where $e1$, $e2$ and -so on are natural numbers. The expression "expr" may not contain -free variables. - -It does this by trying all possible combinations for $e1$, $e2$, ... -Every possibility is numerically evaluated using {N} and compared with the numerical evaluation of -"expr". If the approximations are equal (up to a certain margin), -this possibility is returned. Otherwise, the expression is returned -unevaluated. - -Note that due to the use of numerical approximations, there is a small -chance that the expression returned by {RadSimp} is -close but not equal to {expr}. The last example underneath -illustrates this problem. Furthermore, if the numerical value of -{expr} is large, the number of possibilities becomes exorbitantly -big so the evaluation may take very long. - -*E.G. - - In> RadSimp(Sqrt(9+4*Sqrt(2))) - Out> Sqrt(8)+1; - In> RadSimp(Sqrt(5+2*Sqrt(6)) \ - +Sqrt(5-2*Sqrt(6))) - Out> Sqrt(12); - In> RadSimp(Sqrt(14+3*Sqrt(3+2 - *Sqrt(5-12*Sqrt(3-2*Sqrt(2)))))) - Out> Sqrt(2)+3; - -But this command may yield incorrect results: - - In> RadSimp(Sqrt(1+10^(-6))) - Out> 1; - -*SEE Simplify, N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomIntegerMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomIntegerMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomIntegerMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomIntegerMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="RandomIntegerMatrix" - -RandomIntegerMatrix(_rows,_cols,_coefmin,_coefmax) <-- - GenMatrix({{i,j}, FloorN(coefmin+Random()*(coefmax+1-coefmin))}, rows, cols ); - -%/mathpiper - - - - -%mathpiper_docs,name="RandomIntegerMatrix",categories="User Functions;Numbers (Random)" -*CMD RandomIntegerMatrix --- generate a matrix of random integers - -*STD - -*CALL - RandomIntegerMatrix(rows,cols,from,to) - -*PARMS - -{rows} -- number of rows in matrix - -{cols} -- number of cols in matrix - -{from} -- lower bound - -{to} -- upper bound - -*DESC - -This function generates a {rows x cols} matrix of random integers. All -entries lie between "from" and "to", including the boundaries, and -are uniformly distributed in this interval. - -*E.G. - In> PrettyForm( RandomIntegerMatrix(5,5,-2^10,2^10) ) - - / \ - | ( -506 ) ( 749 ) ( -574 ) ( -674 ) ( -106 ) | - | | - | ( 301 ) ( 151 ) ( -326 ) ( -56 ) ( -277 ) | - | | - | ( 777 ) ( -761 ) ( -161 ) ( -918 ) ( -417 ) | - | | - | ( -518 ) ( 127 ) ( 136 ) ( 797 ) ( -406 ) | - | | - | ( 679 ) ( 854 ) ( -78 ) ( 503 ) ( 772 ) | - \ / - -*SEE RandomPoly, Random, RandomInteger, RandomIntegerVector -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomInteger.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomInteger.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomInteger.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomInteger.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="RandomInteger" - - -10 # RandomInteger(n_IsPositiveInteger) <-- CeilN(Random()*n); - - - -10 # RandomInteger(lowerBoundInclusive_IsInteger, upperBoundInclusive_IsInteger) <-- -[ - Local(difference); - - difference := upperBoundInclusive - lowerBoundInclusive; - - Round(Random() * difference) + lowerBoundInclusive; -]; - - -%/mathpiper - - - - -%mathpiper_docs,name="RandomInteger",categories="User Functions;Numbers (Random)" -*CMD RandomInteger --- generate a random integer - -*STD - -*CALL - RandomInteger(upper_bound) - RandomInteger(lower_bound, upper_bound) - -*PARMS - -{lower_bound} -- the smallest integer that can be generated - -{upper_bound} -- the largest integer that can be generated - - -*DESC - -The single argument version of this function generates a random integer between -1 and the given upper bound integer (inclusive). The two argument version of -the function generates a random integer between a lower bound integer and an -upper bound integer (both inclusive). - -*E.G. -In> RandomInteger(5) -Result> 4 - -In> Repeat(10) Write(RandomInteger(5),,) -Result> 10 -Side Effects>4,3,5,1,2,2,3,5,3,3, - -In> RandomInteger(5,10) -Result: 5 - -In> Repeat(10) Write(RandomInteger(5, 10),,) -Result: 10 -Side Effects: -8,9,9,5,6,8,9,10,8,7, - -*SEE Random, RandomPoly, RandomIntegerVector, RandomIntegerMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomIntegerVector.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomIntegerVector.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomIntegerVector.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomIntegerVector.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="RandomIntegerVector" - -RandomIntegerVector(_count,_coefmin,_coefmax) <-- - Table(FloorN(coefmin+Random()*(coefmax+1-coefmin)),i,1,count,1); - -%/mathpiper - - - - -%mathpiper_docs,name="RandomIntegerVector",categories="User Functions;Numbers (Random)" -*CMD RandomIntegerVector --- generate a vector of random integers - -*STD - -*CALL - RandomIntegerVector(nr, from, to) - -*PARMS - -{nr} -- number of integers to generate - -{from} -- lower bound - -{to} -- upper bound - -*DESC - -This function generates a list with "nr" random integers. All -entries lie between "from" and "to", including the boundaries, and -are uniformly distributed in this interval. - -*E.G. - - In> RandomIntegerVector(4,-3,3) - Out> {0,3,2,-2}; - -*SEE Random, RandomPoly, RandomInteger, RandomIntegerMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/random.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/random.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/random.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/random.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,412 +0,0 @@ -%mathpiper,def="RandomSeed;Random;Rng;RngSeed;RngCreate" - -/* def file definitions - -RandomSeed -Random -Rng -RngSeed -RngCreate -*/ - -/* -Random number generators implemented in an object-oriented manner. - -Old interface (still works): - - RandomSeed(123); - Random(); Random(); - -It provides only one global RNG with a globally assigned seed. - -New interface allows creating many RNG objects: - - r1:=RngCreate(); // create a default RNG object, assign structure to r1 - r2:=RngCreate(12345); // create RNG object with given seed - r3:=RngCreate(seed->0, engine->advanced, dist->gauss); // extended options: specify seed, type of RNG engine and the type of statistical distribution - Rng(r1); Rng(r1); Rng(r2); // generate some floating-point numbers - RngSeed(r1, 12345); // r1 is re-initialized with given seed, r2 is unaffected - -More "RNG engines" and "RNG distribution adaptors" can be defined later (at run time). - -RngCreate() will return an object of the following structure: - {SomeDist, SomeEngine, state } - -here SomeEngine is a function atom that describes the RNG engine, -SomeDist is a function atom that specifies the distribution adaptor, -and state is a "RNG state object", e.g. a list of all numbers that specify the current RNG state (seeds, temporaries, etc.). - -RngSeed(r1, seed) expects an integer seed. -It will re-initialize the RNG object r1 with the given seed. - -The "RNG engine API": calling RngCreate with engine->SomeEngine expects that: - SomeEngine(seed_IsInteger) will create and initialize a state object with given seed and return the new state object (a list). SomeEngine can assume that "seed" is a positive integer. - SomeEngine(state1_IsList) will update the RNG state object state1 and return the pair {new state object, new number}. - -The "RNG distribution adaptor API": calling RngCreate with distribution->SomeDist expects that: - SomeDist(r1) will update the RNG object r1 and return the pair {new state object, new number}. r1 is a full RNG object, not just a state object. - - -*/ - -////////////////////////////////////////////////// -/// lists of defined RNG entities -////////////////////////////////////////////////// - -/// The idea is that options must be easy to type, but procedure names could be long. - -LocalSymbols(knownRNGEngines, knownRNGDists) [ - knownRNGEngines := - { - { "default", "RNGEngine'LCG'2"}, - { "advanced", "RNGEngine'L'Ecuyer"}, - }; - - knownRNGDists := - { - {"default", "FlatRNGDist"}, - {"flat", "FlatRNGDist"}, - // {"uniform", "FlatRNGDist"}, // we probably don't need this alias... - {"gauss", "GaussianRNGDist"}, - }; - - KnownRNGDists() := knownRNGDists; - KnownRNGEngines() := knownRNGEngines; -]; - - -////////////////////////////////////////////////// -/// RNG object API -////////////////////////////////////////////////// - -Function() RngCreate(); -Function() RngCreate(seed, ...); -HoldArg("RngCreate", seed); // this is needed to prevent evaluation of = and also to prevent substitution of variables, e.g. if "seed" is defined -//UnFence("RngCreate", 0); -//UnFence("RngCreate", 1); -Function() RngSeed(r, seed); -//UnFence("RngSeed", 2); -/// accessor for RNG objects -Function() Rng(r); -//UnFence("Rng", 1); - - -RngCreate() <-- RngCreate(0); - -10 # RngCreate(a'seed_IsInteger) <-- (RngCreate @ {Atom("seed") -> a'seed}); - -// a single option given: convert explicitly to a list -20 # RngCreate(_key -> _value) <-- (RngCreate @ {{key -> value}}); -20 # RngCreate(_key = _value) <-- (RngCreate @ {{key -> value}}); - -// expect a list of options -30 # RngCreate(options_IsList) <-- -[ - options := OptionsListToHash @ {options}; - // check options and assign defaults - If( - options["seed"] = Empty Or options["seed"] <= 0, - options["seed"] := 76544321 // some default seed out of the blue sky - ); - If( - options["engine"] = Empty Or Not (Assert("warning", {"RngCreate: invalid engine", options["engine"]}) KnownRNGEngines()[options["engine"] ] != Empty), - options["engine"] := "default" - ); - If( - options["dist"] = Empty Or Not (Assert("warning", {"RngCreate: invalid distribution", options["dist"]}) KnownRNGDists()[options["dist"] ] != Empty), - options["dist"] := "default" - ); - - // construct a new RNG object - // a RNG object has the form {"SomeDist", "SomeEngine", {state}} - { - KnownRNGDists()[options["dist"] ], KnownRNGEngines()[options["engine"] ], - // initialize object with given seed using "SomeEngine"(seed) - KnownRNGEngines()[options["engine"] ] @ { options["seed"] } - }; -]; - -/// accessor function: will call SomeDist(r) and update r -Rng(_r) <-- -[ - Local(state, result); - {state, result} := (r[1] @ {r}); // this calls SomeDist(r) - DestructiveReplace(r, 3, state); // update RNG object - result; // return floating-point number -]; - -/// set seed: will call SomeEngine(r, seed) and update r -RngSeed(_r, seed_IsInteger) <-- -[ - Local(state); - (Assert("warning", {"RngSeed: seed must be positive", seed}) seed > 0 - ) Or (seed:=76544321); - state := (r[2] @ {seed}); // this calls SomeEngine(r) - DestructiveReplace(r, 3, state); // update object - True; -]; - -////////////////////////////////////////////////// -/// RNG distribution adaptors -////////////////////////////////////////////////// - -/// trivial distribution adaptor: flat distribution, simply calls SomeEngine(r) -/* we have to return whole objects; we can't use references b/c the core -function ApplyPure will not work properly on references, i.e. if r = {"", "", {1}} so that -r[3] = {1}, then LCG'2(r[3]) modifies r[3], but LCG'2 @ r[3] or -ApplyPure("LCG'2", {r[3]}) do not actually modify r[3]. -*/ - -// return pair {state, number} -FlatRNGDist(_r) <-- (r[2] @ {r[3]}); // this calls SomeEngine(state) - -/// Gaussian distribution adaptor, returns a complex number with normal distribution with unit variance, i.e. Re and Im are independent and both have unit variance -/* Gaussian random number, Using the Box-Muller transform, from Knuth, - "The Art of Computer Programming", - Volume 2 (Seminumerical algorithms, third edition), section 3.4.1 - */ -GaussianRNGDist(_rng) <-- -[ - // a Gaussian distributed complex number p + I*q is made up of two uniformly distributed numbers x,y according to the formula: - // a:=2*x-1, b:=2*y-1, m:=a^2+b^2; p = a*Sqrt(-2*Ln(m)/m); q:=b*Sqrt(-2*Ln(m)/m); - // here we need to make sure that m is nonzero and strictly less than 1. - Local(a,b,m, new'state, rnumber); - new'state := rng[3]; // this will be updated at the end - m:=0; - While(m=0 Or m>=1) // repeat generating new x,y - should not take more than one iteration really - [ - {new'state, rnumber} := (rng[2] @ {new'state}); - a:=2*rnumber-1; - {new'state, rnumber} := (rng[2] @ {new'state}); - b:=2*rnumber-1; - m:=a*a+b*b; - ]; - {new'state, (a+I*b)*SqrtN(-2*DivideN(Internal'LnNum(m),m))}; -]; - - -////////////////////////////////////////////////// -/// RNG engines -////////////////////////////////////////////////// - -/// default RNG engine: the LCG generator - -// first method: initialize a state object with given seed -RNGEngine'LCG'1(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'1(state_IsList) <-- LCG'1(state); - -// first method: initialize a state object with given seed -RNGEngine'LCG'2(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'2(state_IsList) <-- LCG'2(state); - -// first method: initialize a state object with given seed -RNGEngine'LCG'3(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'3(state_IsList) <-- LCG'3(state); - -// first method: initialize a state object with given seed -RNGEngine'LCG'4(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'4(state_IsList) <-- LCG'4(state); - -/// parameters from P. Hellekalek, 1994; see G. S. Fishman, Math. Comp. vol. 54, 331 (1990) -LCG'1(state) := RandomLCG(state, 2147483647,950706376,0); -LCG'2(state) := RandomLCG(state, 4294967296,1099087573,0); -LCG'3(state) := RandomLCG(state, 281474976710656,68909602460261,0); -LCG'4(state) := RandomLCG(state, 18014398509481984,2783377640906189,0); - -/// Linear congruential generator engine: backend -// state is a list with one element -RandomLCG(_state, _im, _ia, _ic) <-- -{ - DestructiveReplace(state,1, ModN(state[1]*ia+ic,im)), - DivideN(state[1], im) // division should never give 1 -}; - -/// Advanced RNG engine due to L'Ecuyer et al. -/// RNG from P. L'ecuyer et al (2000). Period approximately 2^191 -// state information: 6 32-bit integers, corresponding to {x3,x2,x1,y3,y2,y1} - -// first method: initialize a state object with given seed -RNGEngine'L'Ecuyer(a'seed_IsInteger) <-- -[ - // use LCG'2 as auxiliary RNG to fill the seeds - Local(rng'aux, result); - rng'aux := (RngCreate @ {a'seed}); - // this will be the state vector - result:=ZeroVector(6); - // fill the state object with random numbers - Local(i); - For(i:=1, i<=6, i++) - [ - Rng(rng'aux); - result[i] := rng'aux[3][1]; // hack to get the integer part - ]; - // return the state object - result; -]; - -// second method: update state object and return a new random number (floating-point) -RNGEngine'L'Ecuyer(state_IsList) <-- -[ - Local(new'state, result); - new'state := { - Mod(1403580*state[2]-810728*state[3], 4294967087), state[1], state[2], - Mod(527612*state[4]-1370589*state[6], 4294944433), state[4], state[5] - }; - result:=Mod(state[1]-state[4], 4294967087); - { - new'state, - DivideN(If(result=0, 4294967087, result), 4294967088) - }; -]; - -////////////////////////////////////////////////// -/// old interface: using one global RNG object -////////////////////////////////////////////////// -/* this is a little slower but entirely equivalent to the code below -GlobalRNG := RngCreate(76544321); -Random() := Rng(GlobalRNG); -RandomSeed(seed) := RngSeed(GlobalRNG, seed); -*/ - -LocalSymbols(RandSeed) [ - // initial seed should be nonzero - RandSeed:=76544321; - - /// assign random seed - Function("RandomSeed", {seed}) Set(RandSeed, seed); - - /// Linear congruential generator - RandomLCG(_im, _ia, _ic) <-- - [ - RandSeed:=ModN(RandSeed*ia+ic,im); - DivideN(RandSeed,im); // should never give 1 - ]; -]; // LocalSymbols(RandSeed) - - -Function("Random1",{}) RandomLCG(4294967296,1103515245,12345); -Function("Random6",{}) RandomLCG(1771875,2416,374441); -/// parameters from P. Hellekalek, 1994; see G. S. Fishman, Math. Comp. vol. 54, 331 (1990) -Function("Random2",{}) RandomLCG(2147483647,950706376,0); -Function("Random3",{}) RandomLCG(4294967296,1099087573,0); -Function("Random4",{}) RandomLCG(281474976710656,68909602460261,0); -Function("Random5",{}) RandomLCG(18014398509481984,2783377640906189,0); - -// select one of them -Function("Random",{}) Random3(); - - -%/mathpiper - - - - - -%mathpiper_docs,name="Random;RandomSeed",categories="User Functions;Numbers (Random)" -*CMD Random, RandomSeed --- (pseudo-) random number generator -*STD -*CALL - Random() - RandomSeed(init) - -*PARAMS -{init} -- positive integer, initial random seed - -*DESC - -The function {Random} returns a random number, uniformly distributed in the -interval between 0 and 1. The same sequence of random numbers is -generated in every MathPiper session. - -The random number generator can be initialized by calling {RandomSeed} with an integer value. -Each seed value will result in the same sequence of pseudo-random numbers. - -*SEE RandomInteger, RandomPoly, Rng, Random, RandomIntegerVector, RandomIntegerMatrix -%/mathpiper_docs - - - - - -%mathpiper_docs,name="RngCreate;RngSeed;Rng",categories="User Functions;Numbers (Random)" -*CMD RngCreate --- manipulate random number generators as objects -*CMD RngSeed --- manipulate random number generators as objects -*CMD Rng --- manipulate random number generators as objects -*STD -*CALL - RngCreate() - RngCreate(init) - RngCreate(option->value,...) - RngSeed(r, init) - Rng(r) - -*PARMS -{init} -- integer, initial seed value - -{option} -- atom, option name - -{value} -- atom, option value - -{r} -- a list, RNG object - -*DESC -These commands are an object-oriented interface to (pseudo-)random number generators (RNGs). - -{RngCreate} returns a list which is a well-formed RNG object. -Its value should be saved in a variable and used to call {Rng} and {RngSeed}. - -{Rng(r)} returns a floating-point random number between 0 and 1 and updates the RNG object {r}. -(Currently, the Gaussian option makes a RNG return a complex random number instead of a real random number.) - -{RngSeed(r,init)} re-initializes the RNG object {r} with the seed value {init}. -The seed value should be a positive integer. - -The {RngCreate} function accepts several options as arguments. -Currently the following options are available: - -* {seed} -- specify initial seed value, must be a positive integer -* {dist} -- specify the distribution of the random number; currently {flat} and {gauss} are implemented, and the default is the flat (uniform) distribution -* {engine} -- specify the RNG engine; currently {default} and {advanced} are available ("advanced" is slower but has much longer period) - -If the initial seed is not specified, the value of 76544321 will be used. - -The {gauss} option will create a RNG object that generates pairs of Gaussian distributed random numbers as a complex random number. -The real and the imaginary parts of this number are independent random numbers taken from a Gaussian (i.e. "normal") distribution with unit variance. - -For the Gaussian distribution, the Box-Muller transform method is used. -A good description of this method, along with the proof that the method -generates normally distributed random numbers, can be found in Knuth, -"The Art of Computer Programming", Volume 2 (Seminumerical algorithms, third -edition), section 3.4.1 - -Note that unlike the global {Random} function, the RNG objects created with {RngCreate} are independent RNGs and do not affect each other. -They generate independent streams of pseudo-random numbers. -However, the {Random} function is slightly faster. - -*E.G. - - In> r1:=RngCreate(seed=1,dist=gauss) - Out> {"GaussianRNGDist","RNGEngine'LCG'2",{1}} - In> Rng(r1) - Out> Complex(-1.6668466417,0.228904004); - In> Rng(r1); - Out> Complex(0.0279296109,-0.5382405341); -The second RNG gives a uniform distribution (default option) but uses a more complicated algorithm: - In> [r2:=RngCreate(engine=advanced);Rng(r2);] - Out> 0.3653615377; -The generator {r1} can be re-initialized with seed 1 again to obtain the same sequence: - In> RngSeed(r1, 1) - Out> True; - In> Rng(r1) - Out> Complex(-1.6668466417,0.228904004); - - -*SEE Random, RandomInteger, RandomIntegerVector, RandomIntegerMatrix -%/mathpiper_docs - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomPoly.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomPoly.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/random/RandomPoly.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/random/RandomPoly.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="RandomPoly" - -/* Generate a random polynomial */ - -RandomPoly(_var,_degree,_coefmin,_coefmax) <-- - NormalForm(UniVariate(var,0,RandomIntegerVector(degree+1,coefmin,coefmax))); - -%/mathpiper - - - - -%mathpiper_docs,name="RandomPoly",categories="User Functions;Numbers (Random)" -*CMD RandomPoly --- construct a random polynomial -*STD -*CALL - RandomPoly(var,deg,coefmin,coefmax) - -*PARMS - -{var} -- free variable for resulting univariate polynomial - -{deg} -- degree of resulting univariate polynomial - -{coefmin} -- minimum value for coefficients - -{coefmax} -- maximum value for coefficients - -*DESC - -RandomPoly generates a random polynomial in variable "var", of -degree "deg", with integer coefficients ranging from "coefmin" to -"coefmax" (inclusive). The coefficients are uniformly distributed in -this interval, and are independent of each other. - -*E.G. - - In> RandomPoly(x,3,-10,10) - Out> 3*x^3+10*x^2-4*x-6; - In> RandomPoly(x,3,-10,10) - Out> -2*x^3-8*x^2+8; - -*SEE Random, RandomInteger, RandomIntegerVector, RandomIntegerMatrix -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/Eliminate.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/Eliminate.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/Eliminate.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/Eliminate.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -%mathpiper,def="Eliminate" - -Eliminate(_var,_replace,_function) <-- Simplify(Subst(var,replace)function); - -%/mathpiper - - - -%mathpiper_docs,name="Eliminate",categories="User Functions;Solvers (Symbolic)" -*CMD Eliminate --- substitute and simplify -*STD -*CALL - Eliminate(var, value, expr) - -*PARMS - -{var} -- variable (or subexpression) to substitute - -{value} -- new value of "var" - -{expr} -- expression in which the substitution should take place - -*DESC - -This function uses {Subst} to replace all instances -of the variable (or subexpression) "var" in the expression "expr" -with "value", calls {Simplify} to simplify the -resulting expression, and returns the result. - -*E.G. - - In> Subst(Cos(b), c) (Sin(a)+Cos(b)^2/c) - Out> Sin(a)+c^2/c; - In> Eliminate(Cos(b), c, Sin(a)+Cos(b)^2/c) - Out> Sin(a)+c; - -*SEE SuchThat, Subst, Simplify -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/ExpandBrackets.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/ExpandBrackets.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/ExpandBrackets.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/ExpandBrackets.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="ExpandBrackets" - -//ExpandBrackets(_xx) <-- SimpExpand(SimpImplode(SimpFlatten(xx))); -ExpandBrackets(x) := NormalForm(MM(x)); - -%/mathpiper - - - -%mathpiper_docs,name="ExpandBrackets",categories="User Functions;Polynomials (Operations)" -*CMD ExpandBrackets --- expand all brackets -*STD -*CALL - ExpandBrackets(expr) - -*PARMS - -{expr} -- an expression - -*DESC - -This command tries to expand all the brackets by repeatedly using the -distributive laws $a * (b+c) = a*b + a*c$ and $(a+b) * c = a*c + b*c$. -It goes further than {Expand}, in that it expands all brackets. - -*E.G. - - In> Expand((a-x)*(b-x),x) - Out> x^2-(b+a)*x+a*b; - In> Expand((a-x)*(b-x),{x,a,b}) - Out> x^2-(b+a)*x+b*a; - In> ExpandBrackets((a-x)*(b-x)) - Out> a*b-x*b+x^2-a*x; - -*SEE Expand -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/ExpandFrac.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/ExpandFrac.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/ExpandFrac.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/ExpandFrac.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -%mathpiper,def="ExpandFrac" - -////////////////////////////////////////////////// -/// ExpandFrac --- normalize rational functions (no simplification) -////////////////////////////////////////////////// - -5 # ExpandFrac(expr_IsList) <-- MapSingle("ExpandFrac", expr); - -// expression does not contain fractions -10 # ExpandFrac(_expr)_Not(HasFuncSome(expr, "/", {Atom("+"), Atom("-"), *, /, ^})) <-- expr; -15 # ExpandFrac(a_IsRationalOrNumber) <-- a; -20 # ExpandFrac(_expr) <-- ExpandFrac'combine(GetNumerDenom(expr)); - -ExpandFrac'combine({_a, _b}) <-- a/b; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/factorial/FactorialSimplify.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/factorial/FactorialSimplify.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/factorial/FactorialSimplify.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/factorial/FactorialSimplify.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,297 +0,0 @@ -%mathpiper,def="FactorialSimplify" - - -/* FactorialSimplify algorithm: - 1) expand binomials into factors - 2) expand brackets as much as possible - 3) for the remaining rational expressions x/y, - take all the factors of x and y, and match them - up one by one to determine if they can be - factored out. The algorithm will look at expressions like x^n/x^m - where (n-m) is an integer, or at expressions x!/y! where (x-y) - is an integer. The routine CommonDivisors does these steps, and - returns the new numerator and denominator factor. - FactorialSimplifyWorker does the actual O(n^2) algorithm of - matching all terms up. -*/ - -FactorialNormalForm(x):= -[ - // Substitute binomials - x:=(x/:{BinomialCoefficient(_n,_m)<- (n!)/((m!)*(n-m)!)}); - // Expand expression as much as possible so that the terms become - // simple rationals. - - x:=( - x/::Hold({ - (_a/_b)/_c <- (a)/(b*c), - (-(_a/_b))/_c <- (-a)/(b*c), - (_a/_b)*_c <- (a*c)/b, - (_a*_b)^_m <- a^m*b^m, - (_a/_b)^_m*_c <- (a^m*c)/b^m, - _a*(_b+_c) <- a*b+a*c, - (_b+_c)*_a <- a*b+a*c, - (_b+_c)/_a <- b/a+c/a, - _a*(_b-_c) <- a*b-a*c, - (_b-_c)*_a <- a*b-a*c, - (_b-_c)/_a <- b/a-c/a - })); - x; -]; - -FactorialSimplify(x):= -[ - x := FactorialNormalForm(x); - FactorialSimplifyWorker(x); -]; - - -/* CommonDivisors takes two parameters x and y as input, determines a common divisor g - and then returns {x/g,y/g,g}. - */ -10 # CommonDivisors(_x^(_n),_x^(_m)) <-- {x^Simplify(n-m),1,x^m}; -10 # CommonDivisors(_x^(_n),_x) <-- {x^Simplify(n-1),1,x}; -10 # CommonDivisors(_x,_x^(_m)) <-- {x^Simplify(1-m),1,x^m}; -10 # CommonDivisors((_x) !,_x) <-- {(x-1)!,1,x}; -10 # CommonDivisors(_x,_x) <-- {1,1,x}; -10 # CommonDivisors(- _x,_x) <-- {-1,1,x}; -10 # CommonDivisors(_x,- _x) <-- {1,-1,x}; -10 # CommonDivisors((_x),(_x)!) <-- {1,(x-1)!,x}; -10 # CommonDivisors((_x)!, (_y)!)_IsInteger(Simplify(x-y)) <-- CommonFact(Simplify(x-y),y); - - -10 # CommonDivisors((_x)! ^ _m, (_y)! ^ _m)_IsInteger(Simplify(x-y)) <-- CommonFact(Simplify(x-y),y)^m; - -10 # CommonFact(dist_IsNegativeInteger,_y) - <-- {1,Product(i,1,-dist,Simplify(y+i+dist)),Simplify(y+dist)!}; -11 # CommonFact(_dist,_y) - <-- {Product(i,1,dist,Simplify(y+i)),1,Simplify(y)!}; -60000 # CommonDivisors(_x,_y) <-- {x,y,1}; - -10 # CommonFactors((_x)!,_y)_(Simplify(y-x) = 1) <-- {y!,1}; -10 # CommonFactors((_x)!,_y)_(Simplify((-y)-x) = 1) <-- {(-y)!,-1}; - -10 # CommonFactors(_x^_n,_x^_m) <-- {x^Simplify(n+m),1}; -10 # CommonFactors(_x^_n,_x) <-- {x^Simplify(n+1),1}; - -60000 # CommonFactors(_x,_y) <-- {x,y}; - -10 # FactorialSimplifyWorker(_x+_y) <-- FactorialSimplifyWorker(x)+FactorialSimplifyWorker(y); -10 # FactorialSimplifyWorker(_x-_y) <-- FactorialSimplifyWorker(x)-FactorialSimplifyWorker(y); -10 # FactorialSimplifyWorker( -_y) <-- -FactorialSimplifyWorker(y); - -LocalSymbols(x,y,i,j,n,d)[ - -20 # FactorialSimplifyWorker(_x/_y) <-- -[ - // first separate out factors of the denominator - Local(numerCommon,numerTerms); - {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); - Local(denomCommon,denomTerms); - {denomCommon,denomTerms}:=FactorialGroupCommonDivisors(y); - Local(n,d,c); - {n,d,c} := FactorialDivideTerms(numerCommon,denomCommon); - (n/d)*Simplify((numerTerms)/(denomTerms)); -]; - - - -20 # FactorialGcd(_x,_y) <-- -[ - // first separate out factors of the denominator - Local(numerCommon,numerTerms); - {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); - Local(denomCommon,denomTerms); - {denomCommon,denomTerms}:=FactorialGroupCommonDivisors(y); - Local(n,d,c); - {n,d,c} := FactorialDivideTerms(numerCommon,denomCommon); - c; -]; - - - - - -10 # FactorialDivideTerms(- _x,- _y) <-- FactorialDivideTermsAux(x,y); -LocalSymbols(n,d,c) -[ - 20 # FactorialDivideTerms(- _x, _y) - <-- - [ - Local(n,d,c); - {n,d,c} := FactorialDivideTermsAux(x,y); - {-n,d,c}; - ]; - 30 # FactorialDivideTerms( _x,- _y) - <-- - [ - Local(n,d,c); - {n,d,c} := FactorialDivideTermsAux(x,y); - {n,-d,c}; - ]; -]; -40 # FactorialDivideTerms( _x, _y) - <-- - [ -// Echo("GOTHERE 40"); - FactorialDivideTermsAux(x,y); - ]; - -LocalSymbols(n,d,c) -[ - 10 # FactorialDivideTermsAux(_x,_y) <-- - [ - x:=Flatten(x,"*"); - y:=Flatten(y,"*"); - - Local(i,j,common); - common:=1; - For(i:=1,i<=Length(x),i++) - For(j:=1,j<=Length(y),j++) - [ - Local(n,d,c); -//Echo("inp is ",x[i]," ",y[j]); - {n,d,c} := CommonDivisors(x[i],y[j]); - -//Echo("aux is ",{n,d,c}); - x[i] := n; - y[j] := d; - common:=common*c; - ]; -//Echo("final ",{x,y,common}); -//Echo("finalor ",{Product(x),Product(y),common}); - {Product(x),Product(y),common}; - ]; -]; - -]; - -60000 # FactorialSimplifyWorker(_x) - <-- - [ - // first separate out factors of the denominator - Local(numerCommon,numerTerms); - {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); - numerCommon*numerTerms; - ]; - -/* FactorialFlattenAddition accepts an expression of form a+b+c-d+e-f+ ... +z with arbitrary additions - and subtractions, and converts it to a list of terms. Terms that need to be subtracted start with a - negation sign (useful for pattern matching). - */ -10 # FactorialFlattenAddition(_x+_y) <-- Concat(FactorialFlattenAddition(x), FactorialFlattenAddition(y)); -10 # FactorialFlattenAddition(_x-_y) <-- Concat(FactorialFlattenAddition(x),-FactorialFlattenAddition(y)); -10 # FactorialFlattenAddition( -_y) <-- -FactorialFlattenAddition(y); -20 # FactorialFlattenAddition(_x ) <-- {x}; - -LocalSymbols(n,d,c) -[ - 10 # FactorialGroupCommonDivisors(_x) <-- - [ - Local(terms,common,tail); - terms:=FactorialFlattenAddition(x); -//Echo("terms is ",terms); - common := First(terms); - tail:=Rest(terms); - While (tail != {}) - [ - Local(n,d,c); - {n,d,c} := FactorialDivideTerms(common,First(tail)); - -//Echo(common, " ",First(tail)," ",c); - common := c; - tail:=Rest(tail); - ]; - Local(i,j); - -// Echo("common is ",common); - - For(j:=1,j<=Length(terms),j++) - [ - Local(n,d,c); -// Echo("IN = ",terms[j]," ",common); -// Echo("n = ",n); - {n,d,c} := FactorialDivideTerms(terms[j],common); -// Echo("n = ",n); -// Echo("{n,d,c} = ",{n,d,c}); - Check(d = 1, - ToString()[ - Echo("FactorialGroupCommonDivisors failure 1 : ",d); - ]); -/* - Check(Simplify(c-common) = 0, - ToString() - [ - Echo("FactorialGroupCommonDivisors failure 2 : "); - Echo(c," ",common); - Echo(Simplify(c-common)); - ]); -*/ - terms[j] := n; - ]; - terms:=Add(terms); - - common:=Flatten(common,"*"); - For(j:=1,j<=Length(common),j++) - [ - Local(f1,f2); - {f1,f2}:=CommonFactors(common[j],terms); - common[j]:=f1; - terms:=f2; - - For(i:=1,i<=Length(common),i++) - If(i != j, - [ - {f1,f2}:=CommonFactors(common[j],common[i]); - common[j]:=f1; - common[i]:=f2; - ]); - ]; - common := Product(common); - {common,terms}; - ]; -]; - - - -%/mathpiper - - - -%mathpiper_docs,name="FactorialSimplify",categories="User Functions;Expression Simplification" -*CMD FactorialSimplify --- Simplify hypergeometric expressions containing factorials -*STD -*CALL - FactorialSimplify(expression) - -*PARMS - -{expression} -- expression to simplify - -*DESC - -{FactorialSimplify} takes an expression that may contain factorials, -and tries to simplify it. An expression like $ (n+1)! / n! $ would -simplify to $(n+1)$. - -The following steps are taken to simplify: - -* 1. binomials are expanded into factorials -* 2. the expression is flattened as much as possible, to reduce it to a sum of simple rational terms -* 3. expressions like $ p^n/p^m $ are reduced to $p^(n-m)$ if $n-m$ is an integer -* 4. expressions like $ n! / m! $ are simplified if $n-m$ is an integer - -The function {Simplify} is used to determine if the relevant expressions $n-m$ -are integers. - -*E.G. - - In> FactorialSimplify( (n-k+1)! / (n-k)! ) - Out> n+1-k - In> FactorialSimplify(n! / BinomialCoefficient(n,k)) - Out> k! *(n-k)! - In> FactorialSimplify(2^(n+1)/2^n) - Out> 2 - -*SEE Simplify, !, BinomialCoefficient -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/Flatten.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/Flatten.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/Flatten.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/Flatten.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="Flatten" - -RuleBase("DoFlatten",{doflattenx}); -UnFence("DoFlatten",1); - -10 # DoFlatten(_doflattenx)_(Type(doflattenx)=flattenoper) <-- - Apply("Concat",MapSingle("DoFlatten",Rest(Listify(doflattenx)))); -20 # DoFlatten(_doflattenx) <-- { doflattenx }; - - -Function("Flatten",{body,flattenoper}) -[ - DoFlatten(body); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Flatten",categories="User Functions;Lists (Operations)" -*CMD Flatten --- flatten expression w.r.t. some operator -*STD -*CALL - Flatten(expression,operator) - -*PARMS - -{expression} -- an expression - -{operator} -- string with the contents of an infix operator. - -*DESC - -Flatten flattens an expression with respect to a specific -operator, converting the result into a list. -This is useful for unnesting an expression. Flatten is typically -used in simple simplification schemes. - -*E.G. - - In> Flatten(a+b*c+d,"+"); - Out> {a,b*c,d}; - In> Flatten({a,{b,c},d},"List"); - Out> {a,b,c,d}; - -*SEE UnFlatten -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/GetNumerDenom.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/GetNumerDenom.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/GetNumerDenom.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/GetNumerDenom.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -%mathpiper,def="GetNumerDenom",scope="private" - -/// GetNumerDenom(x) returns a pair of expressions representing normalized numerator and denominator; GetNumerDenom(x, a) multiplies the numerator by the number a -GetNumerDenom(_expr, _a) <-- GetNumerDenom(expr)*{a,1}; - -// on expressions that are not fractions, we return unit denominator -10 # GetNumerDenom(_expr)_Not(HasFuncSome(expr, "/", {Atom("+"), Atom("-"), *, /, ^})) <-- {expr, 1}; -// rational numbers are not simplified -15 # GetNumerDenom(a_IsRationalOrNumber) <-- {a, 1}; -// arithmetic -20 # GetNumerDenom(_a + _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b)); -20 # GetNumerDenom(_a - _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b, -1)); -20 # GetNumerDenom(- _a) <-- GetNumerDenom(a, -1); -20 # GetNumerDenom(+ _a) <-- GetNumerDenom(a); -20 # GetNumerDenom(_a * _b) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(b)); -20 # GetNumerDenom(_a / _b) <-- ExpandFrac'divide(GetNumerDenom(a), GetNumerDenom(b)); -// integer powers -20 # GetNumerDenom(_a ^ b_IsInteger)_(b > 1) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(a^(b-1))); -20 # GetNumerDenom(_a ^ b_IsInteger)_(b < -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a^(-b))); -20 # GetNumerDenom(_a ^ b_IsInteger)_(b = -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a)); -// non-integer powers are not considered to be rational functions -25 # GetNumerDenom(_a ^ _b) <-- {a^b, 1}; - -// arithmetic on fractions; not doing any simplification here, whereas we might want to -ExpandFrac'add({_a, _b}, {_c, _d}) <-- {a*d+b*c, b*d}; -ExpandFrac'multiply({_a, _b}, {_c, _d}) <-- {a*c, b*d}; -ExpandFrac'divide({_a, _b}, {_c, _d}) <-- {a*d, b*c}; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpAdd.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpAdd.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpAdd.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpAdd.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="SimpAdd",scope="private" - -RuleBase("SimpAdd",{x,y}); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpDiv.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpDiv.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpDiv.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpDiv.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="SimpDiv",scope="private" - -RuleBase("SimpDiv",{x,y}); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpExpand.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpExpand.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpExpand.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpExpand.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -%mathpiper,def="SimpExpand",scope="private" - -10 # SimpExpand(SimpAdd(_x,_y)) <-- SimpExpand(x) + SimpExpand(y); -10 # SimpExpand(SimpMul(_x,_y)) <-- SimpExpand(x) * SimpExpand(y); -10 # SimpExpand(SimpDiv(_x,_y)) <-- SimpExpand(x) / SimpExpand(y); -20 # SimpExpand(_x) <-- x; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpFlatten.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpFlatten.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpFlatten.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpFlatten.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="SimpFlatten",scope="private" - -10 # SimpFlatten((_x)+(_y)) <-- SimpAdd(SimpFlatten(x),SimpFlatten(y)); -10 # SimpFlatten((_x)-(_y)) <-- SimpAdd(SimpFlatten(x),SimpMul(-1,SimpFlatten(y))); -10 # SimpFlatten( -(_y)) <-- SimpMul(-1,SimpFlatten(y)); - -10 # SimpFlatten((_x)*(_y)) <-- SimpMul(SimpFlatten(x),SimpFlatten(y)); -10 # SimpFlatten((_x)/(_y)) <-- SimpDiv(SimpFlatten(x),SimpFlatten(y)); -10 # SimpFlatten((_x)^(n_IsPositiveInteger)) <-- - SimpMul(SimpFlatten(x),SimpFlatten(x^(n-1))); - -100 # SimpFlatten(_x) <-- -[ - x; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpImplode.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpImplode.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpImplode.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpImplode.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="SimpImplode",scope="private" - -/* Distributed multiplication rule */ -10 # SimpImplode(SimpMul(SimpAdd(_x,_y),_z)) <-- - SimpImplode(SimpAdd(SimpImplode(SimpMul(x,z)), - SimpImplode(SimpMul(y,z)))); -10 # SimpImplode(SimpMul(_z,SimpAdd(_x,_y))) <-- - SimpImplode(SimpAdd(SimpImplode(SimpMul(z,x)), - SimpImplode(SimpMul(z,y)))); -/* Distributed division rule */ -10 # SimpImplode(SimpDiv(SimpAdd(_x,_y),_z)) <-- - SimpImplode(SimpAdd(SimpImplode(SimpDiv(x,z)), - SimpImplode(SimpDiv(y,z)))); - - - -20 # SimpImplode(SimpAdd(_x,_y)) <-- - SimpAdd(SimpImplode(x),SimpImplode(y)); -20 # SimpImplode(SimpMul(_x,_y)) <-- - SimpMul(SimpImplode(x),SimpImplode(y)); -20 # SimpImplode(SimpDiv(_x,_y)) <-- - SimpDiv(SimpImplode(x),SimpImplode(y)); -30 # SimpImplode(_x) <-- x; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/Simplify.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/Simplify.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/Simplify.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/Simplify.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%mathpiper,def="Simplify" - -10 # Simplify(expr_IsList) <-- MapSingle("Simplify",expr); - -15 # Simplify(Complex(_r,_i)) <-- Complex(Simplify(r),Simplify(i)); - -20 # Simplify((_xex) == (_yex)) <-- (Simplify(xex-yex) == 0); - -20 # Simplify((_xex) > (_yex)) <-- (Simplify(xex-yex) > 0); -20 # Simplify((_xex) < (_yex)) <-- (Simplify(xex-yex) < 0); -20 # Simplify((_xex) >= (_yex)) <-- (Simplify(xex-yex) >= 0); -20 # Simplify((_xex) <= (_yex)) <-- (Simplify(xex-yex) <= 0); -20 # Simplify((_xex) !== (_yex)) <-- (Simplify(xex-yex) !== 0); - -// conditionals -25 # Simplify(if (_a) _b) <-- "if" @ {Simplify(a), Simplify(b)}; -25 # Simplify(_a else _b) <-- "else" @ {Simplify(a), Simplify(b)}; - -50 # Simplify(_expr) <-- MultiSimp(Eval(expr)); - -%/mathpiper - - - -%mathpiper_docs,name="Simplify",categories="User Functions;Expression Simplification" -*CMD Simplify --- try to simplify an expression -*STD -*CALL - Simplify(expr) - -*PARMS - -{expr} -- expression to simplify - -*DESC - -This function tries to simplify the expression {expr} as much -as possible. It does this by grouping powers within terms, and then -grouping similar terms. - -*E.G. - - In> a*b*a^2/b-a^3 - Out> (b*a^3)/b-a^3; - In> Simplify(a*b*a^2/b-a^3) - Out> 0; - -*SEE TrigSimpCombine, RadSimp -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpMul.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpMul.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/SimpMul.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/SimpMul.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="SimpMul",scope="private" - -RuleBase("SimpMul",{x,y}); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/UnFlatten.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/UnFlatten.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/simplify/UnFlatten.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/simplify/UnFlatten.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="UnFlatten" - -10 # UnFlatten({},_op,_identity) <-- identity; -20 # UnFlatten(list_IsList,_op,_identity) <-- - Apply(op,{First(list),UnFlatten(Rest(list),op,identity)}); - -%/mathpiper - - - -%mathpiper_docs,name="UnFlatten",categories="User Functions;Lists (Operations)" -*CMD UnFlatten --- inverse operation of Flatten -*STD -*CALL - UnFlatten(list,operator,identity) - -*PARMS - -{list} -- list of objects the operator is to work on - -{operator} -- infix operator - -{identity} -- identity of the operator - -*DESC - -UnFlatten is the inverse operation of Flatten. Given -a list, it can be turned into an expression representing -for instance the addition of these elements by calling -UnFlatten with "+" as argument to operator, and 0 as -argument to identity (0 is the identity for addition, since -a+0=a). For multiplication the identity element would be 1. - -*E.G. - - In> UnFlatten({a,b,c},"+",0) - Out> a+b+c; - In> UnFlatten({a,b,c},"*",1) - Out> a*b*c; - -*SEE Flatten -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/CheckSolution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/CheckSolution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/CheckSolution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/CheckSolution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -%mathpiper,def="CheckSolution" - -Retract("CheckSolution",*); - -10 # CheckSolution( _expr, _var, solution_IsList )_(Not IsFreeOf(var,expr)) <-- - [ - Local(expr0,result,s,r); - If( IsEquation(expr), - Set(expr0,EquationLeft(expr)-EquationRight(expr)), - Set(expr0,expr) - ); - result := {}; - ForEach(s,solution) - [ - r := ( expr0 Where s ); - If(r=0,Push(result,s)); - ]; - Reverse(result); - ]; - - -20 # CheckSolution( _expr, _var, _solution ) <-- False; - -%/mathpiper - - - - - -%mathpiper_docs,name="CheckSolution",categories="User Functions;Solve" - -*CMD CheckSolution --- Check the validity of solutions returned by the {Solve} function. -*STD -*CALL - CheckSolution(expr,var,solution) - -*PARMS - -{expr} -- a mathematical expression -{var} -- a varible identifier -{solution} -- a List containing solutions to the equation. - - -*DESC - -The function {Solve} will attempt to find solutions to the equation -{expr}, if {expr} is an actual equatio), or to the equivalent equation -represented by {expr==0} if {expr} is NOT an equation. - -Solutions returned by {Solve} will be in the form of a List, such as -{{var==something,var==something_else}}. - -For certain types of expressions or equation, {Solve} might return -invalid solutions as well as valid ones in the output List. To check -the list of solutions, call the function CheckSolutions(). This function -will return a list containing only the valid solutions from among those -in the list (if any). If none of the "solutions" is valid, this -function will return the empty list. - -*E.G. - -In> ss1 := Solve(x^2==4,x) - -Result: {x==2,x==(-2)} - -In> CheckSolution(x^2==4,x,ss1) - -Result: {x==2,x==(-2)} - -In> CheckSolution(x^2==4,x,{x==2,x==3}) // Deliberately incorrect - -Result: {x==2} - -%/mathpiper_docs - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/Newton.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/Newton.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/Newton.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/Newton.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -%mathpiper,def="Newton" - -Function("Newton",{function,variable,initial,accuracy}) -[ // since we call a function with HoldArg(), we need to evaluate some variables by hand - `Newton(@function,@variable,initial,accuracy,-Infinity,Infinity); -]; - -Function("Newton",{function,variable,initial,accuracy,min,max}) -[ - Local(result,adjust,delta,requiredPrec); - MacroLocal(variable); - requiredPrec := BuiltinPrecisionGet(); - accuracy:=N((accuracy/10)*10); // Making sure accuracy is rounded correctly - BuiltinPrecisionSet(requiredPrec+2); - function:=N(function); - adjust:= -function/Apply("D",{variable,function}); - delta:=10000; - result:=initial; - While (result > min And result < max - // avoid numerical underflow due to fixed point math, FIXME when have real floating math - And N(Eval( Max(Re(delta), -Re(delta), Im(delta), -Im(delta)) ) ) > accuracy) - [ - MacroSet(variable,result); - delta:=N(Eval(adjust)); - result:=result+delta; - ]; - - BuiltinPrecisionSet(requiredPrec); - result:=N(Eval((result/10)*10)); // making sure result is rounded to correct precision - if (result <= min Or result >= max) [result := Fail;]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Newton",categories="User Functions;Solvers (Numeric) -*CMD Newton --- solve an equation numerically with Newton's method -*STD -*CALL - Newton(expr, var, initial, accuracy) - Newton(expr, var, initial, accuracy,min,max) - -*PARMS - -{expr} -- an expression to find a zero for - -{var} -- free variable to adjust to find a zero - -{initial} -- initial value for "var" to use in the search - -{accuracy} -- minimum required accuracy of the result - -{min} -- minimum value for "var" to use in the search - -{max} -- maximum value for "var" to use in the search - -*DESC - -This function tries to numerically find a zero of the expression -{expr}, which should depend only on the variable {var}. It uses -the value {initial} as an initial guess. - -The function will iterate using Newton's method until it estimates -that it has come within a distance {accuracy} of the correct -solution, and then it will return its best guess. In particular, it -may loop forever if the algorithm does not converge. - -When {min} and {max} are supplied, the Newton iteration takes them -into account by returning {Fail} if it failed to find a root in -the given range. Note this doesn't mean there isn't a root, just -that this algorithm failed to find it due to the trial values -going outside of the bounds. - -*E.G. - - In> Newton(Sin(x),x,3,0.0001) - Out> 3.1415926535; - In> Newton(x^2-1,x,2,0.0001,-5,5) - Out> 1; - In> Newton(x^2+1,x,2,0.0001,-5,5) - Out> Fail; - -*SEE Solve, NewtonNum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/OldSolve.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/OldSolve.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/OldSolve.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/OldSolve.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,229 +0,0 @@ -%mathpiper,def="OldSolve" -/********** Solve'System **********/ - -// for now, just use a very simple backsubstitution scheme -Solve'System(_eqns, _vars) <-- Solve'SimpleBackSubstitution(eqns,vars); - -// Check(False, "Solve'System: not implemented"); - -10 # Solve'SimpleBackSubstitution'FindAlternativeForms((_lx) == (_rx)) <-- -[ - Local(newEq); - newEq := (Simplify(lx) == Simplify(rx)); - If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq)); - newEq := (Simplify(lx - rx) == 0); - If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq)); -]; -20 # Solve'SimpleBackSubstitution'FindAlternativeForms(_equation) <-- -[ -]; -UnFence("Solve'SimpleBackSubstitution'FindAlternativeForms",1); - -/* Solving sets of equations using simple backsubstitution. - * Solve'SimpleBackSubstitution takes all combinations of equations and - * variables to solve for, and it then uses SuchThat to find an expression - * for this variable, and then if found backsubstitutes it in the other - * equations in the hope that they become simpler, resulting in a final - * set of solutions. - */ -10 # Solve'SimpleBackSubstitution(eq_IsList,var_IsList) <-- -[ - If(InVerboseMode(), Echo({"Entering Solve'SimpleBackSubstitution"})); - - Local(result,i,j,nrvar,nreq,sub,nrSet,origEq); - eq:=FlatCopy(eq); - origEq:=FlatCopy(eq); - nrvar:=Length(var); - result:={FlatCopy(var)}; - nrSet := 0; - -//Echo("Before: ",eq); - ForEach(equation,origEq) - [ -//Echo("equation ",equation); - Solve'SimpleBackSubstitution'FindAlternativeForms(equation); - ]; -// eq:=Simplify(eq); -//Echo("After: ",eq); - - nreq:=Length(eq); - - /* Loop over each variable, solving for it */ - -/* Echo({eq}); */ - - For(j:=1,j<=nreq And nrSet < nrvar,j++) - [ - Local(vlist); - vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt))); - For(i:=1,i<=nrvar And nrSet < nrvar,i++) - [ - -//Echo("eq[",j,"] = ",eq[j]); -//Echo("var[",i,"] = ",var[i]); -//Echo("varlist = ",vlist); -//Echo(); - - If(Count(vlist,var[i]) = 1, - [ - sub := Listify(eq[j]); - sub := sub[2]-sub[3]; -//Echo("using ",sub); - sub:=SuchThat(sub,var[i]); - If(InVerboseMode(), Echo({"From ",eq[j]," it follows that ",var[i]," = ",sub})); - If(SolveFullSimplify=True, - result:=Simplify(Subst(var[i],sub)result), - result[1][i]:=sub - ); -//Echo("result = ",result," i = ",i); - nrSet++; - -//Echo("current result is ",result); - Local(k,reset); - reset:=False; - For(k:=1,k<=nreq And nrSet < nrvar,k++) - If(Contains(VarListAll(eq[k],`Lambda({pt},Contains(@var,pt))),var[i]), - [ - Local(original); - original:=eq[k]; - eq[k]:=Subst(var[i],sub)eq[k]; - If(Simplify(Simplify(eq[k])) = (0 == 0), - eq[k] := (0 == 0), - Solve'SimpleBackSubstitution'FindAlternativeForms(eq[k]) - ); -// eq[k]:=Simplify(eq[k]); -// eq[k]:=Simplify(eq[k]); //@@@??? TODO I found one example where simplifying twice gives a different result from simplifying once! - If(original!=(0==0) And eq[k] = (0 == 0),reset:=True); - If(InVerboseMode(), Echo({" ",original," simplifies to ",eq[k]})); - ]); - nreq:=Length(eq); - vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt))); - i:=nrvar+1; - // restart at the beginning of the variables. - If(reset,j:=1); - ]); - ]; - ]; - - -//Echo("Finished finding results ",var," = ",result); -// eq:=origEq; -// nreq := Length(eq); - Local(zeroeq,tested); - tested:={}; -// zeroeq:=FillList(0==0,nreq); - - ForEach(item,result) - [ -/* - Local(eqSimplified); - eqSimplified := eq; - ForEach(map,Transpose({var,item})) - [ - eqSimplified := Subst(map[1],map[2])eqSimplified; - ]; - eqSimplified := Simplify(Simplify(eqSimplified)); - - Echo(eqSimplified); - - If(eqSimplified = zeroeq, - [ - DestructiveAppend(tested,Map("==",{var,item})); - ]); -*/ - DestructiveAppend(tested,Map("==",{var,item})); - ]; - - - -/* Echo({"tested is ",tested}); */ - If(InVerboseMode(), Echo({"Leaving Solve'SimpleBackSubstitution"})); - tested; -]; - - - - -/********** OldSolve **********/ -10 # OldSolve(eq_IsList,var_IsList) <-- Solve'SimpleBackSubstitution(eq,var); - - -90 # OldSolve((left_IsList) == right_IsList,_var) <-- - OldSolve(Map("==",{left,right}),var); - - -100 # OldSolve(_left == _right,_var) <-- - SuchThat(left - right , 0 , var); - -/* HoldArg("OldSolve",arg1); */ -/* HoldArg("OldSolve",arg2); */ - -%/mathpiper - - - -%mathpiper_docs,name="OldSolve",categories="User Functions;Solvers (Symbolic)" -*CMD OldSolve --- old version of {Solve} -*STD -*CALL - OldSolve(eq, var) - OldSolve(eqlist, varlist) - -*PARMS - -{eq} -- single identity equation - -{var} -- single variable - -{eqlist} -- list of identity equations - -{varlist} -- list of variables - -*DESC - -This is an older version of {Solve}. It is retained for two -reasons. The first one is philosophical: it is good to have multiple -algorithms available. The second reason is more practical: the newer -version cannot handle systems of equations, but {OldSolve} can. - -This command tries to solve one or more equations. Use the first form -to solve a single equation and the second one for systems of -equations. - -The first calling sequence solves the equation "eq" for the variable -"var". Use the {==} operator to form the equation. -The value of "var" which satisfies the equation, is returned. Note -that only one solution is found and returned. - -To solve a system of equations, the second form should be used. It -solves the system of equations contained in the list "eqlist" for -the variables appearing in the list "varlist". A list of results is -returned, and each result is a list containing the values of the -variables in "varlist". Again, at most a single solution is -returned. - -The task of solving a single equation is simply delegated to {SuchThat}. Multiple equations are solved recursively: -firstly, an equation is sought in which one of the variables occurs -exactly once; then this equation is solved with {SuchThat}; and finally the solution is substituted in the -other equations by {Eliminate} decreasing the number -of equations by one. This suffices for all linear equations and a -large group of simple nonlinear equations. - -*E.G. - - In> OldSolve(a+x*y==z,x) - Out> (z-a)/y; - In> OldSolve({a*x+y==0,x+z==0},{x,y}) - Out> {{-z,z*a}}; - -This means that "x = (z-a)/y" is a solution of the first equation -and that "x = -z", "y = z*a" is a solution of the systems of -equations in the second command. - -An example which {OldSolve} cannot solve: - - In> OldSolve({x^2-x == y^2-y,x^2-x == y^3+y},{x,y}); - Out> {}; - -*SEE Solve, SuchThat, Eliminate, PSolve, == -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/SolveMatrix.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/SolveMatrix.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/SolveMatrix.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/SolveMatrix.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="SolveMatrix" - -Function("SolveMatrix",{matrix,vector}) -[ - Local(perms,indices,inv,det,n); - n:=Length(matrix); - indices:=Table(i,i,1,n,1); - perms:=PermutationsList(indices); - inv:=ZeroVector(n); - det:=0; - ForEach(item,perms) - [ - Local(i,lc); - lc := LeviCivita(item); - det:=det+Product(i,1,n,matrix[i][item[i] ])* lc; - For(i:=1,i<=n,i++) - [ - inv[i] := inv[i]+ - Product(j,1,n, - If(item[j] =i,vector[j ],matrix[j][item[j] ]))*lc; - ]; - ]; - Check(det != 0, "Zero determinant"); - (1/det)*inv; -]; - -%/mathpiper - - - -%mathpiper_docs,name="SolveMatrix",categories="User Functions;Linear Algebra" -*CMD SolveMatrix --- solve a linear system -*STD -*CALL - SolveMatrix(M,v) - -*PARMS - -{M} -- a matrix - -{v} -- a vector - -*DESC - -{SolveMatrix} returns the vector $x$ that satisfies -the equation $M*x = v$. The determinant of $M$ should be non-zero. - -*E.G. - - In> A := {{1,2}, {3,4}}; - Out> {{1,2},{3,4}}; - In> v := {5,6}; - Out> {5,6}; - In> x := SolveMatrix(A, v); - Out> {-4,9/2}; - In> A * x; - Out> {5,6}; - -*SEE Inverse, Solve, PSolve, Determinant -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/solve.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/solve.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/solve.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/solve.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,345 +0,0 @@ -%mathpiper,def="Solve" - -/* def file definitions -Solve -OldSolve -*/ - - -/* - * Strategy for Solve(expr, x): - * - * 10. Call Solve'System for systems of equations. - * 20. Check arguments. - * 30. Get rid of "==" in 'expr'. - * 40. Special cases. - * 50. If 'expr' is a polynomial in 'x', try to use PSolve. - * 60. If 'expr' is a product, solve for either factor. - * 70. If 'expr' is a quotient, solve for the denominator. - * 80. If 'expr' is a sum and one of the terms is free of 'x', - * try to use Solve'Simple. - * 90. If every occurance of 'x' is in the same context, use this to reduce - * the equation. For example, in 'Cos(x) + Cos(x)^2 == 1', the variable - * 'x' always occurs in the context 'Cos(x)', and hence we can attack - * the equation by first solving 'y + y^2 == 1', and then 'Cos(x) == y'. - * This does not work for 'Exp(x) + Cos(x) == 2'. - * 100. Apply Simplify to 'expr', and try again. - * 110. Give up. - */ - -LocalSymbols(res) -[ - 10 # Solve(expr_IsList, var_IsList) <-- Solve'System(expr, var); - 20 # Solve(_expr, _var)_(Not IsAtom(var) Or IsNumber(var) Or IsString(var)) <-- - [ Assert("Solve'TypeError", "Second argument, ":(ToString() Write(var)):", is not the name of a variable") False; {}; ]; - 30 # Solve(_lhs == _rhs, _var) <-- Solve(lhs - rhs, var); - 40 # Solve(0, _var) <-- {var == var}; - 41 # Solve(a_IsConstant, _var) <-- {}; - 42 # Solve(_expr, _var)_(Not HasExpr(expr,var)) <-- - [ Assert("Solve", "expression ":(ToString() Write(expr)):" does not depend on ":ToString() Write(var)) False; {}; ]; - 50 # Solve(_expr, _var)_((res := Solve'Poly(expr, var)) != Failed) <-- res; - 60 # Solve(_e1 * _e2, _var) <-- Union(Solve(e1,var), Solve(e2,var)); - 70 # Solve(_e1 / _e2, _var) <-- Solve(e1, var); - 80 # Solve(_e1 + _e2, _var)_(Not HasExpr(e2,var) And (res := Solve'Simple(e1,-e2,var)) != Failed) <-- res; - 80 # Solve(_e1 + _e2, _var)_(Not HasExpr(e1,var) And (res := Solve'Simple(e2,-e1,var)) != Failed) <-- res; - 80 # Solve(_e1 - _e2, _var)_(Not HasExpr(e2,var) And (res := Solve'Simple(e1,e2,var)) != Failed) <-- res; - 80 # Solve(_e1 - _e2, _var)_(Not HasExpr(e1,var) And (res := Solve'Simple(e2,e1,var)) != Failed) <-- res; - 85 # Solve(_expr, _var)_((res := Solve'Simple(expr, 0, var)) != Failed) <-- res; - 90 # Solve(_expr, _var)_((res := Solve'Reduce(expr, var)) != Failed) <-- res; - 95 # Solve(_expr, _var)_((res := Solve'Divide(expr, var)) != Failed) <-- res; - 100 # Solve(_expr, _var)_((res := Simplify(expr)) != expr) <-- Solve(res, var); - 110 # Solve(_expr, _var) <-- - [ Assert("Solve'Fails", "cannot solve equation ":(ToString() Write(expr)):" for ":ToString() Write(var)) False; {}; ]; -]; - -/********** Solve'Poly **********/ - -/* Tries to solve by calling PSolve */ -/* Returns Failed if this doesn't work, and the solution otherwise */ - -/* CanBeUni is not documented, but defined in org/mathpiper/assembledscripts/univar.rep/code.mpi */ -/* It returns True iff 'expr' is a polynomial in 'var' */ - -10 # Solve'Poly(_expr, _var)_(Not CanBeUni(var, expr)) <-- Failed; - -/* The call to PSolve can have three kind of results - * 1) PSolve returns a single root - * 2) PSolve returns a list of roots - * 3) PSolve remains unevaluated - */ - -20 # Solve'Poly(_expr, _var) <-- -LocalSymbols(x) -[ - Local(roots); - roots := PSolve(expr, var); - If(Type(roots) = "PSolve", - Failed, /* Case 3 */ - If(Type(roots) = "List", - MapSingle({{x},var==x}, roots), /* Case 2 */ - {var == roots})); /* Case 1 */ -]; - -/********** Solve'Reduce **********/ - -/* Tries to solve by reduction strategy */ -/* Returns Failed if this doesn't work, and the solution otherwise */ - -10 # Solve'Reduce(_expr, _var) <-- -[ - ClearError("Solve'Fails"); // ..in case one was left over from prior failure - Local(context, expr2, var2, res, sol, sol2, i); - context := Solve'Context(expr, var); - If(context = False, - res := Failed, - [ - expr2 := Eval(Subst(context, var2) expr); - If(CanBeUni(var2, expr2) And (Degree(expr2, var2) = 0 Or (Degree(expr2, var2) = 1 And Coef(expr2, var2, 1) = 1)), - res := Failed, /* to prevent infinite recursion */ - [ - sol2 := Solve(expr2, var2); - If(IsError("Solve'Fails"), - [ - ClearError("Solve'Fails"); - res := Failed; - ], - [ - res := {}; - i := 1; - While(i <= Length(sol2) And res != Failed) [ - sol := Solve(context == (var2 Where sol2[i]), var); - If(IsError("Solve'Fails"), - [ - ClearError("Solve'Fails"); - res := Failed; - ], - res := Union(res, sol)); - i++; - ]; - ]); - ]); - ]); - res; -]; - -/********** Solve'Context **********/ - -/* Returns the unique context of 'var' in 'expr', */ -/* or {} if 'var' does not occur in 'expr', */ -/* or False if the context is not unique. */ - -10 # Solve'Context(expr_IsAtom, _var) <-- If(expr=var, var, {}); - -20 # Solve'Context(_expr, _var) <-- -[ - Local(lst, foundVarP, context, i, res); - lst := Listify(expr); - foundVarP := False; - i := 2; - While(i <= Length(lst) And Not foundVarP) [ - foundVarP := (lst[i] = var); - i++; - ]; - If(foundVarP, - context := expr, - [ - context := {}; - i := 2; - While(i <= Length(lst) And context != False) [ - res := Solve'Context(lst[i], var); - If(res != {} And context != {} And res != context, context := False); - If(res != {} And context = {}, context := res); - i++; - ]; - ]); - context; -]; - -/********** Solve'Simple **********/ - -/* Simple solver of equations - * - * Returns (possibly empty) list of solutions, - * or Failed if it cannot handle the equation - * - * Calling format: Solve'Simple(lhs, rhs, var) - * to solve 'lhs == rhs'. - * - * Note: 'rhs' should not contain 'var'. - */ - -20 # Solve'Simple(_e1 + _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs-e2 }; -20 # Solve'Simple(_e1 + _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == rhs-e1 }; - -20 # Solve'Simple(_e1 - _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs+e2 }; -20 # Solve'Simple(_e1 - _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == e1-rhs }; -20 # Solve'Simple(-(_e1), _rhs, _var)_(e1 = var) <-- { var == -rhs }; - -20 # Solve'Simple(_e1 * _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs/e2 }; -20 # Solve'Simple(_e1 * _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == rhs/e1 }; - -20 # Solve'Simple(_e1 / _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs*e2 }; -10 # Solve'Simple(_e1 / _e2, 0, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { }; -20 # Solve'Simple(_e1 / _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == e1/rhs }; - -LocalSymbols(x) -[ - 20 # Solve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsPositiveInteger(n)) - <-- MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. n)/n)); - 20 # Solve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsNegativeInteger(n)) - <-- MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. (-n))/(-n))); -]; - -20 # Solve'Simple(_e1 ^ _e2, _rhs, _var) - _ (IsPositiveReal(e1) And e1 != 0 And e2 = var And IsPositiveReal(rhs) And rhs != 0) - <-- { var == Ln(rhs)/Ln(e1) }; - -/* Note: These rules do not take the periodicity of the trig. functions into account */ -10 # Solve'Simple(Sin(_e1), 1, _var)_(e1 = var) <-- { var == 1/2*Pi }; -10 # Solve'Simple(Sin(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- { var == 3/2*Pi }; -20 # Solve'Simple(Sin(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcSin(rhs), var == Pi-ArcSin(rhs) }; -10 # Solve'Simple(Cos(_e1), 1, _var)_(e1 = var) <-- { var == 0 }; -10 # Solve'Simple(Cos(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- { var == Pi }; -20 # Solve'Simple(Cos(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcCos(rhs), var == -ArcCos(rhs) }; -20 # Solve'Simple(Tan(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcTan(rhs) }; - -20 # Solve'Simple(ArcSin(_e1), _rhs, _var)_(e1 = var) <-- { var == Sin(rhs) }; -20 # Solve'Simple(ArcCos(_e1), _rhs, _var)_(e1 = var) <-- { var == Cos(rhs) }; -20 # Solve'Simple(ArcTan(_e1), _rhs, _var)_(e1 = var) <-- { var == Tan(rhs) }; - -/* Note: Second rule neglects (2*I*Pi)-periodicity of Exp() */ -10 # Solve'Simple(Exp(_e1), 0, _var)_(e1 = var) <-- { }; -20 # Solve'Simple(Exp(_e1), _rhs, _var)_(e1 = var) <-- { var == Ln(rhs) }; -20 # Solve'Simple(Ln(_e1), _rhs, _var)_(e1 = var) <-- { var == Exp(rhs) }; - -/* The range of Sqrt is the set of (complex) numbers with either - * positive real part, together with the pure imaginary numbers with - * nonnegative real part. */ -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsPositiveReal(Re(rhs)) And Re(rhs) != 0) <-- { var == rhs^2 }; -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsPositiveReal(Im(rhs))) <-- { var == rhs^2 }; -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsNegativeReal(Im(rhs)) And Im(rhs) != 0) <-- { }; -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsNegativeReal(Re(rhs)) And Re(rhs) != 0) <-- { }; - -30 # Solve'Simple(_lhs, _rhs, _var) <-- Failed; - - -/********** Solve'Divide **********/ -/* For some classes of equations, it may be easier to solve them if we - * divide through by their first term. A simple example of this is the - * equation Sin(x)+Cos(x)==0 - * One problem with this is that we may lose roots if the thing we - * are dividing by shares roots with the whole equation. - * The final HasExprs are an attempt to prevent infinite recursion caused by - * the final Simplify step in Solve undoing what we do here. It's conceivable - * though that this won't always work if the recurring loop is more than two - * steps long. I can't think of any ways this can happen though :) - */ - -10 # Solve'Divide(_e1 + _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) - And Not (HasExpr(Simplify(1 + (e2/e1)), e1) - Or HasExpr(Simplify(1 + (e2/e1)), e2))) - <-- Solve(1 + (e2/e1), var); -10 # Solve'Divide(_e1 - _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) - And Not (HasExpr(Simplify(1 - (e2/e1)), e1) - Or HasExpr(Simplify(1 - (e2/e1)), e2))) - <-- Solve(1 - (e2/e1), var); - -20 # Solve'Divide(_e, _v) <-- Failed; - - -%/mathpiper - - - -%mathpiper_docs,name="Solve",categories="User Functions;Solvers (Symbolic)" -*CMD Solve --- solve an equation -*STD -*CALL - Solve(eq, var) - -*PARMS - -{eq} -- equation to solve - -{var} -- variable to solve for - -*DESC - -This command tries to solve an equation. If {eq} does not contain the -{==} operator, it is assumed that the user wants to solve $eq == -0$. The result is a list of equations of the form {var == value}, each -representing a solution of the given equation. The {Where} operator -can be used to substitute this solution in another expression. If the -given equation {eq} does not have any solutions, or if {Solve} is -unable to find any, then an empty list is returned. - -The current implementation is far from perfect. In particular, the -user should keep the following points in mind: -* {Solve} cannot solve all equations. If it is given a equation -it can not solve, it raises an error via {Check}. Unfortunately, this -is not displayed by the inline pretty-printer; call {PrettyPrinter'Set} to -change this. If an equation cannot be solved analytically, you may -want to call {Newton} to get a numerical solution. -* Systems of equations are not handled yet. For linear systems, -{MatrixSolve} can be used. The old version of {Solve}, with the name -{OldSolve} might be able to solve nonlinear systems of equations. -* The periodicity of the trigonometric functions {Sin}, {Cos}, -and {Tan} is not taken into account. The same goes for the (imaginary) -periodicity of {Exp}. This causes {Solve} to miss solutions. -* It is assumed that all denominators are nonzero. Hence, a -solution reported by {Solve} may in fact fail to be a solution because -a denominator vanishes. -* In general, it is wise not to have blind trust in the results -returned by {Solve}. A good strategy is to substitute the solutions -back in the equation. - -*E.G. notest - -First a simple example, where everything works as it should. The -quadratic equation $x^2 + x == 0$ is solved. Then the result is -checked by substituting it back in the quadratic. - - In> quadratic := x^2+x; - Out> x^2+x; - In> Solve(quadratic, x); - Out> {x==0,x==(-1)}; - In> quadratic Where %; - Out> {0,0}; - -If one tries to solve the equation $Exp(x) == Sin(x)$, one finds that -{Solve} can not do this. - - In> PrettyPrinter'Set("DefaultPrint"); - Out> True; - In> Solve(Exp(x) == Sin(x), x); - Error: Solve'Fails: cannot solve equation Exp(x)-Sin(x) for x - Out> {}; - -The equation $Cos(x) == 1/2$ has an infinite number of solutions, -namely $x == (2*k + 1/3) * Pi$ and $x == (2*k - 1/3) * Pi$ for any -integer $k$. However, {Solve} only reports the solutions with $k == 0$. - - In> Solve(Cos(x) == 1/2, x); - Out> {x==Pi/3,x== -Pi/3}; - -For the equation $x/Sin(x) == 0$, a spurious solution at $x == 0$ is -returned. However, the fraction is undefined at that point. - - In> Solve(x / Sin(x) == 0, x); - Out> {x==0}; - -At first sight, the equation $Sqrt(x) == a$ seems to have the solution -$x == a^2$. However, this is not true for eg. $a == -1$. - - In> PrettyPrinter'Set("DefaultPrint"); - Out> True; - In> Solve(Sqrt(x) == a, x); - Error: Solve'Fails: cannot solve equation Sqrt(x)-a for x - Out> {}; - In> Solve(Sqrt(x) == 2, x); - Out> {x==4}; - In> Solve(Sqrt(x) == -1, x); - Out> {}; - -*SEE Check, MatrixSolve, Newton, OldSolve, PrettyPrinter'Set, PSolve, Where, == -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/SuchThat.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/SuchThat.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/solve/SuchThat.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/solve/SuchThat.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -%mathpiper,def="SuchThat" - -10 # ContainsExpression(_body,_body) <-- True; -15 # ContainsExpression(body_IsAtom,_expr) <-- False; -20 # ContainsExpression(body_IsFunction,_expr) <-- -[ - Local(result,args); - result:=False; - args:=Rest(Listify(body)); - While(args != {}) - [ - result:=ContainsExpression(First(args),expr); - args:=Rest(args); - if (result = True) (args:={}); - ]; - result; -]; - - -SuchThat(_function,_var) <-- SuchThat(function,0,var); - -10 # SuchThat(_left,_right,_var)_(left = var) <-- right; - -/*This interferes a little with the multi-equation solver... -15 # SuchThat(_left,_right,_var)_CanBeUni(var,left-right) <-- - PSolve(MakeUni(left-right,var)); -*/ - -20 # SuchThat(left_IsAtom,_right,_var) <-- var; - -30 # SuchThat((_x) + (_y),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right-y , var); -30 # SuchThat((_y) + (_x),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right-y , var); - -30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(r,var) <-- - SuchThat(r , right-I*i , var); -30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(i,var) <-- - SuchThat(i , right+I*r , var); - -30 # SuchThat(_x * _y,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right/y , var); -30 # SuchThat(_y * _x,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right/y , var); - -30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right^(1/y) , var); -30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(y,var) <-- - SuchThat(y , Ln(right)/Ln(x) , var); - -30 # SuchThat(Sin(_x),_right,_var) <-- - SuchThat(x , ArcSin(right) , var); -30 # SuchThat(ArcSin(_x),_right,_var) <-- - SuchThat(x , Sin(right) , var); - -30 # SuchThat(Cos(_x),_right,_var) <-- - SuchThat(x , ArcCos(right) , var); -30 # SuchThat(ArcCos(_x),_right,_var) <-- - SuchThat(x , Cos(right) , var); - -30 # SuchThat(Tan(_x),_right,_var) <-- - SuchThat(x , ArcTan(right) , var); -30 # SuchThat(ArcTan(_x),_right,_var) <-- - SuchThat(x , Tan(right) , var); - -30 # SuchThat(Exp(_x),_right,_var) <-- - SuchThat(x , Ln(right) , var); -30 # SuchThat(Ln(_x),_right,_var) <-- - SuchThat(x , Exp(right) , var); - -30 # SuchThat(_x / _y,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right*y , var); -30 # SuchThat(_y / _x,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , y/right , var); - -30 # SuchThat(- (_x),_right,_var) <-- - SuchThat(x , -right , var); - -30 # SuchThat((_x) - (_y),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right+y , var); -30 # SuchThat((_y) - (_x),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , y-right , var); - -30 # SuchThat(Sqrt(_x),_right,_var) <-- - SuchThat(x , right^2 , var); - -%/mathpiper - - - -%mathpiper_docs,name="SuchThat",categories="User Functions;Solvers (Symbolic)" -*CMD SuchThat --- special purpose solver -*STD -*CALL - SuchThat(expr, var) - -*PARMS - -{expr} -- expression to make zero - -{var} -- variable (or subexpression) to solve for - -*DESC - -This functions tries to find a value of the variable "var" which -makes the expression "expr" zero. It is also possible to pass a -subexpression as "var", in which case {SuchThat} -will try to solve for that subexpression. - -Basically, only expressions in which "var" occurs only once are -handled; in fact, {SuchThat} may even give wrong -results if the variables occurs more than once. This is a consequence -of the implementation, which repeatedly applies the inverse of the top -function until the variable "var" is reached. - -*E.G. - - In> SuchThat(a+b*x, x) - Out> (-a)/b; - In> SuchThat(Cos(a)+Cos(b)^2, Cos(b)) - Out> Cos(a)^(1/2); - In> A:=Expand(a*x+b*x+c, x) - Out> (a+b)*x+c; - In> SuchThat(A, x) - Out> (-c)/(a+b); - -*SEE Solve, OldSolve, Subst, Simplify -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/ApproxInfSum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/ApproxInfSum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/ApproxInfSum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/ApproxInfSum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="ApproxInfSum" - -//Jonathan Leto - -// Ex: -// Bessel of order n: -// ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),1,x,{n} ); - -Function("ApproxInfSum",{expr,start,x})[ - ApproxInfSum(expr,start,x,{0}); -]; - -/// FIXME this has a roundoff problem when InNumericMode()=True -// Summation must be on k -Function("ApproxInfSum",{expr,start,x,c}) -[ - Local(term,result,k); - Local(prec,eps,tmp); - prec:=BuiltinPrecisionGet(); -// BuiltinPrecisionSet(Ceil(1.2*prec)); // this is a guess - BuiltinPrecisionSet(prec+2); // this is a guess -// eps:=5*10^(-prec); - eps:=10^(-prec); -//Echo(expr); -//Echo(" eps = ",N(Eval(eps))); - - term:=1; - k:=start; - result:=0; - While( N(Abs(term) >= eps) )[ - term:=N(Eval(expr)); - //Echo({"term is ",term}); - k:=k+1; - result:=result+term; - - ]; - If(InVerboseMode(), Echo("ApproxInfSum: Info: using ", k, " terms of the series")); - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - -//Echo("lastterm = ",N(Eval(term))); - -//Echo("r1",result); -//Echo("r2",RoundTo(result,prec)); -//Echo("r3",N((result/10)*10)); - - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/Bernoulli1.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/Bernoulli1.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/Bernoulli1.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/Bernoulli1.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="Bernoulli1" - -/// Find one Bernoulli number for large index -/// compute Riemann's zeta function and combine with the fractional part -Bernoulli1(n_IsEven)_(n>=2) <-- [ - Local(B, prec); - prec := BuiltinPrecisionGet(); - // estimate the size of B[n] using Stirling formula - // and compute Ln(B[n])/Ln(10) to find the number of digits - BuiltinPrecisionSet(10); - BuiltinPrecisionSet( - Ceil(N((1/2*Ln(8*Pi*n)-n+n*Ln(n/2/Pi))/Ln(10)))+3 // 3 guard digits - ); - If (InVerboseMode(), Echo({"Bernoulli: using zeta funcion, precision ", BuiltinPrecisionSet(), ", n = ", n})); - B := Floor(N( // compute integer part of B - If( // use different methods to compute Zeta function - n>250, // threshold is roughly right for internal math - Internal'ZetaNum2(n, n/17+1), // with this method, a single Bernoulli number n is computed in O(n*M(P)) operations where P = O(n*Ln(n)) is the required precision - // Brent's method requires n^2*P+n*M(P) - // simple array method requires - Internal'ZetaNum1(n, n/17+1) // this gives O(n*Ln(n)*M(P)) - ) - *N(2*n! /(2*Pi)^n))) - // 2*Pi*e is approx. 17, add 1 to guard precision - * (2*Mod(n/2,2)-1) // sign of B - + BernoulliFracPart(n); // this already has the right sign - BuiltinPrecisionSet(prec); // restore old precision - B; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/BernoulliFracPart.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/BernoulliFracPart.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/BernoulliFracPart.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/BernoulliFracPart.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="BernoulliFracPart" - -/// Find the fractional part of Bernoulli number with even index >=2 -/// return negative if the sign of the Bernoulli number is negative -BernoulliFracPart(n_IsEven)_(n>=2) <-- [ - Local(p, sum); - // always 2 and 3 - sum := 1/2+1/3; - // check whether n+1 and n/2+1 are prime - If(IsPrime(n+1), sum := sum+1/(n+1)); - If(IsPrime(n/2+1), sum := sum+1/(n/2+1)); - // sum over all primes p such that n / p-1 is integer - // enough to check up to n/3 now - For(p:=5, p<=n/3+1, p:=NextPrime(p)) - If(Mod(n, p-1)=0, sum := sum + 1/p); - // for negative Bernoulli numbers, let's change sign - // Mod(n/2, 2) is 0 for negative Bernoulli numbers and 1 for positive ones - Div(Numerator(sum), Denominator(sum)) - sum - + Mod(n/2,2); // we'll return a negative number if the Bernoulli itself is negative -- slightly against our definitions in the manual - //+ 1; // this would be exactly like the manual says -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray1.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray1.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray1.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray1.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="Internal'BernoulliArray1",scope="private" - -/// Bernoulli numbers; algorithm from: R. P. Brent, "A FORTRAN multiple-precision arithmetic package", ACM TOMS vol. 4, no. 1, p. 57 (1978). -/// this may be good for floating-point (not exact) evaluation of B[n] at large n -/// but is not good at all for exact evaluation! (too slow) -/// Brent claims that the usual recurrence is numerically unstable -/// but we can't check this because MathPiper internal math is fixed-point and Brent's algorithm needs real floating point (C[k] are very small and then multiplied by (2*k)! ) -Internal'BernoulliArray1(n_IsEven) _ (n>=2) <-- -[ - Local(C, f, k, j, denom, sum); - C := ArrayCreate(n+1, 0); - f := ArrayCreate(n/2, 0); - C[1] := 1; - C[2] := -1/2; - C[3] := 1/12; // C[2*k+1] = B[2*k]/(2*k)! - f[1] := 2; // f[k] = (2k)! - For(k:=2, k<=n/2, k++) // we could start with k=1 but it would be awkward to compute f[] recursively - [ - // compute f[k] - f[k] := f[k-1] * (2*k)*(2*k-1); - // compute C[k] - C[2*k+1] := 1/(1-4^(-k))/2*( - [ - denom := 4; // = 4^1 - sum := 0; - For(j:=1, j<=k-1, j++) - [ - sum := sum + C[2*(k-j)+1]/denom/f[j]; // + C[k-j]/(2*j)! /4^j - denom := denom * 4; - ]; - (2*k-1)/denom/f[k] - sum; - ] - ); -// Echo({n, k, denom, C[k]}); - ]; - // multiply C's with factorials to get B's - For(k:=1, k<=n/2, k++) - C[2*k+1] := C[2*k+1] * f[k]; - // return array object - C; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bernou/Internal'BernoulliArray.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="Internal'BernoulliArray",scope="private" - -/// Simple implementation of the recurrence relation: create an array of Bernoulli numbers -// special cases: n=0 or n=1 -10 # Internal'BernoulliArray(n_IsInteger)_(n=0 Or n=1) <-- [ - Local(B); - B:=ArrayCreate(n+1,0); - B[1] := 1; - If(n=1, B[2] := -1/2); - B; -]; -/// Assume n>=2 -20 # Internal'BernoulliArray(n_IsInteger) <-- [ - Local(B, i, k, k2, bin); - If (InVerboseMode(), Echo({"Internal'BernoulliArray: using direct recursion, n = ", n})); - B:=ArrayCreate(n+1, 0); // array of B[k], k=1,2,... where B[1] is the 0th Bernoulli number - // it would be better not to store the odd elements but let's optimize this later - // we could also maintain a global cache of Bernoulli numbers computed so far, but it won't really speed up things at large n - // all odd elements after B[2] are zero - B[1] := 1; - B[2] := -1/2; - B[3] := 1/6; - For(i:=4, i<=n, i := i+2) // compute and store B[i] - [ // maintain binomial coefficient - bin := 1; // BinomialCoefficient(i+1,0) - // do not sum over odd elements that are zero anyway - cuts time in half - B[i+1] := 1/2-1/(i+1)*(1 + Sum(k, 1, i/2-1, - [ - bin := bin * (i+3-2*k) * (i+2-2*k)/ (2*k-1) / (2*k); - B[2*k+1]*bin; // *BinomialCoefficient(i+1, 2*k) - ] - ) ); - ]; - B; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Bernoulli.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Bernoulli.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Bernoulli.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Bernoulli.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -%mathpiper,def="Bernoulli" - -///////////////////////////////////////////////// -/// Bernoulli numbers and polynomials -///////////////////////////////////////////////// -/// Serge Winitzki - -/// Bernoulli(n): interface to Bernoulli numbers -10 # Bernoulli(0) <-- 1; -10 # Bernoulli(1) <-- -1/2; -15 # Bernoulli(n_IsInteger)_(n<0) <-- Undefined; -30 # Bernoulli(n_IsOdd) <-- 0; - -/// numerical computations of Bernulli numbers use two different methods, one good for small numbers and one good only for very large numbers (using Zeta function) -20 # Bernoulli(n_IsEven)_(n<=Bernoulli1Threshold()) <-- Internal'BernoulliArray(n)[n+1]; -20 # Bernoulli(n_IsEven)_(n>Bernoulli1Threshold()) <-- Bernoulli1(n); - -LocalSymbols(bernoulli1Threshold) [ - /// Bernoulli1Threshold could in principle be set by the user - If(Not IsBound(bernoulli1Threshold), bernoulli1Threshold := 20); - - Bernoulli1Threshold() := bernoulli1Threshold; - SetBernoulli1Threshold(threshold) := [ bernoulli1Threshold := threshold;]; - -] ; // LocalSymbols(bernoulli1Threshold) - -/// Bernoulli polynomials of degree n in variable x -Bernoulli(n_IsInteger, _x) <-- [ - Local(B, i, result); - B := Internal'BernoulliArray(n); - result := B[1]; - For(i:=n-1, i>=0, i--) [ - result := result * x + B[n-i+1]*BinomialCoefficient(n,i); - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Bernoulli",categories="User Functions;Special" -*CMD Bernoulli --- Bernoulli numbers and polynomials -*STD -*CALL - Bernoulli(index) - Bernoulli(index, x) - -*PARMS - -{x} -- expression that will be the variable in the polynomial - -{index} -- expression that can be evaluated to an integer - -*DESC - -{Bernoulli(n)} evaluates the $n$-th Bernoulli number. {Bernoulli(n, x)} returns the $n$-th Bernoulli polynomial in the variable $x$. The polynomial is returned in the Horner form. - -*E.G. - - In> Bernoulli(20); - Out> -174611/330; - In> Bernoulli(4, x); - Out> ((x-2)*x+1)*x^2-1/30; - -*SEE Gamma, Zeta -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN0.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN0.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN0.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN0.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="BesselJN0",scope="private" - -/// coded by Jonathan Leto - -// Seems to get about 8 digits precision for most real numbers -// Only about 2 digits precision for complex -// This is just a temporary implementation, I would not want to -// expose users to it until it is much more robust -// I am still looking for a good arbitrary precision algorithm. -Function("BesselJN0",{x}) -[ - Local(ax,z,xx,y,result,res1,res2); - Local(c1,c2,c3,c4); - - // Coefficients of the rational polynomials to - // approx J_0 for x < 8 - c1:={57568490574.0,-13362590354.0,651619640.7, - -11214424.18,77392.33017,-184.9052456}; - c2:={57568490411.0,1029532985.0,9494680.718, - 59272.64853,267.8532712}; - // Coefficients of the rational polynomials to - // approx J_0 for x >= 8 - c3:={-0.001098628627,0.00002734510407,-0.000002073370639, - 0.0000002093887211}; - c4:={-0.01562499995,0.0001430488765,-0.000006911147651, - 0.0000007621095161,0.0000000934935152}; - ax:=Abs(x); - - If( ax < 8.0,[ - y:=x^2; - res1:=c1[1]+y*(c1[2]+y*c1[3]+y*(c1[4]+y*(c1[5]+y*(c1[6])))); - res2:=c1[1]+y*(c2[2]+y*c2[3]+y*(c2[4]+y*(c2[5]+y*1.0))); - result:=res1/res2; - ],[ - z:=8/ax; - y:=z^2; - xx:=ax-0.785398164; - res1:=1.0+y*(c3[1]+y*(c3[2]+y*(c3[3]+y*c4[4]))); - res2:=c4[1]+y*(c4[2]+y*(c4[3]+y*(c4[4]-y*c4[5]))); - result:=Sqrt(2/(Pi*x))*(Cos(xx)*res1-z*Sin(xx)*res2); - ] ); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bessel/BesselJN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Was not implemented in the scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bessel/BesselNsmall.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bessel/BesselNsmall.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/bessel/BesselNsmall.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/bessel/BesselNsmall.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="BesselNsmall",scope="private" - -/// coded by Jonathan Leto - -// When x is <= 1, the series is monotonely decreasing from the -// start, so we don't have to worry about loss of precision from the -// series definition. -// When {n} is an integer, this is fast. -// When {n} is not, it is pretty slow due to Gamma() - -Function("BesselNsmall",{n,x,modified}) -[ - Local(term,result,k); - Local(prec,eps,tmp); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(Ceil(1.2*prec)); // this is a guess - eps:=5*10^(-prec); - - term:=1; - k:=0; - result:=0; - While( Abs(term) >= eps )[ - term:=x^(2*k+n); - // The only difference between BesselJ and BesselI - // is an alternating term - If( k%2=1 And modified=0 , term:=term*-1 ); - term:=N(term/(2^(2*k+n)* k! * Gamma(k+n+1) )); - //Echo({"term is ",term}); - result:=result+term; - k:=k+1; - ]; - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - RoundTo(result,prec); - -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/BesselI.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/BesselI.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/BesselI.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/BesselI.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="BesselI" - -//Jonathan Leto - -10 # BesselI(0,0) <-- 1; - -10 # BesselI(_n,0)_(n>0) <-- 0; - -10 # BesselI(_n,0)_(n<0 And IsInteger(n)) <-- 0; - - -// The following should be ComplexInfinity, if/when that is implemented -10 # BesselI(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity; - - -20 # BesselI(1/2,_x) <-- Sqrt(2/(x*Pi))*Sinh(x); - - -20 # BesselI(3/2,_x) <-- Sqrt(2/(x*Pi))*(Cosh(x) - Sinh(x)/x); - - -20 # BesselI(5/2,_x) <-- Sqrt(2/(x*Pi))*((3/x^2 + 1)*Sinh(x) - 3*Cosh(x)/x ); - - -30 # BesselI(_n,_z)_(n<0 And IsInteger(n) ) <-- BesselI(-n,z); - - -// When I put "And InNumericMode()" on the next rule, I lose precision. Why ? -// Also, if I move the the "_IsComplex" to the end with "IsComplex(x)" -// I lose precision. - - -//40 # BesselI(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N(BesselNsmall(n,x,1)); - - -40 # BesselI(_n,x_IsComplex)_(IsConstant(x) And Abs(x)<= 2*Gamma(n) ) <-- -[ -ApproxInfSum((x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} ); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/BesselJ.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/BesselJ.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/BesselJ.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/BesselJ.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -%mathpiper,def="BesselJ" - -//Jonathan Leto - -10 # BesselJ(0,0) <-- 1; -10 # BesselJ(_n,0)_(n>0) <-- 0; -10 # BesselJ(_n,0)_(n<0 And IsInteger(n)) <-- 0; -10 # BesselJ(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity; -10 # BesselJ(0,Infinity)<-- 0; -20 # BesselJ(1/2,_x) <-- Sqrt(2/(x*Pi))*Sin(x); -20 # BesselJ(-1/2,_x) <-- Sqrt(2/(x*Pi))*Cos(x); -20 # BesselJ(3/2,_x) <-- Sqrt(2/(x*Pi))*(Sin(x)/x - Cos(x)); -20 # BesselJ(-3/2,_x) <-- Sqrt(2/(x*Pi))*(Cos(x)/x + Sin(x)); -20 # BesselJ(5/2,_x) <-- Sqrt(2/(x*Pi))*((3/x^2 - 1)*Sin(x) - 3*Cos(x)/x ); -20 # BesselJ(-5/2,_x) <-- Sqrt(2/(x*Pi))*( (3/x^2 -1)*Cos(x) + 3*Sin(x)/x ); - - -// Forward recursion, works great, but really slow when n << x -30 # BesselJ(_n,_x)_(IsConstant(x) And IsInteger(n) And N(Abs(x) > 2*Gamma(n))) <-- N((2*(n+1)/x)*BesselJ(n+1,x) - BesselJ(n+2,x)); - -30 # BesselJ(_n,_z)_(n<0 And IsInteger(n) ) <-- (-1)^n*BesselJ(-n,z); - -// When I put "And InNumericMode()" on the next rule, I lose precision. Why ? -// Also, if I move the the "_IsComplex" to the end with "IsComplex(x)" -// I lose precision. - -//40 # BesselJ(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N(BesselNsmall(n,x,0)); - -40 # BesselJ(_n,x_IsComplex)_(N(Abs(x)<= 2*Gamma(n)) ) <-- -[ -ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} ); -]; - -50 # BesselJ(0,x_IsComplex)_(InNumericMode()) <-- N(BesselJN0(x)); - -//50 # BesselJ(_n_IsPositiveNumber,_z_IsComplex) <-- BesselJN(n,z); - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/BesselY.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/BesselY.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/BesselY.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/BesselY.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="BesselY" -//Jonathan Leto - -// This is buggy -40 # BesselY(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N((Cos(n*Pi)*BesselJ(n,x) - BesselJ(-n,x))/Sin(Pi*n)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Beta.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Beta.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Beta.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Beta.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Beta" - -//Jonathan Leto - -10 # Beta(_n,_m) <-- Gamma(m)*Gamma(n)/Gamma(m+n); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/CatalanConstNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/CatalanConstNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/CatalanConstNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/CatalanConstNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -%mathpiper,def="CatalanConstNum" - -//Jonathan Leto - -///////////////////////////////////////////////// -/// Catalan's constant, various algorithms for comparison. (SW) -///////////////////////////////////////////////// - -/* Brent-Fee's method based on Ramanujan's identity and Brent's trick. - * Geometric convergence as 2^(-n). */ -CatalanConstNum1() := -[ - Local(prec,Aterm,Bterm,nterms,result,n); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(10); - // estimate the number of terms from above - nterms := 1+Floor(N((prec*Ln(10)+Ln(prec*Ln(10)/Ln(2)))/Ln(2))); - BuiltinPrecisionSet(prec+5); - Aterm:=N(1/2); - result:= Aterm; - Bterm:=Aterm; - For(n:=1, n<=nterms, n++ ) - [ -/* - Bterm := MultiplyNum(Bterm, n/(2*n+1)); - Aterm:= DivideN(MultiplyNum(Aterm,n)+Bterm, 2*n+1); -/* this is faster: */ - Bterm:=DivideN(MultiplyN(Bterm,n), 2*n+1); // Bterm = (k!)^2*2^(k-1)/(2*k+1)! - Aterm:=DivideN(MultiplyN(Aterm,n)+Bterm, 2*n+1); // Aterm = Bterm * Sum(k,0,n,1/(2*k+1)) -/**/ - result := result + Aterm; - ]; - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; - -/* Bailey 1997's method. - * Geometric convergence as 4^(-n). */ - -CatalanConstNum() := -[ - Local(prec, n, result); - prec:=BuiltinPrecisionGet(); - - // number of terms - n := 1+Div(prec*1068+642,643); // prec*Ln(10)/Ln(4) - BuiltinPrecisionSet(prec+2); // 2 guard digits - - result := N(1/(2*n+1)); - While(n>0) - [ -/* - result := MultiplyNum(result, n/(4*n+2))+N(1/(2*n-1)); -/* this is faster: */ - result := DivideN(MultiplyN(result, n), 4*n+2)+DivideN(1,2*n-1); -/**/ - n := n-1; - ]; - result := MultiplyNum(result, 3/8) + N(Pi/8*Ln(2+Sqrt(3))); - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; - -/* Broadhurst's series. - * Geometric convergence as 16^(-n). */ - -CatalanConstNum2() := -[ - Local(prec, n, result1, result2); - prec:=BuiltinPrecisionGet(); - - // first series - // number of terms - n := 1+Div(prec*534+642,643); // prec*Ln(10)/Ln(16) - BuiltinPrecisionSet(prec+2); // 2 guard digits - - result1 := 0; - While(n>=0) - [ - result1 := DivideN(result1, 16)+N( - +1/(8*n+1)^2 -1/(8*n+2)^2 +1/2/(8*n+3)^2 -1/4/(8*n+5)^2 +1/4/(8*n+6)^2 -1/8/(8*n+7)^2 - ); - n := n-1; - ]; - - // second series - // number of terms - n := 1+Div(prec*178+642,643); // prec*Ln(10)/Ln(4096) - BuiltinPrecisionSet(prec+2); // 2 guard digits - - result2 := 0; - While(n>=0) - [ - result2 := DivideN(result2, 4096)+N( - +1/(8*n+1)^2 +1/2/(8*n+2)^2 +1/8/(8*n+3)^2 -1/64/(8*n+5)^2 -1/128/(8*n+6)^2 -1/512/(8*n+7)^2 - ); - n := n-1; - ]; - result1 := MultiplyNum(result1, 3/2) - MultiplyNum(result2, 1/4); - BuiltinPrecisionSet(prec); - RoundTo(result1,prec); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DawsonIntegral.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DawsonIntegral.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DawsonIntegral.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DawsonIntegral.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="DawsonIntegral",scope="private" - -//Jonathan Leto - -// needs Erf() that takes complex argument -/* -10 # DawsonIntegral(_x) <-- [ - Local(result,prec); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - result:=N(I*Sqrt(Pi)*Exp(-x^2)*Erf(-I*x)/2); - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; -*/ - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Digamma.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Digamma.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Digamma.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Digamma.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Digamma" - -//Jonathan Leto - -10 # Digamma(_n)_(IsPositiveInteger(n)) <-- Sum(m,1,n-1,1/m) - gamma; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DirichletBeta.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DirichletBeta.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DirichletBeta.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DirichletBeta.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="DirichletBeta" - -//Jonathan Leto - -// This is really slow for x <= 3 -5 # DirichletBeta(1) <-- Pi/4; -5 # DirichletBeta(2) <-- Catalan; -5 # DirichletBeta(3) <-- Pi^3/32; -6 # DirichletBeta(n_IsOdd) <-- [ - Local(k); - k:=(n-1)/2; - (-1)^k*Euler(2*k)*(Pi/2)^(2*k+1)/(2*(2*k)!); -]; - - -10 # DirichletBeta(x_IsRationalOrNumber)_(InNumericMode() And x>=1 ) <-- [ - Local(prec,eps,term,result,k); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+3); - eps:=10^(-prec); - result:=0; - term:=1; - For(k:=0, Abs(term) > eps, k++ )[ - term:=(-1)^k/(2*k+1)^x; - Echo("term is ",term); - result:=result+term; - ]; - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DirichletEta.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DirichletEta.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DirichletEta.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DirichletEta.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="DirichletEta" - -//Jonathan Leto - -10 # DirichletEta(_z) <-- (1-2/2^z)*Zeta(z); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DirichletLambda.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DirichletLambda.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/DirichletLambda.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/DirichletLambda.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="DirichletLambda" - -//Jonathan Leto - -10 # DirichletLambda(_z)<-- (1-1/2^z)*Zeta(z); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Erfc.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Erfc.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Erfc.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Erfc.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Erfc" - -//Jonathan Leto - -10 # Erfc(_x) <-- 1 - Erf(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Erfi.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Erfi.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Erfi.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Erfi.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Erfi" - -//Jonathan Leto - -10 # Erfi(_x) <-- -I*Erf(x*I); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Erf.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Erf.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Erf.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Erf.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -%mathpiper,def="Erf" - -//Jonathan Leto - -///////////////////////////////////////////////// -/// Error and complementary error functions -///////////////////////////////////////////////// - -10 # Erf(0) <-- 0; -//10 # Erfc(0) <-- 1; -10 # Erf(Infinity) <-- 1; -10 # Erf(Undefined) <-- Undefined; -//10 # Erfc(Infinity) <-- 0; -10 # Erf(x_IsNumber)_(x<0) <-- -Erf(-x); -//40 # Erf(x_IsNumber)_(Abs(x) <= 1 ) <-- N(2/Sqrt(Pi)*ApproxInfSum((-1)^k*x^(2*k+1)/((2*k+1)*k!),0,x)); - -LocalSymbols(k) -[ - 40 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x)) And Abs(x) <= 1) <-- -[ - Local(prec); - prec := BuiltinPrecisionGet(); // N(...) modifies the precision - 2 / SqrtN(Internal'Pi()) * x - * SumTaylorNum(x^2, 1, {{k}, -(2*k-1)/(2*k+1)/k}, - // the number of terms n must satisfy n*Ln(n/Exp(1))>10^prec -// Hold({{k}, [Echo(k); k;]}) @ - N(1+87/32*Exp(LambertW(prec*421/497)), 20) - ); - -]; - -]; // LocalSymbols(k) - -// asymptotic expansion, can be used only for low enough precision or large enough |x| (see predicates). Also works for complex x. -LocalSymbols(n'max, k) -[ - - 50 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x)) - And ( - [ // strongest condition: the exp(-x^2) asymptotic is already good - n'max := 0; - Re(x^2) > BuiltinPrecisionGet()*3295/1431+0.121; - ] - Or - [ // next condition: the exp(-x^2) helps but we need a few terms of the series too - n'max := N(Min((BuiltinPrecisionGet()*3295/1431+0.121)/Internal'LnNum(Abs(x)), 2*Internal'LnNum(Abs(x))), 10); - 2*Abs(x)+Re(x^2) > BuiltinPrecisionGet()*3295/1431+0.121; - ] - Or - [ // worst case: exp(-x^2) does not help and we need the full series - // hack: save a value computed in the predicate to use in the body of rule - n'max := N(({{k}, k+Internal'LnNum(k)} @ BuiltinPrecisionGet()*3295/1431)/2 - 3/2, 10); - Abs(x) > n'max+3/2; - ] - ) - ) <-- If(Re(x)!=0, Sign(Re(x)), 0) - Exp(-x^2)/x/SqrtN(Internal'Pi()) - // the series is 1 - 1/2/x^2 + 1*3/2^2/x^4 - 1*3*5/2^3/x^6 + ... - * SumTaylorNum(1/x^2, 1, {{k}, -(2*k-1)/2 }, Max(0, Floor(n'max))); - -]; // LocalSymbols(n'max, k) - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/FresnelCos.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/FresnelCos.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/FresnelCos.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/FresnelCos.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="FresnelCos" - -//Jonathan Leto - -10 # FresnelCos(0) <-- 0; -10 # FresnelCos(Infinity) <-- 1/2; -10 # FresnelCos(x_IsNumber)_(x<0) <-- -FresnelCos(x); - -40 # FresnelCos(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(4*k-3)/((4*k-3) * (2*k-2)! ),1,x)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/FresnelSin.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/FresnelSin.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/FresnelSin.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/FresnelSin.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -%mathpiper,def="FresnelSin" - -//Jonathan Leto - -///////////////////////////////////////////////// -/// Fresnel integrals -///////////////////////////////////////////////// - -10 # FresnelSin(0) <-- 0; -10 # FresnelSin(Infinity) <-- 1/2; -10 # FresnelSin(x_IsNumber)_(x<0) <-- -FresnelSin(x); - -40 # FresnelSin(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(2*k+1)/(k! * (2*k+1)),1,x)); - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/gamma/Internal'GammaNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/gamma/Internal'GammaNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/gamma/Internal'GammaNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/gamma/Internal'GammaNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="Internal'GammaNum",scope="private" - -//Serge Winitzki - -Internal'GammaNum(z) := N(Exp(Internal'LnGammaNum(z))); - -/// this should not be used by applications -Internal'GammaNum(z,a) := N(Exp(Internal'LnGammaNum(z,a))); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/gamma/Internal'LnGammaNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/gamma/Internal'LnGammaNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/gamma/Internal'LnGammaNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/gamma/Internal'LnGammaNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="Internal'LnGammaNum",scope="private" - -///////////////////////////////////////////////// -/// Euler's Gamma function -///////////////////////////////////////////////// - -//Serge Winitzki - -/// This procedure computes the uniform approximation for the Gamma function -/// due to Lanczos and Spouge (the so-called "less precise coefficients") -/// evaluated at arbitrary precision by using a large number of terms -/// See J. L. Spouge, SIAM J. of Num. Anal. 31, 931 (1994) -/// See also Paul Godfrey 2001 (unpublished): http://winnie.fit.edu/~gabdo/gamma.txt for a discussion - -/// Calculate the uniform approximation to the logarithm of the Gamma function -/// in the Re z > 0 half-plane; argument z may be symbolic or complex -/// but current value of precision is used -/// Note that we return LnGamma(z), not of z+1 -/// This function should not be used directly by applications -10 # Internal'LnGammaNum(_z, _a)_(N(Re(z))<0) <-- [ - If (InVerboseMode(), Echo({"Internal'LnGammaNum: using 1-z identity"})); - N(Ln(Pi/Sin(Pi*z)) - Internal'LnGammaNum(1-z, a)); -]; -20 # Internal'LnGammaNum(_z, _a) <-- [ - Local(e, k, tmpcoeff, coeff, result); - a := Max(a, 4); // guard against low values - If (InVerboseMode(), Echo({"Internal'LnGammaNum: precision parameter = ", a})); - e := N(Exp(1)); - k:=Ceil(a); // prepare k=N+1; the k=N term is probably never significant but we don't win much by excluding it - result := 0; // prepare for last term - // use Horner scheme to prevent loss of precision - While(k>1) [ // 'result' will accumulate just the sum for now - k:=k-1; - result := N( PowerN(a-k,k)/((z+k)*Sqrt(a-k))-result/(e*k) ); - ]; - N(Ln(1+Exp(a-1)/Sqrt(2*Pi)*result) + Ln(2*Pi)/2 -a-z+(z+1/2)*Ln(z+a) - Ln(z)); -]; - -Internal'LnGammaNum(z) := [ - Local(a, prec, result); - prec := BuiltinPrecisionGet(); - a:= Div((prec-IntLog(prec,10))*659, 526) + 0.4; // see algorithm docs - /// same as parameter "g" in Godfrey 2001. - /// Chosen to satisfy Spouge's error bound: - /// error < Sqrt(a)/Real(a+z)/(2*Pi)^(a+1/2) -// Echo({"parameter a = ", a, " setting precision to ", Ceil(prec*1.4)}); - BuiltinPrecisionSet(Ceil(prec*1.4)); // need more precision b/c of roundoff errors but don't know exactly how many digits - result := Internal'LnGammaNum(z,a); - BuiltinPrecisionSet(prec); - result; -]; - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/gammaconst/GammaConstNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/gammaconst/GammaConstNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/gammaconst/GammaConstNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/gammaconst/GammaConstNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="GammaConstNum" - -GammaConstNum() := -[ - Local(k, n, A, B, U'old, U, V'old, V, prec, result); - prec:=BuiltinPrecisionGet(); - NonN([ - BuiltinPrecisionSet(prec+IntLog(prec,10)+3); // 2 guard digits and 1 to compensate IntLog - n:= 1+Ceil(prec*0.5757+0.2862); // n>(P*Ln(10)+Ln(Pi))/4 - A:= -Internal'LnNum(n); - B:=1; - U:=A; - V:=1; - k:=0; - U'old := 0; // these variables are for precision control - V'old := 0; - While(U'old-U != 0 Or V'old-V != 0) - [ - k++; - U'old:=U; - V'old:=V; - // B:=N( B*n^2/k^2 ); - B:=MultiplyNum(B,n^2/k^2); // slightly faster - // A:=N( (A*n^2/k+B)/k ); - A:=MultiplyNum(MultiplyNum(A,n^2/k)+B, 1/k); // slightly faster - U:=U+A; - V:=V+B; - ]; - If(InVerboseMode(), Echo("GammaConstNum: Info: used", k, "iterations at working precision", BuiltinPrecisionGet())); - result:=DivideN(U,V); // N(U/V) - ]); - BuiltinPrecisionSet(prec); // restore precision - RoundTo(result, prec); // return correctly rounded result -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Gamma.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Gamma.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Gamma.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Gamma.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -%mathpiper,def="Gamma" - -///////////////////////////////////////////////// -/// Euler's Gamma function -//////////////////////////////////////////////////// -/// Serge Winitzki - -/// User visible functions: Gamma(x), LnGamma(x) - -5 # Gamma(Infinity) <-- Infinity; - -10 # Gamma(_n)_(IsInteger(n) And n<=0) <-- Infinity; - - -20 # Gamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- (Round(2*n)/2-1)!; - - -30 # Gamma(x_IsConstant)_(InNumericMode()) <-- Internal'GammaNum(N(Eval(x))); - - -%/mathpiper - - - -%mathpiper_docs,name="Gamma",categories="User Functions;Special" -*CMD Gamma --- Euler's Gamma function -*STD -*CALL - Gamma(x) - -*PARMS - -{x} -- expression - -{number} -- expression that can be evaluated to a number - -*DESC - -{Gamma(x)} is an interface to Euler's Gamma function $Gamma(x)$. It returns exact values on integer and half-integer arguments. {N(Gamma(x)} takes a numeric parameter and always returns a floating-point number in the current precision. - -Note that Euler's constant $gamma<=>0.57722$ is the lowercase {gamma} in MathPiper. - -*E.G. - - In> Gamma(1.3) - Out> Gamma(1.3); - In> N(Gamma(1.3),30) - Out> 0.897470696306277188493754954771; - In> Gamma(1.5) - Out> Sqrt(Pi)/2; - In> N(Gamma(1.5),30); - Out> 0.88622692545275801364908374167; - -*SEE !, N, gamma -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/LambertW.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/LambertW.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/LambertW.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/LambertW.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -%mathpiper,def="LambertW" - -//Jonathan Leto - -///////////////////////////////////////////////// -/// Lambert's $W$ function. -///////////////////////////////////////////////// -/// Serge Winitzki - -10 # LambertW(0) <-- 0; -10 # LambertW(Infinity) <-- Infinity; -10 # LambertW(Undefined) <-- Undefined; -10 # LambertW(-Infinity) <-- Infinity + I*Pi; -10 # LambertW(-Exp(-1)) <-- -1; -20 # LambertW(_x * Ln(_x)) <-- Ln(x); -20 # LambertW(Ln(_x) * _x) <-- Ln(x); - -30 # LambertW(x_IsConstant) _ InNumericMode() <-- Internal'LambertWNum(Eval(x)); - -/* {Internal'LambertWNum} computes a numeric approximation of Lambert's $W$ function -to the current precision. It uses a Halley iteration -$$ W'=W-(W-x*Exp(-W))/(W+1-(W+2)/(W+1)*(W-x*Exp(-W))/2) $$. -The function has real values for real $x >= -Exp(-1)$. (This point is a logarithmic branching point.) -*/ -10 # Internal'LambertWNum(x_IsNumber)_(x < -ExpN(-1)) <-- Undefined; -20 # Internal'LambertWNum(x_IsNumber) <-- -[ - Local(W); - NewtonNum( - `Hold( - { - {W}, - [ - Local(a); - a:=W- @x*ExpN(-W); - W-a/(W+1-(W+2)/(W+1)*a/2.); - ]}), - // initial approximation is the two-point global Pade: - If( - x<0, - x*ExpN(1) / (1+1 / (1 / SqrtN(2*(x*ExpN(1)+1)) - 1 / SqrtN(2) + 1/(ExpN(1)-1))), - Internal'LnNum(1+x)*(1-Internal'LnNum(1+Internal'LnNum(1+x))/(2+Internal'LnNum(1+x))) - ), - 10, // initial approximation is good to about 3 digits - 3 // 3rd order scheme - ); -]; - -%/mathpiper - - - -%mathpiper_docs,name="LambertW",categories="User Functions;Special" -*CMD LambertW --- Lambert's $W$ function - -*STD -*CALL - LambertW(x) -*PARMS - -{x} -- expression, argument of the function - -*DESC - -Lambert's $W$ function is (a multiple-valued, complex function) defined for any (complex) $z$ by -$$ W(z) * Exp(W(z)) = z$$. -This function is sometimes useful to represent solutions of transcendental equations. For example, the equation $Ln(x)=3*x$ can be "solved" by writing $x= -3*W(-1/3)$. It is also possible to take a derivative or integrate this function "explicitly". - -For real arguments $x$, $W(x)$ is real if $x>= -Exp(-1)$. - -To compute the numeric value of the principal branch of Lambert's $W$ function for real arguments $x>= -Exp(-1)$ to current precision, one can call {N(LambertW(x))} (where the function {N} tries to approximate its argument with a real value). - -*E.G. - In> LambertW(0) - Out> 0; - In> N(LambertW(-0.24/Sqrt(3*Pi))) - Out> -0.0851224014; - -*SEE Exp -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/LnGamma.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/LnGamma.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/LnGamma.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/LnGamma.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="LnGamma" - -///// Serge Winitzki - -10 # LnGamma(_n)_(IsInteger(n) And n<=0) <-- Infinity; - -20 # LnGamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- Ln((Round(2*n)/2-1)!); - -30 # LnGamma(x_IsConstant)_(InNumericMode()) <-- Internal'LnGammaNum(N(Eval(x))); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -OMDef( "Gamma", "nums1", "gamma" ); -OMDef( "LnGamma" , mathpiper, "LnGamma" ); -OMDef( "Zeta" , mathpiper, "Zeta" ); -OMDef( "Bernoulli" , mathpiper, "Bernoulli" ); -OMDef( "ApproxInfSum" , mathpiper, "ApproxInfSum" ); -OMDef( "BesselJ" , mathpiper, "BesselJ" ); -OMDef( "BesselI" , mathpiper, "BesselI" ); -OMDef( "BesselY" , mathpiper, "BesselY" ); -OMDef( "Erf" , mathpiper, "Erf" ); -OMDef( "Erfc" , mathpiper, "Erfc" ); -OMDef( "Erfi" , mathpiper, "Erfi" ); -OMDef( "FresnelSin" , mathpiper, "FresnelSin" ); -OMDef( "FresnelCos" , mathpiper, "FresnelCos" ); -OMDef( "LambertW" , mathpiper, "LambertW" ); -OMDef( "Beta" , mathpiper, "Beta" ); -OMDef( "DirichletEta" , mathpiper, "DirichletEta" ); -OMDef( "DirichletLambda", mathpiper, "DirichletLambda" ); -OMDef( "DirichletBeta" , mathpiper, "DirichletBeta" ); -OMDef( "Sinc" , mathpiper, "Sinc" ); -OMDef( "PolyLog" , mathpiper, "PolyLog" ); -OMDef( "CatalanConstNum", mathpiper, "CatalanConstNum" ); -OMDef( "Digamma" , mathpiper, "Digamma" ); -OMDef( "DawsonIntegral" , mathpiper, "DawsonIntegral" ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/PolyLog.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/PolyLog.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/PolyLog.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/PolyLog.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -%mathpiper,def="PolyLog" - -//Jonathan Leto - -////// Polylogarithm Function -/// coded by Jonathan Leto: PolyLog, Dirichlet*, Digamma, Bessel*, Erf*, Fresnel*, Beta, -/// CatalanConstNum, Sinc, Beta, DawsonIntegral -// Note: currently, the numerics are only working for x \in [-1,1] - -10 # PolyLog(_n,0) <-- 0; -// this is nicer than -Ln(1/2) -10 # PolyLog(1,1/2) <-- Ln(2); -10 # PolyLog(_n,1) <-- Zeta(n); -10 # PolyLog(_n,_m)_(m= -1) <-- DirichletEta(n); -10 # PolyLog(_n,_x)_(n< 0) <-- (1/((1-x)^(-n+1)))*Sum(i,0,-n,Eulerian(-n,i)*x^(-n-i) ); -//10 # PolyLog(_n,_x)_(n= -3) <-- x*(x^2 + 4*x + 1)/(x-1)^4; -//10 # PolyLog(_n,_x)_(n= -2) <-- x*(x+1)/(1-x)^3; -//10 # PolyLog(_n,_x)_(n= -1) <-- x/(1-x)^2; -10 # PolyLog(0,_x) <-- x/(1-x); -10 # PolyLog(1,_x) <-- -Ln(1-x); -// special values -10 # PolyLog(2,1/2) <-- (Pi^2 - 6*Ln(2)^2)/12; -10 # PolyLog(3,1/2) <-- (4*Ln(2)^3 - 2*Pi^2*Ln(2)+21*Zeta(3))/24; -10 # PolyLog(2,2) <-- Pi^2/4 - Pi*I*Ln(2); - -20 # PolyLog(_n,_x)_(InNumericMode() And x < -1 ) <-- [ - Local(prec,result); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - Echo("Warning: PolyLog is only currently accurate for x in [-1,1]"); - result:= (-1)^(n-1)*PolyLog(n,1/x) - ((Ln(-x))^n)/n! - - Sum(r,1,Round(n/2), - 2^(2*r-2)*Pi^(2*r)*Abs(Bernoulli(2*r))*Ln(-x)^(n-2*r)/( (2*r)! * (n - 2*r)! ) ); - BuiltinPrecisionSet(prec); - RoundTo(N(result),prec); -]; -20 # PolyLog(_n,_x)_(InNumericMode() And x>= -1 And x < 0 ) <-- [ - // this makes the domain [-1,0) into [0,1], - // so if the summation representation is used, it is monotone - Local(prec,result); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - - result:=PolyLog(n,x^2)/2^(n-1) - PolyLog(n,-x) ; - BuiltinPrecisionSet(prec); - RoundTo(N(result),prec); - -]; -/* this is very slow at high precision -20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x <= 1) <-- [ - Local(result,prec,term,k,eps); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - eps:=10^(-prec); - result:=0; - // Sorry Serge, I was only getting 2 digits of precision with this - // so why didn't you ask me? :) -- Serge - //terms:=Floor(10 + N(prec*Ln(10)/Ln(prec) - 1)); - //BuiltinPrecisionSet( prec + Floor(N(Ln(6*terms)/Ln(10))) ); - //result:=SumTaylorNum(x, {{k}, x^(k+1)/(k+1)^n }, terms ); - term:=1; - For(k:=1,Abs(term)>eps,k++)[ - term:=N(x^k/k^n); - result:=result+term; - ]; - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; -*/ - -20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x < 1) <-- -[ // use Taylor series x^(k+1)/(k+1)^n, converges for -1Higher Transcendental Functions, vol. 1; -/// P. Borwein, An efficient algorithm for Riemann Zeta function (1995). - -/// Numerical computation of Zeta function using Borwein's "third" algorithm -/// The value of $n$ must be large enough to ensure required precision -/// Also $s$ must satisfy $Re(s)+n+1 > 0$ -Internal'ZetaNum(_s, n_IsInteger) <-- [ - Local(result, j, sign); - If (InVerboseMode(), Echo({"Internal'ZetaNum: Borwein's method, precision ", BuiltinPrecisionGet(), ", n = ", n})); - result := 0; - sign := 1; // flipping sign - For(j:=0, j<=2*n-1, j++) - [ // this is suboptimal b/c we can compute the coefficients a lot faster in this same loop, but ok for now - result := N(result + sign*Internal'ZetaNumCoeffEj(j,n)/(1+j)^s ); - sign := -sign; - ]; - N(result/(2^n)/(1-2^(1-s))); -]; - -/// direct method -- only good for large s -Internal'ZetaNum1(s, limit) := [ - Local(i, sum); - If (InVerboseMode(), Echo({"Internal'ZetaNum: direct method (sum), precision ", BuiltinPrecisionGet(), ", N = ", limit})); - sum := 0; - limit := Ceil(N(limit)); - For(i:=2, i<=limit, i++) sum := sum+N(1/PowerN(i, s)); -// sum := sum + ( N( 1/PowerN(limit, s-1)) + N(1/PowerN(limit+1, s-1)) )/2/(s-1); // these extra terms don't seem to help much - sum+1; // add small terms together and then add 1 -]; -/// direct method -- using infinite product. For internal math, Internal'ZetaNum2 is faster for Bernoulli numbers > 250 or so. -Internal'ZetaNum2(s, limit) := -[ - Local(i, prod); - If (InVerboseMode(), Echo({"Internal'ZetaNum: direct method (product), precision ", BuiltinPrecisionGet(), ", N = ", limit})); - prod := N( (1-1/PowerN(2, s))*(1-1/PowerN(3,s)) ); - limit := Ceil(N(limit)); - For(i:=5, i<=limit, i:= NextPrime(i)) - prod := prod*N(1-1/PowerN(i, s)); - 1/prod; -]; - -/// Compute coefficients e[j] (see Borwein -- excluding (-1)^j ) -Internal'ZetaNumCoeffEj(j,n) := [ - Local(k); - 2^n-If(j1-s identity, s=", s, ", precision ", prec})); - result := 2*Exp(Internal'LnGammaNum(1-s)-(1-s)*Ln(2*Internal'Pi()))*Sin(Internal'Pi()*s/2) * Internal'ZetaNum(1-s); - ], - // choose between methods - If (N(Re(s)) > N(1+(prec*Ln(10))/(Ln(prec)+0.1), 6), - [ // use direct summation - n:= N(10^(prec/(s-1)), 6)+2; // 2 guard terms - BuiltinPrecisionSet(prec+2); // 2 guard digits - result := Internal'ZetaNum1(s, n); - ], - [ // use Internal'ZetaNum(s, n) - n := Ceil( N( prec*Ln(10)/Ln(8) + 2, 6 ) ); // add 2 digits just in case - BuiltinPrecisionSet(prec+2); // 2 guard digits - result := Internal'ZetaNum(s, n); - ] - ) - ); - BuiltinPrecisionSet(prec); - result; -]; - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Zeta.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Zeta.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/specfunc/Zeta.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/specfunc/Zeta.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -%mathpiper,def="Zeta" - -///////////////////////////////////////////////// -/// Riemann's Zeta function -///////////////////////////////////////////////// -/// Serge Winitzki - -/// identities for exact values of Zeta - -10 # Zeta(1) <-- Infinity; -10 # Zeta(0) <-- -1/2; // let's save time -10 # Zeta(3)_InNumericMode() <-- Zeta3(); // special case -10 # Zeta(n_IsEven)_(n>0) <-- Pi^n*(2^(n-1)/n! *Abs(Bernoulli(n))); -10 # Zeta(n_IsInteger)_(n<0) <-- -Bernoulli(-n+1)/(-n+1); -11 # Zeta(n_IsInfinity) <-- 1; - -/// compute numeric value -20 # Zeta(s_IsConstant)_(InNumericMode()) <-- Internal'ZetaNum(N(Eval(s))); - -%/mathpiper - - - -%mathpiper_docs,name="Zeta",categories="User Functions;Special" -*CMD Zeta --- Riemann's Zeta function - -*STD -*CALL - Zeta(x) - -*PARMS - -{x} -- expression - -{number} -- expression that can be evaluated to a number - -*DESC - -{Zeta(x)} is an interface to Riemann's Zeta function $zeta(s)$. It returns exact values on integer and half-integer arguments. {N(Zeta(x)} takes a numeric parameter and always returns a floating-point number in the current precision. - -*E.G. - - In> Precision(30) - Out> True; - In> Zeta(1) - Out> Infinity; - In> Zeta(1.3) - Out> Zeta(1.3); - In> N(Zeta(1.3)) - Out> 3.93194921180954422697490751058798; - In> Zeta(2) - Out> Pi^2/6; - In> N(Zeta(2)); - Out> 1.64493406684822643647241516664602; - -*SEE !, N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/BernoulliDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/BernoulliDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/BernoulliDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/BernoulliDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -%mathpiper,def="BernoulliDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -BernoulliDistribution(p_IsRationalOrNumber)_(p<0 Or p>1) <-- Undefined; - -%/mathpiper - - - -%mathpiper_docs,name="BernoulliDistribution",categories="User Functions;Statistics & Probability" -*CMD BernoulliDistribution --- Bernoulli distribution -*STD -*CALL - BernoulliDistribution(p) - -*PARMS - -{p} -- number, probability of an event in a single trial - -*DESC -A random variable has a Bernoulli distribution with probability {p} if -it can be interpreted as an indicator of an event, where {p} is the -probability to observe the event in a single trial. - -Numerical value of {p} must satisfy $01, False) - Or (IsConstant(n) And Not IsPositiveInteger(n)) ) - <-- Undefined; - -%/mathpiper - - - -%mathpiper_docs,name="BinomialDistribution",categories="User Functions;Statistics & Probability" -*CMD BinomialDistribution --- binomial distribution -*STD -*CALL - BinomialDistribution(p,n) - -*PARMS -{p} -- number, probability to observe an event in single trial - -{n} -- number of trials - -*DESC -Suppose we repeat a trial {n} times, the probability to observe an -event in a single trial is {p} and outcomes in all trials are mutually -independent. Then the number of trials when the event occurred -is distributed according to the binomial distribution. The probability -of that is {BinomialDistribution}{(p,n)}. - -Describes the number of successes for draws with replacement. - -Numerical value of {p} must satisfy $0=b) - <-- Undefined; - -%/mathpiper - - - - -%mathpiper_docs,name="ContinuousUniformDistribution",categories="User Functions;Statistics & Probability" -*CMD ContinuousUniformDistribution --- Discrete uniform distribution -*STD -*CALL - ContinuousUniformDistribution(a, b) - -*PARMS - -{a} -- number, lower range value -{b} -- number, upper range value - - -*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/DiscreteDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/DiscreteDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/DiscreteDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/DiscreteDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="DiscreteDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -DiscreteDistribution( dom_IsRationalOrNumber , prob_IsRationalOrNumber) <-- Undefined; - -%/mathpiper - - - - -%mathpiper_docs,name="DiscreteDistribution",categories="User Functions;Statistics & Probability" -*CMD ContinuousUniformDistribution --- Discrete uniform distribution -*STD -*CALL - DiscreteDistribution(dom, prob) - -*PARMS - -{dom} -- list -{prob} -- list - - -*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/DiscreteUniformDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/DiscreteUniformDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/DiscreteUniformDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/DiscreteUniformDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -%mathpiper,def="DiscreteUniformDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -DiscreteUniformDistribution(a_IsRationalOrNumber, b_IsRationalOrNumber)_(a>=b) - <-- Undefined; - -%/mathpiper - - - - -%mathpiper_docs,name="DiscreteUniformDistribution",categories="User Functions;Statistics & Probability" -*CMD DiscreteUniformDistribution --- Discrete uniform distribution -*STD -*CALL - DiscreteUniformDistribution(a, b) - -*PARMS - -{a} -- number, lower range value -{b} -- number, upper range value - - -*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/ExponentialDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/ExponentialDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/ExponentialDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/ExponentialDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="ExponentialDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -ExponentialDistribution(l_IsRationalOrNumber)_(l<0) <-- Undefined; - -%/mathpiper - - - - -%mathpiper_docs,name="ExponentialDistribution",categories="User Functions;Statistics & Probability" -*CMD ExponentialDistribution --- Exponential distribution -*STD -*CALL - ExponentialDistribution(lambda) - -*PARMS - -{lambda} -- number, the rate parameter - - -*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ContinuousUniformDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/GeometricDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/GeometricDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/GeometricDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/GeometricDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="GeometricDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -GeometricDistribution(p_IsRationalOrNumber)_(p<0 Or p>1) <-- Undefined; - -%/mathpiper - - - - -%mathpiper_docs,name="GeometricDistribution",categories="User Functions;Statistics & Probability" -*CMD GeometricDistribution --- Geometric distribution -*STD -*CALL - GeometricDistribution(p) - -*PARMS - -{p} -- number, probability of an event in a single trial - - -*SEE BinomialDistribution, BernoulliDistribution, DiscreteUniformDistribution, ChiSquareDistribution, ContinuousUniformDistribution, ExponentionalDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/HypergeometricDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/HypergeometricDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/HypergeometricDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/HypergeometricDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="HypergeometricDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -HypergeometricDistribution(N_IsRationalOrNumber, M_IsRationalOrNumber, n_IsRationalOrNumber)_(M > N Or n > N) - <-- Undefined; - -%/mathpiper - - - - -%mathpiper_docs,name="HypergeometricDistribution",categories="User Functions;Statistics & Probability" -*CMD HypergeometricDistribution --- Hypergeometric distribution -*STD -*CALL - HypergeometricDistribution(N, M, n) - -*PARMS - -{N} -- number, a finite population -{M} -- number of items from N that fall into a class of interest -{n} -- number of items drawn from N - -*DESC - -A discrete probability distribution that describes the number of successes in a sequence of -draws from a finite population without replacement. The hypergeometric distribution is the -probability model which is used for selecting a random sample of n items without replacement -from a lot of N items, M of which are nonconforming or defective. - -*E.G. - -/%mathpiper,title="" - -ProbabilityDensityFunction(HypergeometricDistribution(100,5,10),0); - -/%/mathpiper - - /%output,preserve="false" - Result: 0.5837523670 -. /%/output - - - -/%mathpiper,title="" - -CumulativeDistributionFunction(HypergeometricDistribution(100,5,10),1); - -/%/mathpiper - - /%output,preserve="false" - Result: 0.9231432779 -. /%/output - -*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs - - %output,preserve="false" - -. %/output - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/NormalDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/NormalDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/NormalDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/NormalDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="NormalDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -NormalDistribution( _m , s2_IsRationalOrNumber)_(s2<=0) <-- Undefined; - -%/mathpiper - - - - -%mathpiper_docs,name="NormalDistribution",categories="User Functions;Statistics & Probability" -*CMD ContinuousUniformDistribution --- Discrete uniform distribution -*STD -*CALL - NormalDistribution(mean, sigma) - -*PARMS - -{mean} -- Number, the mean of the distribution -{sigma} -- Number, the standard deviation of the distribution - - -*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/PoissonDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/PoissonDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/PoissonDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/PoissonDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="PoissonDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -PoissonDistribution(l_IsRationalOrNumber)_(l<=0) <-- Undefined; - -%/mathpiper - - - - - -%mathpiper_docs,name="PoissonDistribution",categories="User Functions;Statistics & Probability" -*CMD PoissonDistribution --- Poisson distribution -*STD -*CALL - PoissonDistribution(lambda) - -*PARMS - -{lambda} -- number, the expected number of occurrences that occur during the given interval - - -*SEE BinomialDistribution, BernoulliDistribution, DiscreteUniformDistribution, ChiSquareDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/tDistribution.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/tDistribution.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/distributions/tDistribution.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/distributions/tDistribution.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="tDistribution" - -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ - -tDistribution(m_IsRationalOrNumber)_(Not IsPositiveInteger(m)) <-- Undefined; - -%/mathpiper - - - -%mathpiper_docs,name="tDistribution",categories="User Functions;Statistics & Probability" -*CMD tDistribution --- Student's $t$ distribution -*STD -*CALL - {tDistribution}(m) - -*PARMS -{m} -- integer, number of degrees of freedom - -*DESC - -*REM what does it do??? -The function {tDistribution} returns the ... - -Let $Y$ and $Z$ be independent random variables, $Y$ have the -NormalDistribution(0,1), {Z} have ChiSquareDistribution(m). Then -$Y/Sqrt(Z/m)$ has tDistribution(m). - -Numerical value of {m} must be positive integer. -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/GeometricMean.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/GeometricMean.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/GeometricMean.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/GeometricMean.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="GeometricMean" - -GeometricMean(x) := Product(x)^(1/Length(x)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/hypothesystest/ChiSquareTest.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/hypothesystest/ChiSquareTest.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/hypothesystest/ChiSquareTest.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/hypothesystest/ChiSquareTest.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -%mathpiper,def="ChiSquareTest" - -/* - Hypothesys testing routines - Andrei Zorine,2002 -*/ - -/* Stub: ChiSquare's CDF is computed as IncompleteGamma(x,dof/2)/Gamma(dof/2); */ - -100 # ChiSquareTest( observed'freqs_IsList, expected'freqs_IsList, estimated'params_IsInteger) - <-- - [ - Local( nominator, chi2, p'value, k, dof); - k:=Length(observed'freqs); - nominator:=(observed'freqs-expected'freqs)^2; //threading - chi2:=Sum(i,1,k,nominator[i]/(expected'freqs[i])); - dof := k-estimated'params-1; // degrees of freedom - p'value:=1-N(IncompleteGamma(chi2/2,dof/2)/Gamma(dof/2)); - { TestStatistics <- chi2 , P'value <- p'value,Atom("dof") <- dof}; - - ]; - - -100 # ChiSquareTest( observed'freqs_IsList, - expected'freqs_IsList) <-- ChiSquareTest( observed'freqs, expected'freqs, 0); - - -%/mathpiper - - - -%mathpiper_docs,name="ChiSquareTest",categories="User Functions;Statistics & Probability" -*CMD ChiSquareTest --- Pearson's ChiSquare test -*STD - -*CALL - ChiSquareTest(observed,expected) - ChiSquareTest(observed,expected,params) - -*PARMS -{observed} -- list of observed frequencies - -{expected} -- list of expected frequencies - -{params} -- number of estimated parameters - -*DESC -{ChiSquareTest} is intended to find out if our sample was drawn from a -given distribution or not. To find this out, one has to calculate -observed frequencies into certain intervals and expected ones. To -calculate expected frequency the formula $n[i]:=n*p[i]$ must be used, -where $p[i]$ is the probability measure of $i$-th interval, and $n$ is -the total number of observations. If any of the parameters of the -distribution were estimated, this number is given as -{params}. - -The function returns a list of three local substitution rules. First -of them contains the test statistic, the second contains the value of the parameters, and -the last one contains the degrees of freedom. - -The test statistic is distributed as ChiSquareDistribution. -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/incompletegamma/IncompleteGamma.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/incompletegamma/IncompleteGamma.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/incompletegamma/IncompleteGamma.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/incompletegamma/IncompleteGamma.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -%mathpiper,def="IncompleteGamma" - -/* IncompleteGamma function \int\limits_{0}^xt^{a-1}e^{-t}dt - - Calculation is based on series - IncompleteGamma(x,a)=x^a*Sum(k,0,infinity,(-1)^k*x^k/k!/(a+k) - (see D.S.Kouznetsov. Special functions. Vysshaia Shkola, Moscow, 1965) - for small x, and on asymptotic expansion - IncompleteGamma(x,a)=Gamma(x)-x^(a-1)*Exp(-x)*(1+(a-1)/z+(a-1)(a-2)/z^2+...) - (see O.E.Barndorf-Nielsen & D.R.Cox. Asymptotic techniques for Use - in Statistics.. Russian translation is also available) - for large x. -*/ - -IncompleteGamma(_x, _a)_(x<=a+1) <-- -[ - Local(prec,eps); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(Ceil(prec+1)); // this is a guess - eps:=5*10^(-prec); - - Local(term,result,k); - - term:=1/a; - k:=0; - result:=0; - While( Abs(term) >= eps )[ - k:=k+1; - result:=result+term; - term:= -x*(a+k-1)*term/k/(a+k); - ]; - result:= N(x^a*result); - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - RoundTo(result,prec); -]; - - -100 # IncompleteGamma(_x, _a)_(x>a+1) <-- -[ // Asymptotic expansion - Local(prec,eps); - prec:=BuiltinPrecisionGet(); - BuiltinPrecision'Set(Ceil(prec+1)); // this is a guess - eps:=5*10^(-prec); - - Local(term,result,k,expr); - - term:=1; - k:=0; - result:=0; - While( Abs(term) >= eps )[ - k:=k+1; - result:=result+term; - term:=term*(a-k)/x; - //Echo({"term is ",term}); - ]; - result:=N(Gamma(a)-x^(a-1)*Exp(-x)*result); - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - RoundTo(result,prec); -]; - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/Mean.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/Mean.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/Mean.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/Mean.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="Mean" - -Mean(x) := Add(x)/Length(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/Median.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/Median.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/Median.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/Median.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="Median" - -Median(x) := -[ - Local(sx,n,n2); // s[orted]x - sx := BubbleSort(x,"<"); - n := Length(x); - n2 := (n>>1); - If(Mod(n,2) = 1, sx[n2+1], (sx[n2]+sx[n2+1])/2); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/randomtest.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/randomtest.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/randomtest.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/randomtest.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -%mathpiper,def="",scope="nobuild",subtype="manual_test" - -/* - Tests MathPiper's Randomnumber generator - Author Andrei Zorine, zoav1@uic.nnov.ru -*/ - -DefaultDerivtory("c:/src/ys/prob"); -Load("incompletegamma.mpi"); -Load("hypothesystest.mpi"); - - -Function("DoTest",{size}) -[ - Local(arr,o'f,e'f,i,j,m); -// size:=200; // sample size - arr := Table(Random(),i,1,size,1); - arr := HeapSort(arr,"<"); - o'f := {}; - e'f :={}; - m:=1; - For(i:=1, i<=10 And m<=size, i++) - [ - j:=0; - While(arr[m] Sqrt(1.01) ? - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/UnbiasedVariance.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/UnbiasedVariance.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/UnbiasedVariance.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/UnbiasedVariance.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="UnbiasedVariance" - -UnbiasedVariance(x) := Add((x-Mean(x))^2)/(Length(x)-1); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/Variance.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/Variance.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/statistics/Variance.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/statistics/Variance.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="Variance" - -Variance(x) := Add((x-Mean(x))^2)/Length(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stats/ExpressionDepth.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stats/ExpressionDepth.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stats/ExpressionDepth.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stats/ExpressionDepth.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -%mathpiper,def="ExpressionDepth" - -10 # ExpressionDepth(expression_IsFunction) <-- -[ - Local(result); - result:=0; - ForEach(item,Rest(Listify(expression))) - [ - Local(newresult); - newresult:=ExpressionDepth(item); - result:=Max(result,newresult); - ]; - result+1; -]; -20 # ExpressionDepth(_expression) <-- 1; -UnFence("ExpressionDepth",1); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCosh.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCosh.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCosh.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCosh.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="ArcCosh" - -10 # ArcCosh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln(x+Sqrt(x^2-1)) )); - -200 # ArcCosh(Infinity) <-- Infinity; -200 # ArcCosh(-Infinity) <-- Infinity+I*Pi/2; -200 # ArcCosh(Undefined) <-- Undefined; - -ArcCosh(xlist_IsList) <-- MapSingle("ArcCosh",xlist); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCos.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCos.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCos.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCos.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -%mathpiper,def="ArcCos" - -2 # ArcCos(x_IsNumber)_InNumericMode() <-- Internal'Pi()/2-ArcSin(x); -4 # ArcCos(Cos(_x)) <-- x; - - /* TODO check! */ -200 # ArcCos(0) <-- Pi/2; -200 # ArcCos(1/2) <-- Pi/3; -200 # ArcCos(Sqrt(1/2)) <-- Pi/4; -200 # ArcCos(Sqrt(3/4)) <-- Pi/6; -200 # ArcCos(1) <-- 0; -200 # ArcCos(_n)_(n = -1) <-- Pi; -200 # ArcCos(_n)_(-n = Sqrt(3/4)) <-- 5/6*Pi; -200 # ArcCos(_n)_(-n = Sqrt(1/2)) <-- 3/4*Pi; -200 # ArcCos(_n)_(-n = 1/2) <-- 2/3*Pi; - -200 # ArcCos(Undefined) <-- Undefined; - -ArcCos(xlist_IsList) <-- MapSingle("ArcCos",xlist); - -110 # ArcCos(Complex(_r,_i)) <-- - (- I)*Ln(Complex(r,i) + (Complex(r,i)^2 - 1)^(1/2)); - -%/mathpiper - - - -%mathpiper_docs,name="ArcCos",categories="User Functions;Calculus Related (Symbolic)" - -*CMD ArcCos --- inverse trigonometric function arc-cosine -*STD -*CALL - ArcCos(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function represents the inverse trigonometric function arc-cosine. For -instance, the value of $ArcCos(x)$ is a number $y$ such that -$Cos(y)$ equals $x$. - -Note that the number $y$ is not unique. For instance, $Cos(Pi/2)$ and -$Cos(3*Pi/2)$ both equal 0, so what should $ArcCos(0)$ be? In MathPiper, -it is agreed that the value of $ArcCos(x)$ should be in the interval [0,$Pi$] . - -Usually, MathPiper leaves this function alone unless it is forced to do -a numerical evaluation by the {N} function. If the -argument is -1, 0, or 1 however, MathPiper will simplify the -expression. If the argument is complex, the expression will be -rewritten using the {Ln} function. - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - - In> ArcCos(0) - Out> Pi/2 - - In> ArcCos(1/3) - Out> ArcCos(1/3) - In> Cos(ArcCos(1/3)) - Out> 1/3 - - In> x:=N(ArcCos(0.75)) - Out> 0.7227342478 - In> N(Cos(x)) - Out> 0.75 - - -*SEE Sin, Cos, Tan, N, Pi, Ln, ArcSin, ArcTan - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCoth.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCoth.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCoth.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCoth.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCot.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCot.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCot.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCot.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts yet. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCsch.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCsch.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCsch.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCsch.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCsc.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCsc.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcCsc.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcCsc.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts yet. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSech.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSech.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSech.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSech.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSec.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSec.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSec.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSec.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts yet. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSinh.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSinh.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSinh.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSinh.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper,def="ArcSinh" - -10 # ArcSinh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln(x+Sqrt(x^2+1)) )); - -200 # ArcSinh(Infinity) <-- Infinity; -200 # ArcSinh(-Infinity) <-- -Infinity; -200 # ArcSinh(Undefined) <-- Undefined; - -ArcSinh(xlist_IsList) <-- MapSingle("ArcSinh",xlist); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSin.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSin.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcSin.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcSin.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -%mathpiper,def="ArcSin" - -2 # ArcSin(x_IsNumber)_(InNumericMode() And Abs(x)<=1) <-- ArcSinNum(x); -/// complex ArcSin -3 # ArcSin(x_IsNumber)_InNumericMode() <-- Sign(x)*(Pi/2+I*ArcCosh(x)); -4 # ArcSin(Sin(_x)) <-- x; -110 # ArcSin(Complex(_r,_i)) <-- - (- I) * Ln((I*Complex(r,i)) + ((1-(Complex(r,i)^2))^(1/2))); - -150 # ArcSin(- _x)_(Not IsConstant(x)) <-- -ArcSin(x); -160 # (ArcSin(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcSin(-x); - -200 # ArcSin(0) <-- 0; -200 # ArcSin(1/2) <-- Pi/6; -200 # ArcSin(Sqrt(1/2)) <-- Pi/4; -200 # ArcSin(Sqrt(3/4)) <-- Pi/3; -200 # ArcSin(1) <-- Pi/2; -200 # ArcSin(_n)_(n = -1) <-- -Pi/2; -200 # ArcSin(_n)_(-n = Sqrt(3/4)) <-- -Pi/3; -200 # ArcSin(_n)_(-n = Sqrt(1/2)) <-- -Pi/4; -200 # ArcSin(_n)_(-n = 1/2) <-- -Pi/6; - -ArcSin(xlist_IsList) <-- MapSingle("ArcSin",xlist); - -200 # ArcSin(Undefined) <-- Undefined; - -%/mathpiper - - - -%mathpiper_docs,name="ArcSin",categories="User Functions;Calculus Related (Symbolic)" -*CMD ArcSin --- inverse trigonometric function arc-sine -*STD -*CALL - ArcSin(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function represents the inverse trigonometric function arcsine. For -instance, the value of $ArcSin(x)$ is a number $y$ such that -$Sin(y)$ equals $x$. - -Note that the number $y$ is not unique. For instance, $Sin(0)$ and -$Sin(Pi)$ both equal 0, so what should $ArcSin(0)$ be? In MathPiper, -it is agreed that the value of $ArcSin(x)$ should be in the interval -[-$Pi$/2,$Pi$/2]. - -Usually, MathPiper leaves this function alone unless it is forced to do -a numerical evaluation by the {N} function. If the -argument is -1, 0, or 1 however, MathPiper will simplify the -expression. If the argument is complex, the expression will be -rewritten using the {Ln} function. - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> ArcSin(1) - Out> Pi/2; - - In> ArcSin(1/3) - Out> ArcSin(1/3); - In> Sin(ArcSin(1/3)) - Out> 1/3; - - In> x:=N(ArcSin(0.75)) - Out> 0.848062; - In> N(Sin(x)) - Out> 0.7499999477; - -*SEE Sin, Cos, Tan, N, Pi, Ln, ArcCos, ArcTan -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcTanh.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcTanh.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcTanh.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcTanh.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -%mathpiper,def="ArcTanh" - -10 # ArcTanh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln((1+x)/(1-x))/2 )); - -200 # ArcTanh(Infinity) <-- Infinity+I*Pi/2; -200 # ArcTanh(-Infinity) <-- -Infinity-I*Pi/2; // this is a little silly b/c we don't support correct branch cuts yet -200 # ArcTanh(Undefined) <-- Undefined; - -ArcTanh(xlist_IsList) <-- MapSingle("ArcTanh",xlist); - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcTan.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcTan.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/ArcTan.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/ArcTan.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -%mathpiper,def="ArcTan" - -5 # (ArcTan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcTan(-x); - -//TODO fix! 4 # ArcTan(Tan(_x)) <-- x; -4 # ArcTan(-Tan(_x)) <-- -ArcTan(Tan(x)); -110 # ArcTan(Complex(_r,_i)) <-- - (- I*0.5)*Ln(Complex(1,Complex(r,i))/ Complex(1, - Complex(r,i))); - -150 # ArcTan(- _x)_(Not IsConstant(x)) <-- -ArcTan(x); -160 # (ArcTan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcTan(-x); - -200 # ArcTan(Sqrt(3)) <-- Pi/3; -200 # ArcTan(-Sqrt(3)) <-- -Pi/3; -200 # ArcTan(1) <-- Pi/4; -200 # ArcTan(0) <-- 0; -200 # ArcTan(_n)_(n = -1) <-- -Pi/4; - -200 # ArcTan(Infinity) <-- Pi/2; -200 # ArcTan(-Infinity) <-- -Pi/2; -200 # ArcTan(Undefined) <-- Undefined; - -ArcTan(xlist_IsList) <-- MapSingle("ArcTan",xlist); - -2 # ArcTan(x_IsNumber)_InNumericMode() <-- ArcTanNum(x); - - -%/mathpiper - - - -%mathpiper_docs,name="ArcTan",categories="User Functions;Calculus Related (Symbolic)" -*CMD ArcTan --- inverse trigonometric function arc-tangent -*STD -*CALL - ArcTan(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function represents the inverse trigonometric function arctangent. For -instance, the value of $ArcTan(x)$ is a number $y$ such that -$Tan(y)$ equals $x$. - -Note that the number $y$ is not unique. For instance, $Tan(0)$ and -$Tan(2*Pi)$ both equal 0, so what should $ArcTan(0)$ be? In MathPiper, -it is agreed that the value of $ArcTan(x)$ should be in the interval -[-$Pi$/2,$Pi$/2]. - -Usually, MathPiper leaves this function alone unless it is forced to do -a numerical evaluation by the {N} function. MathPiper will try to simplify -as much as possible while keeping the result exact. If the argument is -complex, the expression will be rewritten using the {Ln} function. - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> ArcTan(1) - Out> Pi/4 - - In> ArcTan(1/3) - Out> ArcTan(1/3) - In> Tan(ArcTan(1/3)) - Out> 1/3 - - In> x:=N(ArcTan(0.75)) - Out> 0.643501108793285592213351264945231378078460693359375 - In> N(Tan(x)) - Out> 0.75 - -*SEE Sin, Cos, Tan, N, Pi, Ln, ArcSin, ArcCos -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Cosh.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Cosh.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Cosh.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Cosh.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="Cosh" - -5 # Cosh(- _x) <-- Cosh(x); - -// this is never activated - -//100 # Cosh(I*_x) <-- Cos(x); - -100 # Cosh(_x)*Sech(_x) <-- 1; - -200 # Cosh(0) <-- 1; -200 # Cosh(Infinity) <-- Infinity; -200 # Cosh(-Infinity) <-- Infinity; -200 # Cosh(ArcCosh(_x)) <-- x; -200 # Cosh(ArcSinh(_x)) <-- Sqrt(1+x^2); -200 # Cosh(ArcTanh(_x)) <-- 1/Sqrt(1-x^2); - -200 # Cosh(Undefined) <-- Undefined; - -Cosh(xlist_IsList) <-- MapSingle("Cosh",xlist); - -2 # Cosh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( (Exp(x)+Exp(-x))/2 )); - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Cos.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Cos.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Cos.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Cos.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -%mathpiper,def="Cos" - -1 # CosMap( _n )_(Not(IsRationalOrNumber(n))) <-- UnList({Atom("Cos"),n*Pi}); -2 # CosMap( _n )_(n<0) <-- CosMap(-n); -2 # CosMap( _n )_(n>2) <-- CosMap(Mod(n,2)); -3 # CosMap( _n )_(n>1) <-- CosMap(2-n); -4 # CosMap( _n )_(n>1/2) <-- -CosMap(1-n); - -5 # CosMap( 0 ) <-- 1; -5 # CosMap( 1/6 ) <-- Sqrt(3)/2; -5 # CosMap( 1/4 ) <-- Sqrt(2)/2; -5 # CosMap( 1/3 ) <-- 1/2; -5 # CosMap( 1/2 ) <-- 0; -5 # CosMap( 2/5 ) <-- (Sqrt(5)-1)/4; - -10 # CosMap(_n) <-- UnList({Atom("Cos"),n*Pi}); - - - -2 # Cos(x_IsNumber)_InNumericMode() <-- CosNum(x); -4 # Cos(ArcCos(_x)) <-- x; -4 # Cos(ArcSin(_x)) <-- Sqrt(1-x^2); -4 # Cos(ArcTan(_x)) <-- 1/Sqrt(1+x^2); -5 # Cos(- _x)_(Not IsConstant(x)) <-- Cos(x); -6 # (Cos(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- Cos(-x); -// must prevent it from looping - -110 # Cos(Complex(_r,_i)) <-- - (Exp(I*Complex(r,i)) + Exp(- I*Complex(r,i))) / (2) ; - -6 # Cos(x_IsInfinity) <-- Undefined; -6 # Cos(Undefined) <-- Undefined; - -200 # Cos(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- - CosMap(Coef(v,Pi,1)); - -400 # Cos(x_IsRationalOrNumber) <-- - [ - Local(ll); - ll:= FloorN(N(Eval(x/Pi))); - If(IsEven(ll),x:=(x - Pi*ll),x:=(-x + Pi*(ll+1))); - UnList({Cos,x}); - ]; - -400 # Cos(x_IsRationalOrNumber) <-- - [ - Local(ll); - ll:= FloorN(N(Eval(Abs(x)/Pi))); - If(IsEven(ll),x:=(Abs(x) - Pi*ll),x:=(-Abs(x) + Pi*(ll+1))); - UnList({Cos,x}); - ]; - -100 # Cos(_x)*Tan(_x) <-- Sin(x); -100 # Cos(_x)/Sin(_x) <-- (1/Tan(x)); - -Cos(xlist_IsList) <-- MapSingle("Cos",xlist); - - -%/mathpiper - - - -%mathpiper_docs,name="Cos",categories="User Functions;Calculus Related (Symbolic)" -*CMD Cos --- trigonometric cosine function -*STD -*CALL - Cos(x) - -*PARMS - -{x} -- argument to the function, in radians - -*DESC - -This function represents the trigonometric function cosine. MathPiper leaves -expressions alone even if x is a number, trying to keep the result as -exact as possible. The floating point approximations of these functions -can be forced by using the {N} function. - -MathPiper knows some trigonometric identities, so it can simplify to exact -results even if {N} is not used. This is the case, for instance, -when the argument is a multiple of $Pi$/6 or $Pi$/4. - -These functions are threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Cos(1) - Out> Cos(1); - In> N(Cos(1),20) - Out> 0.5403023058681397174; - In> Cos(Pi/4) - Out> Sqrt(1/2); - -*SEE Sin, Tan, ArcSin, ArcCos, ArcTan, N, Pi -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Coth.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Coth.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Coth.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Coth.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -%mathpiper,def="Coth" - -100 # 1/Coth(_x) <-- Tanh(x); - -100 # Coth(_x) <-- 1/Tanh(x); - -100 # Coth(_x)*Sinh(_x) <-- Cosh(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Cot.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Cot.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Cot.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Cot.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Cot" - -100 # 1/Cot(_x) <-- Tan(x); - -100 # Cot(_x) <-- 1/Tan(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Csch.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Csch.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Csch.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Csch.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Csch" - -100 # 1/Csch(_x) <-- Sinh(x); - -100 # Csch(_x) <-- 1/Sinh(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Csc.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Csc.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Csc.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Csc.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Csc" - -100 # 1/Csc(_x) <-- Sin(x); - -100 # Csc(_x) <-- 1/Sin(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCoshN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCoshN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCoshN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCoshN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper - - - - - - -%mathpiper_docs,name="ArcCoshN",categories="User Functions;Numeric" -*CMD ArcCoshN --- inverse hyperbolic cosine (arbitrary-precision math function) -*CALL - ArcCoshN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCosN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCosN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCosN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcCosN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -//Not implemented in scripts. todo:tk. - -%/mathpiper - - - - - -%mathpiper_docs,name="ArcCosN",categories="User Functions;Numeric" -*CMD ArcCosN --- inverse cosine (arbitrary-precision math function) -*CALL - ArcCosN(x) () - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinhN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinhN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinhN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinhN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper - - - - - - -%mathpiper_docs,name="ArcSinhN",categories="User Functions;Numeric" -*CMD ArcSinhN --- inverse hyperbolic sine (arbitrary-precision math function) -*STD -*CALL - ArcSinhN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcSinN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%mathpiper,def="ArcSinN" - -Defun("ArcSinN",{int1}) -[ - Local(result,eps); - Set(result,FastArcSin(int1)); - Local(x,q,s,c); - Set(q,SubtractN(SinN(result),int1)); - Set(eps,MathIntPower(10,MathNegate(BuiltinPrecisionGet()))); - While(GreaterThan(AbsN(q),eps)) - [ - Set(s,SubtractN(int1,SinN(result))); - Set(c,CosN(result)); - Set(q,DivideN(s,c)); - Set(result,AddN(result,q)); - ]; - result; -]; - -%/mathpiper - - - - -%mathpiper_docs,name="ArcSinN",categories="User Functions;Numeric" -*CMD ArcSinN --- inverse sine (arbitrary-precision math function) -*CALL - ArcSinN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanhN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanhN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanhN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanhN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper - - - - - -%mathpiper_docs,name="ArcTanhN",categories="User Functions;Numeric" -*CMD ArcTanhN --- inverse hyperbolic tangent (arbitrary-precision math function) -*CALL - ArcTanhN(x) () - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -//Not implemented in scripts. todo:tk. - -%/mathpiper - - - - - -%mathpiper_docs,name="ArcTanN",categories="User Functions;Numeric" -*CMD ArcTanN --- inverse tangent (arbitrary-precision math function) -*CALL - ArcTanN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN'Taylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN'Taylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN'Taylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ArcTanN'Taylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="ArcTanN'Taylor" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// ArcTan(x), Taylor series for ArcTan(x)/x, use only with -1/2>1; - - // initialize u and u2 (u2==u^2). - u := 1 << l2; - u2 := u << l2; - - // Now for each lower bit: - While( l2 != 0 ) - [ - l2--; - // Get that bit in v, and v2 == v^2. - v := 1<must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Doubling.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Doubling.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Doubling.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Doubling.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -%mathpiper,def="CosN'Doubling",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Identity transformation, compute 1-Cos(x) from value=1-Cos(x/2^n) - -//Changed CosN'Doubling1 to CosN'Doubling. Note:tk. -CosN'Doubling(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ - result := MultiplyN(MathMul2Exp(result, 1), 2 - result); - shift--; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Taylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Taylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Taylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/CosN'Taylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="CosN'Taylor",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Cos(x), Taylor series -CosN'Taylor(x) := -[ - Local(num'terms, prec, Bx); - prec := DivN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) - Bx := -DivN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 - num'terms := DivN( DivN( prec-1, DivN( MathBitCount( prec-1)*1588, 2291)+Bx), 2)+1; - // (P*Ln(10)-1)/(Ln(P*Ln(10)-1)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) - SumTaylorNum(MultiplyN(x,x), 1, {{k}, -1/(2*k*(2*k-1))}, num'terms); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/DigitsToBits.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/DigitsToBits.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/DigitsToBits.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/DigitsToBits.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="DigitsToBits" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// BitsToDigits(n,base) and DigitsToBits(n,base). Enough to compute at low precision. -// this is now a call to the kernel functions, so leave as a reference implementation -DigitsToBits(n, base) := FloorN(0.51+n*N(Ln(base)/Ln(2),10)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Doubling.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Doubling.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Doubling.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Doubling.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -%mathpiper,def="ExpN'Doubling",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Identity transformation, compute Exp(x)-1 from value=Exp(x/2^n)-1 - -ExpN'Doubling1(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ - result := MathMul2Exp(result, 1) + MultiplyN(result, result); - shift--; - ]; - result; -]; - -/// Identity transformation, compute Exp(x) from value=Exp(x/2^n) -/* -ExpN'Doubling(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ - result := MultiplyN(result, result); - shift--; - ]; - result; -]; -*/ - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Taylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Taylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Taylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/ExpN'Taylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="ExpN'Taylor",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Compute Exp(x)-1 from the Taylor series for (Exp(x)-1)/x. -//Note:tk:changed name from ExpN'Taylor1 to ExpN'Taylor. -ExpN'Taylor(x) := -[ - Local(num'terms, prec, Bx); - prec := DivN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) - Bx := -DivN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 - num'terms := DivN( prec-1, DivN( MathBitCount( prec-1)*1588, 2291)+Bx)+1; - // (P*Ln(10)-1)/(Ln(P*Ln(10)-1)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) - x*SumTaylorNum(x, 1, {{k}, 1/(k+1)}, num'terms); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/GcdN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/GcdN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/GcdN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/GcdN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="" - -/* -todo:tk:this function was accidently shadowed by a built in function when the names of all MathXXX functions -were changed to XXXN. However, I checked JYacas and GcdN was not used anyplace in the scripts anyway -so the shadowing did not seem to cause any harm. I am commenting this function out until a reason -can be found to uncomment it. -*/ -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - - -/// GcdN(x,y). Compute the GCD of two integers using the binary Euclidean algorithm. -5 # GcdN(x_IsNegativeInteger, y_IsInteger) <-- GcdN(-x, y); -5 # GcdN(y_IsNegativeInteger, x_IsNegativeInteger) <-- GcdN(x, -y); -6 # GcdN(0, _x) <-- 0; -6 # GcdN(_x, 0) <-- 0; - -10 # GcdN(x_IsInteger, y_IsInteger) <-- -[ - Local(z); - While(x!=y) - [ - While(x=1) - [ - nbits++; - value := MathMul2Exp(value, -1); - ]; - ]); - nbits; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Doubling.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Doubling.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Doubling.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Doubling.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -%mathpiper,def="MathLn'Doubling",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Compute Ln(x) from Ln(x^(2^(1/n))) -MathLn'Doubling(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ - result := MultiplyN(result, result); - shift--; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Taylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Taylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Taylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathLn'Taylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="MathLn'Taylor",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Ln(x), Taylor series for Ln(1+y)/y, use only with 1/2=curprec, k:=Div(k,order)+2) True; - If(k<5, curprec:=5, curprec:=k); - // Echo("initial precision", curprec); - // now k is the iteration counter - For(k:=0, curprec < prec, k := k+1) [ - // at this iteration we know the result to curprec digits - curprec := Min(prec, curprec * order-2); // 2 guard digits - BuiltinPrecisionSet(curprec+2); - // Echo("Iteration ", k, " setting precision to ", BuiltinPrecisionGet()); - // Echo("old result=", CosN(result)); - /*EchoTime()*/[ - delta := CosN(result); - ]; - /*EchoTime()*/[ - deltasq := MultiplyN(delta,delta); - ]; - result := /*EchoTime()*/result + delta*(1 + deltasq*(1/6 + deltasq*(3/40 + deltasq*(5/112 + deltasq*(35/1152 + (deltasq*63)/2816))))); - ]; - // Echo({"Method 3, using Pi/2 and order", order, ":", k, "iterations"}); - ]); - result*2; -]; - -%/mathpiper - - - - - - - -%mathpiper_docs,name="MathPi",categories="User Functions;Numeric" -*CMD MathPi --- The constant Pi. -*CALL - MathPi() - -*DESC - -The constant Pi. Using a simple method, solve Cos(x)=0. -iterate x := x + Cos(x) + 1/6 *Cos(x)^3 + ... to converge to x=Pi/2 - -It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) -The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - -If a better optimized version of this function is available through the kernel, -then the kernel version will automatically shadow this function. -This implementation is not necessarily the best optimized version. - - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathSqrtFloat.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathSqrtFloat.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathSqrtFloat.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/MathSqrtFloat.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -%mathpiper,def="MathSqrtFloat",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -// This function is *only* for float and positive A! -// The answer is only obtained at the current precision. -MathSqrtFloat(_A) <-- -[ - Local(bitshift, a0, x0, x0sq, targetbits, subtargetbits, gotbits, targetprec); - bitshift := ShiftRight(MathBitCount(A)-1,1); - // this is how many bits of precision we need - targetprec := BuiltinPrecisionGet(); - // argument reduction: a0 is between 1 and 4 and has the full target precision - a0 := MathMul2Exp(A, -bitshift*2); // this bit shift would be wrong for integer A - BuiltinPrecisionSet(10); // enough to compute at this point - // cannot get more target bits than 1 + (the bits in A) - // if this is less than the requested precision, the result will be silently less precise, but c'est la vie - targetbits := Min(DigitsToBits(targetprec, 10), 1+GetExactBitsN(A)); - // initial approximation - x0 := DivideN(14+22*a0, 31+5*a0); - // this approximation gives at least 7 bits (relative error < 0.005) of Sqrt(a0) for 1 <= a0 <= 4 - gotbits := 7; - // find the conditions for the last 2 iterations to be done in almost optimal precision - subtargetbits := DivN(targetbits+8, 9); - If(gotbits >= subtargetbits, subtargetbits := DivN(targetbits+2, 3)); - If(gotbits >= subtargetbits, subtargetbits := targetbits*4); -// Echo("debug: subtargetbits=", subtargetbits, "a0=", a0, "targetbits=", targetbits, "bitshift=", bitshift, "targetprec=", targetprec); - // now perform Halley iterations until we get at least subtargetbits, then start with subtargetbits and perform further Halley iterations - While(gotbits < targetbits) - [ - gotbits := 3*gotbits+1; // Halley iteration; get 3n+2 bits, allow 1 bit for roundoff - // check for suboptimal last iterations - If(gotbits >= subtargetbits, - [ // it could be very suboptimal to continue with our value of gotbits, so we curb precision for the last 2 iterations which dominate the calculation time at high precision - gotbits := subtargetbits; - subtargetbits := targetbits*4; // make sure that the above condition never becomes true again - ]); - BuiltinPrecisionSet(BitsToDigits(gotbits, 10)+2); // guard digits - x0 := SetExactBitsN(x0, gotbits+6); // avoid roundoff - x0sq := MultiplyN(x0, x0); -// this gives too much roundoff error x0 := MultiplyN(x0, DivideN(3*a0+x0sq, a0+3*x0sq)); -// rather use this equivalent formula: - x0 := AddN(x0, MultiplyN(x0*2, DivideN(a0-x0sq, a0+3*x0sq))); -// Echo("debug: ", gotbits, x0, GetExactBitsN(x0), BuiltinPrecisionGet()); - ]; - // avoid truncating a precise result in x0 by calling BuiltinPrecisionSet() too soon - x0 := SetExactBitsN(MathMul2Exp(x0, bitshift), gotbits); - BuiltinPrecisionSet(targetprec); -// Echo("debug: answer=", x0); - x0; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinhN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinhN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinhN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinhN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper - - - - - - -%mathpiper_docs,name="SinhN",categories="User Functions;Numeric" -*CMD SinhN --- hyperbolic sine (arbitrary-precision math function) -*CALL - SinhN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Taylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Taylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Taylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Taylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="SinN'Taylor",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Compute Sin(x), Taylor series for Sin(x)/x -SinN'Taylor(x) := -[ - Local(num'terms, prec, Bx); - prec := DivN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) - Bx := -DivN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 - num'terms := DivN( DivN( prec+Bx, DivN( MathBitCount( prec+Bx)*1588, 2291)+Bx)+1, 2)+1; - // (P*Ln(10)-Ln(x)-2)/(Ln(P*Ln(10)-Ln(x)-2)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) - x*SumTaylorNum(MultiplyN(x,x), 1, {{k}, -1/(2*k*(2*k+1))}, num'terms); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Tripling.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Tripling.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Tripling.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SinN'Tripling.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -%mathpiper,def="SinN'Tripling",scope="private" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// Identity transformation, compute Sin(x) from value=Sin(x/3^n) - -SinN'Tripling(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ // Sin(x)*(3-4*Sin(x)^2) - result := MultiplyN(result, 3 - MathMul2Exp(MultiplyN(result,result), 2) ); - shift--; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SqrtN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SqrtN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SqrtN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/SqrtN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -%mathpiper,def="SqrtN" - -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// SqrtN(x). -SqrtN(x) := MathSqrt1(x); // to have another function is easier for debugging - -/// Compute square root(x) with nonnegative x. FIXME: No precision tracking yet. -10 # MathSqrt1(0) <-- 0; -/// negative or non-numeric arguments give error message -100 # MathSqrt1(_x) <-- [ Echo("SqrtN: invalid argument: ", x); False;]; - -// this is too slow at the moment -30 # MathSqrt1(x_IsPositiveNumber) <-- x*NewtonNum({{r}, r+r*(1-x*r^2)/2}, FastPower(x,-0.5), 4, 2); - -30 # MathSqrt1(x_IsPositiveNumber) <-- MathSqrtFloat(x); - -// for integers, we need to compute Sqrt(x) to (the number of bits in x) + 1 bits to figure out whether Sqrt(x) is itself an integer. If Sqrt(x) for integer x is exactly equal to an integer, we should return the integer answer rather than the float answer. For this answer, the current precision might be insufficient, therefore we compute with potentially more digits. This is slower but we assume this is what the user wants when calling SqrtN() on an integer. -20 # MathSqrt1(x_IsInteger) _ (GreaterThan(x,0)) <-- -[ - Local(result); - If(ModN(x,4)<2 And ModN(x,3)<2 And ModN(x+1,5)<3, - // now the number x has a nonzero chance of being an exact square - [ - // check whether increased precision would be at all necessary -// Echo("checking integer case"); - GlobalPush(BuiltinPrecisionGet()); - If(MathBitCount(x)+3>DigitsToBits(BuiltinPrecisionGet(), 10), - BuiltinPrecisionSet(BitsToDigits(MathBitCount(x), 10)+1)); - // need one more digit to decide whether Sqrt(x) is integer - // otherwise the current precision is sufficient - - // convert x to float and use the float routine - result := MathSqrtFloat(x+0.); - // decide whether result is integer: decrease precision and compare - If(FloatIsInt(SetExactBitsN(result, GetExactBitsN(result)-3)), result:= Floor(result+0.5)); - BuiltinPrecisionSet(GlobalPop()); - ], - // now the number x cannot be an exact square; current precision is sufficient - result := MathSqrtFloat(x+0.) - ); - // need to set the correct precision on the result - will have no effect on integer answers - SetExactBitsN(result, DigitsToBits(BuiltinPrecisionGet(),10)); -]; - -%/mathpiper - - - - - -%mathpiper_docs,name="SqrtN",categories="User Functions;Numeric" -*CMD SqrtN --- square root (x must be >= 0) (arbitrary-precision math function) -*CALL - SqrtN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> BuiltinPrecisionSet(10) - Out> True - In> Sqrt(10) - Out> Sqrt(10) - In> SqrtN(10) - Out> 3.16227766 - In> SqrtN(490000*2^150) - Out> 26445252304070013196697600 - In> SqrtN(490000*2^150+1) - Out> 0.264452523e26 - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/TanhN.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/TanhN.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/TanhN.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/elemfuncs/TanhN.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper - - - - - - -%mathpiper_docs,name="TanhN",categories="User Functions;Numeric" -*CMD TanhN --- hyperbolic tangent (arbitrary-precision math function) -*CALL - TanhN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Exp.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Exp.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Exp.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Exp.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="Exp" - -2 # Exp(x_IsNumber)_InNumericMode() <-- ExpNum(x); -4 # Exp(Ln(_x)) <-- x; -110 # Exp(Complex(_r,_i)) <-- Exp(r)*(Cos(i) + I*Sin(i)); -200 # Exp(0) <-- 1; -200 # Exp(-Infinity) <-- 0; -200 # Exp(Infinity) <-- Infinity; -200 # Exp(Undefined) <-- Undefined; - -Exp(xlist_IsList) <-- MapSingle("Exp",xlist); - -%/mathpiper - - - -%mathpiper_docs,name="Exp",categories="User Functions;Calculus Related (Symbolic)" -*CMD Exp --- exponential function -*STD -*CALL - Exp(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function calculates $e$ raised to the power $x$, where $e$ is the -mathematic constant 2.71828... One can use {Exp(1)} -to represent $e$. - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Exp(0) - Out> 1; - In> Exp(I*Pi) - Out> -1; - In> N(Exp(1)) - Out> 2.7182818284; - -*SEE Ln, Sin, Cos, Tan, N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Ln.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Ln.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Ln.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Ln.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%mathpiper,def="Ln" - -2 # Ln(0) <-- -Infinity; -2 # Ln(1) <-- 0; -2 # Ln(Infinity) <-- Infinity; -2 # Ln(Undefined) <-- Undefined; - -/* 2 # Ln(-Infinity) <-- 0; */ -2 # Ln(x_IsNegativeNumber)_InNumericMode() <-- Complex(Ln(-x), Pi); -3 # Ln(x_IsNumber)_(InNumericMode() And x>=1) <-- Internal'LnNum(x); -4 # Ln(Exp(_x)) <-- x; - -3 # Ln(Complex(_r,_i)) <-- Complex(Ln(Abs(Complex(r,i))), Arg(Complex(r,i))); -4 # Ln(x_IsNegativeNumber) <-- Complex(Ln(-x), Pi); -5 # Ln(x_IsNumber)_(InNumericMode() And x<1) <-- - Internal'LnNum(DivideN(1, x)); - -Ln(xlist_IsList) <-- MapSingle("Ln",xlist); - -%/mathpiper - - - -%mathpiper_docs,name="Ln",categories="User Functions;Calculus Related (Symbolic)" -*CMD Ln --- natural logarithm -*STD -*CALL - Ln(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function calculates the natural logarithm of "x". This is the -inverse function of the exponential function, {Exp}, i.e. $Ln(x) = y$ implies that $Exp(y) = x$. For complex -arguments, the imaginary part of the logarithm is in the interval -(-$Pi$,$Pi$]. This is compatible with the branch cut of {Arg}. - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Ln(1) - Out> 0; - In> Ln(Exp(x)) - Out> x; - In> D(x) Ln(x) - Out> 1/x; - -*SEE Exp, Arg -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcSinNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcSinNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcSinNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcSinNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="ArcSinNum" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -ArcSinNum(x) := -[ - // need to be careful when |x| close to 1 - If( - 239*Abs(x) >= 169, // 169/239 is a good enough approximation of 1/Sqrt(2) - // use trigonometric identity to avoid |x| close to 1 - Sign(x)*(Internal'Pi()/2-ArcSinN(Sqrt(1-x^2))), - ArcSinN(x) - ); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcTanNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcTanNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcTanNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/ArcTanNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -%mathpiper,def="ArcTanNum" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -ArcTanNum(x) := -[ - // using trigonometric identities is faster for now - If( - Abs(x)>1, - Sign(x)*(Internal'Pi()/2-ArcSin(1/Sqrt(x^2+1))), - ArcSin(x/Sqrt(x^2+1)) - ); -]; - - - - - -/* old methods -- slower for now -/// numerical evaluation of ArcTan using continued fractions: top level -2 # ArcTan(x_IsNumber)_InNumericMode() <-- -Sign(x) * -// now we need to compute ArcTan of a nonnegative number Abs(x) -[ - Local(nterms, y); - y := Abs(x); - // use identities to improve convergence -- see essays book - If( - y>1, - y:=1/y // now y <= 1 - // we shall know that the first identity was used because Abs(x) > 1 still - ); - // use the second identity - y := y/(1+Sqrt(1+y^2)); // now y <= Sqrt(2)-1 - // find the required number of terms in the continued fraction - nterms := 1/y; // this needs to be calculated at full precision - // see essays book on the choice of the number of terms (added 2 "guard terms"). - // we need Hold() because otherwise, if InNumericMode() returns True, N(..., 5) will not avoid the full precision calculation of Ln(). - // the value of x should not be greater than 1 here! - nterms := 2 + Ceil( N(Hold(Ln(10)/(Ln(4)+2*Ln(nterms))), 5) * BuiltinPrecisionGet() ); - If( // call the actual routine - Abs(x)>1, - Pi/2-2*MyArcTan(y, nterms), // this is for |x|>1 - 2*MyArcTan(y, nterms) - // MyArcTan(x, nterms) - ); -]; -*/ - - - -/// numerical evaluation of ArcTan using continued fractions: low level - -// evaluation using recursion -- slightly faster but lose some digits to roundoff errors and needs large recursion depth -/* -10 # ContArcTan(_x,_n,_n) <-- (2*n-1); -20 # ContArcTan(_x,_n,_m) <-- -[ - (2*n-1) + (n*x)^2/ContArcTan(x,n+1,m); -]; - -MyArcTan(x,n) := -[ - x/ContArcTan(x,1,n); -]; -*/ -/* -/// evaluate n terms of the continued fraction for ArcTan(x) without recursion. -/// better control of roundoff errors -MyArcTan(x, n) := -[ - Local(i, p, q, t); - // initial numerator and denominator - p:=1; - q:=1; - // start evaluating from the last term upwards - For(i:=n, i>=1, i--) - [ - //{p,q} := {p + q*(i*x)^2/(4*i^2-1), p}; - // t := p*(2*i-1) + q*(i*x)^2; then have to start with p:=2*n+1 - t := p + q*(i*x)^2/(4*i^2-1); - q := p; - p := t; - ]; - // answer is x/(p/q) - x*q/p; -]; -*/ - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/BrentLn.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/BrentLn.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/BrentLn.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/BrentLn.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -%mathpiper,def="BrentLn" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -/* The BrentLn() algorithm is currently slower in internal math but should be asymptotically faster. */ - -CachedConstant(Ln2, Internal'LnNum(2)); // this is only useful for BrentLn - -// compute Ln(x_IsInteger) using the AGM sequence. See: Brent paper rpb028 (1975). -// this is currently faster than LogN(n) for precision > 40 digits -10 # BrentLn(x_IsInteger)_(BuiltinPrecisionGet()>40) <-- -[ - Local(y, n, k, eps); - n := BuiltinPrecisionGet(); // decimal digits - // initial power of x - k := 1 + Div(IntLog(4*10^n, x), 2); // now x^(2*k)>4*10^n - BuiltinPrecisionSet(n+5); // guard digits - eps := DivideN(1, 10^n); // precision - y := PowerN(x, k); // not yet divided by 4 - // this is Brent's AGM times y. This way we work around the MathPiper limitation of fixed precision, at cost of slightly slower initial iterations - y := DivideN(Internal'Pi()*y, (2*k)*AG'Mean(4, y, eps)); - BuiltinPrecisionSet(n); - RoundTo(y, n); // do not return a more precise number than we really have -]; - -15 # BrentLn(x_IsInteger) <-- LogN(x); - -/// calculation of Ln(x) using Brent's AGM sequence - use precomputed Pi and Ln2. -20 # BrentLn(_x)_(x<1) <-- -BrentLn(1/x); - -// this is currently faster than LogN() for precision > 85 digits and numbers >2 -30 # BrentLn(_x)_(BuiltinPrecisionGet()>85) <-- -[ - Local(y, n, n1, k, eps); - N([ - n := BuiltinPrecisionGet(); // decimal digits - // effective precision is n+Ln(n)/Ln(10) - n1 := n + IntLog(n,10); // Ln(2) < 7050/10171 - // initial power of 2 - k := 2 + Div(n1*28738, 2*8651) // Ln(10)/Ln(2) < 28738/8651; now 2^(2*k)>4*10^n1 - // find how many binary digits we already have in x, and multiply by a sufficiently large power of 2 so that y=x*2^k is larger than 2*10^(n1/2) - - IntLog(Floor(x), 2); - // now we need k*Ln(2)/Ln(10) additional digits to compensate for cancellation at the final subtraction - BuiltinPrecisionSet(n1+2+Div(k*3361, 11165)); // Ln(2)/Ln(10) < 3361/11165 - eps := DivideN(1, 10^(n1+1)); // precision - y := x*2^(k-2); // divided already by 4 - // initial values for AGM - // this is Brent's AGM times y. This way we work around the MathPiper limitation of fixed precision, at cost of slightly slower initial iterations - y:=Internal'Pi()*y/(2*AG'Mean(1,y,eps)) - k*Ln2(); - BuiltinPrecisionSet(n); - ]); - y; // do not return a more precise number than we really have -]; - -40 # BrentLn(x_IsNumber) <-- LogN(x); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/CosNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/CosNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/CosNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/CosNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="CosNum" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -CosNum(x) := -[ - If(x<0 Or 113*x>710, x:=TruncRadian(x)); - CosN(x); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/ExpNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/ExpNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/ExpNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/ExpNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -%mathpiper,def="ExpNum" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -// large positive x -10 # ExpNum(x_IsNumber) _ (x > MathExpThreshold()) <-- [ - Local(i, y); - i:=0; - For(i:=0, x > MathExpThreshold(), i++) - x := DivideN(x, 2.); - For(y:= ExpN(x), i>0, i--) - y := MultiplyN(y, y); - y; - -]; -// large negative x -20 # ExpNum(x_IsNumber) _ (2*x < -MathExpThreshold()) <-- DivideN(1, ExpNum(-x)); -// other values of x -30 # ExpNum(x_IsNumber) <-- ExpN(x); - - -//CachedConstant(Exp1, ExpN(1)); // Exp1 is useless so far - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/expthreshold.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/expthreshold.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/expthreshold.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/expthreshold.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="MathExpThreshold;SetMathExpThreshold" - -/* def file definitions -MathExpThreshold -SetMathExpThreshold -*/ - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -////////////////////////////////////////////////// -/// Exponent -////////////////////////////////////////////////// - -LocalSymbols(mathExpThreshold) [ - // improve convergence of Exp(x) for large x - mathExpThreshold := If(Not IsBound(mathExpThreshold), 500); - - MathExpThreshold() := mathExpThreshold; - SetMathExpThreshold(threshold) := [mathExpThreshold:= threshold; ]; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/Internal'LnNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/Internal'LnNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/Internal'LnNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/Internal'LnNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -%mathpiper,def="Internal'LnNum",scope="private" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -// natural logarithm: this should be called only for real x>1 -//Internal'LnNum(x) := LogN(x); -// right now the fastest algorithm is Halley's method for Exp(x)=a -// when internal math is fixed, we may want to use Brent's method (below) -// this method is using a cubically convergent Newton iteration for Exp(x/2)-a*Exp(-x/2)=0: -// x' := x - 2 * (Exp(x)-a) / (Exp(x)+a) = x-2+4*a/(Exp(x)+a) -Internal'LnNum(x_IsNumber)_(x>=1) <-- NewtonLn(x); - -Internal'LnNum(x_IsNumber)_(0 0 (arbitrary-precision math function) -*CALL - LogN(x) - -*DESC - -This command performs the calculation of an elementary mathematical -function. The arguments must be numbers. The reason for the -postfix {N} is that the library needs to define equivalent non-numerical -functions for symbolic computations, such as {Exp}, {Sin}, etc. - -Note that all xxxN functions accept integers as well as floating-point numbers. -The resulting values may be integers or floats. If the mathematical result is an -exact integer, then the integer is returned. For example, {Sqrt(25)} returns -the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the -integer result is returned even if the calculation requires more digits than set by -{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, -the functions return a floating-point result which is correct only to the current precision. - -*E.G. - In> - Result> - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/NewtonLn.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/NewtonLn.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/NewtonLn.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/NewtonLn.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -%mathpiper,def="NewtonLn" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -NewtonLn(x) := - LocalSymbols(y) -[ -// we need ExpN instead of Exp to avoid N() which is used in the definition of Exp. -// and we need ExpNum() instead of ExpN so that it is faster for large arguments and to avoid the error generated when core functions like ExpN are called on symbolic arguments. - NewtonNum({{y}, 4*x/(ExpNum(y)+x)-2+y}, - // initial guess is obtained as Ln(x^2)/Ln(2) * (Ln(2)/2) - DivideN(794*IntLog(Floor(x*x), 2), 2291), 10, 3); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/SinNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/SinNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/SinNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/SinNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="SinNum" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -SinNum(x) := -[ - If(x<0 Or 113*x>710, x:=TruncRadian(x)); // 710/113 is close to 2*Pi - SinN(x); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/TanNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/TanNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/TanNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/TanNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -%mathpiper,def="TanNum" -TanNum(x) := -[ - If(x<0 Or 113*x>710, x:=TruncRadian(x)); - TanN(x); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/TruncRadian.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/TruncRadian.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/numerical/TruncRadian.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/numerical/TruncRadian.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="TruncRadian" - -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -/* TruncRadian truncates the radian r so it is between 0 and 2*Pi. - * It calculates r mod 2*Pi using the required precision. - */ -TruncRadian(_r) <-- -[ - Local(twopi); - // increase precision by the number of digits of r before decimal point; enough to evaluate Abs(r) with 1 digit of precision - N([ - r:=Eval(r); - twopi:=2*Internal'Pi(); - r:=r-FloorN(r/twopi)*twopi; - ], BuiltinPrecisionGet() + IntLog(Ceil(Abs(N(Eval(r), 1))), 10)); - r; -]; -HoldArg("TruncRadian",r); - -%/mathpiper - - - -%mathpiper_docs,name="TruncRadian",categories="Programmer Functions;Numerical (Arbitrary Precision)" -*CMD TruncRadian --- remainder modulo $2*Pi$ -*STD -*CALL - TruncRadian(r) - -*PARMS - -{r} -- a number - -*DESC - -{TruncRadian} calculates $Mod(r,2*Pi)$, returning a value between $0$ -and $2*Pi$. This function is used in the trigonometry functions, just -before doing a numerical calculation using a Taylor series. It greatly -speeds up the calculation if the value passed is a large number. - -The library uses the formula -$$TruncRadian(r) = r - Floor( r/(2*Pi) )*2*Pi$$, -where $r$ and $2*Pi$ are calculated with twice the precision used in the -environment to make sure there is no rounding error in the significant -digits. - -*E.G. - - In> 2*Internal'Pi() - Out> 6.283185307; - In> TruncRadian(6.28) - Out> 6.28; - In> TruncRadian(6.29) - Out> 0.0068146929; - -*SEE Sin, Cos, Tan - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/AG'Mean.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/AG'Mean.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/AG'Mean.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/AG'Mean.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="AG'Mean" - -/// coded by Serge Winitzki. See essays documentation for algorithms. - -////////////////////////////////////////////////// -/// Numerical method: AGM sequence -////////////////////////////////////////////////// - -/// compute the AGM sequence up to a given precision -AG'Mean(a, b, eps) := -[ - Local(a1, b1); - If(InVerboseMode(), Echo("AG'Mean: Info: at prec. ", BuiltinPrecisionGet())); - // AGM main loop - While(Abs(a-b)>=eps) - [ - a1 := DivideN(a+b, 2); - b1 := SqrtN(MultiplyN(a, b)); // avoid Sqrt() which uses N() inside it - a := a1; - b := b1; - ]; - DivideN(a+b, 2); -]; -//UnFence(AG'Mean, 3); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/binsplit.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/binsplit.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/binsplit.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/binsplit.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,111 +0,0 @@ -%mathpiper,def="BinSplitNum;BinSplitData;BinSplitFinal" - -/* -def file definitions -BinSplitNum -BinSplitData -BinSplitFinal -*/ - -/// coded by Serge Winitzki. See essays documentation for algorithms. - -////////////////////////////////////////////////// -/// Numerical method: binary splitting technique for simple series -////////////////////////////////////////////////// - -/// Binary splitting for series of the form -/// S(m,n) = Sum(k,m,n, a(k)/b(k)*(p(0)*...*p(k))/(q(0)*...*q(k))) - - -/// High-level interface routine -BinSplitNum(m,n,a,b,p,q) := BinSplitFinal(BinSplitData(m,n,a,b,p,q)); - -/// Low-level routine: compute the floating-point answer from P, Q, B, T data -BinSplitFinal({_P,_Q,_B,_T}) <-- DivideN(T, MultiplyN(B, Q)); - -/// Low-level routine: combine two binary-split intermediate results -BinSplitCombine({_P1, _Q1, _B1, _T1}, {_P2, _Q2, _B2, _T2}) <-- {P1*P2, Q1*Q2, B1*B2, B1*P1*T2+B2*Q2*T1}; - -/// Low-level routine: compute the list of four integers P, Q, B, T. (T=BQS) -/// Input: m, n and four functions a,b,p,q of one integer argument. - -// base of recursion -10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m>n) <-- {1,1,1,0}; - -10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m=n) <-- {p@m, q@m, b@m, (a@m)*(p@m)}; - -10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m+1=n) <-- {(p@m)*(p@n), (q@m)*(q@n), (b@m)*(b@n), (p@m)*((a@m)*(b@n)*(q@n)+(a@n)*(b@m)*(p@n))}; - -// could implement some more cases of recursion base, to improve speed - -// main recursion step -20 # BinSplitData(_m, _n, _a, _b, _p, _q) <-- -[ - BinSplitCombine(BinSplitData(m,(m+n)>>1, a,b,p,q), BinSplitData(1+((m+n)>>1),n, a,b,p,q)); -]; - - -%/mathpiper - - - -%mathpiper_docs,name="BinSplitNum;BinSplitData;BinSplitFinal",categories="User Functions;Series" -*CMD BinSplitNum --- computations of series by the binary splitting method -*CMD BinSplitData --- computations of series by the binary splitting method -*CMD BinSplitFinal --- computations of series by the binary splitting method -*STD -*CALL - BinSplitNum(n1, n2, a, b, c, d) - BinSplitData(n1,n2, a, b, c, d) - BinSplitFinal({P,Q,B,T}) - -*PARMS - -{n1}, {n2} -- integers, initial and final indices for summation - -{a}, {b}, {c}, {d} -- functions of one argument, coefficients of the series - -{P}, {Q}, {B}, {T} -- numbers, intermediate data as returned by {BinSplitData} - -*DESC - -The binary splitting method is an efficient way to evaluate many series when fast multiplication is available and when the series contains only rational numbers. -The function {BinSplitNum} evaluates a series of the form -$$ S(n[1],n[2])=Sum(k,n[1],n[2], a(k)/b(k)*(p(0)/q(0)) * ... * p(k)/q(k)) $$. -Most series for elementary and special functions at rational points are of this form when the functions $a(k)$, $b(k)$, $p(k)$, $q(k)$ are chosen appropriately. - -The last four arguments of {BinSplitNum} are functions of one argument that give the coefficients $a(k)$, $b(k)$, $p(k)$, $q(k)$. -In most cases these will be short integers that are simple to determine. -The binary splitting method will work also for non-integer coefficients, but the calculation will take much longer in that case. - -Note: the binary splitting method outperforms the straightforward summation only if the multiplication of integers is faster than quadratic in the number of digits. -See <*the algorithm documentation|mathpiperdoc://Algo/3/14/*> for more information. - -The two other functions are low-level functions that allow a finer control over the calculation. -The use of the low-level routines allows checkpointing or parallelization of a binary splitting calculation. - -The binary splitting method recursively reduces the calculation of $S(n[1],n[2])$ to the same calculation for the two halves of the interval [$n[1]$, $n[2]$]. -The intermediate results of a binary splitting calculation are returned by {BinSplitData} and consist of four integers $P$, $Q$, $B$, $T$. -These four integers are converted into the final answer $S$ by the routine {BinSplitFinal} using the relation -$$ S = T / (B*Q) $$. - -*E.G. - -Compute the series for $e=Exp(1)$ using binary splitting. -(We start from $n=1$ to simplify the coefficient functions.) - In> BuiltinPrecisionSet(21) - Out> True; - In> BinSplitNum(1,21, {{k},1}, - {{k},1},{{k},1},{{k},k}) - Out> 1.718281828459045235359; - In> N(Exp(1)-1) - Out> 1.71828182845904523536; - In> BinSplitData(1,21, {{k},1}, - {{k},1},{{k},1},{{k},k}) - Out> {1,51090942171709440000,1, - 87788637532500240022}; - In> BinSplitFinal(%) - Out> 1.718281828459045235359; - -*SEE SumTaylorNum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/IntPowerNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/IntPowerNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/IntPowerNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/IntPowerNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -%mathpiper,def="IntPowerNum" - -/// coded by Serge Winitzki. See essays documentation for algorithms. - -////////////////////////////////////////////////// -/// Numerical method: integer powers by binary reduction -////////////////////////////////////////////////// - -/// generalized integer Power function using the classic binary method. -5 # IntPowerNum(_x, 0, _func, _unity) <-- unity; -10 # IntPowerNum(_x, n_IsInteger, _func, _unity) <-- -[ - // use binary method - Local(result); - // unity might be of non-scalar type, avoid assignment - While(n > 0) - [ - If( - (n&1) = 1, - If( - IsBound(result), // if result is already assigned - result := Apply(func, {result,x}), - result := x, // avoid multiplication - ) - ); - x := Apply(func, {x,x}); - n := n>>1; - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="IntPowerNum" -*CMD IntPowerNum --- optimized computation of integer powers -*STD -*CALL - IntPowerNum(x, n, mult, unity) - -*PARMS - -{x} -- a number or an expression - -{n} -- a non-negative integer (power to raise {x} to) - -{mult} -- a function that performs one multiplication - -{unity} -- value of the unity with respect to that multiplication - -*DESC - -{IntPowerNum} computes the power $x^n$ using the fast binary algorithm. -It can compute integer powers with $n>=0$ in any ring where multiplication with unity is defined. -The multiplication function and the unity element must be specified. -The number of multiplications is no more than $2*Ln(n)/Ln(2)$. - -Mathematically, this function is a generalization of {MathPower} to rings other than that of real numbers. - -In the current implementation, the {unity} argument is only used when the given power {n} is zero. - -*E.G. - -For efficient numerical calculations, the {MathMultiply} function can be passed: - In> IntPowerNum(3, 3, MathMultiply,1) - Out> 27; -Otherwise, the usual {*} operator suffices: - In> IntPowerNum(3+4*I, 3, *,1) - Out> Complex(-117,44); - In> IntPowerNum(HilbertMatrix(2), 4, *, - Identity(2)) - Out> {{289/144,29/27},{29/27,745/1296}}; -Compute $Mod(3^100,7)$: - In> IntPowerNum(3,100,{{x,y},Mod(x*y,7)},1) - Out> 4; - -*SEE MultiplyNum, MathPower, MatrixPower -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/MultiplyNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/MultiplyNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/MultiplyNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/MultiplyNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -%mathpiper,def="MultiplyNum" - -/// coded by Serge Winitzki. See essays documentation for algorithms. - -////////////////////////////////////////////////// -/// Numerical method: multiply floats by rationals -////////////////////////////////////////////////// - -/// aux function: optimized numerical multiplication. Use MultiplyN() and DivideN(). -/// optimization consists of multiplying or dividing by integers if one of the arguments is a rational number. This is presumably always better than floating-point calculations, except if we use Rationalize() on everything. -/// note that currently this is not a big optimization b/c of slow arithmetic but it already helps for rational numbers under InNumericMode() returns True and it will help even more when faster math is done - -Function() MultiplyNum(x, y, ...); -Function() MultiplyNum(x); - -10 # MultiplyNum(x_IsList)_(Length(x)>1) <-- MultiplyNum(First(x), Rest(x)); - -10 # MultiplyNum(x_IsRational, y_IsRationalOrNumber) <-- -[ - If( - Type(y) = "/", // IsRational(y), changed by Nobbi before redefinition of IsRational - DivideN(Numerator(x)*Numerator(y), Denominator(x)*Denominator(y)), - // y is floating-point - // avoid multiplication or division by 1 - If( - Numerator(x)=1, - DivideN(y, Denominator(x)), - If( - Denominator(x)=1, - MultiplyN(y, Numerator(x)), - DivideN(MultiplyN(y, Numerator(x)), Denominator(x)) - ) - ) - ); -]; - -20 # MultiplyNum(x_IsNumber, y_IsRational) <-- MultiplyNum(y, x); - -25 # MultiplyNum(x_IsNumber, y_IsNumber) <-- MultiplyN(x,y); - -30 # MultiplyNum(Complex(r_IsNumber, i_IsNumber), y_IsRationalOrNumber) <-- Complex(MultiplyNum(r, y), MultiplyNum(i, y)); - -35 # MultiplyNum(y_IsNumber, Complex(r_IsNumber, i_IsRationalOrNumber)) <-- MultiplyNum(Complex(r, i), y); - -40 # MultiplyNum(Complex(r1_IsNumber, i1_IsNumber), Complex(r2_IsNumber, i2_IsNumber)) <-- Complex(MultiplyNum(r1,r2)-MultiplyNum(i1,i2), MultiplyNum(r1,i2)+MultiplyNum(i1,r2)); - -/// more than 2 operands -30 # MultiplyNum(x_IsRationalOrNumber, y_IsNumericList)_(Length(y)>1) <-- MultiplyNum(MultiplyNum(x, First(y)), Rest(y)); -40 # MultiplyNum(x_IsRationalOrNumber, y_IsNumericList)_(Length(y)=1) <-- MultiplyNum(x, First(y)); - -%/mathpiper - - - -%mathpiper_docs,name="MultiplyNum" -*CMD MultiplyNum --- optimized numerical multiplication -*STD -*CALL - MultiplyNum(x,y) - MultiplyNum(x,y,z,...) - MultiplyNum({x,y,z,...}) - -*PARMS - -{x}, {y}, {z} -- integer, rational or floating-point numbers to multiply - -*DESC -The function {MultiplyNum} is used to speed up multiplication of floating-point numbers with rational numbers. Suppose we need to compute $(p/q)*x$ where $p$, $q$ are integers and $x$ is a floating-point number. At high precision, it is faster to multiply $x$ by an integer $p$ and divide by an integer $q$ than to compute $p/q$ to high precision and then multiply by $x$. The function {MultiplyNum} performs this optimization. - -The function accepts any number of arguments (not less than two) or a list of numbers. The result is always a floating-point number (even if {InNumericMode()} returns False). - -*SEE MathMultiply -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/NewtonNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/NewtonNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/NewtonNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/NewtonNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -%mathpiper,def="NewtonNum" - -/// coded by Serge Winitzki. See essays documentation for algorithms. - -////////////////////////////////////////////////// -/// Numerical method: Newton-like superconvergent iteration -////////////////////////////////////////////////// - -// Newton's method, generalized, with precision control and diagnostics - -/// auxiliary utility: compute the number of common decimal digits of x and y (using relative precision) -Common'digits(x,y) := -[ - Local(diff); - diff := Abs(x-y); - If( - diff=0, - Infinity, - // use approximation Ln(2)/Ln(10) > 351/1166 - Div(IntLog(FloorN(DivideN(Max(Abs(x), Abs(y)), diff)), 2)*351, 1166) - ); // this many decimal digits in common -]; - -///interface -NewtonNum(_func, _x0) <-- NewtonNum(func, x0, 5); // default prec0 -NewtonNum(_func, _x0, _prec0) <-- NewtonNum(func, x0, prec0, 2); - -// func is the function to iterate, i.e. x' = func(x). -// prec0 is the initial precision necessary to get convergence started. -// order is the order of convergence of the given sequence (e.g. 2 or 3). -// x0 must be close enough so that x1 has a few common digits with x0 after at most 5 iterations. -NewtonNum(_func, _x'init, _prec0, _order) <-- -[ - Check(prec0>=4, "NewtonNum: Error: initial precision must be at least 4"); - Check(IsInteger(order) And order>1, "NewtonNum: Error: convergence order must be an integer and at least 2"); - Local(x0, x1, prec, exact'digits, int'part, initial'tries); - N([ - x0 := x'init; - prec := BuiltinPrecisionGet(); - int'part := IntLog(Ceil(Abs(x0)), 10); // how many extra digits for numbers like 100.2223 - // int'part must be set to 0 if we have true floating-point semantics of BuiltinPrecisionSet() - BuiltinPrecisionSet(2+prec0-int'part); // 2 guard digits - x1 := (func @ x0); // let's run one more iteration by hand - // first, we get prec0 exact digits - exact'digits := 0; - initial'tries := 5; // stop the loop the the initial value is not good - While(exact'digits*order < prec0 And initial'tries>0) - [ - initial'tries--; - x0 := x1; - x1 := (func @ x0); - exact'digits := Common'digits(x0, x1); - // If(InVerboseMode(), Echo("NewtonNum: Info: got", exact'digits, "exact digits at prec. ", BuiltinPrecisionGet())); - ]; - // need to check that the initial precision is achieved - If( - Assert("value", {"NewtonNum: Error: need a more accurate initial value than", x'init}) - exact'digits >= 1, - [ - exact'digits :=Min(exact'digits, prec0+2); - // run until get prec/order exact digits - int'part := IntLog(Ceil(Abs(x1)), 10); // how many extra digits for numbers like 100.2223 - While(exact'digits*order <= prec) - [ - exact'digits := exact'digits*order; - BuiltinPrecisionSet(2+Min(exact'digits, Div(prec,order)+1)-int'part); - x0 := x1; - x1 := (func @ x0); - // If(InVerboseMode(), Echo("NewtonNum: Info: got", Common'digits(x0, x1), "exact digits at prec. ", BuiltinPrecisionGet())); - ]; - // last iteration by hand - BuiltinPrecisionSet(2+prec); - x1 := RoundTo( (func @ x1), prec); - ], - // did not get a good initial value, so return what we were given - x1 := x'init - ); - BuiltinPrecisionSet(prec); - ]); - x1; -]; - - -/* -example: logarithm function using cubically convergent Newton iteration for -Exp(x/2)-a*Exp(-x/2)=0: - -x' := x - 2 * (Exp(x)-a) / (Exp(x)+a) - -LN(x_IsNumber)_(x>1 ) <-- - LocalSymbols(y) -[ -// initial guess is obtained as Ln(x^2)/Ln(2) * (Ln(2)/2) - NewtonNum({{y},4*x/(Exp(y)+x)-2+y}, N(794/2291*IntLog(Floor(x*x),2),5), 10, 3); -]; -*/ - -%/mathpiper - - - -%mathpiper_docs,name="NewtonNum" -*CMD NewtonNum --- low-level optimized Newton's iterations -*STD -*CALL - NewtonNum(func, x0, prec0, order) - NewtonNum(func, x0, prec0) - NewtonNum(func, x0) - -*PARMS - -{func} -- a function specifying the iteration sequence - -{x0} -- initial value (must be close enough to the root) - -{prec0} -- initial precision (at least 4, default 5) - -{order} -- convergence order (typically 2 or 3, default 2) - -*DESC - -This function is an optimized interface for computing Newton's -iteration sequences for numerical solution of equations in arbitrary precision. - -{NewtonNum} will iterate the given function starting from the initial -value, until the sequence converges within current precision. -Initially, up to 5 iterations at the initial precision {prec0} is -performed (the low precision is set for speed). The initial value {x0} -must be close enough to the root so that the initial iterations -converge. If the sequence does not produce even a single correct digit -of the root after these initial iterations, an error message is -printed. The default value of the initial precision is 5. - -The {order} parameter should give the convergence order of the scheme. -Normally, Newton iteration converges quadratically (so the default -value is {order}=2) but some schemes converge faster and you can speed -up this function by specifying the correct order. (Caution: if you give -{order}=3 but the sequence is actually quadratic, the result will be -silently incorrect. It is safe to use {order}=2.) - -*REM -The verbose option {V} can be used to monitor the convergence. The -achieved exact digits should roughly form a geometric progression. - -*E.G. - - In> BuiltinPrecisionSet(20) - Out> True; - In> NewtonNum({{x}, x+Sin(x)}, 3, 5, 3) - Out> 3.14159265358979323846; - -*SEE Newton -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/SumTaylorNum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/SumTaylorNum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/nummethods/SumTaylorNum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/nummethods/SumTaylorNum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,231 +0,0 @@ -%mathpiper,def="SumTaylorNum" - -/// coded by Serge Winitzki. See essays documentation for algorithms. - -////////////////////////////////////////////////// -/// Numerical method: Taylor series, rectangular summation -////////////////////////////////////////////////// - -/// Fast summation of Taylor series using a rectangular scheme. -/// SumTaylorNum(x, nth'term'func, n'terms) = Sum(k, 0, n'terms, nth'term'func(k)*x^k) -/// Note that sufficient precision must be preset to avoid roundoff errors (these methods do not modify precision). -/// The only reason to try making these functions HoldArg is to make sure that the closures nth'term'func and next'term'factor are passed intact. But it's probably not desired in most cases because a closure might contain parameters that should be evaluated. - -/// The short form is used when only the nth term is known but no simple relation between a term and the next term. -/// The long form is used when there is a simple relation between consecutive terms. In that case, the n'th term function is not needed, only the 0th term value. - -/// SumTaylorNum0 is summing the terms with direct methods (Horner's scheme or simple summation). SumTaylorNum1 is for the rectangular method. - -/// nth'term'func and next'term'func must be functions applicable to one argument. - -/// interface -SumTaylorNum0(_x, _nth'term'func, _n'terms) <-- SumTaylorNum0(x, nth'term'func, {}, n'terms); - -SumTaylorNum1(_x, _nth'term'func, _n'terms) <-- SumTaylorNum1(x, nth'term'func, {}, n'terms); - -/// interface -SumTaylorNum(_x, _nth'term'func, _n'terms) <-- -If( - n'terms >= 30, // threshold for calculation with next'term'factor - // use the rectangular algorithm for large enough number of terms - SumTaylorNum1(x, nth'term'func, n'terms), - SumTaylorNum0(x, nth'term'func, n'terms) -); - -SumTaylorNum(_x, _nth'term'func, _next'term'factor, _n'terms) <-- -If( - n'terms >= 5, // threshold for calculation with next'term'factor - SumTaylorNum1(x, nth'term'func, next'term'factor, n'terms), - SumTaylorNum0(x, nth'term'func, next'term'factor, n'terms) -); -//HoldArgNr(SumTaylorNum, 3, 2); - -/// straightforward algorithms for a small number of terms -1# SumTaylorNum0(_x, _nth'term'func, {}, _n'terms) <-- -[ - Local(sum, k); - N([ - // use Horner scheme starting from the last term - x:=Eval(x); - sum := 0; - For(k:=n'terms, k>=0, k--) - sum := AddN(sum*x, nth'term'func @ k); - ]); - sum; -]; - -//HoldArgNr(SumTaylorNum0, 3, 2); - -2# SumTaylorNum0(_x, _nth'term'func, _next'term'factor, _n'terms) <-- -[ - Local(sum, k, term, delta); - N([ - x:=Eval(x); // x must be floating-point - If (IsConstant(nth'term'func), - term := nth'term'func, - term := (nth'term'func @ {0}), - ); - sum := term; // sum must be floating-point - ]); - NonN([ - delta := 1; - For(k:=1, k<=n'terms And delta != 0, k++) - [ - term := MultiplyNum(term, next'term'factor @ {k}, x); // want to keep exact fractions here, but the result is floating-point - delta := sum; - sum := sum + term; // term must be floating-point - delta := Abs(sum-delta); // check for underflow - ]; - ]); - sum; -]; - -/// interface -SumTaylorNum0(_x, _nth'term'func, _n'terms) <-- SumTaylorNum0(x, nth'term'func, {}, n'terms); - -//HoldArgNr(SumTaylorNum0, 4, 2); -//HoldArgNr(SumTaylorNum0, 4, 3); - -/// this is to be used when a simple relation between a term and the next term is known. -/// next'term'factor must be a function applicable to one argument, so that if term = nth'term'func(k-1), then nth'term'func(k) = term / next'term'factor(k). (This is optimized for Taylor series of elementary functions.) In this case, nth'term'func is either a number, value of the 0th term, or a function. -/// A special case: when next'term'factor is an empty list; then we act as if there is no next'term'factor available. -/// In this case, nth'term'func must be a function applicable to one argument. -/// Need IntLog(n'terms, 10) + 1 guard digits due to accumulated roundoff error. -SumTaylorNum1(x, nth'term'func, next'term'factor, n'terms) := -[ - // need Sqrt(n'terms/2) units of storage (rows) and Sqrt(n'terms*2) columns. Let's underestimate the storage. - Local(sum, rows, cols, rows'tmp, last'power, i, j, x'power, term'tmp); - N([ // want to keep exact fractions - x:=Eval(x); // x must be floating-point - rows := IntNthRoot(n'terms+1, 2); - cols := Div(n'terms+rows, rows); // now: rows*cols >= n'terms+1 - Check(rows>1 And cols>1, "SumTaylorNum1: Internal error: number of Taylor sum terms must be at least 4"); - rows'tmp := ArrayCreate(rows, 0); - x'power := x ^ rows; // do not use PowerN b/c x might be complex - // initialize partial sums (array rows'tmp) - the 0th column (i:=0) - // prepare term'tmp for the first element - // if we are using next'term'factor, then term'tmp is x^(rows*i)*a[rows*i] - // if we are not using it, then term'tmp is x^(rows*i) - If( - next'term'factor = {}, - term'tmp := 1, - // term'tmp := (nth'term'func @ 0) // floating-point - If (IsConstant(nth'term'func), - term'tmp := nth'term'func, - term'tmp := (nth'term'func @ {0}), - ) - ); - ]); - NonN([ // want to keep exact fractions below - // do horizontal summation using term'tmp to get the first element - For(i:=0, i0, j--) - sum := sum*x + rows'tmp[j]; - ]); - sum; -]; - -//HoldArgNr(SumTaylorNum, 4, 2); -//HoldArgNr(SumTaylorNum, 4, 3); - -/* -Examples: -In> SumTaylorNum(1,{{k}, 1/k!},{{k}, 1/k}, 10 ) -Out> 2.7182818006; -In> SumTaylorNum(1,{{k},1/k!}, 10 ) -Out> 2.7182818007; -*/ - -%/mathpiper - - - -%mathpiper_docs,name="SumTaylorNum" -*CMD SumTaylorNum --- optimized numerical evaluation of Taylor series -*STD -*CALL - SumTaylorNum(x, NthTerm, order) - SumTaylorNum(x, NthTerm, TermFactor, order) - SumTaylorNum(x, ZerothTerm, TermFactor, order) - -*PARMS - -{NthTerm} -- a function specifying $n$-th coefficient of the series - -{ZerothTerm} -- value of the $0$-th coefficient of the series - -{x} -- number, value of the expansion variable - -{TermFactor} -- a function specifying the ratio of $n$-th term to the previous one - -{order} -- power of $x$ in the last term - -*DESC - -{SumTaylorNum} computes a Taylor series $Sum(k,0,n,a[k]*x^k)$ -numerically. This function allows very efficient computations of -functions given by Taylor series, although some tweaking of the -parameters is required for good results. - -The coefficients $a[k]$ of the Taylor series are given as functions of one integer variable ($k$). It is convenient to pass them to {SumTaylorNum} as closures. -For example, if a function {a(k)} is defined, then - SumTaylorNum(x, {{k}, a(k)}, n) -computes the series $Sum(k, 0, n, a(k)*x^k)$. - -Often a simple relation between successive coefficients $a[k-1]$, -$a[k]$ of the series is available; usually they are related by a -rational factor. In this case, the second form of {SumTaylorNum} should -be used because it will compute the series faster. The function -{TermFactor} applied to an integer $k>=1$ must return the ratio -$a[k]$/$a[k-1]$. (If possible, the function {TermFactor} should return -a rational number and not a floating-point number.) The function -{NthTerm} may also be given, but the current implementation only calls -{NthTerm(0)} and obtains all other coefficients by using {TermFactor}. -Instead of the function {NthTerm}, a number giving the $0$-th term can be given. - -The algorithm is described elsewhere in the documentation. -The number of terms {order}+1 -must be specified and a sufficiently high precision must be preset in -advance to achieve the desired accuracy. -(The function {SumTaylorNum} does not change the current precision.) - -*E.G. -To compute 20 digits of $Exp(1)$ using the Taylor series, one needs 21 -digits of working precision and 21 terms of the series. - - In> BuiltinPrecisionSet(21) - Out> True; - In> SumTaylorNum(1, {{k},1/k!}, 21) - Out> 2.718281828459045235351; - In> SumTaylorNum(1, 1, {{k},1/k}, 21) - Out> 2.71828182845904523535; - In> SumTaylorNum(1, {{k},1/k!}, {{k},1/k}, 21) - Out> 2.71828182845904523535; - In> RoundTo(N(Ln(%)),20) - Out> 1; - - -*SEE Taylor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -%mathpiper,def="" - -/// coded by Serge Winitzki. See essays documentation for algorithms. - -// From code.mpi.def: -OMDef( "ArcSin" , "transc1","arcsin" ); -OMDef( "ArcCos" , "transc1","arccos" ); -OMDef( "ArcTan" , "transc1","arctan" ); -OMDef( "ArcSec" , "transc1","arcsec" ); -OMDef( "ArcCsc" , "transc1","arccsc" ); -OMDef( "ArcCot" , "transc1","arccot" ); -OMDef( "ArcSinh", "transc1","arcsinh" ); -OMDef( "ArcCosh", "transc1","arccosh" ); -OMDef( "ArcTanh", "transc1","arctanh" ); -OMDef( "ArcSech", "transc1","arcsech" ); -OMDef( "ArcCsch", "transc1","arccsch" ); -OMDef( "ArcCoth", "transc1","arccoth" ); -OMDef( "Sin" , "transc1","sin" ); -OMDef( "Cos" , "transc1","cos" ); -OMDef( "Tan" , "transc1","tan" ); -OMDef( "Sec" , "transc1","sec" ); -OMDef( "Csc" , "transc1","csc" ); -OMDef( "Cot" , "transc1","cot" ); -OMDef( "Sinh" , "transc1","sinh" ); -OMDef( "Cosh" , "transc1","cosh" ); -OMDef( "Tanh" , "transc1","tanh" ); -OMDef( "Sech" , "transc1","sech" ); -OMDef( "Csch" , "transc1","csch" ); -OMDef( "Coth" , "transc1","coth" ); -OMDef( "Exp" , "transc1","exp" ); -OMDef( "Ln" , "transc1","ln" ); - -// Related OM symbols not yet defined in MathPiper: -// "log" , "transc1","log" - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sech.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sech.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sech.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sech.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -%mathpiper,def="Sech" - -100 # Sech(_x) <-- 1/Cosh(x); - -100 # 1/Sech(_x) <-- Cosh(x); - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sec.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sec.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sec.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sec.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Sec" - -100 # 1/Sec(_x) <-- Cos(x); -100 # Sec(_x) <-- 1/Cos(x); - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sinh.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sinh.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sinh.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sinh.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="Sinh" - -2 # Sinh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( (Exp(x)-Exp(-x))/2 )); -5 # Sinh(- _x) <-- -Sinh(x); - -5 # Sinh(- _x) <-- -Sinh(x); - -100 # Sinh(_x)^2-Cosh(_x)^2 <-- 1; -100 # Sinh(_x)+Cosh(_x) <-- Exp(x); -100 # Sinh(_x)-Cosh(_x) <-- Exp(-x); - -//100 # Sinh(I*_x) <-- I*Sin(x); - -100 # Sinh(_x)/Cosh(_x) <-- Tanh(x); -100 # Sinh(_x)*Csch(_x) <-- 1; - -200 # Sinh(0) <-- 0; -200 # Sinh(Infinity) <-- Infinity; -200 # Sinh(-Infinity) <-- -Infinity; -200 # Sinh(ArcSinh(_x)) <-- x; -200 # Sinh(ArcCosh(_x)) <-- Sqrt((x-1)/(x+1))*(x+1); -200 # Sinh(ArcTanh(_x)) <-- x/Sqrt(1-x^2); - -200 # Sinh(Undefined) <-- Undefined; - -/* Threading of standard analytic functions */ -Sinh(xlist_IsList) <-- MapSingle("Sinh",xlist); - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sin.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sin.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Sin.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Sin.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -%mathpiper,def="Sin" - - -1 # SinMap( _n )_(Not(IsRationalOrNumber(n))) <-- UnList({Atom("Sin"),n*Pi}); -2 # SinMap( _n )_(n<0) <-- -SinMap(-n); -2 # SinMap( _n )_(n>2) <-- SinMap(Mod(n,2)); -3 # SinMap( _n )_(n>1) <-- SinMap(n-2); -4 # SinMap( _n )_(n>1/2) <-- SinMap(1-n); - -5 # SinMap( n_IsInteger ) <-- 0; -5 # SinMap( 1/6 ) <-- 1/2; -5 # SinMap( 1/4 ) <-- Sqrt(2)/2; -5 # SinMap( 1/3 ) <-- Sqrt(3)/2; -5 # SinMap( 1/2 ) <-- 1; -5 # SinMap( 1/10) <-- (Sqrt(5)-1)/4; - -10 # SinMap(_n) <-- UnList({Atom("Sin"),n*Pi}); - - - - -2 # Sin(x_IsNumber)_InNumericMode() <-- SinNum(x); -4 # Sin(ArcSin(_x)) <-- x; -4 # Sin(ArcCos(_x)) <-- Sqrt(1-x^2); -4 # Sin(ArcTan(_x)) <-- x/Sqrt(1+x^2); -5 # Sin(- _x)_(Not IsConstant(x)) <-- -Sin(x); -6 # (Sin(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -Sin(-x); - -// must prevent it from looping -6 # Sin(x_IsInfinity) <-- Undefined; -6 # Sin(Undefined) <-- Undefined; - -110 # Sin(Complex(_r,_i)) <-- - (Exp(I*Complex(r,i)) - Exp(- I*Complex(r,i))) / (I*2) ; - -200 # Sin(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- -[ - SinMap(Coef(v,Pi,1)); -]; - -100 # Sin(_x)/Tan(_x) <-- Cos(x); -100 # Sin(_x)/Cos(_x) <-- Tan(x); - -Sin(xlist_IsList) <-- MapSingle("Sin",xlist); - -%/mathpiper - - - -%mathpiper_docs,name="Sin",categories="User Functions;Calculus Related (Symbolic)" -*CMD Sin --- trigonometric sine function -*STD -*CALL - Sin(x) - -*PARMS - -{x} -- argument to the function, in radians - -*DESC - -This function represents the trigonometric function sine. MathPiper leaves -expressions alone even if x is a number, trying to keep the result as -exact as possible. The floating point approximations of these functions -can be forced by using the {N} function. - -MathPiper knows some trigonometric identities, so it can simplify to exact -results even if {N} is not used. This is the case, for instance, -when the argument is a multiple of $Pi$/6 or $Pi$/4. - -These functions are threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Sin(1) - Out> Sin(1); - In> N(Sin(1),20) - Out> 0.84147098480789650665; - In> Sin(Pi/4) - Out> Sqrt(2)/2; - -*SEE Cos, Tan, ArcSin, ArcCos, ArcTan, N, Pi -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Tanh.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Tanh.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Tanh.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Tanh.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -%mathpiper,def="Tanh" - -2 # Tanh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Sinh(x)/Cosh(x) )); - -100 # Tanh(_x)*Cosh(_x) <-- Sinh(x); - -200 # Tanh(0) <-- 0; -200 # Tanh(Infinity) <-- 1; -200 # Tanh(-Infinity) <-- -1; -200 # Tanh(ArcTanh(_x)) <-- x; -200 # Tanh(ArcSinh(_x)) <-- x/Sqrt(1+x^2); -200 # Tanh(ArcCosh(_x)) <-- Sqrt((x-1)/(x+1))*(x+1)/x; - -200 # Tanh(Undefined) <-- Undefined; - -/* Threading of standard analytic functions */ -Tanh(xlist_IsList) <-- MapSingle("Tanh",xlist); - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Tan.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Tan.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stdfuncs/Tan.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stdfuncs/Tan.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -%mathpiper,def="Tan" - -1 # TanMap( _n )_(Not(IsRationalOrNumber(n))) <-- UnList({Atom("Tan"),n*Pi}); -2 # TanMap( _n )_(n<0) <-- -TanMap(-n); -2 # TanMap( _n )_(n>1) <-- TanMap(Mod(n,1)); -4 # TanMap( _n )_(n>1/2) <-- -TanMap(1-n); - -5 # TanMap( 0 ) <-- 0; -5 # TanMap( 1/6 ) <-- 1/3*Sqrt(3); -5 # TanMap( 1/4 ) <-- 1; -5 # TanMap( 1/3 ) <-- Sqrt(3); -5 # TanMap( 1/2 ) <-- Infinity; - -10 # TanMap(_n) <-- UnList({Atom("Tan"),n*Pi}); - - - - -2 # Tan(x_IsNumber)_InNumericMode() <-- TanNum(x); -4 # Tan(ArcTan(_x)) <-- x; -4 # Tan(ArcSin(_x)) <-- x/Sqrt(1-x^2); -4 # Tan(ArcCos(_x)) <-- Sqrt(1-x^2)/x; -5 # Tan(- _x)_(Not IsConstant(x)) <-- -Tan(x); -6 # (Tan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -Tan(-x); - -// must prevent it from looping -6 # Tan(Infinity) <-- Undefined; -6 # Tan(Undefined) <-- Undefined; - -110 # Tan(Complex(_r,_i)) <-- Sin(Complex(r,i))/Cos(Complex(r,i)); - -200 # Tan(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- - TanMap(Coef(v,Pi,1)); - -100 # Tan(_x)/Sin(_x) <-- (1/Cos(x)); -100 # Tan(_x)*Cos(_x) <-- Sin(x); - -Tan(xlist_IsList) <-- MapSingle("Tan",xlist); - -%/mathpiper - - - -%mathpiper_docs,name="Tan",categories="User Functions;Calculus Related (Symbolic)" -*CMD Tan --- trigonometric tangent function -*STD -*CALL - Tan(x) - -*PARMS - -{x} -- argument to the function, in radians - -*DESC - -This function represents the trigonometric function tangent. MathPiper leaves -expressions alone even if x is a number, trying to keep the result as -exact as possible. The floating point approximations of these functions -can be forced by using the {N} function. - -MathPiper knows some trigonometric identities, so it can simplify to exact -results even if {N} is not used. This is the case, for instance, -when the argument is a multiple of $Pi$/6 or $Pi$/4. - -These functions are threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Tan(1) - Out> Tan(1); - In> N(Tan(1),20) - Out> 1.5574077246549022305; - In> Tan(Pi/4) - Out> 1; - -*SEE Sin, Cos, ArcSin, ArcCos, ArcTan, N, Pi -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Abs.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Abs.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Abs.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Abs.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="Abs" - -10 # Abs(Infinity) <-- Infinity; //Note:tk:moved here from stdfuncts. - -10 # Abs(n_IsNumber) <-- AbsN(n); -10 # Abs(n_IsPositiveNumber/m_IsPositiveNumber) <-- n/m; -10 # Abs(n_IsNegativeNumber/m_IsPositiveNumber) <-- (-n)/m; -10 # Abs(n_IsPositiveNumber/m_IsNegativeNumber) <-- n/(-m); -10 # Abs( Sqrt(_x)) <-- Sqrt(x); -10 # Abs(-Sqrt(_x)) <-- Sqrt(x); -10 # Abs(Complex(_r,_i)) <-- Sqrt(r^2 + i^2); -10 # Abs(n_IsInfinity) <-- Infinity; -10 # Abs(Undefined) <-- Undefined; -20 # Abs(n_IsList) <-- MapSingle("Abs",n); - -100 # Abs(_a^_n) <-- Abs(a)^n; -100 # Abs(_a)^n_IsEven <-- a^n; -100 # Abs(_a)^n_IsOdd <-- Sign(a)*a^n; - - - -%/mathpiper - - - -%mathpiper_docs,name="Abs",categories="User Functions;Calculus Related (Symbolic)" -*CMD Abs --- absolute value or modulus of complex number -*STD -*CALL - Abs(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function returns the absolute value (also called the modulus) of -"x". If "x" is positive, the absolute value is "x" itself; if -"x" is negative, the absolute value is "-x". For complex "x", -the modulus is the "r" in the polar decomposition -$x = r *Exp(I*phi)$. - -This function is connected to the {Sign} function by -the identity "Abs(x) * Sign(x) = x" for real "x". - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Abs(2); - Out> 2; - In> Abs(-1/2); - Out> 1/2; - In> Abs(3+4*I); - Out> 5; - -*SEE Sign, Arg -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/CanonicalAdd.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/CanonicalAdd.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/CanonicalAdd.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/CanonicalAdd.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -%mathpiper,def="CanonicalAdd",scope="private" - -// Canonicalise an expression so its terms are grouped to the right -// ie a+(b+(c+d)) -// This doesn't preserve order of terms, when doing this would cause more -// subtractions and nested parentheses than necessary. -1 # CanonicalAdd((_a+_b)+_c) <-- CanonicalAdd(CanonicalAdd(a)+ - CanonicalAdd(CanonicalAdd(b)+ - CanonicalAdd(c))); -1 # CanonicalAdd((_a-_b)+_c) <-- CanonicalAdd(CanonicalAdd(a)+ - CanonicalAdd(CanonicalAdd(c)- - CanonicalAdd(b))); -1 # CanonicalAdd((_a+_b)-_c) <-- CanonicalAdd(CanonicalAdd(a)+ - CanonicalAdd(CanonicalAdd(b)- - CanonicalAdd(c))); -1 # CanonicalAdd((_a-_b)-_c) <-- CanonicalAdd(CanonicalAdd(a)- - CanonicalAdd(CanonicalAdd(b)+ - CanonicalAdd(c))); -2 # CanonicalAdd(_a) <-- a; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Ceil.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Ceil.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Ceil.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Ceil.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="Ceil" - -5 # Ceil(Infinity) <-- Infinity; -5 # Ceil(-Infinity) <-- -Infinity; -5 # Ceil(Undefined) <-- Undefined; - -10 # Ceil(x_IsRationalOrNumber) - <-- - [ - x:=N(x); - Local(prec,result,n); - Set(prec,BuiltinPrecisionGet()); - If(IsZero(x),Set(n,2), - If(x>0, - Set(n,2+FloorN(N(FastLog(x)/FastLog(10)))), - Set(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) - )); - If(n>prec,BuiltinPrecisionSet(n)); - Set(result,CeilN(x)); - BuiltinPrecisionSet(prec); - result; - ]; -// CeilN (N(x)); - -%/mathpiper - - - -%mathpiper_docs,name="Ceil",categories="User Functions;Numbers (Operations)" -*CMD Ceil --- round a number upwards -*STD -*CALL - Ceil(x) - -*PARMS - -{x} -- a number - -*DESC - -This function returns $Ceil(x)$, the smallest integer larger than or equal to $x$. - -*E.G. - - In> Ceil(1.1) - Out> 2; - In> Ceil(-1.1) - Out> -1; - -*SEE Floor, Round -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/comparison_operators.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/comparison_operators.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/comparison_operators.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/comparison_operators.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,312 +0,0 @@ -%mathpiper,def="<;>;<=;>=;!=" - -/* def file definitions -= -< -> -<= ->= -!= - -*/ - -/* Comparison operators. They call the internal comparison routines when - * both arguments are numbers. The value Infinity is also understood. -*/ - -// Undefined is a very special case as we return False for everything -1 # Undefined < _x <-- False; -1 # Undefined <= _x <-- False; -1 # Undefined > _x <-- False; -1 # Undefined >= _x <-- False; -1 # _x < Undefined <-- False; -1 # _x <= Undefined <-- False; -1 # _x > Undefined <-- False; -1 # _x >= Undefined <-- False; - - -// If n and m are numbers, use the standard LessThan function immediately -5 # (n_IsNumber < m_IsNumber) <-- LessThan(n-m,0); - - -// If n and m are symbolic after a single evaluation, see if they can be coerced in to a real-valued number. -LocalSymbols(nNum,mNum) -[ - 10 # (_n < _m)_[nNum:=N(Eval(n)); mNum:=N(Eval(m));IsNumber(nNum) And IsNumber(mNum);] <-- LessThan(nNum-mNum,0); -]; - -// Deal with Infinity -20 # (Infinity < _n)_(Not(IsInfinity(n))) <-- False; -20 # (-Infinity < _n)_(Not(IsInfinity(n))) <-- True; -20 # (_n < Infinity)_(Not(IsInfinity(n))) <-- True; -20 # (_n < -Infinity)_(Not(IsInfinity(n))) <-- False; - -// Lots of known identities go here -30 # (_n1/_n2) < 0 <-- (n1 < 0) != (n2 < 0); -30 # (_n1*_n2) < 0 <-- (n1 < 0) != (n2 < 0); - -// This doesn't sadly cover the case where a and b have opposite signs -30 # ((_n1+_n2) < 0)_((n1 < 0) And (n2 < 0)) <-- True; -30 # ((_n1+_n2) < 0)_((n1 > 0) And (n2 > 0)) <-- False; -30 # _x^a_IsOdd < 0 <-- x < 0; -30 # _x^a_IsEven < 0 <-- False; // This is wrong for complex x - -// Add other functions here! Everything we can compare to 0 should be here. -40 # (Sqrt(_x))_(x > 0) < 0 <-- False; - -40 # (Sin(_x) < 0)_(Not(IsEven(N(x/Pi))) And IsEven(N(Floor(x/Pi)))) <-- False; -40 # (Sin(_x) < 0)_(Not(IsOdd (N(x/Pi))) And IsOdd (N(Floor(x/Pi)))) <-- True; - -40 # Cos(_x) < 0 <-- Sin(Pi/2-x) < 0; - -40 # (Tan(_x) < 0)_(Not(IsEven(N(2*x/Pi))) And IsEven(N(Floor(2*x/Pi)))) <-- False; -40 # (Tan(_x) < 0)_(Not(IsOdd (N(2*x/Pi))) And IsOdd (N(Floor(2*x/Pi)))) <-- True; - -// Functions that need special treatment with more than one of the comparison -// operators as they always return true or false. For these we must define -// both the `<' and `>=' operators. -40 # (Complex(_a,_b) < 0)_(b!=0) <-- False; -40 # (Complex(_a,_b) >= 0)_(b!=0) <-- False; -40 # (Sqrt(_x))_(x < 0) < 0 <-- False; -40 # (Sqrt(_x))_(x < 0) >= 0 <-- False; - -// Deal with negated terms -50 # -(_x) < 0 <-- Not((x<0) Or (x=0)); - -// Define each of {>,<=,>=} in terms of < -50 # _n > _m <-- m < n; -50 # _n <= _m <-- m >= n; -50 # _n >= _m <-- Not(n 2 < 5; - Out> True; - In> Cos(1) < 5; - Out> True; - -*SEE IsNumber, IsInfinity, N -%/mathpiper_docs - - - -%mathpiper_docs,name=">",categories="Operators" -*CMD > --- test for "greater than" -*STD -*CALL - e1 > e2 -Precedence: -*EVAL OpPrecedence(">") - - -*PARMS - -{e1}, {e2} -- expressions to be compared - -*DESC - -The two expression are evaluated. If both results are numeric, they -are compared. If the first expression is larger than the second one, -the result is {True} and it is {False} otherwise. If either of the expression is not numeric, after -evaluation, the expression is returned with evaluated arguments. - -The word "numeric" in the previous paragraph has the following -meaning. An expression is numeric if it is either a number (i.e. {IsNumber} returns {True}), or the -quotient of two numbers, or an infinity (i.e. {IsInfinity} returns {True}). MathPiper will try to -coerce the arguments passed to this comparison operator to a real value before making the comparison. - -*E.G. - - In> 2 > 5; - Out> False; - In> Cos(1) > 5; - Out> False - -*SEE IsNumber, IsInfinity, N -%/mathpiper_docs - - - -%mathpiper_docs,name="<=",categories="Operators" -*CMD <= --- test for "less or equal" -*STD -*CALL - e1 <= e2 -Precedence: -*EVAL OpPrecedence("<=") - - -*PARMS - -{e1}, {e2} -- expressions to be compared - -*DESC - -The two expression are evaluated. If both results are numeric, they -are compared. If the first expression is smaller than or equals the -second one, the result is {True} and it is {False} otherwise. If either of the expression is not -numeric, after evaluation, the expression is returned with evaluated -arguments. - -The word "numeric" in the previous paragraph has the following -meaning. An expression is numeric if it is either a number (i.e. {IsNumber} returns {True}), or the -quotient of two numbers, or an infinity (i.e. {IsInfinity} returns {True}). MathPiper will try to -coerce the arguments passed to this comparison operator to a real value before making the comparison. - -*E.G. - - In> 2 <= 5; - Out> True; - In> Cos(1) <= 5; - Out> True - -*SEE IsNumber, IsInfinity, N -%/mathpiper_docs - - - -%mathpiper_docs,name=">=",categories="Operators" -*CMD >= --- test for "greater or equal" -*STD -*CALL - e1 >= e2 -Precedence: -*EVAL OpPrecedence(">=") - - -*PARMS - -{e1}, {e2} -- expressions to be compared - -*DESC - -The two expression are evaluated. If both results are numeric, they -are compared. If the first expression is larger than or equals the -second one, the result is {True} and it is {False} otherwise. If either of the expression is not -numeric, after evaluation, the expression is returned with evaluated -arguments. - -The word "numeric" in the previous paragraph has the following -meaning. An expression is numeric if it is either a number (i.e. {IsNumber} returns {True}), or the -quotient of two numbers, or an infinity (i.e. {IsInfinity} returns {True}). MathPiper will try to -coerce the arguments passed to this comparison operator to a real value before making the comparison. - -*E.G. - - In> 2 >= 5; - Out> False; - In> Cos(1) >= 5; - Out> False - -*SEE IsNumber, IsInfinity, N -%/mathpiper_docs - - - -%mathpiper_docs,name="!=",categories="Operators" -*CMD != --- test for "not equal" -*STD -*CALL - e1 != e2 -Precedence: -*EVAL OpPrecedence("!=") - - -*PARMS - -{e1}, {e2} -- expressions to be compared - -*DESC - -Both expressions are evaluated and compared. If they turn out to be -equal, the result is {False}. Otherwise, the result -is {True}. - -The expression {e1 != e2} is equivalent to {Not(e1 = e2)}. - -*E.G. - - In> 1 != 2; - Out> True; - In> 1 != 1; - Out> False; - -*SEE = -%/mathpiper_docs - - - -%mathpiper_docs,name="=",categories="Operators" -*CMD = --- test for equality of expressions -*STD -*CALL - e1 = e2 -Precedence: -*EVAL OpPrecedence("=") - - -*PARMS - -{e1}, {e2} -- expressions to be compared - -*DESC - -Both expressions are evaluated and compared. If they turn out to be equal, the -result is {True}. Otherwise, the result is {False}. The function {Equals} does -the same. - -Note that the test is on syntactic equality, not mathematical equality. Hence -even if the result is {False}, the expressions can still be -mathematically equal; see the examples below. Put otherwise, this -function tests whether the two expressions would be displayed in the same way -if they were printed. - -*E.G. - - In> e1 := (x+1) * (x-1); - Out> (x+1)*(x-1); - In> e2 := x^2 - 1; - Out> x^2-1; - - In> e1 = e2; - Out> False; - In> Expand(e1) = e2; - Out> True; - -*SEE !=, Equals -%/mathpiper_docs - - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Div.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Div.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Div.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Div.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -%mathpiper,def="Div" - -/* Integer divisions */ -0 # Div(n_IsInteger,m_IsInteger) <-- DivN(n,m); -1 # Div(0 ,_m) <-- 0; -2 # Div(n_IsRationalOrNumber,m_IsRationalOrNumber) <-- -[ - Local(n1,n2,m1,m2,sgn1,sgn2); - n1:=Numerator(n); - n2:=Denominator(n); - m1:=Numerator(m); - m2:=Denominator(m); - sgn1 := Sign(n1*m2); - sgn2 := Sign(m1*n2); - sgn1*sgn2*Floor(DivideN(sgn1*n1*m2,sgn2*m1*n2)); -]; -30 # Div(n_CanBeUni,m_CanBeUni)_(Length(VarList(n*m))=1) <-- -[ - - Local(vars,nl,ml); - vars:=VarList(n*m); - nl := MakeUni(n,vars); - ml := MakeUni(m,vars); - NormalForm(Div(nl,ml)); -]; - - -//Note:tk:moved here from univariate.rep. -0 # Div(n_IsUniVar,m_IsUniVar)_(Degree(n) < Degree(m)) <-- 0; -1 # Div(n_IsUniVar,m_IsUniVar)_ - (n[1] = m[1] And Degree(n) >= Degree(m)) <-- -[ - UniVariate(n[1],0, - UniDivide(Concat(ZeroVector(n[2]),n[3]), - Concat(ZeroVector(m[2]),m[3]))[1]); -]; - -%/mathpiper - - -%mathpiper_docs,name="Div",categories="User Functions;Numbers (Operations)" -*CMD Div --- Determine quotient of two mathematical objects - -*STD -*CALL - Div(x,y) - -*PARMS - -{x}, {y} -- integers or univariate polynomials - -*DESC - -{Div} performs integer division. {Div} is also defined for polynomials. - -If {Div(x,y)} returns "a" and {Mod(x,y)} equals "b", then these numbers satisfy $x =a*y + b$ and $0 <= b < y$. - -*E.G. - - In> Div(5,3) - Out> 1; - In> Mod(5,3) - Out> 2; - -*SEE Gcd, Lcm, Mod -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Expand.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Expand.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Expand.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Expand.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -%mathpiper,def="Expand" - -/* Expand expands polynomials. - */ -10 # Expand(expr_CanBeUni) <-- NormalForm(MakeUni(expr)); -20 # Expand(_expr) <-- expr; - -10 # Expand(expr_CanBeUni(var),_var) <-- NormalForm(MakeUni(expr,var)); -20 # Expand(_expr,_var) <-- expr; - -%/mathpiper - - - -%mathpiper_docs,name="Expand",categories="User Functions;Polynomials (Operations)" -*CMD Expand --- transform a polynomial to an expanded form -*STD -*CALL - Expand(expr) - Expand(expr, var) - Expand(expr, varlist) - -*PARMS - -{expr} -- a polynomial expression - -{var} -- a variable - -{varlist} -- a list of variables - -*DESC - -This command brings a polynomial in expanded form, in which -polynomials are represented in the form -$c0 + c1*x + c2*x^2 + ... + c[n]*x^n$. In this form, it is easier to test whether a polynomial is -zero, namely by testing whether all coefficients are zero. - -If the polynomial "expr" contains only one variable, the first -calling sequence can be used. Otherwise, the second form should be -used which explicitly mentions that "expr" should be considered as a -polynomial in the variable "var". The third calling form can be used -for multivariate polynomials. Firstly, the polynomial "expr" is -expanded with respect to the first variable in "varlist". Then the -coefficients are all expanded with respect to the second variable, and -so on. - -*E.G. - - In> PrettyPrinter'Set("PrettyForm"); - - True - - In> Expand((1+x)^5); - - 5 4 3 2 - x + 5 * x + 10 * x + 10 * x + 5 * x + 1 - - In> Expand((1+x-y)^2, x); - - 2 2 - x + 2 * ( 1 - y ) * x + ( 1 - y ) - - In> Expand((1+x-y)^2, {x,y}); - - 2 2 - x + ( -2 * y + 2 ) * x + y - 2 * y + 1 - - -*SEE ExpandBrackets -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Floor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Floor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Floor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Floor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -%mathpiper,def="Floor" - -5 # Floor(Infinity) <-- Infinity; -5 # Floor(-Infinity) <-- -Infinity; -5 # Floor(Undefined) <-- Undefined; - - -10 # Floor(x_IsRationalOrNumber) - <-- - [ - x:=N(Eval(x)); -//Echo("x = ",x); - Local(prec,result,n); - Set(prec,BuiltinPrecisionGet()); - If(IsZero(x), - Set(n,2), - If(x>0, - Set(n,2+FloorN(N(FastLog(x)/FastLog(10)))), - Set(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) - )); - If(n>prec,BuiltinPrecisionSet(n)); -//Echo("Before"); - Set(result,FloorN(x)); -//Echo("After"); - BuiltinPrecisionSet(prec); - result; - ]; - -// FloorN(N(x)); - - -//todo:tk:should this be removed because it is no longer needed? -/* Changed by Nobbi before redefinition of Rational -10 # Floor(x_IsNumber) <-- FloorN(x); -10 # Ceil (x_IsNumber) <-- CeilN (x); -10 # Round(x_IsNumber) <-- FloorN(x+0.5); - -20 # Floor(x_IsRational) _ (IsNumber(Numerator(x)) And IsNumber(Denominator(x))) <-- FloorN(N(x)); -20 # Ceil (x_IsRational) _ (IsNumber(Numerator(x)) And IsNumber(Denominator(x))) <-- CeilN (N(x)); -20 # Round(x_IsRational) _ (IsNumber(Numerator(x)) And IsNumber(Denominator(x))) <-- FloorN(N(x+0.5)); -*/ - -%/mathpiper - - - -%mathpiper_docs,name="Floor",categories="User Functions;Numbers (Operations)" -*CMD Floor --- round a number downwards -*STD -*CALL - Floor(x) - -*PARMS - -{x} -- a number - -*DESC - -This function returns $Floor(x)$, the largest integer smaller than or equal to $x$. - -*E.G. - - In> Floor(1.1) - Out> 1; - In> Floor(-1.1) - Out> -2; - -*SEE Ceil, Round -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Gcd.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Gcd.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Gcd.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Gcd.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -%mathpiper,def="Gcd" - -0 # Gcd(0,0) <-- 1; -1 # Gcd(0,_m) <-- Abs(m); -1 # Gcd(_n,0) <-- Abs(n); -1 # Gcd(_m,_m) <-- Abs(m); -2 # Gcd(_n,1) <-- 1; -2 # Gcd(1,_m) <-- 1; -2 # Gcd(n_IsInteger,m_IsInteger) <-- GcdN(n,m); -3 # Gcd(_n,_m)_(IsGaussianInteger(m) And IsGaussianInteger(n) )<-- GaussianGcd(n,m); - -4 # Gcd(-(_n), (_m)) <-- Gcd(n,m); -4 # Gcd( (_n),-(_m)) <-- Gcd(n,m); -4 # Gcd(Sqrt(n_IsInteger),Sqrt(m_IsInteger)) <-- Sqrt(Gcd(n,m)); -4 # Gcd(Sqrt(n_IsInteger),m_IsInteger) <-- Sqrt(Gcd(n,m^2)); -4 # Gcd(n_IsInteger,Sqrt(m_IsInteger)) <-- Sqrt(Gcd(n^2,m)); - -5 # Gcd(n_IsRational,m_IsRational) <-- -[ - Gcd(Numerator(n),Numerator(m))/Lcm(Denominator(n),Denominator(m)); -]; - - -10 # Gcd(list_IsList)_(Length(list)>2) <-- - [ - Local(first); - first:=Gcd(list[1],list[2]); - Gcd(first:Rest(Rest(list))); - ]; -14 # Gcd({0}) <-- 1; -15 # Gcd({_head}) <-- head; - -20 # Gcd(list_IsList)_(Length(list)=2) <-- Gcd(list[1],list[2]); - -30 # Gcd(n_CanBeUni,m_CanBeUni)_(Length(VarList(n*m))=1) <-- -[ - Local(vars); - vars:=VarList(n+m); - NormalForm(Gcd(MakeUni(n,vars),MakeUni(m,vars))); -]; - -100 # Gcd(n_IsConstant,m_IsConstant) <-- 1; -110 # Gcd(_m,_n) <-- -[ - Echo("Not simplified"); -]; - - -//Note:tk:moved here from univar.rep. -0 # Gcd(n_IsUniVar,m_IsUniVar)_ - (n[1] = m[1] And Degree(n) < Degree(m)) <-- Gcd(m,n); - -1 # Gcd(nn_IsUniVar,mm_IsUniVar)_ - (nn[1] = mm[1] And Degree(nn) >= Degree(mm)) <-- -[ - UniVariate(nn[1],0, - UniGcd(Concat(ZeroVector(nn[2]),nn[3]), - Concat(ZeroVector(mm[2]),mm[3]))); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Gcd",categories="User Functions;Numbers (Operations)" -*CMD Gcd --- greatest common divisor -*STD -*CALL - Gcd(n,m) - Gcd(list) - -*PARMS - -{n}, {m} -- integers or Gaussian integers or univariate polynomials - -{list} -- a list of all integers or all univariate polynomials - -*DESC - -This function returns the greatest common divisor of "n" and "m". -The gcd is the largest number that divides "n" and "m". It is -also known as the highest common factor (hcf). The library code calls -{MathGcd}, which is an internal function. This -function implements the "binary Euclidean algorithm" for determining the -greatest common divisor: - -*HEAD Routine for calculating {Gcd(n,m)} - -* 1. if $n = m$ then return $n$ -* 2. if both $n$ and $m$ are even then return $2*Gcd(n/2,m/2)$ -* 3. if exactly one of $n$ or $m$ (say $n$) is even then return $Gcd(n/2,m)$ -* 4. if both $n$ and $m$ are odd and, say, $n>m$ then return $Gcd((n-m)/2,m)$ - -This is a rather fast algorithm on computers that can efficiently shift -integers. When factoring Gaussian integers, a slower recursive algorithm is used. - -If the second calling form is used, {Gcd} will -return the greatest common divisor of all the integers or polynomials -in "list". It uses the identity -$$Gcd(a,b,c) = Gcd(Gcd(a,b),c)$$. - -*E.G. - - In> Gcd(55,10) - Out> 5; - In> Gcd({60,24,120}) - Out> 12; - In> Gcd( 7300 + 12*I, 2700 + 100*I) - Out> Complex(-4,4); - - -*SEE Lcm -%/mathpiper_docs - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Lcm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Lcm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Lcm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Lcm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%mathpiper,def="Lcm" - -/* Least common multiple */ -5 # Lcm(a_IsInteger,b_IsInteger) <-- Div(a*b,Gcd(a,b)); - -10 # Lcm(list_IsList)_(Length(list)>2) <-- -[ - Local(first); - first:=Lcm(list[1],list[2]); - Lcm(first:Rest(Rest(list))); -]; - -10 # Lcm(list_IsList)_(Length(list)=2) <-- Lcm(list[1],list[2]); - -%/mathpiper - - - -%mathpiper_docs,name="Lcm",categories="User Functions;Numbers (Operations)" -*CMD Lcm --- least common multiple -*STD -*CALL - Lcm(n,m) - Lcm(list) - -*PARMS - -{n}, {m} -- integers or univariate polynomials -{list} -- list of integers - -*DESC - -This command returns the least common multiple of "n" and "m" or all of -the integers in the list {list}. -The least common multiple of two numbers "n" and "m" is the lowest -number which is an integer multiple of both "n" and "m". -It is calculated with the formula -$$Lcm(n,m) = Div(n*m,Gcd(n,m))$$. - -This means it also works on polynomials, since {Div}, {Gcd} and multiplication are also defined for -them. - -*E.G. - - In> Lcm(60,24) - Out> 120; - In> Lcm({3,5,7,9}) - Out> 315; - - -*SEE Gcd - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/LnCombine.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/LnCombine.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/LnCombine.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/LnCombine.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -%mathpiper,def="LnCombine" - -////////////////////// Log rules stuff ////////////////////// - -// LnCombine is nice and simple now -LnCombine(_a) <-- DoLnCombine(CanonicalAdd(a)); - -// Combine single terms. This can always be done without a recursive call. -1 # DoLnCombine(Ln(_a)) <-- Ln(a); -1 # DoLnCombine(Ln(_a)*_b) <-- Ln(a^b); -1 # DoLnCombine(_b*Ln(_a)) <-- Ln(a^b); - -// Deal with the first two terms so they are both simple logs if at all -// possible. This involves converting a*Ln(b) to Ln(b^a) and moving log terms -// to the start of expressions. One of either of these operations always takes -// us to a strictly simpler form than we started in, so we can get away with -// calling DoLnCombine again with the partly simplified argument. - -// TODO: Make this deal with division everywhere it deals with multiplication - -// first term is a log multiplied by something -2 # DoLnCombine(Ln(_a)*_b+_c) <-- DoLnCombine(Ln(a^b)+c); -2 # DoLnCombine(Ln(_a)*_b-_c) <-- DoLnCombine(Ln(a^b)-c); -2 # DoLnCombine(_b*Ln(_a)+_c) <-- DoLnCombine(Ln(a^b)+c); -2 # DoLnCombine(_b*Ln(_a)-_c) <-- DoLnCombine(Ln(a^b)-c); - -// second term of a two-term expression is a log multiplied by something -2 # DoLnCombine(_a+(_c*Ln(_b))) <-- DoLnCombine(a+Ln(b^c)); -2 # DoLnCombine(_a-(_c*Ln(_b))) <-- DoLnCombine(a-Ln(b^c)); -2 # DoLnCombine(_a+(Ln(_b)*_c)) <-- DoLnCombine(a+Ln(b^c)); -2 # DoLnCombine(_a-(Ln(_b)*_c)) <-- DoLnCombine(a-Ln(b^c)); - -// second term of a three-term expression is a log multiplied by something -2 # DoLnCombine(_a+((Ln(_b)*_c)+_d)) <-- DoLnCombine(a+(Ln(b^c)+d)); -2 # DoLnCombine(_a+((Ln(_b)*_c)-_d)) <-- DoLnCombine(a+(Ln(b^c)-d)); -2 # DoLnCombine(_a-((Ln(_b)*_c)+_d)) <-- DoLnCombine(a-(Ln(b^c)+d)); -2 # DoLnCombine(_a-((Ln(_b)*_c)-_d)) <-- DoLnCombine(a-(Ln(b^c)-d)); - -2 # DoLnCombine(_a+((_c*Ln(_b))+_d)) <-- DoLnCombine(a+(Ln(b^c)+d)); -2 # DoLnCombine(_a+((_c*Ln(_b))-_d)) <-- DoLnCombine(a+(Ln(b^c)-d)); -2 # DoLnCombine(_a-((_c*Ln(_b))+_d)) <-- DoLnCombine(a-(Ln(b^c)+d)); -2 # DoLnCombine(_a-((_c*Ln(_b))-_d)) <-- DoLnCombine(a-(Ln(b^c)-d)); - -// Combine the first two terms if they are logs, otherwise move one or both to -// the front, then recurse on the remaining possibly-log-containing portion. -// (the code makes more sense than this comment) -3 # DoLnCombine(Ln(_a)+Ln(_b)) <-- Ln(a*b); -3 # DoLnCombine(Ln(_a)-Ln(_b)) <-- Ln(a/b); -3 # DoLnCombine(Ln(_a)+(Ln(_b)+_c)) <-- DoLnCombine(Ln(a*b)+c); -3 # DoLnCombine(Ln(_a)+(Ln(_b)-_c)) <-- DoLnCombine(Ln(a*b)-c); -3 # DoLnCombine(Ln(_a)-(Ln(_b)+_c)) <-- DoLnCombine(Ln(a/b)-c); -3 # DoLnCombine(Ln(_a)-(Ln(_b)-_c)) <-- DoLnCombine(Ln(a/b)+c); - -// We know that at least one of the first two terms isn't a log -4 # DoLnCombine(Ln(_a)+(_b+_c)) <-- b+DoLnCombine(Ln(a)+c); -4 # DoLnCombine(Ln(_a)+(_b-_c)) <-- b+DoLnCombine(Ln(a)-c); -4 # DoLnCombine(Ln(_a)-(_b+_c)) <-- DoLnCombine(Ln(a)-c)-b; -4 # DoLnCombine(Ln(_a)-(_b-_c)) <-- DoLnCombine(Ln(a)+c)-b; - -4 # DoLnCombine(_a+(Ln(_b)+_c)) <-- a+DoLnCombine(Ln(b)+c); -4 # DoLnCombine(_a+(Ln(_b)-_c)) <-- a+DoLnCombine(Ln(b)-c); -4 # DoLnCombine(_a-(Ln(_b)+_c)) <-- a-DoLnCombine(Ln(b)+c); -4 # DoLnCombine(_a-(Ln(_b)-_c)) <-- a-DoLnCombine(Ln(b)-c); - -// If we get here we know that neither of the first two terms is a log -5 # DoLnCombine(_a+(_b+_c)) <-- a+(b+DoLnCombine(c)); - -// Finished -6 # DoLnCombine(_a) <-- a; - - -%/mathpiper - - - -%mathpiper_docs,name="LnCombine",categories="User Functions;Expression Simplification" -*CMD LnCombine --- combine logarithmic expressions using standard logarithm rules -*STD -*CALL - LnCombine(expr) - -*PARMS - -{expr} -- an expression possibly containing multiple {Ln} terms to be combined - -*DESC - -{LnCombine} finds {Ln} terms in the expression it is given, and combines them -using logarithm rules. It is intended to be the exact converse of {LnExpand}. - -*E.G. - In> LnCombine(Ln(a)+Ln(b)*n) - Out> Ln(a*b^n) - In> LnCombine(2*Ln(2)+Ln(3)-Ln(5)) - Out> Ln(12/5) - -*SEE Ln, LnExpand -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/LnExpand.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/LnExpand.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/LnExpand.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/LnExpand.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -%mathpiper,def="LnExpand" - -////////////////////// Log rules stuff ////////////////////// - -// LnExpand -1 # LnExpand(Ln(x_IsInteger)) - <-- Add(Map({{n,m},m*Ln(n)},Transpose(Factors(x)))); -1 # LnExpand(Ln(_a*_b)) <-- LnExpand(Ln(a))+LnExpand(Ln(b)); -1 # LnExpand(Ln(_a/_b)) <-- LnExpand(Ln(a))-LnExpand(Ln(b)); -1 # LnExpand(Ln(_a^_n)) <-- LnExpand(Ln(a))*n; -2 # LnExpand(_a) <-- a; - -%/mathpiper - - - -%mathpiper_docs,name="LnExpand",categories="User Functions;Expression Simplification" -*CMD LnExpand --- expand a logarithmic expression using standard logarithm rules -*STD -*CALL - LnExpand(expr) - -*PARMS - -{expr} -- the logarithm of an expression - -*DESC - -{LnExpand} takes an expression of the form $Ln(expr)$, and applies logarithm -rules to expand this into multiple {Ln} expressions where possible. An -expression like $Ln(a*b^n)$ would be expanded to $Ln(a)+n*Ln(b)$. - -If the logarithm of an integer is discovered, it is factorised using {Factors} -and expanded as though {LnExpand} had been given the factorised form. So -$Ln(18)$ goes to $Ln(x)+2*Ln(3)$. - -*E.G. - In> LnExpand(Ln(a*b^n)) - Out> Ln(a)+Ln(b)*n - In> LnExpand(Ln(a^m/b^n)) - Out> Ln(a)*m-Ln(b)*n - In> LnExpand(Ln(60)) - Out> 2*Ln(2)+Ln(3)+Ln(5) - In> LnExpand(Ln(60/25)) - Out> 2*Ln(2)+Ln(3)-Ln(5) - -*SEE Ln, LnCombine, Factors -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Mod.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Mod.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Mod.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Mod.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -%mathpiper,def="Mod" - -0 # Mod(_n,m_IsRationalOrNumber)_(m<0) <-- `Hold(Mod(@n,@m)); - -1 # Mod(n_IsNegativeInteger,m_IsPositiveInteger) <-- -[ - Local(result); - result := ModN(n,m); - If (result < 0,result := result + m); - result; -]; -1 # Mod(n_IsPositiveInteger,m_IsPositiveInteger) <-- ModN(n,m); -2 # Mod(0,_m) <-- 0; -2 # Mod(n_IsPositiveInteger,Infinity) <-- n; -3 # Mod(n_IsInteger,m_IsInteger) <-- ModN(n,m); -4 # Mod(n_IsNumber,m_IsNumber) <-- NonN(Mod(Rationalize(n),Rationalize(m))); - -5 # Mod(n_IsRationalOrNumber,m_IsRationalOrNumber)/*_(n>0 And m>0)*/ <-- -[ - Local(n1,n2,m1,m2); - n1:=Numerator(n); - n2:=Denominator(n); - m1:=Numerator(m); - m2:=Denominator(m); - Mod(n1*m2,m1*n2)/(n2*m2); -]; - -6 # Mod(n_IsList,m_IsList) <-- Map("Mod",{n,m}); -7 # Mod(n_IsList,_m) <-- Map("Mod",{n,FillList(m,Length(n))}); - - -30 # Mod(n_CanBeUni,m_CanBeUni) <-- -[ - Local(vars); - vars:=VarList(n+m); - NormalForm(Mod(MakeUni(n,vars),MakeUni(m,vars))); -]; - - -//Note:tk:moved here from univariate.rep. -0 # Mod(n_IsUniVar,m_IsUniVar)_(Degree(n) < Degree(m)) <-- n; -1 # Mod(n_IsUniVar,m_IsUniVar)_ - (n[1] = m[1] And Degree(n) >= Degree(m)) <-- -[ - UniVariate(n[1],0, - UniDivide(Concat(ZeroVector(n[2]),n[3]), - Concat(ZeroVector(m[2]),m[3]))[2]); -]; - -%/mathpiper - - -%mathpiper_docs,name="Mod",categories="User Functions;Numbers (Operations)" -*CMD Mod --- Determine remainder of two mathematical objects after dividing one by the other - -*STD -*CALL - Mod(x,y) - -*PARMS - -{x}, {y} -- integers or univariate polynomials - -*DESC - -{Mod} returns the remainder after division. {Mod} is also defined for polynomials. - -If {Div(x,y)} returns "a" and {Mod(x,y)} equals "b", then these numbers satisfy $x =a*y + b$ and $0 <= b < y$. - -*E.G. - - In> Div(5,3) - Out> 1; - In> Mod(5,3) - Out> 2; - -*SEE Gcd, Lcm, Div -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Object.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Object.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Object.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Object.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="Object" - -RuleBase("Object",{pred,x}); -Rule("Object",2,0,Apply(pred,{x})=True) x; - -%/mathpiper - - - -%mathpiper_docs,name="Object",categories="User Functions;Variables" -*CMD Object --- create an incomplete type -*STD -*CALL - Object("pred", exp) - -*PARMS - -{pred} -- name of the predicate to apply - -{exp} -- expression on which "pred" should be applied - -*DESC - -This function returns "obj" as soon as "pred" returns {True} when applied on "obj". This is used to declare -so-called incomplete types. - -*E.G. - - In> a := Object("IsNumber", x); - Out> Object("IsNumber",x); - In> Eval(a); - Out> Object("IsNumber",x); - In> x := 5; - Out> 5; - In> Eval(a); - Out> 5; - -*SEE IsNonObject -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="false" - -// From code.mpi.def: -OMDef( "Not", "logic1","not" ); -OMDef( "=" , "relation1","eq" ); -OMDef( ">=", "relation1","geq" ); -OMDef( ">" , "relation1","gt" ); -OMDef( "<=", "relation1","leq" ); -OMDef( "<" , "relation1","lt" ); -OMDef( "!=", "relation1","neq" ); -OMDef( "Gcd", "arith1","gcd" ); -OMDef( "Sqrt", "arith1","root", { $, _1, 2 }, $(_1)_(_2=2) | (_1^(1/_2)) ); -// Test [result: Sqrt(16)]: -// FromString("162 ")OMRead() -// Test [result: IntNthRoot(16,3))]: -// FromString("163 ")OMRead() -OMDef( "Abs", "arith1","abs" ); -OMDef( "Lcm", "arith1","lcm" ); - -OMDef( "Floor", "rounding1","floor" ); -OMDef( "Ceil" , "rounding1","ceiling" ); -OMDef( "Round", "rounding1","round" ); - -OMDef( "Div" , mathpiper,"div" ); -OMDef( "Mod" , mathpiper,"mod" ); -OMDef( "Expand", mathpiper,"expand" ); -OMDef( "Object", mathpiper,"object" ); -OMDef( "Sign" , mathpiper,"sign" ); - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Rem.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Rem.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Rem.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Rem.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="Rem",scope="private" - -//Note:tk:this was not listed in the def file. -0 # Rem(n_IsNumber,m_IsNumber) <-- n-m*Div(n,m); -30 # Rem(n_CanBeUni,m_CanBeUni) <-- Mod(n,m); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Round.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Round.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Round.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Round.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="Round" - -5 # Round(Infinity) <-- Infinity; -5 # Round(-Infinity) <-- -Infinity; -5 # Round(Undefined) <-- Undefined; - -10 # Round(x_IsRationalOrNumber) <-- FloorN(N(x+0.5)); -10 # Round(x_IsList) <-- MapSingle("Round",x); - -20 # Round(x_IsComplex) _ (IsRationalOrNumber(Re(x)) And IsRationalOrNumber(Im(x)) ) - <-- FloorN(N(Re(x)+0.5)) + FloorN(N(Im(x)+0.5))*I; - -%/mathpiper - - - -%mathpiper_docs,name="Round",categories="User Functions;Numbers (Operations)" -*CMD Round --- round a number to the nearest integer -*STD -*CALL - Round(x) - -*PARMS - -{x} -- a number - -*DESC - -This function returns the integer closest to $x$. Half-integers -(i.e. numbers of the form $n + 0.5$, with $n$ an integer) are -rounded upwards. - -*E.G. - - In> Round(1.49) - Out> 1; - In> Round(1.51) - Out> 2; - In> Round(-1.49) - Out> -1; - In> Round(-1.51) - Out> -2; - -*SEE Floor, Ceil -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/shifting_operators.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/shifting_operators.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/shifting_operators.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/shifting_operators.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -%mathpiper,def="<<;>>" - -/* def file definitions -<< ->> -*/ - -/* Shifting operators */ - -n_IsInteger << m_IsInteger <-- ShiftLeft(n,m); -n_IsInteger >> m_IsInteger <-- ShiftRight(n,m); - -%/mathpiper - - -%mathpiper_docs,name="<<;>>",categories="Operators" -*CMD << --- binary shift left operator -*CMD >> --- binary shift right operator -*STD -*CALL - n<>m - -*PARMS - -{n}, {m} -- integers - -*DESC - -These operators shift integers to the left or to the right. -They are similar to the C shift operators. These are sign-extended -shifts, so they act as multiplication or division by powers of 2. - -*E.G. - - In> 1 << 10 - Out> 1024; - In> -1024 >> 10 - Out> -1; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Sign.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Sign.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Sign.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Sign.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -%mathpiper,def="Sign" - -10 # Sign(n_IsPositiveNumber) <-- 1; -10 # Sign(n_IsZero) <-- 0; -20 # Sign(n_IsNumber) <-- -1; -15 # Sign(n_IsInfinity)_(n < 0) <-- -1; -15 # Sign(n_IsInfinity)_(n > 0) <-- 1; -15 # Sign(n_IsNumber/m_IsNumber) <-- Sign(n)*Sign(m); -20 # Sign(n_IsList) <-- MapSingle("Sign",n); - -100 # Sign(_a)^n_IsEven <-- 1; -100 # Sign(_a)^n_IsOdd <-- Sign(a); - -%/mathpiper - - - -%mathpiper_docs,name="Sign",categories="User Functions;Calculus Related (Symbolic)" -*CMD Sign --- sign of a number -*STD -*CALL - Sign(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function returns the sign of the real number $x$. It is "1" -for positive numbers and "-1" for negative numbers. Somewhat -arbitrarily, {Sign(0)} is defined to be 1. - -This function is connected to the {Abs} function by -the identity $Abs(x) * Sign(x) = x$ for real $x$. - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Sign(2) - Out> 1; - In> Sign(-3) - Out> -1; - In> Sign(0) - Out> 1; - In> Sign(-3) * Abs(-3) - Out> -3; - -*SEE Arg, Abs -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Sqrt.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Sqrt.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/stubs/Sqrt.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/stubs/Sqrt.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -%mathpiper,def="Sqrt" - -0 # Sqrt(0) <-- 0; -0 # Sqrt(Infinity) <-- Infinity; -0 # Sqrt(-Infinity) <-- Complex(0,Infinity); -0 # Sqrt(Undefined) <-- Undefined; -1 # Sqrt(x_IsPositiveInteger)_(IsInteger(SqrtN(x))) <-- SqrtN(x); -2 # Sqrt(x_IsPositiveNumber)_InNumericMode() <-- SqrtN(x); -2 # Sqrt(x_IsNegativeNumber) <-- Complex(0,Sqrt(-x)); -/* 3 # Sqrt(x_IsNumber/y_IsNumber) <-- Sqrt(x)/Sqrt(y); */ -3 # Sqrt(x_IsComplex)_InNumericMode() <-- x^(1/2); -/* Threading */ -Sqrt(xlist_IsList) <-- MapSingle("Sqrt",xlist); - -90 # (Sqrt(x_IsConstant))_(IsNegativeNumber(N(x))) <-- Complex(0,Sqrt(-x)); - -400 # x_IsRationalOrNumber * Sqrt(y_IsRationalOrNumber) <-- Sign(x)*Sqrt(x^2*y); -400 # Sqrt(y_IsRationalOrNumber) * x_IsRationalOrNumber <-- Sign(x)*Sqrt(x^2*y); -400 # x_IsRationalOrNumber / Sqrt(y_IsRationalOrNumber) <-- Sign(x)*Sqrt(x^2/y); -400 # Sqrt(y_IsRationalOrNumber) / x_IsRationalOrNumber <-- Sign(x)*Sqrt(y/(x^2)); -400 # Sqrt(y_IsRationalOrNumber) / Sqrt(x_IsRationalOrNumber) <-- Sqrt(y/x); -400 # Sqrt(y_IsRationalOrNumber) * Sqrt(x_IsRationalOrNumber) <-- Sqrt(y*x); -400 # Sqrt(x_IsInteger)_IsInteger(SqrtN(x)) <-- SqrtN(x); -400 # Sqrt(x_IsInteger/y_IsInteger)_(IsInteger(SqrtN(x)) And IsInteger(SqrtN(y))) <-- SqrtN(x)/SqrtN(y); - -%/mathpiper - - - -%mathpiper_docs,name="Sqrt",categories="User Functions;Calculus Related (Symbolic)" -*CMD Sqrt --- square root -*STD -*CALL - Sqrt(x) - -*PARMS - -{x} -- argument to the function - -*DESC - -This function calculates the square root of "x". If the result is -not rational, the call is returned unevaluated unless a numerical -approximation is forced with the {N} function. This -function can also handle negative and complex arguments. - -This function is threaded, meaning that if the argument {x} is a -list, the function is applied to all entries in the list. - -*E.G. - - In> Sqrt(16) - Out> 4; - In> Sqrt(15) - Out> Sqrt(15); - In> N(Sqrt(15)) - Out> 3.8729833462; - In> Sqrt(4/9) - Out> 2/3; - In> Sqrt(-1) - Out> Complex(0,1); - -*SEE Exp, ^, N -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/substitute/MacroSubstitute.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/substitute/MacroSubstitute.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/substitute/MacroSubstitute.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/substitute/MacroSubstitute.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -%mathpiper,def="MacroSubstitute",scope="private" - -/*Extremely hacky workaround, MacroSubstitute is actually the same as Substitute, - but without re-evaluating its arguments. I could not just change Substitute, as - it changed behaviour such that tests started to break. - */ -Function("MacroSubstitute",{body,predicate,change}) -[ - `MacroSubstitute((Hold(@body))); -]; -HoldArg("MacroSubstitute",predicate); -HoldArg("MacroSubstitute",change); -UnFence("MacroSubstitute",3); -RuleBase("MacroSubstitute",{body}); -UnFence("MacroSubstitute",1); - -Rule("MacroSubstitute",1,1,`ApplyPure(predicate,{Hold(Hold(@body))}) = True) -[ - `ApplyPure(change,{Hold(Hold(@body))}); -]; -Rule("MacroSubstitute",1,2,`IsFunction(Hold(@body))) -[ - `ApplyPure("MacroMapArgs",{Hold(Hold(@body)),"MacroSubstitute"}); -]; -Rule("MacroSubstitute",1,3,True) -[ - `Hold(@body); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/substitute/Select.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/substitute/Select.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/substitute/Select.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/substitute/Select.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="Select",scope="public" - -LocalSymbols(predicate,list,result,item) -[ - Function("Select",{predicate,list}) - [ - Local(result); - result:={}; - ForEach(item,list) - [ - If(Apply(predicate,{item}),DestructiveAppend(result,item)); - ]; - result; - ]; - HoldArg("Select",predicate); - UnFence("Select",2); -]; - -%/mathpiper - - - -%mathpiper_docs,name="Select",categories="User Functions;Lists (Operations)" -*CMD Select --- select entries satisfying some predicate -*STD -*CALL - Select(pred, list) - -*PARMS - -{pred} -- a predicate - -{list} -- a list of elements to select from - -*DESC - -{Select} returns a sublist of "list" which contains all -the entries for which the predicate "pred" returns -{True} when applied to this entry. - -The {Lambda} function can be used in place of a predicate function -if desired. - -*E.G. - -In> Select("IsInteger",{a,b,2,c,3,d,4,e,f}) -Out> {2,3,4}; - - -/%mathpiper - -list := {1,-3,2,-6,-4,3}; - -Select(Lambda({i}, i > 0 ),list); - -/%/mathpiper - - /%output,preserve="false" - Result: {1,2,3} -. /%/output - -*SEE Length, Find, Count, Lambda -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/substitute/Substitute.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/substitute/Substitute.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/substitute/Substitute.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/substitute/Substitute.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="Substitute",scope="private" - -Function("Substitute",{body,predicate,change}) -[ - Substitute(body); -]; -HoldArg("Substitute",predicate); -HoldArg("Substitute",change); -UnFence("Substitute",3); -RuleBase("Substitute",{body}); -UnFence("Substitute",1); - -Rule("Substitute",1,1,Apply(predicate,{body}) = True) -[ - Apply(change,{body}); -]; -Rule("Substitute",1,2,IsFunction(body)) -[ - Apply("MapArgs",{body,"Substitute"}); -]; -Rule("Substitute",1,3,True) body; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Add.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Add.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Add.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Add.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -%mathpiper,def="Add",scope="private" - -Function() Add(val, ...); - -10 # Add({}) <-- 0; -20 # Add(values_IsList) <-- -[ - Local(i, sum); - sum:=0; - ForEach(i, values) [ sum := sum + i; ]; - sum; -]; - -// Add(1) should return 1 -30 # Add(_value) <-- value; - -%/mathpiper - - - -%mathpiper_docs,name="Add",categories="User Functions;Series" -*CMD Add --- find sum of a list of values -*STD -*CALL - Add(val1, val2, ...) - Add({list}) - -*PARMS - -{val1}, {val2} -- expressions - -{{list}} -- list of expressions to add - -*DESC - -This function adds all its arguments and returns their sum. It accepts any -number of arguments. The arguments can be also passed as a list. - -*E.G. - - In> Add(1,4,9); - Out> 14; - In> Add(1 .. 10); - Out> 55; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/asterisk_asterisk_asterisk_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/asterisk_asterisk_asterisk_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/asterisk_asterisk_asterisk_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/asterisk_asterisk_asterisk_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not defined in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Average.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Average.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Average.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Average.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not defined in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/exclamationpoint_exclamationpoint_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/exclamationpoint_exclamationpoint_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/exclamationpoint_exclamationpoint_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/exclamationpoint_exclamationpoint_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -%mathpiper,def="!!" - -/// even/odd double factorial: product of even or odd integers up to n -1# (n_IsPositiveInteger)!! _ (n<=3) <-- n; -2# (n_IsPositiveInteger)!! <-- -[ - Check(n<=65535, "Double factorial: Error: the argument " : ( ToString() Write(n) ) : " is too large, you may want to avoid exact calculation"); - Factorial'double(2+Mod(n, 2), n); -]; -// special cases -3# (_n)!! _ (n= -1 Or n=0)<-- 1; - -// the purpose of this mess "Div(a+b,2)+1+Mod(Div(a+b,2)+1-a, 2)" is to obtain the smallest integer which is >= Div(a+b,2)+1 and is also odd or even when a is odd or even; we need to add at most 1 to (Div(a+b,2)+1) -2# Factorial'double(_a, _b) _ (b-a>=6) <-- Factorial'double(a, Div(a+b,2)) * Factorial'double(Div(a+b,2)+1+Mod(Div(a+b,2)+1-a, 2), b); -3# Factorial'double(_a, _b) _ (b-a>=4) <-- a*(a+2)*(a+4); -4# Factorial'double(_a, _b) _ (b-a>=2) <-- a*(a+2); -5# Factorial'double(_a, _b) <-- a; - -/// double factorial for lists is threaded -30 # (n_IsList)!! <-- MapSingle("!!",n); - -%/mathpiper - - - -%mathpiper_docs,name="!!",categories="Operators" -*CMD ! --- factorial -*CMD !! --- factorial and related functions -*CMD *** --- factorial and related functions -*CMD Subfactorial --- factorial and related functions -*STD -*CALL - n! - n!! - a *** b - Subfactorial(m) - -*PARMS - -{m} -- integer -{n} -- integer, half-integer, or list -{a}, {b} -- numbers - -*DESC - -The factorial function {n!} calculates the factorial of integer or half-integer numbers. For -nonnegative integers, $n! := n*(n-1)*(n-2)*...*1$. The factorial of -half-integers is defined via Euler's Gamma function, $z! := Gamma(z+1)$. If $n=0$ the function returns $1$. - -The "double factorial" function {n!!} calculates $n*(n-2)*(n-4)*...$. This product terminates either with $1$ or with $2$ depending on whether $n$ is odd or even. If $n=0$ the function returns $1$. - -The "partial factorial" function {a *** b} calculates the product $a*(a+1)*...$ which is terminated at the least integer not greater than $b$. The arguments $a$ and $b$ do not have to be integers; for integer arguments, {a *** b} = $b! / (a-1)!$. This function is sometimes a lot faster than evaluating the two factorials, especially if $a$ and $b$ are close together. If $a>b$ the function returns $1$. - -The {Subfactorial} function can be interpreted as the number of permutations of {m} objects in which no object -appears in its natural place, also called "derangements." - -The factorial functions are threaded, meaning that if the argument {n} is a -list, the function will be applied to each element of the list. - -Note: For reasons of MathPiper syntax, the factorial sign {!} cannot precede other -non-letter symbols such as {+} or {*}. Therefore, you should enter a space -after {!} in expressions such as {x! +1}. - -The factorial functions terminate and print an error message if the arguments are too large (currently the limit is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision. - -*E.G. - - In> 5! - Out> 120; - In> 1 * 2 * 3 * 4 * 5 - Out> 120; - In> (1/2)! - Out> Sqrt(Pi)/2; - In> 7!!; - Out> 105; - In> 1/3 *** 10; - Out> 17041024000/59049; - In> Subfactorial(10) - Out> 1334961; - - -*SEE BinomialCoefficient, Product, Gamma, !!, ***, Subfactorial -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/exclamationpoint_operator.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/exclamationpoint_operator.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/exclamationpoint_operator.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/exclamationpoint_operator.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -%mathpiper,def="!" - -/* Factorials */ - -10 # 0! <-- 1; -10 # (Infinity)! <-- Infinity; -20 # ((n_IsPositiveInteger)!) <-- [ - Check(n <= 65535, "Factorial: Error: the argument " : ( ToString() Write(n) ) : " is too large, you may want to avoid exact calculation"); - MathFac(n); -]; - -25 # ((x_IsConstant)!)_(FloatIsInt(x) And x>0) <-- (Round(x)!); - -30 # ((x_IsNumber)!)_InNumericMode() <-- Internal'GammaNum(x+1); - -40 # (n_IsList)! <-- MapSingle("!",n); - -/* formulae for half-integer factorials: - -(+(2*z+1)/2)! = Sqrt(Pi)*(2*z+1)! / (2^(2*z+1)*z!) for z >= 0 -(-(2*z+1)/2)! = Sqrt(Pi)*(-1)^z*z!*2^(2*z) / (2*z)! for z >= 0 - -Double factorials are more efficient: - (2*n-1)!! := 1*3*...*(2*n-1) = (2*n)! / (2^n*n!) - (2*n)!! := 2*4*...*(2*n) = 2^n*n! - -*/ -/* // old version - not using double factorials -HalfIntegerFactorial(n_IsOdd) _ (n>0) <-- - Sqrt(Pi) * ( n! / ( 2^n*((n-1)/2)! ) ); -HalfIntegerFactorial(n_IsOdd) _ (n<0) <-- - Sqrt(Pi) * ( (-1)^((-n-1)/2)*2^(-n-1)*((-n-1)/2)! / (-n-1)! ); -*/ -// new version using double factorials -HalfIntegerFactorial(n_IsOdd) _ (n>0) <-- - Sqrt(Pi) * ( n!! / 2^((n+1)/2) ); -HalfIntegerFactorial(n_IsOdd) _ (n<0) <-- - Sqrt(Pi) * ( (-1)^((-n-1)/2)*2^((-n-1)/2) / (-n-2)!! ); -//HalfIntegerFactorial(n_IsOdd) _ (n= -1) <-- Sqrt(Pi); - -/* Want to also compute (2.5)! */ -40 # (n_IsRationalOrNumber)! _(Denominator(Rationalize(n))=2) <-- HalfIntegerFactorial(Numerator(Rationalize(n))); - -/// partial factorial -n1_IsRationalOrNumber *** n2_IsRationalOrNumber <-- -[ - Check(n2-n1 <= 65535, "Partial factorial: Error: the range " : ( ToString() Write(n2-n1) ) : " is too large, you may want to avoid exact calculation"); - If(n2-n1<0, - 1, - Factorial'partial(n1, n2) - ); -]; - -/// recursive routine to evaluate "partial factorial" a*(a+1)*...*b -// TODO lets document why the >>1 as used here is allowed (rounding down? What is the idea behind this algorithm?) -2# Factorial'partial(_a, _b) _ (b-a>=4) <-- Factorial'partial(a, a+((b-a)>>1)) * Factorial'partial(a+((b-a)>>1)+1, b); -3# Factorial'partial(_a, _b) _ (b-a>=3) <-- a*(a+1)*(a+2)*(a+3); -4# Factorial'partial(_a, _b) _ (b-a>=2) <-- a*(a+1)*(a+2); -5# Factorial'partial(_a, _b) _ (b-a>=1) <-- a*(a+1); -6# Factorial'partial(_a, _b) _ (b-a>=0) <-- a; - -%/mathpiper - - - -%mathpiper_docs,name="!",categories="Operators" -*CMD ! --- factorial -*CMD !! --- factorial and related functions -*CMD *** --- factorial and related functions -*CMD Subfactorial --- factorial and related functions -*STD -*CALL - n! - n!! - a *** b - Subfactorial(m) - -*PARMS - -{m} -- integer -{n} -- integer, half-integer, or list -{a}, {b} -- numbers - -*DESC - -The factorial function {n!} calculates the factorial of integer or half-integer numbers. For -nonnegative integers, $n! := n*(n-1)*(n-2)*...*1$. The factorial of -half-integers is defined via Euler's Gamma function, $z! := Gamma(z+1)$. If $n=0$ the function returns $1$. - -The "double factorial" function {n!!} calculates $n*(n-2)*(n-4)*...$. This product terminates either with $1$ or with $2$ depending on whether $n$ is odd or even. If $n=0$ the function returns $1$. - -The "partial factorial" function {a *** b} calculates the product $a*(a+1)*...$ which is terminated at the least integer not greater than $b$. The arguments $a$ and $b$ do not have to be integers; for integer arguments, {a *** b} = $b! / (a-1)!$. This function is sometimes a lot faster than evaluating the two factorials, especially if $a$ and $b$ are close together. If $a>b$ the function returns $1$. - -The {Subfactorial} function can be interpreted as the number of permutations of {m} objects in which no object -appears in its natural place, also called "derangements." - -The factorial functions are threaded, meaning that if the argument {n} is a -list, the function will be applied to each element of the list. - -Note: For reasons of MathPiper syntax, the factorial sign {!} cannot precede other -non-letter symbols such as {+} or {*}. Therefore, you should enter a space -after {!} in expressions such as {x! +1}. - -The factorial functions terminate and print an error message if the arguments are too large (currently the limit is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision. - -*E.G. - - In> 5! - Out> 120; - In> 1 * 2 * 3 * 4 * 5 - Out> 120; - In> (1/2)! - Out> Sqrt(Pi)/2; - In> 7!!; - Out> 105; - In> 1/3 *** 10; - Out> 17041024000/59049; - In> Subfactorial(10) - Out> 1334961; - - -*SEE BinomialCoefficient, Product, Gamma, !!, ***, Subfactorial -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Max.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Max.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Max.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Max.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -%mathpiper,def="Max" - -/* this is disabled because some functions seem to implicitly define Min / Max with a different number of args, and then MathPiper is confused if it hasn't loaded all the Function() declarations beforehand. -FIXME -/// Min, Max with many arguments -*/ - -Retract("Max", 1); -Retract("Max", 2); -Retract("Max", 3); - -//Function() Max(list); - -//Function() Max(l1, l2); - -Function() Max(l1, l2, l3, ...); - - - -10 # Max(_l1, _l2, l3_IsList) <-- Max(Concat({l1, l2}, l3)); -20 # Max(_l1, _l2, _l3) <-- Max({l1, l2, l3}); -/**/ - -10 # Max(l1_IsList,l2_IsList) <-- Map("Max",{l1,l2}); - - -20 # Max(l1_IsRationalOrNumber,l2_IsRationalOrNumber) <-- If(l1>l2,l1,l2); - - -30 # Max(l1_IsConstant,l2_IsConstant) <-- If(N(Eval(l1-l2))>0,l1,l2); - -// Max on empty lists -10 # Max({}) <-- Undefined; - - -20 # Max(list_IsList) <-- -[ - Local(result); - result:= list[1]; - ForEach(item,Rest(list)) result:=Max(result,item); - result; -]; - - -30 # Max(_x) <-- x; - -%/mathpiper - - - -%mathpiper_docs,name="Max",categories="User Functions;Numbers (Operations)" -*CMD Max --- maximum of a number of values -*STD -*CALL - Max(x,y) - Max(list) - -*PARMS - -{x}, {y} -- pair of values to determine the maximum of - -{list} -- list of values from which the maximum is sought - -*DESC - -This function returns the maximum value of its argument(s). If the -first calling sequence is used, the larger of "x" and "y" is -returned. If one uses the second form, the largest of the entries in -"list" is returned. In both cases, this function can only be used -with numerical values and not with symbolic arguments. - -*E.G. - - In> Max(2,3); - Out> 3; - In> Max({5,8,4}); - Out> 8; - -*SEE Min, Sum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Min.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Min.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Min.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Min.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -%mathpiper,def="Min" - -/* this is disabled because some functions seem to implicitly define Min / Max with a different number of args, -and then MathPiper is confused if it hasn't loaded all the Function() declarations beforehand. -FIXME -/// Min, Max with many arguments -*/ - -Retract("Min", 1); -Retract("Min", 2); -Retract("Min", 3); - -//Function() Min(list); - -//Function() Min(l1, l2) - -Function() Min(l1, l2, l3, ...); - -10 # Min(_l1, _l2, l3_IsList) <-- Min(Concat({l1, l2}, l3)); -20 # Min(_l1, _l2, _l3) <-- Min({l1, l2, l3}); - -10 # Min(l1_IsList,l2_IsList) <-- Map("Min",{l1,l2}); - -20 # Min(l1_IsRationalOrNumber,l2_IsRationalOrNumber) <-- If(l1 Min(2,3); - Out> 2; - In> Min({5,8,4}); - Out> 4; - -*SEE Max, Sum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/om/om.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/om/om.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/om/om.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/om/om.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -%mathpiper,def="" - -// From code.mpi.def: -// [2005-12-28 matmota]: I have to implement some better solution for the -// MathPiper -> OM mapping for these symbols. -OMDef( "Min", "minmax1","min", - { "", "", - 1,2,3,4,5,6,7,8,9,10,11,12,13,14, - "", "" }, - ($):_1 ); -OMDef( "Max", "minmax1","max", - { "", "", - 1,2,3,4,5,6,7,8,9,10,11,12,13,14, - "", "" }, - ($):_1 ); -OMDef( "!", "integer1","factorial" ); -OMDef( "BinomialCoefficient", "combinat1","binomial" ); -OMDef( "!!", mathpiper,"double_factorial" ); -OMDef( "***", mathpiper,"partial_factorial" ); -OMDef( "Add", mathpiper,"Add" ); -OMDef( "Sum", "arith1","sum", // Same argument reordering as Integrate. - { $, _2 .. _3, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }, - { $, _{2,2,1}, _{1,1}, _{1,2}, _{2,3} } - ); -OMDef( "Product", mathpiper,"Product" ); -OMDef( "Taylor", mathpiper,"Taylor" ); -OMDef( "Subfactorial", mathpiper,"Subfactorial" ); - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Product.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Product.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Product.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Product.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -%mathpiper,def="Product" - -Function("Product",{sumvar,sumfrom,sumto,sumbody}) -[ - Local(sumi,sumsum); - sumsum:=1; - For(sumi:=sumfrom,sumi<=sumto And sumsum!=0,sumi++) - [ - MacroLocal(sumvar); - MacroSet(sumvar,sumi); - sumsum:=sumsum*Eval(sumbody); - ]; - sumsum; -]; -UnFence("Product",4); -HoldArg("Product",sumvar); -HoldArg("Product",sumbody); - -Product(sumlist_IsList) <-- -[ - Local(sumi,sumsum); - sumsum:=1; - ForEach(sumi,sumlist) - [ - sumsum:=sumsum*sumi; - ]; - sumsum; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Product",categories="User Functions;Series" -*CMD Product --- product of a list of values -*STD -*CALL - Product(list) - Product(var, from, to, body) - -*PARMS - -{list} -- list of values to multiply - -{var} -- variable to iterate over - -{from} -- integer value to iterate from - -{to} -- integer value to iterate up to - -{body} -- expression to evaluate for each iteration - -*DESC - -The first form of the {Product} command simply -multiplies all the entries in "list" and returns their product. - -If the second calling sequence is used, the expression "body" is -evaluated while the variable "var" ranges over all integers from -"from" up to "to", and the product of all the results is -returned. Obviously, "to" should be greater than or equal to -"from". - -*E.G. - - In> Product({1,2,3,4}); - Out> 24; - In> Product(i, 1, 4, i); - Out> 24; - -*SEE Sum, Apply -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Subfactorial.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Subfactorial.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Subfactorial.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Subfactorial.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -%mathpiper,def="Subfactorial" - -Function("Subfactorial",{n}) -[ - n! * Sum(k,0,n,(-1)^(k)/k!); -]; - -30 # Subfactorial(n_IsList) <-- MapSingle("Subfactorial",n); - -%/mathpiper - - - -%mathpiper_docs,name="Subfactorial",categories="User Functions;Combinatorics" -*CMD ! --- factorial -*CMD !! --- factorial and related functions -*CMD *** --- factorial and related functions -*CMD Subfactorial --- factorial and related functions -*STD -*CALL - n! - n!! - a *** b - Subfactorial(m) - -*PARMS - -{m} -- integer -{n} -- integer, half-integer, or list -{a}, {b} -- numbers - -*DESC - -The factorial function {n!} calculates the factorial of integer or half-integer numbers. For -nonnegative integers, $n! := n*(n-1)*(n-2)*...*1$. The factorial of -half-integers is defined via Euler's Gamma function, $z! := Gamma(z+1)$. If $n=0$ the function returns $1$. - -The "double factorial" function {n!!} calculates $n*(n-2)*(n-4)*...$. This product terminates either with $1$ or with $2$ depending on whether $n$ is odd or even. If $n=0$ the function returns $1$. - -The "partial factorial" function {a *** b} calculates the product $a*(a+1)*...$ which is terminated at the least integer not greater than $b$. The arguments $a$ and $b$ do not have to be integers; for integer arguments, {a *** b} = $b! / (a-1)!$. This function is sometimes a lot faster than evaluating the two factorials, especially if $a$ and $b$ are close together. If $a>b$ the function returns $1$. - -The {Subfactorial} function can be interpreted as the number of permutations of {m} objects in which no object -appears in its natural place, also called "derangements." - -The factorial functions are threaded, meaning that if the argument {n} is a -list, the function will be applied to each element of the list. - -Note: For reasons of MathPiper syntax, the factorial sign {!} cannot precede other -non-letter symbols such as {+} or {*}. Therefore, you should enter a space -after {!} in expressions such as {x! +1}. - -The factorial functions terminate and print an error message if the arguments are too large (currently the limit is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision. - -*E.G. - - In> 5! - Out> 120; - In> 1 * 2 * 3 * 4 * 5 - Out> 120; - In> (1/2)! - Out> Sqrt(Pi)/2; - In> 7!!; - Out> 105; - In> 1/3 *** 10; - Out> 17041024000/59049; - In> Subfactorial(10) - Out> 1334961; - - -*SEE BinomialCoefficient, Product, Gamma, !!, ***, Subfactorial -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/SumFunc.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/SumFunc.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/SumFunc.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/SumFunc.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -%mathpiper,def="SumFunc",scope="private" - -// Attempt to Sum series - -Function() SumFunc(k,from,to,summand, sum, predicate ); -Function() SumFunc(k,from,to,summand, sum); -HoldArg(SumFunc,predicate); -HoldArg(SumFunc,sum); -HoldArg(SumFunc,summand); - -// Difference code does not work -SumFunc(_sumvar,sumfrom_IsInteger,_sumto,_sumbody,_sum) <-- -[ - // Take the given answer and create 2 rules, one for an exact match - // for sumfrom, and one which will catch sums starting at a different - // index and subtract off the difference - - `(40 # Sum(@sumvar,@sumfrom,@sumto,@sumbody ) <-- Eval(@sum) ); - `(41 # Sum(@sumvar,p_IsInteger,@sumto,@sumbody)_(p > @sumfrom) - <-- - [ - Local(sub); - (sub := Eval(UnList({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg}))); - Simplify(Eval(@sum) - sub ); - ]); -]; - -SumFunc(_sumvar,sumfrom_IsInteger,_sumto,_sumbody,_sum,_condition) <-- -[ - - `(40 # Sum(@sumvar,@sumfrom,@sumto,@sumbody)_(@condition) <-- Eval(@sum) ); - `(41 # Sum(@sumvar,p_IsInteger,@sumto,@sumbody )_(@condition And p > @sumfrom) - <-- - [ - Local(sub); - `(sub := Eval(UnList({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg}))); - Simplify(Eval(@sum) - sub ); - ]); -]; - -// Some type of canonical form is needed so that these match when -// given in a different order, like x^k/k! vs. (1/k!)*x^k -// works ! -SumFunc(_k,1,_n,_c + _d, - Eval(UnList({Sum,sumvar'arg,1,n,c})) + - Eval(UnList({Sum,sumvar'arg,1,n,d})) -); -SumFunc(_k,1,_n,_c*_expr,Eval(c*UnList({Sum,sumvar'arg,1,n,expr})), IsFreeOf(k,c) ); -SumFunc(_k,1,_n,_expr/_c,Eval(UnList({Sum,sumvar'arg,1,n,expr})/c), IsFreeOf(k,c) ); - -// this only works when the index=1 -// If the limit of the general term is not zero, then the series diverges -// We need something like IsUndefined(term), because this croaks when limit return Undefined -//SumFunc(_k,1,Infinity,_expr,Infinity,Eval(Abs(UnList({Limit,sumvar'arg,Infinity,expr})) > 0)); -SumFunc(_k,1,Infinity,1/k,Infinity); - -SumFunc(_k,1,_n,_c,c*n,IsFreeOf(k,c) ); -SumFunc(_k,1,_n,_k, n*(n+1)/2 ); -//SumFunc(_k,1,_n,_k^2, n*(n+1)*(2*n+1)/6 ); -//SumFunc(_k,1,_n,_k^3, (n*(n+1))^2 / 4 ); -SumFunc(_k,1,_n,_k^_p,(Bernoulli(p+1,n+1) - Bernoulli(p+1))/(p+1), IsInteger(p) ); -SumFunc(_k,1,_n,2*_k-1, n^2 ); -SumFunc(_k,1,_n,HarmonicNumber(_k),(n+1)*HarmonicNumber(n) - n ); - -// Geometric series! The simplest of them all ;-) -SumFunc(_k,0,_n,(r_IsFreeOf(k))^(_k), (1-r^(n+1))/(1-r) ); - -// Infinite Series -// this allows Zeta a complex argument, which is not supported yet -SumFunc(_k,1,Infinity,1/(_k^_d), Zeta(d), IsFreeOf(k,d) ); -SumFunc(_k,1,Infinity,_k^(-_d), Zeta(d), IsFreeOf(k,d) ); - -SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1)!,Sinh(x) ); -SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k+1)/(2*_k+1)!,Sin(x) ); -SumFunc(_k,0,Infinity,_x^(2*_k)/(2*_k)!,Cosh(x) ); -SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k)/(2*_k)!,Cos(x) ); -SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1),ArcTanh(x) ); -SumFunc(_k,0,Infinity,1/(_k)!,Exp(1) ); -SumFunc(_k,0,Infinity,_x^_k/(_k)!,Exp(x) ); -40 # Sum(_var,_from,Infinity,_expr)_( `(Limit(@var,Infinity)(@expr)) = Infinity) <-- Infinity; - -SumFunc(_k,1,Infinity,1/BinomialCoefficient(2*_k,_k), (2*Pi*Sqrt(3)+9)/27 ); -SumFunc(_k,1,Infinity,1/(_k*BinomialCoefficient(2*_k,_k)), (Pi*Sqrt(3))/9 ); -SumFunc(_k,1,Infinity,1/(_k^2*BinomialCoefficient(2*_k,_k)), Zeta(2)/3 ); -SumFunc(_k,1,Infinity,1/(_k^3*BinomialCoefficient(2*_k,_k)), 17*Zeta(4)/36 ); -SumFunc(_k,1,Infinity,(-1)^(_k-1)/_k, Ln(2) ); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Sum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Sum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Sum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Sum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -%mathpiper,def="Sum" - -/* Sums */ - - -RuleBase("Sum",{sumvar'arg,sumfrom'arg,sumto'arg,sumbody'arg}); - - - - -10 # Sum(_sumvar,sumfrom_IsNumber,sumto_IsNumber,_sumbody)_(sumfrom>sumto) <-- 0; - -20 # Sum(_sumvar,sumfrom_IsNumber,sumto_IsNumber,_sumbody)_(sumto Sum({1,2,3}) - Result> 6 - - In> Add(1 .. 10); - Out> 55; - - In> Sum(i, 1, 3, i^2); - Out> 14; - -*SEE Product -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Taylor2.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Taylor2.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Taylor2.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Taylor2.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,804 +0,0 @@ -%mathpiper,def="Taylor2" - -/* - * Taylor(x,a,n) y --- ENTRY POINT - * ~~~~~~~~~~~~~~~ - * The n-th degree Taylor polynomial of y around x=a - * - * This function is implemented by doing calculus on power series. For - * instance, the Taylor series of Sin(x)^2 around x=0 is computed as - * follows. First, we look up the series for Sin(x) - * Sin(x) = x - 1/6 x^3 + 1/120 x^5 - 1/5040 x^7 + ... - * and then we compute the square of this series - * Sin(x)^2 = x^2 - x^4/3 + 2/45 x^6 - 1/315 x^8 + ... - * - * An alternative method is to use the formula - * Taylor(x,a,n) y = \sum_{k=0}^n 1/k! a_k x^k, - * where a_k is the k-th order derivative of y with respect to x, - * evaluated at x=a. In fact, the old implementation of "Taylor", which - * is retained in obsolete.mpi, uses this method. However, we found out - * that the expressions for the derivatives often grow very large, which - * makes the computation too slow. - * - * The power series are implemented as lazy power series, which means - * that the coefficients are computed on demand. Lazy power series are - * encapsulated in expressions of the form - * Taylor'LPS(order, coeffs, var, expr). - * This represent the power series of "expr", seen as a function of - * "var". "coeffs" is list of coefficients that have been computed thus - * far. The integer "order" is the order of the first coefficient. - * - * For instance, the expression - * Taylor'LPS(1, {1,0,-1/6,0}, x, Sin(x)) - * contains the power series of Sin(x), viewed as a function of x, where - * the four coefficients corresponding to x, x^2, x^3, and x^4 have been - * computed. One can view this expression as x - 1/6 x^3 + O(x^5). - * - * "coeffs" is the empty list in the following special cases: - * 1) order = Infinity represents the zero power series - * 2) order = Undefined represents a power series of which no - * coefficients have yet been computed. - * 3) order = n represents a power series of order at least n, - * of which no coefficients have yet been computed. - * - * "expr" may contain subexpressions of the form - * Taylor'LPS'Add(lps1, lps2) = lps1)x) + lps2(x) - * Taylor'LPS'ScalarMult(a, lps) = a*lps(x) (a is scalar) - * Taylor'LPS'Multiply(lps1, lps2) = lps1(x) * lps2(x) - * Taylor'LPS'Inverse(lps) = 1/lps(x) - * Taylor'LPS'Power(lps, n) = lps(x)^n (n is natural number) - * Taylor'LPS'Compose(lps1, lps2) = lps1(lps2(x)) - * - * A well-formed LPS is an expression of the form - * Taylor'LPS(order, coeffs, var, expr) - * satisfying the following conditions: - * 1) order is an integer, Infinity, or Undefined; - * 2) coeffs is a list; - * 3) if order is Infinity or Undefined, then coeffs is {}; - * 4) if order is an integer, then coeffs is empty - * or its first entry is nonzero; - * 5) var does not appear in coeffs; - * 6) expr is normalized with Taylor'LPS'NormalizeExpr. - * - */ - -/* For the moment, the function is called Taylor2. */ - -/* HELP: Is this the correct mechanism to signal incorrect input? */ -/*COMMENT FROM AYAL: Formally, I would do it the other way around, although this is more efficient. This - scheme says: all following rules hold if n>=0. Ideally you'd have a rule "this transformation rule holds - if n>=0". But then you would end up checking that n>=0 for each transformation rule, making things a little - bit slower (but more correct, more elegant). - */ -10 # (Taylor2(_x, _a, _n) _y) - _ (Not(IsPositiveInteger(n) Or IsZero(n))) - <-- Check(False, - "Third argument to Taylor should be a nonnegative integer"); - -20 # (Taylor2(_x, 0, _n) _y) <-- -[ - Local(res); - res := Taylor'LPS'PowerSeries(Taylor'LPS'Construct(x, y), n, x); - If (ClearError("singularity"), - Echo(y, "has a singularity at", x, "= 0.")); - If (ClearError("dunno"), - Echo("Cannot determine power series of", y)); - res; -]; - -30 # (Taylor2(_x, _a, _n) _y) - <-- Subst(x,x-a) Taylor2(x,0,n) Subst(x,x+a) y; - -/********************************************************************** - * - * Parameters - * ~~~~~~~~~~ - * The number of coefficients to be computed before concluding that a - * given power series is zero */ - - - -/*TODO COMMENT FROM AYAL: This parameter, 15, seems to be a bit arbitrary. This implies that there is an input - with more than 15 zeroes, and then a non-zero coefficient, that this would fail on. Correct? Is there not - a more accurate estimation of this parameter? - */ -Taylor'LPS'Param1() := 15; - -/********************************************************************** - * - * Taylor'LPS'Construct(var, expr) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * construct a LPS - * PRE: var is a name - * POST: returns a well-formed LPS - */ - -10 # Taylor'LPS'Construct(_var, _expr) - <-- Taylor'LPS(Undefined, {}, var, - Taylor'LPS'NormalizeExpr(var, expr)); - -/********************************************************************** - * - * Taylor'LPS'Coeffs(lps, n1, n2) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * List of coefficients of order n1 up to n2 - * PRE: lps is a well-formed LPS, n1 in Z, n2 in Z, n2 >= n1 - * POST: returns list of length n2-n1+1, - * or raises "dunno", "div-by-zero", or "maybe-div-by-zero" - * lps may be changed, but it's still a well-formed LPS - */ - -Taylor'LPS'Coeffs(_lps, _n1, _n2) <-- -[ - Local(res, finished, order, j, k, n, tmp, c1, c2); - finished := False; - - /* Case 1: Zero power series */ - - If (lps[1] = Infinity, - [ - res := FillList(0, n2-n1+1); - finished := True; - ]); - - /* Case 2: Coefficients are already computed */ - - If (Not finished And lps[1] != Undefined And n2 < lps[1]+Length(lps[2]), - [ - If (n1 >= lps[1], - res := Take(lps[2], {n1-lps[1]+1, n2-lps[1]+1}), - If (n2 >= lps[1], - res := Concat(FillList(0, lps[1]-n1), - Take(lps[2], n2-lps[1]+1)), - res := FillList(0, n2-n1+1))); - finished := True; - ]); - - /* Case 3: We need to compute the coefficients */ - - If (Not finished, - [ - /* Subcase 3a: Expression is recognized by Taylor'LPS'CompOrder */ - - order := Taylor'LPS'CompOrder(lps[3], lps[4]); - If (Not ClearError("dunno"), - [ - If (lps[1] = Undefined, - [ - lps[1] := order; - If (order <= n2, - [ - lps[2] := Table(Taylor'LPS'CompCoeff(lps[3], lps[4], n), - n, order, n2, 1); - ]); - ],[ - tmp := Table(Taylor'LPS'CompCoeff(lps[3], lps[4], n), - n, lps[1]+Length(lps[2]), n2, 1); - lps[2] := Concat(lps[2], tmp); - ]); - finished := True; - ]); - - /* Subcase 3b: Addition */ - - If (Not finished And lps[4][0] = Taylor'LPS'Add, - [ - lps[1] := Min(Taylor'LPS'GetOrder(lps[4][1])[1], - Taylor'LPS'GetOrder(lps[4][2])[1], n2); - If (IsError("dunno"), - [ - ClearError("dunno"); - ClearError("dunno"); - ],[ - If (lps[1] <= n2, - [ - c1 := Taylor'LPS'Coeffs(lps[4][1], lps[1] + Length(lps[2]), n2); - c2 := Taylor'LPS'Coeffs(lps[4][2], lps[1] + Length(lps[2]), n2); - lps[2] := Concat(lps[2], c1 + c2); - ]); - finished := True; - ]); - ]); - - /* Subcase 3c: Scalar multiplication */ - - If (Not finished And lps[4][0] = Taylor'LPS'ScalarMult, - [ - lps[1] := Min(Taylor'LPS'GetOrder(lps[4][2])[1], n2); - If (Not ClearError("dunno"), - [ - If (lps[1] <= n2, - [ - tmp := Taylor'LPS'Coeffs(lps[4][2], - lps[1] + Length(lps[2]), n2); - tmp := lps[4][1] * tmp; - lps[2] := Concat(lps[2], tmp); - ]); - finished := True; - ]); - ]); - - /* Subcase 3d: Multiplication */ - - If (Not finished And lps[4][0] = Taylor'LPS'Multiply, - [ - lps[1] := Taylor'LPS'GetOrder(lps[4][1])[1] - + Taylor'LPS'GetOrder(lps[4][2])[1]; - If (IsError("dunno"), - [ - ClearError("dunno"); - ClearError("dunno"); - ],[ - If (lps[1] <= n2, - [ - c1 := Taylor'LPS'Coeffs(lps[4][1], lps[4][1][1], - n2 - lps[4][2][1]); - c2 := Taylor'LPS'Coeffs(lps[4][2], lps[4][2][1], - n2 - lps[4][1][1]); - tmp := lps[2]; - ForEach(k, (Length(lps[2])+1) .. Length(c1)) - tmp := Append(tmp, Sum(j, 1, k, c1[j]*c2[k+1-j])); - lps[2] := tmp; - ]); - finished := True; - ]); - ]); - - /* Subcase 3e: Inversion */ - - If (Not finished And lps[4][0] = Taylor'LPS'Inverse, - [ - If (lps[4][1][1] = Infinity, - [ - Assert("div-by-zero") False; - finished := True; - ]); - If (Not finished And lps[2] = {}, - [ - order := Taylor'LPS'GetOrder(lps[4][1])[1]; - n := order; - c1 := Taylor'LPS'Coeffs(lps[4][1], n, n)[1]; - While (c1 = 0 And n < order + Taylor'LPS'Param1()) - [ - n := n + 1; - c1 := Taylor'LPS'Coeffs(lps[4][1], n, n)[1]; - ]; - If (c1 = 0, - [ - Assert("maybe-div-by-zero") False; - finished := True; - ]); - ]); - If (Not finished, - [ - lps[1] := -lps[4][1][1]; - c1 := Taylor'LPS'Coeffs(lps[4][1], lps[4][1][1], - lps[4][1][1]+n2-lps[1]); - tmp := lps[2]; - If (tmp = {}, tmp := {1/c1[1]}); - If (Length(c1)>1, - [ - ForEach(k, (Length(tmp)+1) .. Length(c1)) - [ - n := -Sum(j, 1, k-1, c1[k+1-j]*tmp[j]) / c1[1]; - tmp := Append(tmp, n); - ]; - ]); - lps[2] := tmp; - finished := True; - ]); - ]); - - /* Subcase 3f: Composition */ - - If (Not finished And lps[4][0] = Taylor'LPS'Compose, - [ - j := Taylor'LPS'GetOrder(lps[4][1])[1]; - Check(j >= 0, "Expansion of f(g(x)) where f has a" - : "singularity is not implemented"); - k := Taylor'LPS'GetOrder(lps[4][2])[1]; - c1 := {j, Taylor'LPS'Coeffs(lps[4][1], j, n2)}; - c2 := {k, Taylor'LPS'Coeffs(lps[4][2], k, n2)}; - c1 := Taylor'TPS'Compose(c1, c2); - lps[1] := c1[1]; - lps[2] := c1[2]; - finished := True; - ]); - - /* Case 3: The end */ - - If (finished, - [ - /* normalization: remove initial zeros from lps[2] */ - - While (lps[2] != {} And lps[2][1] = 0) - [ - lps[1] := lps[1] + 1; - lps[2] := Rest(lps[2]); - ]; - - /* get result */ - - If (Not IsError("dunno") And Not IsError("div-by-zero") - And Not IsError("maybe-div-by-zero"), - [ - If (lps[1] <= n1, - res := Take(lps[2], {n1-lps[1]+1, n2-lps[1]+1}), - If (lps[1] <= n2, - res := Concat(FillList(0, lps[1]-n1), lps[2]), - res := FillList(0, n2-n1+1))); - ]); - ],[ - Assert("dunno") False; - res := False; - ]); - ]); - - /* Return res */ - - res; -]; - - -/********************************************************************** - * - * Truncated power series - * ~~~~~~~~~~~~~~~~~~~~~~ - * Here is the start of an implementation of truncated power series. - * This should be cleaned up. - * - * {n, {a0,a1,a2,a3,...}} represents - * a0 x^n + a1 x^(n+1) + a2 x^(n+2) + a3 x^(n+3) + ... - * - * The function Taylor'TPS'Add(tps1, tps2) adds two of such beasts, - * and returns the sum in the same truncated power series form. - * Similar for the other functions. - */ - -10 # Taylor'TPS'GetCoeff({_n,_c}, _k) _ (k < n) <-- 0; -10 # Taylor'TPS'GetCoeff({_n,_c}, _k) _ (k >= n+Length(c)) <-- Undefined; -20 # Taylor'TPS'GetCoeff({_n,_c}, _k) <-- c[k-n+1]; - - -10 # Taylor'TPS'Add({_n1,_c1}, {_n2,_c2}) <-- -[ - Local(n, len, c1b, c2b); - n := Min(n1,n2); - len := Min(n1+Length(c1), n2+Length(c2)) - n; - c1b := Take(Concat(FillList(0, n1-n), c1), len); - c2b := Take(Concat(FillList(0, n2-n), c2), len); - {n, c1b+c2b}; -]; - -10 # Taylor'TPS'ScalarMult(_a, {_n2,_c2}) <-- {n2, a*c2}; - -10 # Taylor'TPS'Multiply({_n1,_c1}, {_n2,_c2}) <-- -[ - Local(j,k,c); - c := {}; - For (k:=1, k<=Min(Length(c1), Length(c2)), k++) - [ - c := c : Sum(j, 1, k, c1[j]*c2[k+1-j]); - ]; - {n1+n2, c}; -]; - -10 # Taylor'TPS'Compose({_n1,_c1}, {_n2,_c2}) <-- -[ - Local(res, tps, tps2, k, n); - n := Min(n1+Length(c1)-1, n2+Length(c2)-1); - tps := {0, 1 : FillList(0, n)}; // tps = {n2,c2} ^ k - res := Taylor'TPS'ScalarMult(Taylor'TPS'GetCoeff({n1,c1}, 0), tps); - For (k:=1, k<=n, k++) - [ - tps := Taylor'TPS'Multiply(tps, {n2,c2}); - tps2 := Taylor'TPS'ScalarMult(Taylor'TPS'GetCoeff({n1,c1}, k), tps); - res := Taylor'TPS'Add(res, tps2); - ]; - res; -]; - - - -/********************************************************************** - * - * Taylor'LPS'NormalizeExpr(var, expr) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Return expr, with "+" replaced by Taylor'LPS'Add, etc. - * PRE: var is a name - */ - -5 # Taylor'LPS'NormalizeExpr(_var, _e1) - _ [Taylor'LPS'CompOrder(var,e1); Not ClearError("dunno");] - <-- e1; - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 + _e2) - <-- Taylor'LPS'Add(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e2)); - -10 # Taylor'LPS'NormalizeExpr(_var, - _e1) - <-- Taylor'LPS'ScalarMult(-1, Taylor'LPS'Construct(var, e1)); - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 - _e2) - <-- (Taylor'LPS'Add(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e3)) - Where e3 == Taylor'LPS'ScalarMult(-1, Taylor'LPS'Construct(var, e2))); - -10 # Taylor'LPS'NormalizeExpr(_var, e1_IsFreeOf(var) * _e2) - <-- Taylor'LPS'ScalarMult(e1, Taylor'LPS'Construct(var, e2)); - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 * e2_IsFreeOf(var)) - <-- Taylor'LPS'ScalarMult(e2, Taylor'LPS'Construct(var, e1)); - -20 # Taylor'LPS'NormalizeExpr(_var, _e1 * _e2) - <-- Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e2)); - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 / e2_IsFreeOf(var)) - <-- Taylor'LPS'ScalarMult(1/e2, Taylor'LPS'Construct(var, e1)); - -20 # Taylor'LPS'NormalizeExpr(_var, 1 / _e1) - <-- Taylor'LPS'Inverse(Taylor'LPS'Construct(var, e1)); - -30 # Taylor'LPS'NormalizeExpr(_var, _e1 / _e2) - <-- (Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e3)) - Where e3 == Taylor'LPS'Inverse(Taylor'LPS'Construct(var, e2))); - -/* Implement powers as repeated multiplication, - * which is seriously inefficient. - */ -10 # Taylor'LPS'NormalizeExpr(_var, _e1 ^ (n_IsPositiveInteger)) - _ (e1 != var) - <-- Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e1^(n-1))); - -10 # Taylor'LPS'NormalizeExpr(_var, Tan(_x)) - <-- (Taylor'LPS'Multiply(Taylor'LPS'Construct(var, Sin(x)), - Taylor'LPS'Construct(var, e3)) - Where e3 == Taylor'LPS'Inverse(Taylor'LPS'Construct(var, Cos(x)))); - -LocalSymbols(res) -[ -50 # Taylor'LPS'NormalizeExpr(_var, _e1) -_[ - Local(c, lps1, lps2, lps3, success); - success := True; - If (IsAtom(e1), success := False); - If (success And Length(e1) != 1, success := False); - If (success And IsAtom(e1[1]), success := False); - If (success And CanBeUni(var, e1[1]) And Degree(e1[1], var) = 1, - [ - success := False; - ]); - If (success, - [ - lps2 := Taylor'LPS'Construct(var, e1[1]); - c := Taylor'LPS'Coeffs(lps2, 0, 0)[1]; - If (IsError(), - [ - ClearErrors(); - success := False; - ]); - If (success And Taylor'LPS'GetOrder(lps2)[1] < 0, - [ - success := False; - ],[ - If (c = 0, - [ - lps1 := Taylor'LPS'Construct(var, Apply(e1[0], {var})); - res := Taylor'LPS'Compose(lps1, lps2); - ],[ - lps1 := Taylor'LPS'Construct(var, Apply(e1[0], {var+c})); - lps3 := Taylor'LPS'Construct(var, -c); - lps2 := Taylor'LPS'Construct(var, Taylor'LPS'Add(lps2, lps3)); - res := Taylor'LPS'Compose(lps1, lps2); - ]); - ]); - ]); - success; - ] <-- res; -]; - -60000 # Taylor'LPS'NormalizeExpr(_var, _e1) <-- e1; - - -/********************************************************************** - * - * Taylor'LPS'CompOrder(var, expr) --- HOOK - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Compute order of expr as a power series in var - * PRE: var is a name - * POST: returns an integer, or raises "dunno" - * - * Taylor'LPS'CompCoeff(var, expr, n) --- HOOK - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Compute n-th coefficient of expr as a power series in var - * PRE: var is a name, n is an integer, - * Taylor'LPS'CompOrder(var, expr) does not raise "dunno" - * POST: returns an expression not containing var - */ - -5 # Taylor'LPS'CompCoeff(_var, _expr, _n) - _ (n < Taylor'LPS'CompOrder(var, expr)) - <-- 0; - -/* Zero */ - -10 # Taylor'LPS'CompOrder(_x, 0) <-- Infinity; - -/* Constant */ - -20 # Taylor'LPS'CompOrder(_x, e_IsFreeOf(x)) <-- 0; -20 # Taylor'LPS'CompCoeff(_x, e_IsFreeOf(x), 0) <-- e; -21 # Taylor'LPS'CompCoeff(_x, e_IsFreeOf(x), _n) <-- 0; - -/* Identity */ - -30 # Taylor'LPS'CompOrder(_x, _x) <-- 1; -30 # Taylor'LPS'CompCoeff(_x, _x, 1) <-- 1; -31 # Taylor'LPS'CompCoeff(_x, _x, _n) <-- 0; - -/* Powers */ - -40 # Taylor'LPS'CompOrder(_x, _x^(k_IsPositiveInteger)) <-- k; -40 # Taylor'LPS'CompCoeff(_x, _x^(k_IsPositiveInteger), _k) <-- 1; -41 # Taylor'LPS'CompCoeff(_x, _x^(k_IsPositiveInteger), _n) <-- 0; - -/* Sqrt */ - -50 # Taylor'LPS'CompOrder(_x, Sqrt(_y)) - _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) - <-- 0; - -50 # Taylor'LPS'CompCoeff(_x, Sqrt(_y), 0) - _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) - <-- Sqrt(Coef(y,x,0)); - -51 # Taylor'LPS'CompCoeff(_x, Sqrt(_y), _n) - _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) <-- -[ - Local(j); - Coef(y,x,0)^(1/2-n) * Product(j,0,n-1,1/2-j) * Coef(y,x,1)^n/n!; -]; - -/* Exp */ - -60 # Taylor'LPS'CompOrder(_x, Exp(_x)) <-- 0; -60 # Taylor'LPS'CompCoeff(_x, Exp(_x), _n) <-- 1/n!; - -70 # Taylor'LPS'CompOrder(_x, Exp(_y))_(CanBeUni(x,y) And Degree(y,x) = 1) - <-- 0; - -70 # Taylor'LPS'CompCoeff(_x, Exp(_y), _n)_(CanBeUni(x,y) And Degree(y,x) = 1) - <-- Exp(Coef(y,x,0)) * Coef(y,x,1)^n / n!; - -/* Ln */ - -80 # Taylor'LPS'CompOrder(_x, Ln(_x+1)) <-- 1; -80 # Taylor'LPS'CompCoeff(_x, Ln(_x+1), _n) <-- (-1)^(n+1)/n; - -/* Sin */ - -90 # Taylor'LPS'CompOrder(_x, Sin(_x)) <-- 1; -90 # Taylor'LPS'CompCoeff(_x, Sin(_x), n_IsOdd) <-- (-1)^((n-1)/2) / n!; -90 # Taylor'LPS'CompCoeff(_x, Sin(_x), n_IsEven) <-- 0; - -/* Cos */ - -100 # Taylor'LPS'CompOrder(_x, Cos(_x)) <-- 0; -100 # Taylor'LPS'CompCoeff(_x, Cos(_x), n_IsOdd) <-- 0; -100 # Taylor'LPS'CompCoeff(_x, Cos(_x), n_IsEven) <-- (-1)^(n/2) / n!; - -/* Inverse (not needed but speeds things up) */ - -110 # Taylor'LPS'CompOrder(_x, 1/_x) <-- -1; -110 # Taylor'LPS'CompCoeff(_x, 1/_x, -1) <-- 1; -111 # Taylor'LPS'CompCoeff(_x, 1/_x, _n) <-- 0; - - -/*COMMENT FROM AYAL: Jitse, what do you think, fall-through defaulting to calculating the coefficient - the hard way? Worst-case, if people define a taylor series in this module it is faster, otherwise it uses - the old scheme that does explicit derivatives, which is slower, but still better than not returning a result - at all? With this change the new taylor code is at least as good as the old code? - - The ugly part is obvious: instead of having a rule here that says "I work for the following input" I had to - find out empirically what the "exclude list" is, eg. the input it will not work on. This because the system - as it works currently yields "dunno", at which moment some other routine picks up. - - I think we can refactor this. - */ - - - - -Taylor'LPS'AcceptDeriv(_expr) <-- - (Contains({"ArcTan"},Type(expr))); -/* - ( Type(Deriv(x)(expr)) != "Deriv" - And Not Contains({ - "/","+","*","^","-","Sin","Cos","Sqrt","Ln","Exp","Tan" - },Type(expr))); -*/ - -200 # Taylor'LPS'CompOrder(_x, (_expr))_(Taylor'LPS'AcceptDeriv(expr)) - <-- - [ -//Echo("CompOrder for ",expr); -// 0; //generic case, assume zeroeth coefficient is non-zero. - Local(n); - n:=0; - While ((Limit(x,0)expr) = 0 And n=0 ) <-- - [ - // This routine is written out for debugging purposes - Local(result); - result:=(Limit(x,0)(Deriv(x,n)expr))/(n!); -Echo(expr," ",n," ",result); - result; - ]; - -/* Default */ - -60000 # Taylor'LPS'CompOrder(_var, _expr) - <-- Assert("dunno") False; - -60000 # Taylor'LPS'CompCoeff(_var, _expr, _n) - <-- Check(False, "Taylor'LPS'CompCoeff'FallThrough" - : ToString() Write({var,expr,n})); - -/********************************************************************** - * - * Taylor'LPS'GetOrder(lps) - * ~~~~~~~~~~~~~~~~~~~~~~~~ - * Returns a pair {n,flag}. If flag is True, then n is the order of - * the LPS. If flag is False, then n is a lower bound on the order. - * PRE: lps is a well-formed LPS - * POST: returns a pair {n,flag}, where n is an integer or Infinity, - * and flag is True or False, or raises "dunno"; - * may update lps. - */ - -20 # Taylor'LPS'GetOrder(Taylor'LPS(_order, _coeffs, _var, _expr)) - _ (order != Undefined) - <-- {order, coeffs != {}}; - -40 # Taylor'LPS'GetOrder(_lps) <-- -[ - Local(res, computed, exact, res1, res2); - computed := False; - - res := Taylor'LPS'CompOrder(lps[3], lps[4]); - If (Not ClearError("dunno"), - [ - res := {res, True}; - computed := True; - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Add, - [ - res1 := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - res2 := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), - [ - res := {Min(res1[1],res2[1]), False}; - /* flag = False, since terms may cancel */ - computed := True; - ]); - ]); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'ScalarMult, - [ - res := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), computed := True); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Multiply, - [ - res1 := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - res2 := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), - [ - res := {res1[1]+res2[1], res1[1] And res2[1]}; - computed := True; - ]); - ]); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Inverse, - [ - res := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - If (res[1] = Infinity, - [ - res[1] = Undefined; - Assert("div-by-zero") False; - computed := True; - ]); - If (Not computed And res[2] = False, - [ - Local(c, n); - n := res[1]; - c := Taylor'LPS'Coeffs(lps[4][1], res[1], res[1])[1]; - While (c = 0 And res[1] < n + Taylor'LPS'Param1()) - [ - res[1] := res[1] + 1; - c := Taylor'LPS'Coeffs(lps[4][1], res[1], res[1])[1]; - ]; - If (c = 0, - [ - res[1] := Undefined; - Assert("maybe-div-by-zero") False; - computed := True; - ]); - ]); - If (Not computed, - [ - res := {-res[1], True}; - computed := True; - ]); - ]); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Compose, - [ - res1 := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - res2 := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), - [ - res := {res1[1]*res2[1], res1[1] And res2[1]}; - computed := True; - ]); - ]); - ]); - - If (computed, lps[1] := res[1]); - Assert("dunno") computed; - res; -]; - -/********************************************************************** - * - * Taylor'LPS'PowerSeries(lps, n, var) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Convert the LPS in a power series in var up to order n - * PRE: lps is a well-formed LPS, n is a natural number - * POST: returns an expression, or raises "singularity" or "dunno" - */ - -10 # Taylor'LPS'PowerSeries(_lps, _n, _var) <-- -[ - Local(ord, k, coeffs); - coeffs := Taylor'LPS'Coeffs(lps, 0, n); - If (IsError("dunno"), - [ - False; - ],[ - If (lps[1] < 0, - [ - Assert("singularity") False; - Undefined; - ],[ - Sum(k, 0, n, coeffs[k+1]*var^k); - ]); - ]); -]; - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Taylor3.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Taylor3.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Taylor3.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Taylor3.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,198 +0,0 @@ -%mathpiper,def="Taylor3" - - - -/* Taylor3, implementation of Taylor series expansion by doing calculation on series directly. - */ - -Defun("Taylor3'MultiplyCoefs",{coefs1,coefs2,degree}) -[ - Local(result,i,j,jset,ilimit,jlimit); - Set(result, ArrayCreate(AddN(degree,1),0)); - Set(i,1); - Set(ilimit,AddN(degree,2)); - While (Not Equals(i,ilimit)) - [ -//Echo(coefs1,coefs2); - Set(j,1); - Set(jlimit,AddN(degree,SubtractN(3,i))); - While (Not Equals(j,jlimit)) - [ - Set(jset,AddN(i,SubtractN(j,1))); -//Echo("index = ",i+j-1); - ArraySet(result,jset,ArrayGet(result,jset) + ArrayGet(coefs1,i)*ArrayGet(coefs2,j)); - Set(j,AddN(j,1)); - ]; - Set(i,AddN(i,1)); - ]; - result; -]; - - -Bodied("Taylor3'TaylorCoefs",0); -10 # (Taylor3'TaylorCoefs(_var,_degree)(_var)) <-- -[ - Local(result); - Set(result,ArrayCreate(degree+1,0)); - ArraySet(result,2, 1); - result; -//Echo("degree = ",degree); -// BaseVector(2,degree+1); -]; -20 # (Taylor3'TaylorCoefs(_var,_degree)(_atom))_(IsFreeOf(var,atom)) - <-- - [ - Local(result); - Set(result,ArrayCreate(degree+1,0)); - ArraySet(result,1, atom); - result; -// atom*BaseVector(1,degree+1); - ]; -30 # (Taylor3'TaylorCoefs(_var,_degree)(_X + _Y)) - <-- - [ - Local(result,add,i); - Set(result,Taylor3'TaylorCoefs(var,degree)(X)); - Set(add, Taylor3'TaylorCoefs(var,degree)(Y)); - For(i:=1,i<=degree+1,i++) - [ - ArraySet(result,i,ArrayGet(result,i)+ArrayGet(add,i)); - ]; - result; - ]; - -30 # (Taylor3'TaylorCoefs(_var,_degree)(_X - _Y)) - <-- - [ - Local(result,add,i); - Set(result,Taylor3'TaylorCoefs(var,degree)(X)); - Set(add, Taylor3'TaylorCoefs(var,degree)(Y)); - For(i:=1,i<=degree+1,i++) - [ - ArraySet(result,i,ArrayGet(result,i)-ArrayGet(add,i)); - ]; - result; - ]; - -30 # (Taylor3'TaylorCoefs(_var,_degree)( - _Y)) - <-- - [ - Local(result,add,i); - Set(result,Taylor3'TaylorCoefs(var,degree)(Y)); - For(i:=1,i<=degree+1,i++) - [ - ArraySet(result,i,-ArrayGet(result,i)); - ]; - result; - ]; - -30 # (Taylor3'TaylorCoefs(_var,_degree)(_X * _Y)) - <-- Taylor3'MultiplyCoefs( - Taylor3'TaylorCoefs(var,degree)(X), - Taylor3'TaylorCoefs(var,degree)(Y), - degree); - -30 # (Taylor3'TaylorCoefs(_var,_degree)((_X) ^ N_IsPositiveInteger)) - <-- -[ - Local(result,factor); - factor:=Taylor3'TaylorCoefs(var,degree)(X); - result:=ArrayCreate(degree+1,0); - result[1] := 1; - //TODO@@@ optimize - While(N>0) - [ - result:=Taylor3'MultiplyCoefs(result,factor,degree); - N--; - ]; - result; -]; - -60 # Taylor3'UniFunction("Exp") <-- True; -60 # Taylor3'CompCoeff("Exp", _n) <-- 1/n!; - -80 # Taylor3'UniFunction("Ln") <-- False; // False because this rule is only applicable for Ln(x+1) -80 # Taylor3'CompCoeff("Ln", 0) <-- 0; -81 # Taylor3'CompCoeff("Ln", _n) <-- (-1)^(n+1)/n; - -90 # Taylor3'UniFunction("Sin") <-- True; -90 # Taylor3'CompCoeff("Sin", n_IsOdd) <-- (-1)^((n-1)/2) / n!; -90 # Taylor3'CompCoeff("Sin", n_IsEven) <-- 0; - -100 # Taylor3'UniFunction("Cos") <-- True; -100 # Taylor3'CompCoeff("Cos", n_IsOdd) <-- 0; -100 # Taylor3'CompCoeff("Cos", n_IsEven) <-- (-1)^(n/2) / n!; - - -210 # Taylor3'UniFunction(_any)_ - ( - [ - Local(result); - result:= Deriv(var)UnList({Atom(any),var}); - Type(result) != "Deriv"; - ] - ) <-- - [ - True; - ]; -210 # Taylor3'CompCoeff(_any, n_IsInteger) - <-- - [ - Limit(var,0)(Deriv(var,n)(UnList({Atom(any),var}))/n!); - ]; - - - -60000 # Taylor3'UniFunction(_any) <-- False; - - -Taylor3'FuncCoefs(_fname,_degree) <-- -[ - Local(sins,i); - Set(sins, ArrayCreate(degree+1,0)); - For (i:=0,i<=degree,Set(i,i+1)) - [ - ArraySet(sins,i+1, Taylor3'CompCoeff(fname,i)); - ]; - sins; -]; - - -100 # (Taylor3'TaylorCoefs(_var,_degree)(Ln(_f)))_(Simplify(f-1) = var) <-- Taylor3'FuncCoefs("Ln",degree); - - -110 # (Taylor3'TaylorCoefs(_var,_degree)(f_IsFunction))_(NrArgs(f) = 1 And (Taylor3'UniFunction(Type(f)))) <-- -[ - Local(sins,i,j,result,xx,expr,sinfact); - expr := f[1]; - sins:=Taylor3'FuncCoefs(Type(f),degree); -//Echo("sins = ",sins); - expr:=Taylor3'TaylorCoefs(var,degree)expr; - result:=ArrayCreate(degree+1,0); - ArraySet(result,1, ArrayGet(sins,1)); - xx:=expr; -//Echo("8...",sins,expr); - For (i:=2,i<=degree+1,i++) - [ - Set(sinfact,sins[i]); -//Echo("8.1..",i," ",j); - For (j:=1,j<=degree+1,j++) - [ - ArraySet(result,j,ArrayGet(result,j) + (ArrayGet(xx,j) * sinfact)); - ]; -//Echo("8.2.."); - Set(xx,Taylor3'MultiplyCoefs(xx,expr,degree)); -//Echo("8.3.."); - ]; - result; -]; - - -(Taylor3(_var,_degree)(_expr)) <-- Add((Taylor3'TaylorCoefs(var,degree)(expr))[1 .. degree+1]*var^(0 .. degree)); -10 # (Taylor3(_x, 0, _n) _y) <-- Taylor3(x,n) y; -20 # (Taylor3(_x, _a, _n) _y) <-- Subst(x,x-a) Taylor3(x,n) Subst(x,x+a) y; - - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Taylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Taylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/sums/Taylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/sums/Taylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -%mathpiper,def="Taylor" - -/*COMMENT FROM AYAL: Jitse, I added some code to make Taylor2 work in the most general case too I believe. - Could you check to see if you agree with my changes? If that is correct, perhaps we can start calling Taylor2 - by default in stead of Taylor1. - */ -Function("Taylor",{taylorvariable,taylorat,taylororder,taylorfunction}) - Taylor1(taylorvariable,taylorat,taylororder)(taylorfunction); - -/*COMMENT FROM AYAL: this is the old slow but working version of Taylor series expansion. Jitse wrote a - * faster version which resides in taylor.mpi, and uses lazy power series. This slow but correct version is still - * useful for tests (the old and the new routine should yield identical results). - */ -Function("Taylor1",{taylorvariable,taylorat,taylororder,taylorfunction}) -[ - Local(n,result,dif,polf); - [ - MacroLocal(taylorvariable); - [ - MacroLocal(taylorvariable); - MacroSet(taylorvariable, taylorat); - result:=Eval(taylorfunction); - ]; - If(result=Undefined, - [ - result:=Apply("Limit",{taylorvariable,taylorat,taylorfunction}); - ]); -/* - MacroSet(taylorvariable,taylorat); - result:=Eval(taylorfunction); -*/ - ]; - dif:=taylorfunction; - polf:=(taylorvariable-taylorat); - For(n:=1,result != Undefined And n<=taylororder,n++) - [ - dif:= Deriv(taylorvariable) dif; - Local(term); - MacroLocal(taylorvariable); - [ - MacroLocal(taylorvariable); - MacroSet(taylorvariable, taylorat); - term:=Eval(dif); - ]; - If(term=Undefined, - [ - term:=Apply("Limit",{taylorvariable,taylorat,dif}); - ]); - - result:=result+(term/(n!))*(polf^n); -/* result:=result+Apply("Limit",{taylorvariable,taylorat,(dif/(n!))})*(polf^n); */ -/* - MacroSet(taylorvariable,taylorat); - result:=result+(Eval(dif)/(n!))*(polf^n); -*/ - ]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Taylor",categories="User Functions;Series" -*CMD Taylor --- univariate Taylor series expansion -*STD -*CALL - Taylor(var, at, order) expr - -*PARMS - -{var} -- variable - -{at} -- point to get Taylor series around - -{order} -- order of approximation - -{expr} -- expression to get Taylor series for - -*DESC - -This function returns the Taylor series expansion of the expression -"expr" with respect to the variable "var" around "at" up to order -"order". This is a polynomial which agrees with "expr" at the -point "var = at", and furthermore the first "order" derivatives of -the polynomial at this point agree with "expr". Taylor expansions -around removable singularities are correctly handled by taking the -limit as "var" approaches "at". - -*E.G. - - In> PrettyForm(Taylor(x,0,9) Sin(x)) - - 3 5 7 9 - x x x x - x - -- + --- - ---- + ------ - 6 120 5040 362880 - - Out> True; - -*SEE D, InverseTaylor, ReversePoly, BigOh -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/ApplyDelta.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/ApplyDelta.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/ApplyDelta.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/ApplyDelta.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="ApplyDelta",scope="private" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -10 # ApplyDelta(_result,Delta(_i,_j)) <-- - DestructiveInsert(result,1,Delta(i,j)); -20 # ApplyDelta(_result,(_x) ^ (n_IsInteger))_(n>0) <-- - [ - Local(i); - For(i:=1,i<=n,i++) - [ - ApplyDelta(result,x); - ]; - ]; -100 # ApplyDelta(_result,_term) <-- - DestructiveAppend(result,term); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/Delta.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/Delta.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/Delta.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/Delta.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="Delta" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -/* functions internal to tensors */ -RuleBase("Delta",{ind1,ind2}); - -//Not defined in the scripts. todo:tk. - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/MoveDeltas.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/MoveDeltas.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/MoveDeltas.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/MoveDeltas.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="MoveDeltas",scope="private" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -/* Move the delta factors to the front, so they can be simplified - away. It uses ApplyDelta to move a factor either to the front - or to the back of the list. Input is a list of factors, as - returned by Flatten(expressions,"*") - */ -MoveDeltas(_list) <-- -[ - Local(result,i,nr); - result:={}; - nr:=Length(list); - For(i:=1,i<=nr,i++) - [ - ApplyDelta(result,list[i]); - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TD.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TD.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TD.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TD.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -%mathpiper,def="TD" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -RuleBase("TD",{ind}); - -/* And the simplificaiton rules for X, addition, subtraction - and multiplication */ -10 # (TD(_i)X(_j)) <-- Delta(i,j); -10 # (TD(_i) ( (_f) + (_g) ) ) <-- (TD(i)f) + (TD(i)g); -10 # (TD(_i) ( (_f) - (_g) ) ) <-- (TD(i)f) - (TD(i)g); -10 # (TD(_i) ( - (_g) ) ) <-- - TD(i)g; -10 # (TD(_i) ( (_f) * (_g) ) ) <-- (TD(i)f)*g + f*(TD(i)g); -10 # (TD(_i) ( (_f) ^ (n_IsPositiveInteger) ) ) <-- n*(TD(i)f)*f^(n-1); -10 # (TD(_i)Delta(_j,_k)) <-- 0; -10 # (TD(_i)f_IsNumber) <-- 0; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TExplicitSum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TExplicitSum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TExplicitSum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TExplicitSum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="TExplicitSum" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -/* TExplicitSum sets the dimension of the space under consideration, - so summation can proceed */ -(TExplicitSum(Ndim_IsInteger)(_body)) <-- Eval(body); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="TList",scope="private" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -RuleBase("TList",{head,tail}); - -//Not defined in the scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSimplify.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSimplify.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSimplify.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSimplify.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -%mathpiper,def="TSimplify" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -/* TSimplify : expand brackets, and send the expression of addition - of terms to TSimplifyAux */ -TSimplify(TSum(_indices)(_f)) <-- -[ - TSimplifyAux(TSum(indices)ExpandBrackets(f)); -]; - - -/* TSimplifyAux : simplify each term independently */ -10 # TSimplifyAux(TSum(_indices)((_f) + (_g))) <-- - TSimplifyAux(TSum(FlatCopy(indices))(f)) + - TSimplifyAux(TSum(FlatCopy(indices))(g)); -10 # TSimplifyAux(TSum(_indices)((_f) - (_g))) <-- - TSimplifyAux(TSum(FlatCopy(indices))(f)) - - TSimplifyAux(TSum(FlatCopy(indices))(g)); -10 # TSimplifyAux(TSum(_indices)( - (_g))) <-- - - TSimplifyAux(TSum(indices)(g)); - -40 # TSimplifyAux(TSum(_indices)_body) <-- -[ - Local(flat); - - /* Convert expressions of the form (a*b*c) to {a,b,c} */ - flat:=Flatten(body,"*"); - - /* Move the deltas to the front. */ - flat:=MoveDeltas(flat); - - /* Simplify the deltas away (removing the required indices) */ - flat:=TSumRest(flat); - - /* Determine if there are indices the summand still depends on */ - Local(varlist,independ,nrdims); - varlist:=VarList(flat); - independ:=Intersection(indices,varlist); - nrdims:=Length(indices)-Length(independ); - - /* Return result, still summing over the indices not removed by deltas */ - Ndim^nrdims*TSum(independ)flat; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSum.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSum.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSum.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSum.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -%mathpiper,def="TSum" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -RuleBase("TSum",{indices,body}); - -/* The only TSum summation simplification: summing over no indices - means no summation. */ -10 # (TSum({})(_body)) <-- body; - -/* Explicit summation when Ndim is defined. This summation will - be invoked when using TExplicitSum. */ -20 # (TSum(_indices)(_body))_(IsInteger(Ndim)) <-- - LocalSymbols(index,i,sum) - [ - Local(index,i,sum); - index:=indices[1]; - sum:=0; - MacroLocal(index); - For(i:=1,i<=Ndim,i++) - [ - MacroSet(index,i); - sum:=sum+Eval(TSum(Rest(indices))body); - ]; - sum; - ]; - -UnFence("TSum",2); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSumRest.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSumRest.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSumRest.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSumRest.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -%mathpiper,def="TSumRest",scope="private" - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -10 # TSumRest({}) <-- 1; -20 # TSumRest(_list) <-- -[ - TSumSimplify(TList(First(list),Rest(list))); -]; - -UnFence("TSumRest",1); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSumSimplify.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSumSimplify.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/TSumSimplify.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/TSumSimplify.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -%mathpiper,def="TSumSimplify",scope="private" - -/* Terminating condition for the tensorial simplification */ - -10 # TSumSimplify(TList(Delta(_ind,_ind),_list))_Contains(indices,ind) <-- - -[ - /* Remove the index from the list of indices to sum over, since - it is now implicitly summed over by simplifying the delta */ - DestructiveDelete(indices,Find(indices,ind)); - -/* Return result simplified for this delta */ - Ndim*TSumRest(list); -]; - -11 # TSumSimplify(TList(Delta(_ind1,_ind2),_list))_ - Contains(indices,ind2) <-- -[ - /* Remove the index from the list of indices to sum over, since - it is now implicitly summed over by simplifying the delta */ - DestructiveDelete(indices,Find(indices,ind2)); - - /* Return result simplified for this delta */ - TSumRest( Subst(ind2,ind1)list ); -]; -11 # TSumSimplify(TList(Delta(_ind1,_ind2),_list))_ - Contains(indices,ind1) <-- -[ - /* Remove the index from the list of indices to sum over, since - it is now implicitly summed over by simplifying the delta */ - DestructiveDelete(indices,Find(indices,ind1)); - - /* Return result simplified for this delta */ - TSumRest( Subst(ind1,ind2)list ); -]; - - - -1010 # TSumSimplify(TList(_term,_list)) <-- -[ - term*TSumRest(list); -]; - -UnFence("TSumSimplify",1); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/X.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/X.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/tensor/X.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/tensor/X.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -%mathpiper,def="",scope="private" -//todo:tk:this conflicts with "org/mathpiper/assembledscripts/linalg.rep/code.mpi" when published as a def file. -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -RuleBase("X",{ind}); - -//Not implemented in the scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/BenchCall.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/BenchCall.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/BenchCall.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/BenchCall.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -%mathpiper,def="BenchCall",scope="private" - -Function("BenchCall",{expr}) -[ - Echo({"In> ",expr}); - WriteString(""); - Eval(expr); - WriteString(""); - True; -]; -HoldArg("BenchCall",expr); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/BenchShow.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/BenchShow.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/BenchShow.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/BenchShow.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="BenchShow" - -Function("BenchShow",{expr}) -[ - Echo({"In> ",expr}); - WriteString(" "); - Echo({"Out> ",Eval(expr),""}); - True; -]; -HoldArg("BenchShow",expr); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/KnownFailure.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/KnownFailure.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/KnownFailure.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/KnownFailure.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="KnownFailure" - -Function("KnownFailure",{expr}) -[ - Local(rfail); - Echo({"Known failure: ", expr}); - Set(rfail,Eval(expr)); - If(rfail,Echo({"Failure resolved!"})); -]; -HoldArg("KnownFailure",expr); - -%/mathpiper - - - - -%mathpiper_docs,name="KnownFailure",categories="Programmer Functions;Testing" -*CMD KnownFailure --- Mark a test as a known failure -*STD -*CALL - KnownFailure(test) - -*PARMS - -{test} -- expression that should return {False} on failure - -*DESC - -The command {KnownFailure} marks a test as known to fail -by displaying a message to that effect on screen. - -This might be used by developers when they have no time -to fix the defect, but do not wish to alarm users who download -MathPiper and type {make test}. - -*E.G. - - In> KnownFailure(Verify(1,2)) - Known failure: - ****************** - 1 evaluates to 1 which differs from 2 - ****************** - Out> False; - In> KnownFailure(Verify(1,1)) - Known failure: - Failure resolved! - Out> True; - -*SEE Verify, TestMathPiper, LogicVerify, LogicTest - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/LogicTest.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/LogicTest.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/LogicTest.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/LogicTest.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -%mathpiper,def="LogicTest" - -/* LogicTest compares the truth tables of two expressions. */ -LocalSymbols(TrueFalse) -[ - MacroRuleBase(TrueFalse,{var,expr}); - 10 # TrueFalse(var_IsAtom,_expr) <-- `{(@expr) Where (@var)==False,(@expr) Where (@var)==True}; - 20 # TrueFalse({},_expr) <-- `(@expr); - 30 # TrueFalse(var_IsList,_expr) <-- - `[ - Local(t,h); - Set(h,First(@var)); - Set(t,Rest(@var)); - TrueFalse(h,TrueFalse(t,@expr)); - ]; - - Macro(LogicTest,{vars,expr1,expr2}) Verify(TrueFalse((@vars),(@expr1)), TrueFalse((@vars),(@expr2))); -]; - -%/mathpiper - - - - - -%mathpiper_docs,name="LogicTest",categories="Programmer Functions;Testing" -*CMD LogicTest --- verifying equivalence of two expressions -*STD -*CALL - LogicTest(variables,expr1,expr2) - -*PARMS - -{variables} -- list of variables - -{exprN} -- Some boolean expression - -*DESC - -The command {LogicTest} can be used to verify that an -expression is equivalent to a correct answer after evaluation. -It returns {True} or {False}. - - -*E.G. - - In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or B) - Out> True - In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or C) - ****************** - CommandLine: 1 - - $TrueFalse4({A,B,C},Not(Not A And Not B)) - evaluates to - {{{False,False},{True,True}},{{True,True},{True,True}}} - which differs from - {{{False,True},{False,True}},{{True,True},{True,True}}} - ****************** - Out> False - -*SEE Simplify, CanProve, KnownFailure, Verify, TestMathPiper, LogicVerify - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/LogicVerify.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/LogicVerify.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/LogicVerify.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/LogicVerify.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="LogicVerify" - -Function("LogicVerify",{aLeft,aRight}) -[ - If(aLeft != aRight, - Verify(CanProve(aLeft => aRight),True) - ); -]; - -%/mathpiper - - - -%mathpiper_docs,name="LogicVerify",categories="Programmer Functions;Testing" -*CMD LogicVerify --- verifying equivalence of two expressions -*STD -*CALL - LogicVerify(question,answer) - -*PARMS - -{question} -- expression to check for - -{answer} -- expected result after evaluation - - -*DESC - -The command {LogicVerify} can be used to verify that an -expression is equivalent to a correct answer after evaluation. -It returns {True} or {False} - -*E.G. - In> LogicVerify(a And c Or b And Not c,a Or b) - Out> True; - In> LogicVerify(a And c Or b And Not c,b Or a) - Out> True; - -*SEE Simplify, CanProve, KnownFailure, Verify, TestMathPiper, LogicTest - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/NextTest.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/NextTest.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/NextTest.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/NextTest.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="NextTest" - -Function("NextTest",{aLeft}) -[ -// curline++; -WriteString(" -Test suite for ":aLeft:" : " - ); - NewLine(); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/NumericEqual.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/NumericEqual.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/NumericEqual.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/NumericEqual.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not defined in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/RandVerifyArithmetic.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/RandVerifyArithmetic.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/RandVerifyArithmetic.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/RandVerifyArithmetic.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="RandVerifyArithmetic" - -RandVerifyArithmetic(_n)<-- -[ - While(n>0) - [ - n--; - VerifyArithmetic(FloorN(300*Random()),FloorN(80*Random()),FloorN(90*Random())); - ]; -]; - -%/mathpiper - - - - -%mathpiper_docs,name="RandVerifyArithmetic",categories="Programmer Functions;Testing" -*CMD RandVerifyArithmetic --- Special purpose arithmetic verifiers -*STD -*CALL - RandVerifyArithmetic(n) - -*PARMS - -{n} -- integer arguments - -*DESC - -{RandVerifyArithmetic(n)} calls {VerifyArithmetic} with -random values, {n} times. - -*E.G. - - In> RandVerifyArithmetic(4) - Out> True; - -*SEE Verify, VerifyArithmetic, RandVerifyArithmetic, VerifyDiv, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/RoundTo.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/RoundTo.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/RoundTo.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/RoundTo.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -%mathpiper,def="RoundTo" - -/* Functions that aid in testing */ - -/* Round to specified number of digits */ -10 # RoundTo(x_IsNumber, precision_IsPositiveInteger) <-- -[ - Local(oldPrec,result); - - oldPrec:=BuiltinPrecisionGet(); - - BuiltinPrecisionSet(precision); - - Set(result,DivideN( Round( MultiplyN(x, 10^precision) ), 10^precision )); - - BuiltinPrecisionSet(oldPrec); - - result; -]; - - - -// complex numbers too -10 # RoundTo(Complex(r_IsNumber, i_IsNumber), precision_IsPositiveInteger) <-- Complex(RoundTo(r, precision), RoundTo(i, precision)); - - - - -// Infinities, rounding does not apply. -20 # RoundTo( Infinity,precision_IsPositiveInteger) <-- Infinity; - -20 # RoundTo(-Infinity,precision_IsPositiveInteger) <-- -Infinity; - - - - -Macro(NumericEqual,{left,right,precision}) -[ - Verify(RoundTo((@left)-(@right),@precision),0); -]; - - -%/mathpiper - - - - - -%mathpiper_docs,name="RoundTo",categories="Programmer Functions;Testing" -*CMD RoundTo --- Round a real-valued result to a set number of digits -*STD -*CALL - RoundTo(number,precision) - -*PARMS - -{number} -- number to round off - -{precision} -- precision to use for round-off - -*DESC - -The function {RoundTo} rounds a floating point number to a -specified precision, allowing for testing for correctness -using the {Verify} command. - -*E.G. - - In> N(RoundTo(Exp(1),30),30) - Out> 2.71828182110230114951959786552; - In> N(RoundTo(Exp(1),20),20) - Out> 2.71828182796964237096; - -*SEE Verify, VerifyArithmetic, VerifyDiv - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/ShowLine.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/ShowLine.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/ShowLine.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/ShowLine.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -%mathpiper,def="ShowLine",scope="private" - -// print current file and line -ShowLine() := [Echo({CurrentFile(),": ",CurrentLine()});]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/Testing.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/Testing.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/Testing.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/Testing.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -%mathpiper,def="Testing" - -Function("Testing",{aLeft}) -[ - WriteString("--"); - WriteString(aLeft); NewLine(); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/TestMathPiper.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/TestMathPiper.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/TestMathPiper.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/TestMathPiper.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -%mathpiper,def="TestMathPiper" - -/* Testing MathPiper functionality by checking expressions against correct - answer. - Use with algebraic expressions only, since we need Simplify() for that to work. - */ - -/* -Macro ("TestMathPiper", {expr, ans}) -[ - Local(diff,exprEval, ansEval); - exprEval:= @expr; - ansEval:= @ans; - - diff := Simplify(exprEval - ansEval); - If (Simplify(diff)=0, True, - [ - WriteString("******************"); - NewLine(); - ShowLine(); - Write(Hold(@expr)); - WriteString(" evaluates to "); - NewLine(); - Write(exprEval); - NewLine(); - WriteString(" which differs from "); - NewLine(); - Write(ansEval); - NewLine(); - WriteString(" by "); - NewLine(); - Write(diff); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ] - ); -]; -*/ - - - -Function ("TestMathPiper", {expr, ans}) -[ - Local(diff); - diff := Simplify(Eval(expr)-Eval(ans)); - If (Simplify(diff)=0, True, - [ - WriteString("******************"); - NewLine(); - ShowLine(); - Write(expr); - WriteString(" evaluates to "); - NewLine(); - Write(Eval(expr)); - NewLine(); - WriteString(" which differs from "); - NewLine(); - Write(Eval(ans)); - NewLine(); - WriteString(" by "); - NewLine(); - Write(diff); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ] - ); -]; - -HoldArg("TestMathPiper", expr); -HoldArg("TestMathPiper", ans); - - -%/mathpiper - - - - -%mathpiper_docs,name="TestMathPiper",categories="Programmer Functions;Testing" -*CMD TestMathPiper --- verifying equivalence of two expressions -*STD -*CALL - TestMathPiper(question,answer) - -*PARMS - -{question} -- expression to check for - -{answer} -- expected result after evaluation - -*DESC - -The command {TestMathPiper} can be used to verify that an -expression is equivalent to a correct answer after evaluation. -It returns {True} or {False}. - -*E.G. - In> TestMathPiper(x*(1+x),x^2+x) - Out> True; - - -*SEE Simplify, CanProve, KnownFailure, Verify, LogicVerify, LogicTest - -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/VerifyArithmetic.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/VerifyArithmetic.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/VerifyArithmetic.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/VerifyArithmetic.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%mathpiper,def="VerifyArithmetic" - -LocalSymbols(f1,f2) -[ - // f1 and f2 are used inside VerifyArithmetic - f1(x,n,m):=(x^n-1)*(x^m-1); - f2(x,n,m):=x^(n+m)-(x^n)-(x^m)+1; - - VerifyArithmetic(x,n,m):= - [ - Verify(f1(x,n,m),f2(x,n,m)); - ]; -]; - -%/mathpiper - - - - -%mathpiper_docs,name="VerifyArithmetic",categories="Programmer Functions;Testing" -*CMD VerifyArithmetic --- Special purpose arithmetic verifiers -*STD -*CALL - VerifyArithmetic(x,n,m) - -*PARMS - -{x}, {n}, {m} -- integer arguments - -*DESC - -The command {VerifyArithmetic} tests a -mathematic equality which should hold, testing that the -result returned by the system is mathematically correct -according to a mathematically provable theorem. - -{VerifyArithmetic} verifies for an arbitrary set of numbers -$ x $, $ n $ and $ m $ that -$$ (x^n-1)*(x^m-1) = x^(n+m)-(x^n)-(x^m)+1 $$. - -The left and right side represent two ways to arrive at the -same result, and so an arithmetic module actually doing the -calculation does the calculation in two different ways. -The results should be exactly equal. - -*E.G. - - In> VerifyArithmetic(100,50,60) - Out> True; - -*SEE Verify, VerifyArithmetic, RandVerifyArithmetic, VerifyDiv, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/VerifyDiv.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/VerifyDiv.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/VerifyDiv.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/VerifyDiv.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -%mathpiper,def="VerifyDiv" - -VerifyDiv(_u,_v) <-- -[ - Local(q,r); - q:=Div(u,v); - r:=Rem(u,v); - - Verify(Expand(u),Expand(q*v+r)); -]; - -%/mathpiper - - - - -%mathpiper_docs,name="VerifyDiv",categories="Programmer Functions;Testing" -*CMD VerifyDiv --- Special purpose arithmetic verifiers -*STD -*CALL - VerifyDiv(u,v) - -*PARMS - -{u}, {v} -- integer arguments - -*DESC - -{VerifyDiv(u,v)} checks that -$$ u = v*Div(u,v) + Mod(u,v) $$. - - -*E.G. - - In> VerifyDiv(x^2+2*x+3,x+1) - Out> True; - In> VerifyDiv(3,2) - Out> True; - -*SEE Verify, VerifyArithmetic, RandVerifyArithmetic, VerifyDiv, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/Verify.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/Verify.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/testers/Verify.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/testers/Verify.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,169 +0,0 @@ -%mathpiper,def="Verify" - -/* -Macro("Verify",{aLeft,aRight}) -[ - - Local(result); - result := @aLeft; // to save time - If (Not(Equals(result,@aRight)), - [ - WriteString("******************"); - NewLine(); - ShowLine(); - NewLine(); - Write(Hold(@aLeft)); - NewLine(); - WriteString(" evaluates to "); - NewLine(); - Write(result); - WriteString(" which differs from "); - NewLine(); - Write(Hold(@aRight)); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ], - True - ); -]; -*/ - - -Function("Verify",{aLeft,aRight}) -[ - - Local(result); - result := Eval(aLeft); // to save time - If (Not(Equals(result,aRight)), - [ - WriteString("******************"); - NewLine(); - ShowLine(); - NewLine(); - Write(aLeft); - NewLine(); - WriteString(" evaluates to "); - NewLine(); - Write(result); - NewLine(); - WriteString(" which differs from "); - NewLine(); - Write(aRight); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ], - True - ); -]; -HoldArg("Verify",aLeft); -UnFence("Verify",2); -/* -HoldArg("Verify",aRight); -*/ - -Macro("Verify", {a,b,message}) -[ - Echo("test ", @message); - Verify(@a, @b); -]; - - -%/mathpiper - - - - - - -%mathpiper_docs,name="Verify",categories="Programmer Functions;Testing" -*CMD Verify --- verifying equivalence of two expressions -*STD -*CALL - Verify(question,answer) - -*PARMS - -{question} -- expression to check for - -{answer} -- expected result after evaluation - - -*DESC - -The command {Verify} can be used to verify that an -expression is equivalent to a correct answer after evaluation. -It returns {True} or {False}. - -For some calculations, the demand that two expressions -are identical syntactically is too stringent. The -MathPiper system might change at various places in the future, -but $ 1+x $ would still be equivalent, from a mathematical -point of view, to $ x+1 $. - -The general problem of deciding that two expressions $ a $ and $ b $ -are equivalent, which is the same as saying that $ a-b=0 $ , -is generally hard to decide on. The following commands solve -this problem by having domain-specific comparisons. - -The comparison commands do the following comparison types: - -* {Verify} -- verify for literal equality. -This is the fastest and simplest comparison, and can be -used, for example, to test that an expression evaluates to $ 2 $. -* {TestMathPiper} -- compare two expressions after simplification as -multivariate polynomials. If the two arguments are equivalent -multivariate polynomials, this test succeeds. {TestMathPiper} uses {Simplify}. Note: {TestMathPiper} currently should not be used to test equality of lists. -* {LogicVerify} -- Perform a test by using {CanProve} to verify that from -{question} the expression {answer} follows. This test command is -used for testing the logic theorem prover in MathPiper. -* {LogicTest} -- Generate a truth table for the two expressions and compare these two tables. They should be the same if the two expressions are logically the same. - -*E.G. - In> Verify(1+2,3) - Out> True; - - In> Verify(x*(1+x),x^2+x) - ****************** - x*(x+1) evaluates to x*(x+1) which differs - from x^2+x - ****************** - Out> False; - - In> TestMathPiper(x*(1+x),x^2+x) - Out> True; - - In> Verify(a And c Or b And Not c,a Or b) - ****************** - a And c Or b And Not c evaluates to a And c - Or b And Not c which differs from a Or b - ****************** - Out> False; - - In> LogicVerify(a And c Or b And Not c,a Or b) - Out> True; - - In> LogicVerify(a And c Or b And Not c,b Or a) - Out> True; - - In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or B) - Out> True - - In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or C) - ****************** - CommandLine: 1 - - $TrueFalse4({A,B,C},Not(Not A And Not B)) - evaluates to - {{{False,False},{True,True}},{{True,True},{True,True}}} - which differs from - {{{False,True},{False,True}},{{True,True},{True,True}}} - ****************** - Out> False - -*SEE Simplify, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/texform/texform.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/texform/texform.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/texform/texform.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/texform/texform.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,383 +0,0 @@ -%mathpiper,def="TeXForm" - -/* def file definitions -TeXForm -TeXFormMaxPrec -TexForm -*/ - -/* TeXForm: convert MathPiper objects to TeX math mode strings */ - -/* version 0.4 */ - -/* Changelog - 0.1 basic functionality - 0.2 fixed bracketing of Exp, added all infix ops and math functions - 0.3 fixed bracketing of lists, changed bracketing of math functions, modified TeX representation of user-defined functions (up to two-letter functions are in italics), added TeX Greek letters - 0.4 added nth roots, Sum, Limit, Integrate, hyperbolics, set operations, Abs, Max, Min, "==", ":=", Infinity; support indexed expressions A[i] and matrices. - 0.4.1 bugfixes for [] operator, support for multiple indices a[1][2][3] - 0.4.2 fix for variable names ending on digits "a2" represented as $a_2$ - 0.4.3 bugfixes: complex I, indeterminate integration; relaxed bracketing of Sin()-like functions; implemented $TeX$ and $LaTeX$ correctly now (using \textrm{}) - 0.4.4 use ordinary instead of partial derivative if expression has only one variable - 0.4.5 fixes for bracketing of Sum(); added <> to render as \sim and <=> to render as \approx; added BinomialCoefficient() - 0.4.6 moved the <> and <=> operators to org/mathpiper/assembledscripts/initialization.rep/stdopers.mpi - 0.4.7 added Product() i.e. Product() - 0.4.8 added D(x,n), Deriv(x,n), =>, and fixed errors with ArcSinh, ArcCosh, ArcTanh - 0.4.9 fixed omission: (fraction)^n was not put in brackets - 0.4.10 cosmetic change: insert \cdot between numbers in cases like 2*10^n - 0.4.11 added DumpErrors() to TexForm for the benefit of TeXmacs notebooks - 0.4.12 implement the % operation as Mod - 0.4.13 added Bessel{I,J,K,Y}, Ortho{H,P,T,U}, with a general framework for usual two-argument functions of the form $A_n(x)$; fix for Max, Min - 0.4.14 added mathematical notation for Floor(), Ceil() - 0.4.15 added Prog() represented by ( ) - 0.4.16 added Zeta() -*/ - -/* To do: - 0. Find and fix bugs. - 1. The current bracketing approach has limitations: can't omit extra brackets sometimes. " sin a b" is ambiguous, so need to do either "sin a sin b" or "(sin a) b" Hold((a*b)*Sqrt(x)). The current approach is *not* to bracket functions unless the enveloping operation is more binding than multiplication. This produces "sin a b" for both Sin(a*b) and Sin(a)*b but this is the current mathematical practice. - 2. Need to figure out how to deal with variable names such as "alpha3" -*/ - -/// TeXmacs prettyprinter -TexForm(_expr) <-- [DumpErrors();WriteString(TeXForm(expr));NewLine();]; - -RuleBase("TeXForm",{expression}); -RuleBase("TeXForm",{expression, precedence}); - -/* Boolean predicate */ - - -/* this function will put TeX brackets around the string if predicate holds */ - -Function ("TeXFormBracketIf", {predicate, string}) -[ - Check(IsBoolean(predicate) And IsString(string), "TeXForm internal error: non-boolean and/or non-string argument of TeXFormBracketIf"); - If(predicate, ConcatStrings("\\left( ", string, "\\right) "), string); -]; - -/* First, we convert TeXForm(x) to TeXForm(x, precedence). The enveloping precedence will determine whether we need to bracket the results. So TeXForm(x, TeXFormMaxPrec()) will always print "x", while TeXForm(x,-TeXFormMaxPrec()) will always print "(x)". -*/ - -TeXFormMaxPrec() := 60000; /* This precedence will never be bracketed. It is equal to KMaxPrec */ - -/// main front-end -100 # TeXForm(_x) <-- ConcatStrings("$", TeXForm(x, TeXFormMaxPrec()), "$"); - -/* Replace numbers and variables -- never bracketed except explicitly */ - -110 # TeXForm(x_IsNumber, _p) <-- String(x); -/* Variables */ -200 # TeXForm(x_IsAtom, _p) <-- TeXFormTeXify(String(x)); - -/* Strings must be quoted but not bracketed */ -100 # TeXForm(x_IsString, _p) <-- ConcatStrings("\\mathrm{", x, "}"); - -/* Listify(...) can generate lists with atoms that would otherwise result in unparsable expressions. */ -100 # TeXForm(x_IsAtom, _p)_(IsInfix(String(x))) <-- ConcatStrings("\\mathrm{", String(x), "}"); - - -/* Lists: make sure to have matrices processed before them. Enveloping precedence is irrelevant because lists are always bracketed. List items are never bracketed. Note that TeXFormFinishList({a,b}) generates ",a,b" */ - -100 # TeXForm(x_IsList, _p)_(Length(x)=0) <-- TeXFormBracketIf(True, ""); -110 # TeXForm(x_IsList, _p) <-- TeXFormBracketIf(True, ConcatStrings(TeXForm(First(x), TeXFormMaxPrec()), TeXFormFinishList(Rest(x)) ) ); -100 # TeXFormFinishList(x_IsList)_(Length(x)=0) <-- ""; -110 # TeXFormFinishList(x_IsList) <-- ConcatStrings(", ", TeXForm(First(x), TeXFormMaxPrec()), TeXFormFinishList(Rest(x))); - -/* Replace operations */ - - - /* Template for "regular" binary infix operators: -100 # TeXForm(_x + _y, _p) <-- TeXFormBracketIf(p=","\\geq "}, - {"<"," < "}, - {">"," > "}, - {"And","\\wedge "}, - {"Or", "\\vee "}, - {"<>", "\\sim "}, - {"<=>", "\\approx "}, - {"=>", "\\Rightarrow "}, - {"%", "\\bmod "}, - }; - - TeXFormRegularPrefixOps := { {"+"," + "}, {"-"," - "}, {"Not"," \\neg "} }; - - - - /* Unknown function: precedence 200. Leave as is, never bracket the function itself and bracket the argumentPointer(s) automatically since it's a list. Other functions are precedence 100 */ - - TeXFormGreekLetters := {"Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon", "Phi", "Psi", "Omega", "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega", "varpi", "varrho", "varsigma", "varphi", "varepsilon"}; - TeXFormSpecialNames := { - {"I", "\\imath "}, // this prevents a real uppercase I, use BesselI instead - {"Pi", "\\pi "}, // this makes it impossible to have an uppercase Pi... hopefully it's not needed - {"Infinity", "\\infty "}, - {"TeX", "\\textrm{\\TeX\\/}"}, - {"LaTeX", "\\textrm{\\LaTeX\\/}"}, - {"Max", "\\max "}, // this replaces these function names - {"Min", "\\min "}, - {"Prog", " "}, - {"Zeta", "\\zeta "}, - }; - - - /* this function will take a user-defined variable or function name and output either this name unmodified if it's only 2 characters long, or the name in normal text if it's longer, or a TeX Greek letter code */ - Function ("TeXFormTeXify", {string}) - [ - Check(IsString(string), "TeXForm internal error: non-string argument of TeXFormTeXify"); - /* Check if it's a greek letter or a special name */ - If (Contains(AssocIndices(TeXFormSpecialNames), string), TeXFormSpecialNames[string], - If (Contains(TeXFormGreekLetters, string), ConcatStrings("\\", string, " "), - If (Contains(AssocIndices(TeXFormRegularOps), string), TeXFormRegularOps[string], - If (Contains(AssocIndices(TeXFormRegularPrefixOps), string), TeXFormRegularPrefixOps[string], - If (Length(string) >= 2 And IsNumber(Atom(StringMidGet(2, Length(string)-1, string))), ConcatStrings(StringMidGet(1,1,string), "_{", StringMidGet(2, Length(string)-1, string), "}"), - If (Length(string) > 2, ConcatStrings("\\mathrm{ ", string, " }"), - string - )))))); - ]; - -]; - -/* */ - -/* Unknown bodied function */ - -200 # TeXForm(x_IsFunction, _p) _ (IsBodied(Type(x))) <-- [ - Local(func, args, last'arg); - func := Type(x); - args := Rest(Listify(x)); - last'arg := PopBack(args); - TeXFormBracketIf(p1, "\\frac{\\partial}{\\partial ", "\\frac{d}{d " - ), TeXForm(x, OpPrecedence("^")), "}", TeXForm(y, OpPrecedence("/")) ) ); - -100 # TeXForm(Deriv(_x, _n)_y, _p) <-- TeXFormBracketIf(p1, - "\\frac{\\partial^" : TeXForm(n, TeXFormMaxPrec()) : "}{\\partial ", - "\\frac{d^" : TeXForm(n, TeXFormMaxPrec()) : "}{d " - ), TeXForm(x, OpPrecedence("^")), " ^", TeXForm(n, TeXFormMaxPrec()), "}", TeXForm(y, OpPrecedence("/")) ) ); -100 # TeXForm(D(_x)_y, _p) <-- TeXForm(Deriv(x) y, p); -100 # TeXForm(D(_x, _n)_y, _p) <-- TeXForm(Deriv(x, n) y, p); - -/* Indexed expressions */ - -/* This seems not to work because x[i] is replaced by Nth(x,i) */ -/* -100 # TeXForm(_x [ _i ], _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); -*/ -/* Need to introduce auxiliary function, or else have trouble with arguments of Nth being lists */ -100 # TeXForm(Nth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p); -100 # TeXForm(TeXFormNth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p); -110 # TeXForm(Nth(Nth(_x, _i), _j), _p) <-- TeXForm(TeXFormNth(x, List(i,j)), p); -120 # TeXForm(Nth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); -120 # TeXForm(TeXFormNth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); - -/* Matrices are always bracketed. Precedence 80 because lists are at 100. */ - -80 # TeXForm(M_IsMatrix, _p) <-- TeXFormBracketIf(True, TeXFormPrintMatrix(M)); - -Function ("TeXFormPrintMatrix", {M}) -[ -/* - Want something like "\begin{array}{cc} a & b \\ c & d \\ e & f \end{array}" - here, "cc" is alignment and must be given for each column -*/ - Local(row, col, result, ncol); - result := "\\begin{array}{"; - ForEach(col, M[1]) result:=ConcatStrings(result, "c"); - result := ConcatStrings(result, "}"); - - ForEach(row, 1 .. Length(M)) [ - ForEach(col, 1 .. Length(M[row])) [ - result := ConcatStrings( result, " ", TeXForm(M[row][col], TeXFormMaxPrec()), If(col = Length(M[row]), If(row = Length(M), "", " \\\\"), " &")); - ]; - ]; - - ConcatStrings(result, " \\end{array} "); -]; - -%/mathpiper - - - -%mathpiper_docs,name="TeXForm",categories="User Functions;Input/Output" -*CMD TeXForm --- export expressions to $LaTeX$ -*STD -*CALL - TeXForm(expr) - -*PARMS - -{expr} -- an expression to be exported - -*DESC - -{TeXForm} returns a string containing a $LaTeX$ representation of the MathPiper expression {expr}. Currently the exporter handles most expression types but not all. - -*E.G. - - In> TeXForm(Sin(a1)+2*Cos(b1)) - Out> "$\sin a_{1} + 2 \cos b_{1}$"; - -*SEE PrettyForm, CForm -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/transforms/laplace/LaplaceTransform.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/transforms/laplace/LaplaceTransform.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/transforms/laplace/LaplaceTransform.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/transforms/laplace/LaplaceTransform.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -%mathpiper,def="LaplaceTransform" - -10 # LaplaceTransform(_var1,_var2, _expr ) <-- LapTran(var1,var2,expr); - -// Linearity properties -10 # LapTran(_var1,_var2,_x + _y) <-- LapTran(var1,var2,x) + LapTran(var1,var2,y); -10 # LapTran(_var1,_var2,_x - _y) <-- LapTran(var1,var2,x) - LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, - _y) <-- LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, c_IsConstant*_y) <-- c*LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, _y*c_IsConstant) <-- c*LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, _y/c_IsConstant) <-- LapTran(var1,var2,y)/c; - -// Shift properties -10 # LapTran(_var1,_var2, Exp(c_IsConstant*_var1)*_expr ) <-- LapTran(var1,var2-c,expr); -10 # LapTran(_var1,_var2, Exp(-c_IsConstant*_var1)*_expr ) <-- LapTran(var1,var2+c,expr); -10 # LapTran(_var1,_var2, _expr*Exp(c_IsConstant*_var1) ) <-- LapTran(var1,var2-c,expr); -10 # LapTran(_var1,_var2, _expr*Exp(-c_IsConstant*_var1) ) <-- LapTran(var1,var2+c,expr); - -// Other operational properties -10 # LapTran(_var1,_var2, _expr/_var1 ) <-- Integrate(var2,var2,Infinity) LapTran(var1,var2,expr) ; -10 # LapTran(_var1,_var2, _var1*_expr ) <-- - Deriv(var2) LapTran(var1,var2,expr); -10 # LapTran(_var1,_var2, _var1^(n_IsInteger)*_expr ) <-- (-1)^n * Deriv(var2,n) LapTran(var1,var2,expr); -10 # LapTran(_var1,_var2, _expr*_var1 ) <-- - Deriv(var2) LapTran(var1,var2,expr); -10 # LapTran(_var1,_var2, _expr*_var1^(n_IsInteger) ) <-- (-1)^n * Deriv(var2,n) LapTran(var1,var2,expr); - -// didn't match, return unevaled -100 # LapTran(_var1,_var2, _expr ) <-- `Hold(LaplaceTransform(@var1,@var2,@expr)); - -LapTranDef(_in,_out) <-- -[ - Local(i,o); - - //Echo("50 # LapTran(_t,_s,",in,") <-- ",out,";"); - `(50 # LapTran(_t,_s,@in) <-- @out ); - - i:=Subst(_t,c_IsPositiveInteger*_t) in; - o:=Subst(s,s/c) out; - - //Echo("50 # LapTran(_t,_s,",i,") <-- ",o/c,";"); - `(50 # LapTran(_t,_s,@i ) <-- @o/c ); - - i:=Subst(_t,_t/c_IsPositiveInteger) in; - o:=Subst(s,s*c) out; - - //Echo("50 # LapTran(_t,_s,",i,") <-- ",o/c,";"); - `(50 # LapTran(_t,_s,@i ) <-- @o*c ); - -]; - -// transforms of specific functions -LapTranDef( (_t)^(n_IsConstant), Gamma(n+1)/s^(n+1) ); -LapTranDef( _t, 1/s^2 ); -LapTranDef( Sqrt(_t), Sqrt(Pi)/(2*s^(3/2)) ); -LapTranDef( c_IsFreeOf({t,s}), c/s ); -LapTranDef( Sin(_t), 1/(s^2+1) ); -LapTranDef( Cos(_t), s/(s^2+1) ); -LapTranDef( Sinh(_t), c/(s^2-1) ); -LapTranDef( Cosh(_t), s/(s^2-1) ); -LapTranDef( Exp(_t), 1/(s-1) ); -LapTranDef( BesselJ(n_IsConstant,_t), (Sqrt(s^2+1)-s)^n /Sqrt(s^2+1) ); -LapTranDef( BesselI(n_IsConstant,_t), (s-Sqrt(s^2+1))^n /Sqrt(s^2-1) ); -LapTranDef( Ln(_t), -(gamma+Ln(s))/s); -LapTranDef( Ln(_t)^2, Pi^2/(6*s)+(gamma+Ln(s))/s ); -LapTranDef( Erf(_t), Exp(s^2/4)*Erfc(s/2)/s ); -LapTranDef( Erf(Sqrt(_t)), 1/(Sqrt(s+1)*s) ); - - -%/mathpiper - - - -%mathpiper_docs,name="LaplaceTransform",categories="User Functions;Transforms" -*CMD LaplaceTransform --- Laplace Transform -*STD -*CALL - LaplaceTransform(t,s,func) -*PARMS - -{t} -- independent variable that is being transformed - -{s} -- independent variable that is being transformed into - -{f} -- function - -*DESC - -This function attempts to take the function {f(t)} and find the Laplace transform -of it,{F(s)}, which is defined as {Integrate(t,0,Infinity) Exp(-s*t)*f}. This is -also sometimes referred to the "unilateral" Laplace tranform. {LaplaceTransform} -can transform most elementary functions that do not require a convolution integral, -as well as any polynomial times an elementary function. If a transform cannot -be found then {LaplaceTransform} will return unevaluated. This can happen -for function which are not of "exponential order", which means that they grow -faster than exponential functions. - - -*E.G. - - In> LaplaceTransform(t,s,2*t^5+ t^2/2 ) - Out> 240/s^6+2/(2*s^3); - In> LaplaceTransform(t,s,t*Sin(2*t)*Exp(-3*t) ) - Out> (2*(s+3))/(2*(2*(((s+3)/2)^2+1))^2); - In> LaplaceTransform(t,s, BesselJ(3,2*t) ) - Out> (Sqrt((s/2)^2+1)-s/2)^3/(2*Sqrt((s/2)^2+1)); - In> LaplaceTransform(t,s,Exp(t^2)); // not of exponential order - Out> LaplaceTransform(t,s,Exp(t^2)); - In> LaplaceTransform(p,q,Ln(p)) - Out> -(gamma+Ln(q))/q; -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/trigsimp/TrigSimpCombine.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/trigsimp/TrigSimpCombine.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/trigsimp/TrigSimpCombine.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/trigsimp/TrigSimpCombine.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,513 +0,0 @@ -%mathpiper,def="TrigSimpCombine" - - -/* This file defines TrigSimpCombine. TrigSimpCombine is designed to - simplify expressions like Cos(a)*Sin(b) to additions - only (in effect, removing multiplications between - trigonometric functions). - - The accepted expressions allow additions and multiplications - between trig. functions, and raising trig. functions to an - integer power. - - You can invoke it by calling TrigSimpCombine(f). Examples: - TrigSimpCombine(Cos(a)*Sin(a^2+b)^2) - TrigSimpCombine(Cos(a)*Sin(a)^2) - TrigSimpCombine(Cos(a)^3*Sin(a)^2) - TrigSimpCombine(d*Cos(a)^3*Sin(a)^2) - TrigSimpCombine(Cos(a)^3*Sin(a)^2) - TrigSimpCombine(Cos(a)*Sin(a)) - TrigSimpCombine(Cos(a)*Sin(b)*Cos(c)) - - */ - - -/* FSin, FCos and :*: are used for the internal representation - of the expression to work on: - - a*b -> a:*:b this is used because we want to expand powers, - without the standard engine collapsing them back again. - - a*Sin(b) -> FSin(a,b) and a*Cos(b) -> FCos(a,b). This makes - adding and multiplying expressions with trig. functions, non-trig. - functions, constants, etc. a lot easier. -*/ -RuleBase("FSin",{f,x}); -RuleBase("FCos",{f,x}); -RuleBase(":*:",{x,y}); -Infix(":*:",3); - - -IsTrig(f) := (Type(f) = "Sin" Or Type(f) = "Cos"); -IsFTrig(f) := (Type(f) = "FSin" Or Type(f) = "FCos"); -IsMul(f) := (Type(f) = "*"); -IsMulF(f) := (Type(f) = ":*:"); - -IsPow(f):= - (Type(f) = "^" And - IsInteger(f[2]) And - f[2] > 1 - ); - - -/* Convert Sin/Cos to FSin/FCos */ -RuleBase("TrigChange",{f}); -Rule("TrigChange",1,1,Type(f)="Cos") FCos(1,f[1]); -Rule("TrigChange",1,1,Type(f)="Sin") FSin(1,f[1]); - -RuleBase("TrigUnChange",{f}); -Rule("TrigUnChange",1,1,Type(f)="FCos") Cos(f[2]); -Rule("TrigUnChange",1,1,Type(f)="FSin") Sin(f[2]); - - -/* Do a full replacement to internal format on a term. */ -RuleBase("FReplace",{f}); -UnFence("FReplace",1); -Rule("FReplace",1,1,IsMul(f)) Substitute(f[1]) :*: Substitute(f[2]); -Rule("FReplace",1,2,IsPow(f)) (Substitute(f[1]) :*: Substitute(f[1])) :*: Substitute(f[1]^(f[2]-2)); -/* -Rule("FReplace",1,2,IsPow(f)) -[ - Local(trm,i,res,n); - Set(trm,Substitute(f[1])); - Set(n,f[2]); - Set(res,trm); - For(i:=2,i<=n,i++) - [ - Set(res,res :*: trm); - ]; - res; -]; -*/ - -Rule("FReplace",1,3,IsTrig(f)) TrigChange(f); -FTest(f):=(IsMul(f) Or IsPow(f) Or IsTrig(f)); - -/* Central function that converts to internal format */ -FToInternal(f):=Substitute(f,"FTest","FReplace"); - -FReplaceBack(f):=(Substitute(f[1])*Substitute(f[2])); -UnFence("FReplaceBack",1); -FFromInternal(f):=Substitute(f,"IsMulF","FReplaceBack"); - - -/* FLog(s,f):=[WriteString(s:" ");Write(f);NewLine();]; */ - FLog(s,f):=[]; - - -/* FSimpTerm simplifies the current term, wrt. trigonometric functions. */ -RuleBase("FSimpTerm",{f,rlist}); -UnFence("FSimpTerm",2); - -/* Addition: add all the subterms */ -Rule("FSimpTerm",2,1,Type(f) = "+") -[ - Local(result,lst); - lst:=Flatten(f,"+"); - - result:={{},{}}; -FLog("simpadd",lst); - - ForEach(tt,lst) - [ - Local(new); - new:=FSimpTerm(tt,{{},{}}); - result:={Concat(result[1],new[1]),Concat(result[2],new[2])}; - ]; - result; -]; - - -TrigNegate(f):= -[ - UnList({f[0],-(f[1]),f[2]}); -]; - - -FUnTrig(result) := Substitute(result,"IsFTrig","TrigUnChange"); - -Rule("FSimpTerm",2,1,Type(f) = "-" And NrArgs(f)=1) -[ - Local(result); - result:=FSimpTerm(f[1],{{},{}}); - Substitute(result,"IsFTrig","TrigNegate"); -]; -Rule("FSimpTerm",2,1,Type(f) = "-" And NrArgs(f)=2) -[ - Local(result1,result2); - result1:=FSimpTerm(f[1],{{},{}}); - result2:=FSimpTerm(-(f[2]),{{},{}}); - {Concat(result1[1],result2[1]),Concat(result1[2],result2[2])}; -]; - -Rule("FSimpTerm",2,2,Type(f) = ":*:") -[ - FSimpFactor({Flatten(f,":*:")}); -]; -Rule("FSimpTerm",2,3,Type(f) = "FSin") -[ - {rlist[1],f:(rlist[2])}; -]; -Rule("FSimpTerm",2,3,Type(f) = "FCos") -[ - {f:(rlist[1]),rlist[2]}; -]; - -Rule("FSimpTerm",2,4,True) -[ - {(FCos(f,0)):(rlist[1]),rlist[2]}; -]; - -/* FSimpFactor does the difficult part. it gets a list, representing - factors, a*b*c -> {{a,b,c}}, and has to add terms from it. - Special cases to deal with: - - (a+b)*c -> a*c+b*c -> {{a,c},{b,c}} - - {a,b,c} where one of them is not a trig function or an addition: - replace with FCos(b,0), which is b*Cos(0) = b - - otherwise, combine two factors and make them into an addition. - - the lists should get shorter, but the number of lists should - get longer, until there are only single terms to be added. - */ -FSimpFactor(flist):= -[ - Local(rlist); - rlist:={{},{}}; - /* Loop over each term */ - While(flist != {}) - [ - Local(term); -FLog("simpfact",flist); - term:=First(flist); - flist:=Rest(flist); - FProcessTerm(term); - ]; -FLog("simpfact",flist); - -FLog("rlist",rlist); - rlist; -]; -UnFence("FSimpFactor",1); - - -RuleBase("FProcessTerm",{t}); -UnFence("FProcessTerm",1); - -/* Deal with (a+b)*c -> a*c+b*c */ -Rule("FProcessTerm",1,1,Type(t[1]) = "+") -[ - Local(split,term1,term2); - split:=t[1]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[1]:=split[1]; - term2[1]:=split[2]; - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; -Rule("FProcessTerm",1,1,Type(t[1]) = "-" And NrArgs(t[1]) = 2) -[ - Local(split,term1,term2); - split:=t[1]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[1]:=split[1]; - term2[1]:=split[2]; - DestructiveInsert(term2,1,FCos(-1,0)); - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "-" And NrArgs(t[2]) = 2) -[ - Local(split,term1,term2); - split:=t[2]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[2]:=split[1]; - term2[2]:=split[2]; - DestructiveInsert(term2,1,FCos(-1,0)); - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - -Rule("FProcessTerm",1,1,Type(t[1]) = ":*:") -[ - Local(split,term); - split:=t[1]; - term:=FlatCopy(t); - term[1]:=split[1]; - DestructiveInsert(term,1,split[2]); - DestructiveInsert(flist,1,term); -]; - -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = ":*:") -[ - Local(split,term); - split:=t[2]; - term:=FlatCopy(t); - term[2]:=split[1]; - DestructiveInsert(term,1,split[2]); - DestructiveInsert(flist,1,term); -]; - -Rule("FProcessTerm",1,1,Type(t[1]) = "-" And NrArgs(t[1]) = 1) -[ - Local(split,term); - split:=t[1]; - term:=FlatCopy(t); - term[1]:=split[1]; - DestructiveInsert(term,1,FCos(-1,0)); - DestructiveInsert(flist,1,term); -]; -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "-" And NrArgs(t[2]) = 1) -[ - Local(split,term); - split:=t[2]; - term:=FlatCopy(t); - term[2]:=split[1]; - DestructiveInsert(term,1,FCos(-1,0)); - DestructiveInsert(flist,1,term); -]; - - -/* Deal with (a*(b+c) -> a*b+a*c */ -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "+") -[ - Local(split,term1,term2); - split:=t[2]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[2]:=split[1]; - term2[2]:=split[2]; - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - - - -/* Deal with a*FCos(1,b) ->FCos(a,0)*FCos(1,b) */ -Rule("FProcessTerm",1,2,Not(IsFTrig(t[1])) ) -[ - t[1]:=FCos(t[1],0); - DestructiveInsert(flist,1,t); -]; -Rule("FProcessTerm",1,2,Length(t)>1 And Not(IsFTrig(t[2])) ) -[ - t[2]:=FCos(t[2],0); - DestructiveInsert(flist,1,t); -]; - - -Rule("FProcessTerm",1,4,Length(t)=1 And Type(t[1]) = "FCos") -[ - DestructiveInsert(rlist[1],1,t[1]); -]; -Rule("FProcessTerm",1,4,Length(t)=1 And Type(t[1]) = "FSin") -[ - DestructiveInsert(rlist[2],1,t[1]); -]; - -/* Now deal with the real meat: FSin*FCos etc. Reduce the multiplication - of the first two terms to an addition, adding two new terms to - the pipe line. - */ -Rule("FProcessTerm",1,5,Length(t)>1) -[ - Local(x,y,term1,term2,news); - x:=t[1]; - y:=t[2]; - news:=TrigSimpCombineB(x,y); - /* Drop one term */ - t:=Rest(t); - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[1]:=news[1]; - term2[1]:=news[2]; - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - -/* TrigSimpCombineB : take two FSin/FCos factors, and write them out into two terms */ -RuleBase("TrigSimpCombineB",{x,y}); -Rule("TrigSimpCombineB",2,1,Type(x) = "FCos" And Type(y) = "FCos") - { FCos((x[1]*y[1])/2,x[2]+y[2]) , FCos((x[1]*y[1])/2,x[2]-y[2]) }; -Rule("TrigSimpCombineB",2,1,Type(x) = "FSin" And Type(y) = "FSin") - { FCos(-(x[1]*y[1])/2,x[2]+y[2]) , FCos((x[1]*y[1])/2,x[2]-y[2]) }; -Rule("TrigSimpCombineB",2,1,Type(x) = "FSin" And Type(y) = "FCos") - { FSin((x[1]*y[1])/2,x[2]+y[2]) , FSin( (x[1]*y[1])/2,x[2]-y[2]) }; -Rule("TrigSimpCombineB",2,1,Type(x) = "FCos" And Type(y) = "FSin") - { FSin((x[1]*y[1])/2,x[2]+y[2]) , FSin(-(x[1]*y[1])/2,x[2]-y[2]) }; - - -RuleBase("TrigSimpCombine",{f}); -Rule("TrigSimpCombine",1,1,IsList(f)) - Map("TrigSimpCombine",{f}); - -Rule("TrigSimpCombine",1,10,True) -[ - Local(new,varlist); - new:=f; - - /* varlist is used for normalizing the trig. arguments */ - varlist:=VarList(f); - -/* Convert to internal format. */ - new:=FToInternal(new); -FLog("Internal",new); - - /* terms will contain FSin/FCos entries, the final result */ - - /* rlist gathers the true final result */ - Local(terms); - terms:=FSimpTerm(new,{{},{}}); - /* terms now contains two lists: terms[1] is the list of cosines, - and terms[2] the list of sines. - */ -FLog("terms",terms); - - /* cassoc and sassoc will contain the assoc lists with the cos/sin - arguments as key. - */ - Local(cassoc,sassoc); - cassoc:={}; - sassoc:={}; - ForEach(item,terms[1]) - [ - CosAdd(item); - ]; - ForEach(item,terms[2]) - [ - SinAdd(item); - ]; -FLog("cassoc",cassoc); -FLog("sassoc",sassoc); - - /* Now rebuild the normal form */ - Local(result); - result:=0; - -//Echo({cassoc}); -//Echo({sassoc}); - ForEach(item,cassoc) - [ -Log("item",item); - result:=result+Expand(FUnTrig(FFromInternal(item[2])))*Cos(item[1]); - ]; - ForEach(item,sassoc) - [ -Log("item",item); - result:=result+Expand(FUnTrig(FFromInternal(item[2])))*Sin(item[1]); - ]; - - result; -]; - - - -CosAdd(t):= -[ - Local(look,arg); - arg:=Expand(t[2],varlist); - look:=Assoc(arg,cassoc); - If(look = Empty, - [ - arg:=Expand(-arg,varlist); - look:=Assoc(arg,cassoc); - If(look = Empty, - DestructiveInsert(cassoc,1,{arg,t[1]}), - look[2]:=look[2]+t[1] - ); - ] - , - look[2]:=look[2]+t[1] - ); -]; -UnFence("CosAdd",1); - -SinAdd(t):= -[ - Local(look,arg); - arg:=Expand(t[2],varlist); - look:=Assoc(arg,sassoc); - If(look = Empty, - [ - arg:=Expand(-arg,varlist); - look:=Assoc(arg,sassoc); - If(look = Empty, - DestructiveInsert(sassoc,1,{arg,-(t[1])}), - look[2]:=look[2]-(t[1]) - ); - ] - , - look[2]:=look[2]+t[1] - ); -]; -UnFence("SinAdd",1); - - -/* -In( 4 ) = Exp(I*a)*Exp(I*a) -Out( 4 ) = Complex(Cos(a)^2-Sin(a)^2,Cos(a)*Sin(a)+Sin(a)*Cos(a)); -In( 5 ) = Exp(I*a)*Exp(-I*a) -Out( 5 ) = Complex(Cos(a)^2+Sin(a)^2,Sin(a)*Cos(a)-Cos(a)*Sin(a)); - -In( 5 ) = Exp(I*a)*Exp(I*b) -Out( 5 ) = Complex(Cos(a)*Cos(b)-Sin(a)*Sin(b),Cos(a)*Sin(b)+Sin(a)*Cos(b)); -In( 6 ) = Exp(I*a)*Exp(-I*b) -Out( 6 ) = Complex(Cos(a)*Cos(b)+Sin(a)*Sin(b),Sin(a)*Cos(b)-Cos(a)*Sin(b)); - - -*/ - - - -%/mathpiper - - - -%mathpiper_docs,name="TrigSimpCombine",categories="User Functions;Expression Simplification" -*CMD TrigSimpCombine --- combine products of trigonometric functions -*STD -*CALL - TrigSimpCombine(expr) - -*PARMS - -{expr} -- expression to simplify - -*DESC - -This function applies the product rules of trigonometry, e.g. -$Cos(u)*Sin(v) = (1/2)*(Sin(v-u) + Sin(v+u))$. As a -result, all products of the trigonometric functions {Cos} and {Sin} disappear. The function also tries to simplify the resulting expression as much as -possible by combining all similar terms. - -This function is used in for instance {Integrate}, -to bring down the expression into a simpler form that hopefully can be -integrated easily. - -*E.G. - - In> PrettyPrinter'Set("PrettyForm"); - - True - - In> TrigSimpCombine(Cos(a)^2+Sin(a)^2) - - 1 - - In> TrigSimpCombine(Cos(a)^2-Sin(a)^2) - - Cos( -2 * a ) - - Out> - In> TrigSimpCombine(Cos(a)^2*Sin(b)) - - Sin( b ) Sin( -2 * a + b ) - -------- + ----------------- - 2 4 - - Sin( -2 * a - b ) - - ----------------- - 4 - -*SEE Simplify, Integrate, Expand, Sin, Cos, Tan -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/BigOh.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/BigOh.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/BigOh.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/BigOh.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="BigOh" - -10 # BigOh(UniVariate(_var,_first,_coefs),_var,_degree) <-- - [ - While(first+Length(coefs)>=(degree+1) And Length(coefs)>0) DestructiveDelete(coefs,Length(coefs)); - UniVariate(var,first,coefs); - ]; -20 # BigOh(_uv,_var,_degree)_CanBeUni(uv,var) <-- NormalForm(BigOh(MakeUni(uv,var),var,degree)); - -%/mathpiper - - - -%mathpiper_docs,name="BigOh",categories="User Functions;Series" -*CMD BigOh --- drop all terms of a certain order in a polynomial -*STD -*CALL - BigOh(poly, var, degree) - -*PARMS - -{poly} -- a univariate polynomial - -{var} -- a free variable - -{degree} -- positive integer - -*DESC - -This function drops all terms of order "degree" or higher in -"poly", which is a polynomial in the variable "var". - -*E.G. - - In> BigOh(1+x+x^2+x^3,x,2) - Out> x+1; - -*SEE Taylor, InverseTaylor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/CanBeUni.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/CanBeUni.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/CanBeUni.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/CanBeUni.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -%mathpiper,def="CanBeUni" - -/* CanBeUni returns whether the function can be converted to a - * univariate, with respect to a variable. - */ -Function("CanBeUni",{expression}) CanBeUni(UniVarList(expression),expression); - - -/* Accepting an expression as being convertable to univariate */ - -/* Dealing wiht a list of variables. The poly should be expandable - * to each of these variables (smells like tail recursion) - */ -10 # CanBeUni({},_expression) <-- True; -20 # CanBeUni(var_IsList,_expression) <-- - CanBeUni(First(var),expression) And CanBeUni(Rest(var),expression); - -/* Atom can always be a polynom to any variable */ -30 # CanBeUni(_var,expression_IsAtom) <-- True; -35 # CanBeUni(_var,expression_IsFreeOf(var)) <-- True; - -/* Other patterns supported. */ -40 # CanBeUni(_var,_x + _y) <-- CanBeUni(var,x) And CanBeUni(var,y); -40 # CanBeUni(_var,_x - _y) <-- CanBeUni(var,x) And CanBeUni(var,y); -40 # CanBeUni(_var, + _y) <-- CanBeUni(var,y); -40 # CanBeUni(_var, - _y) <-- CanBeUni(var,y); -40 # CanBeUni(_var,_x * _y) <-- CanBeUni(var,x) And CanBeUni(var,y); -40 # CanBeUni(_var,_x / _y) <-- CanBeUni(var,x) And IsFreeOf(var,y); -/* Special case again: raising powers */ -40 # CanBeUni(_var,_x ^ y_IsInteger)_(y >= 0 And CanBeUni(var,x)) <-- True; -41 # CanBeUni(_var,(x_IsFreeOf(var)) ^ (y_IsFreeOf(var))) <-- True; -50 # CanBeUni(_var,UniVariate(_var,_first,_coefs)) <-- True; -1000 # CanBeUni(_var,_f)_(Not(IsFreeOf(var,f))) <-- False; -1001 # CanBeUni(_var,_f) <-- True; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Coef.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Coef.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Coef.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Coef.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%mathpiper,def="Coef" - -5 # Coef(uv_IsUniVar,order_IsList) <-- -[ - Local(result); - result:={}; - ForEach(item,order) - [ - DestructiveAppend(result,Coef(uv,item)); - ]; - result; -]; - -10 # Coef(uv_IsUniVar,order_IsInteger)_(order=uv[2]+Length(uv[3])) <-- 0; -20 # Coef(uv_IsUniVar,order_IsInteger) <-- uv[3][(order-uv[2])+1]; -30 # Coef(uv_CanBeUni,_order)_(IsInteger(order) Or IsList(order)) <-- Coef(MakeUni(uv),order); - -Function("Coef",{expression,var,order}) - NormalForm(Coef(MakeUni(expression,var),order)); - - - -%/mathpiper - - - -%mathpiper_docs,name="Coef",categories="User Functions;Polynomials (Operations)" -*CMD Coef --- coefficient of a polynomial -*STD -*CALL - Coef(expr, var, order) - -*PARMS - -{expr} -- a polynomial - -{var} -- a variable occurring in "expr" - -{order} -- integer or list of integers - -*DESC - -This command returns the coefficient of "var" to the power "order" -in the polynomial "expr". The parameter "order" can also be a list -of integers, in which case this function returns a list of -coefficients. - -*E.G. - - In> e := Expand((a+x)^4,x) - Out> x^4+4*a*x^3+(a^2+(2*a)^2+a^2)*x^2+ - (a^2*2*a+2*a^3)*x+a^4; - In> Coef(e,a,2) - Out> 6*x^2; - In> Coef(e,a,0 .. 4) - Out> {x^4,4*x^3,6*x^2,4*x,1}; - -*SEE Expand, Degree, LeadingCoef -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Content.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Content.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Content.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Content.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -%mathpiper,def="Content" - -10 # Content(UniVariate(_var,_first,_coefs)) <-- Gcd(coefs)*var^first; -20 # Content(poly_CanBeUni) <-- NormalForm(Content(MakeUni(poly))); - -%/mathpiper - - - -%mathpiper_docs,name="Content",categories="User Functions;Polynomials (Operations)" -*CMD Content --- content of a univariate polynomial -*STD -*CALL - Content(expr) - -*PARMS - -{expr} -- univariate polynomial - -*DESC - -This command determines the content of a univariate polynomial. The -content is the greatest common divisor of all the terms in the -polynomial. Every polynomial can be written as the product of the -content with the primitive part. - -*E.G. - - In> poly := 2*x^2 + 4*x; - Out> 2*x^2+4*x; - In> c := Content(poly); - Out> 2*x; - In> pp := PrimitivePart(poly); - Out> x+2; - In> Expand(pp*c); - Out> 2*x^2+4*x; - -*SEE PrimitivePart, Gcd -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/cyclotomic/Cyclotomic.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/cyclotomic/Cyclotomic.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/cyclotomic/Cyclotomic.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/cyclotomic/Cyclotomic.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,226 +0,0 @@ -%mathpiper,def="Cyclotomic" - -// Cyclotomic(n,x): -// Returns the cyclotomic polinomial in the variable x -// (which is the minimal polynomial of the n-th primitive -// roots of the unit). -// Autor: Pablo De Napoli - -Use("org/mathpiper/assembledscripts/univar.rep/code.mpi"); - -// Auxiliar function for Cyclotomic: returns the internal representation of -// x^q+a as an univarate polinomial (like MakeUni(x^q+a) but more efficient) - -Function ("UniVariateBinomial",{x,q,a}) -[ -Local(L,i); -L := {a}; -For (i:=1,i0,i--) - [ - Local(term); - exponent := first+i-1; - c:= coefs[i]; - nc := If(IsEven(exponent),c,-c); - term:=NormalForm(nc*var^(exponent*k)); - result:=result+term; - ]; - result; -]; - -// Returns a list of elements of the form {d1,d2,m} -// where -// 1) d1,d2 runs through the square free divisors of n -// 2) d1 divides d2 and d2/d1 is a prime factor of n -// 3) m=Moebius(d1) -// Addapted form: MoebiusDivisorsList - -CyclotomicDivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {{1,nFactors[1][1],1}}; - nFactors := Rest(nFactors); - ForEach (f,nFactors) - [ - oldresult := result; - ForEach (x,oldresult) - result:=Append(result,{x[1]*f[1],x[2]*f[1],-x[3]}); - ]; - result; -]; - -// CyclotomicFactor(x,a,b): Auxiliary function that constructs the term list of -// the polynomial -// Div(x^a-1,x^b-1) = -// x^(b*(p-1)) + x^(b^*(p-2)) + ... + x^(b) + 1 -// p= a/b, b should divide a - - -CyclotomicFactor(_a,_b) <-- -[ - Local(coef,p,i,j,result); p := a/b; result:= {{b*(p-1),1}}; For (i:= - p-2,i>=0,i--) - DestructiveAppend(result,{b*i,1}); - result; -]; - - - -// This new implementation makes use of the internal representations of univariate -// polynomials as SparseUniVar(var,termlist). - - -// For n even, we write n= m*k, where k is a Power of 2 -// and m is odd, and redce it to the case m even since: -// -// Cyclotomic(n,x) = Cyclotomic(m,-x^{k/2}) -// -// If m=1, n is a power of 2, and Cyclotomic(n,x)= x^k+1 */ - - -10 # InternalCyclotomic(n_IsEven,_x) <-- - [ - Local(k,m,result,p,t); - k := 1; - m := n; - While(IsEven(m)) - [ - k := k*2; - m := m/2; - ]; - k := k/2 ; - If(m>1, [ - p:= InternalCyclotomic(m,x)[2]; - // Substitute x by -x^k - result:={}; - ForEach(t,p) - DestructiveAppend(result, {t[1]*k,If(IsEven(t[1]),t[2],-t[2])}); - ], - result := {{k,1},{0,1}} // x^k+1 - ); - SparseUniVar(x,result); - ]; - - -// For n odd, the algoritm is based on the formula -// -// Cyclotomic(n,x) := Prod (x^(n/d)-1)^Moebius(d) -// -// where d runs through the divisors of n. - -// We compute in poly1 the product -// of (x^(n/d)-1) with Moebius(d)=1 , and in poly2 the product of these polynomials -// with Moebius(d)=-1. Finally we compute the quotient poly1/poly2 - -// In order to compute this in a efficient way, we use the functions -// CyclotomicDivisorsList and CyclotomicFactors (in order to avoid -// unnecesary polynomial divisions) - - -20 # InternalCyclotomic(n_IsOdd,_x)_(n>1) <-- -[ - Local(divisors,poly1,poly2,q,d,f,coef,i,j,result); - divisors := CyclotomicDivisorsList(n); - poly1 := {{0,1}}; - poly2 := {{0,1}}; - ForEach (d,divisors) - [ - If(InVerboseMode(),Echo("d=",d)); - f:= CyclotomicFactor(n/d[1],n/d[2]); - If (d[3]=1,poly1:=MultiplyTerms(poly1,f),poly2:=MultiplyTerms(poly2,f)); - If(InVerboseMode(), - [ - Echo("poly1=",poly1); - Echo("poly2=",poly2); - ]); - ]; - If(InVerboseMode(),Echo("End ForEach")); - result := If(poly2={{0,1}},poly1,DivTermList(poly1,poly2)); - SparseUniVar(x,result); -]; - - -10 # Cyclotomic(1,_x) <-- x-1; -20 # Cyclotomic(n_IsInteger,_x) <-- ExpandSparseUniVar(InternalCyclotomic(n,x)); - - - -%/mathpiper - - - -%mathpiper_docs,name="Cyclotomic",categories="User Functions;Number Theory" -*CMD Cyclotomic --- construct the cyclotomic polynomial -*STD -*CALL - Cyclotomic(n,x) - -*PARMS - -{n} -- positive integer - -{x} -- variable - -*DESC - -Returns the cyclotomic polynomial in the variable {x} -(which is the minimal polynomial of the $n$-th primitive -roots of the unit, over the field of rational numbers). - -For $n$ even, we write $n= m*k$, where $k$ is a power of $2$ -and $m$ is odd, and reduce it to the case of even $m$ since -$$ Cyclotomic(n,x) = Cyclotomic(m,-x^(k/2)) $$. - -If $m=1$, $n$ is a power of $2$, and $Cyclotomic(n,x)= x^k+1$. - -For $n$ odd, the algorithm is based on the formula -$$ Cyclotomic(n,x) := Prod((x^(n/d)-1)^mu(d)) $$, -where $d$ runs through the divisors of $n$. -In order to compute this in a efficient way, we use the function -{MoebiusDivisorsList}. Then we compute in {poly1} the product -of $x^(n/d)-1$ with $mu(d)=1$ , and in {poly2} the product of these polynomials -with $mu(d)= -1$. Finally we compute the quotient {poly1}/{poly2}. - -*SEE RamanujanSum -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/cyclotomic/OldCyclotomic.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/cyclotomic/OldCyclotomic.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/cyclotomic/OldCyclotomic.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/cyclotomic/OldCyclotomic.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="OldCyclotomic" - -// OldInternalCyclotomic(n,x,WantNormalForm) is the internal implementation -// WantNormalForm is a boolean parameter. If it is true, returns the normal -// form, if it is false returns the UniVariate representation. - -// This (old) implementation makes use of the internal representations of univariate -// polynomials as UniVariate(var,begining,coefficients). -// There is also a version UniVariateCyclotomic(n,x) that returns the -// cyclotomic polynomial in the UniVariate representation. - - -10 # OldInternalCyclotomic(n_IsEven,_x,WantNormalForm_IsBoolean) <-- - [ - Local(k,m,p); - k := 1; - m := n; - While(IsEven(m)) - [ - k := k*2; - m := m/2; - ]; - k := k/2 ; - If(m>1, [ - p := OldInternalCyclotomic(m,x,False); - If (WantNormalForm, SubstituteAndExpandInUniVar(p,k),SubstituteInUniVar(p,k)); - ], - If (WantNormalForm, x^k+1, UniVariateBinomial(x,k,1)) - ); - ]; - -20 # OldInternalCyclotomic(n_IsOdd,_x,WantNormalForm_IsBoolean)_(n>1) <-- -[ - Local(divisors,poly1,poly2,q,d,f,result); - divisors := MoebiusDivisorsList(n); - poly1 :=1 ; - poly2 := 1; - ForEach (d,divisors) - [ - q:=n/d[1]; - f:=UniVariateBinomial(x,q,-1); - If (d[2]=1,poly1:=poly1*f,poly2:=poly2*f); - ]; - result := Div(poly1,poly2); - If(WantNormalForm,NormalForm(result),result); -]; - -10 # OldCyclotomic(1,_x) <-- _x-1; -20 # OldCyclotomic(n_IsInteger,_x) <-- OldInternalCyclotomic(n,x,True); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/cyclotomic/UniVariateCyclotomic.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/cyclotomic/UniVariateCyclotomic.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/cyclotomic/UniVariateCyclotomic.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/cyclotomic/UniVariateCyclotomic.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -%mathpiper,def="UniVariateCyclotomic" - -// This function returns the Cyclotomic polynomial, but in the univariate -// representation - -10 # UniVariateCyclotomic(1,_x) <-- UniVariate(x,0,{-1,1}); -20 # UniVariateCyclotomic(n_IsInteger,_x) <-- OldInternalCyclotomic(n,x,False); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Degree.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Degree.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Degree.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Degree.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="Degree" - -RuleBase("Degree",{expr}); -Rule("Degree",1,0, IsUniVar(expr)) -[ - - Local(i,min,max); - min:=expr[2]; - max:=min+Length(expr[3]); - i:=max; - While(i >= min And IsZero(Coef(expr,i))) i--; - i; -]; - -10 # Degree(_poly) <-- Degree(MakeUni(poly)); -10 # Degree(_poly,_var) <-- Degree(MakeUni(poly,var)); - -%/mathpiper - - - -%mathpiper_docs,name="Degree",categories="User Functions;Polynomials (Operations)" -*CMD Degree --- degree of a polynomial -*STD -*CALL - Degree(expr) - Degree(expr, var) - -*PARMS - -{expr} -- a polynomial - -{var} -- a variable occurring in "expr" - -*DESC - -This command returns the degree of the polynomial "expr" with -respect to the variable "var". The degree is the highest power of -"var" occurring in the polynomial. If only one variable occurs in -"expr", the first calling sequence can be used. Otherwise the user -should use the second form in which the variable is explicitly -mentioned. - -*E.G. - - In> Degree(x^5+x-1); - Out> 5; - In> Degree(a+b*x^3, a); - Out> 1; - In> Degree(a+b*x^3, x); - Out> 3; - -*SEE Expand, Coef -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/DivPoly.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/DivPoly.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/DivPoly.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/DivPoly.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -%mathpiper,def="DivPoly" - -DivPoly(_A,_B,_var,_deg) <-- -[ - Local(a,b,c,i,j,denom); - b:=MakeUni(B,var); - denom:=Coef(b,0); - - if (denom = 0) - [ - Local(f); - f:=Content(b); - b:=PrimitivePart(b); - A:=Simplify(A/f); - denom:=Coef(b,0); - ]; - a:=MakeUni(A,var); - - c:=FillList(0,deg+1); - For(i:=0,i<=deg,i++) - [ - Local(sum,j); - sum:=0; - For(j:=0,j0,i--) - [ - Local(term); - term:=NormalForm(coefs[i])*var^(first+i-1); - result:=result+term; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/FactorUniVar.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/FactorUniVar.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/FactorUniVar.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/FactorUniVar.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Horner.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Horner.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Horner.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Horner.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -%mathpiper,def="Horner" - -Horner(_e,_v) <-- -[ - Local(uni,coefs,result); - uni := MakeUni(e,v); - coefs:=DestructiveReverse(uni[3]); - result:=0; - - While(coefs != {}) - [ - result := result*v; - result := result+First(coefs); - coefs := Rest(coefs); - ]; - result:=result*v^uni[2]; - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="Horner",categories="User Functions;Polynomials (Operations)" -*CMD Horner --- convert a polynomial into the Horner form -*STD -*CALL - Horner(expr, var) - -*PARMS - -{expr} -- a polynomial in "var" - -{var} -- a variable - -*DESC - -This command turns the polynomial "expr", considered as a univariate -polynomial in "var", into Horner form. A polynomial in normal form -is an expression such as -$$c[0] + c[1]*x + ... + c[n]*x^n$$. - -If one converts this polynomial into Horner form, one gets the -equivalent expression -$$(...( c[n] * x + c[n-1] ) * x + ... + c[1] ) * x + c[0]$$. - -Both expression are equal, but the latter form gives a more -efficient way to evaluate the polynomial as the powers have -disappeared. - -*E.G. - - In> expr1:=Expand((1+x)^4) - Out> x^4+4*x^3+6*x^2+4*x+1; - In> Horner(expr1,x) - Out> (((x+4)*x+6)*x+4)*x+1; - -*SEE Expand, ExpandBrackets, EvaluateHornerScheme -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/IsUniVar.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/IsUniVar.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/IsUniVar.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/IsUniVar.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -%mathpiper,def="IsUniVar" - -10 # IsUniVar(UniVariate(_var,_first,_coefs)) <-- True; -20 # IsUniVar(_anything) <-- False; - -200 # aLeft_IsUniVar ^ aRight_IsPositiveInteger <-- - RepeatedSquaresMultiply(aLeft,aRight); - - -200 # aLeft_IsUniVar - aRight_IsUniVar <-- -[ - Local(from,result); - Local(curl,curr,left,right); - - curl:=aLeft[2]; - curr:=aRight[2]; - left:=aLeft[3]; - right:=aRight[3]; - result:={}; - from:=Min(curl,curr); - - While(curl poly := 2*x^2 + 4*x; - Out> 2*x^2+4*x; - In> lc := LeadingCoef(poly); - Out> 2; - In> m := Monic(poly); - Out> x^2+2*x; - In> Expand(lc*m); - Out> 2*x^2+4*x; - - In> LeadingCoef(2*a^2 + 3*a*b^2 + 5, a); - Out> 2; - In> LeadingCoef(2*a^2 + 3*a*b^2 + 5, b); - Out> 3*a; - -*SEE Coef, Monic - -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/MakeUni.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/MakeUni.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/MakeUni.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/MakeUni.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -%mathpiper,def="MakeUni" - -Function("MakeUni",{expression}) MakeUni(expression,UniVarList(expression)); - -/* Convert normal form to univariate expression */ -RuleBase("MakeUni",{expression,var}); - -5 # MakeUni(_expr,{}) <-- UniVariate(dummyvar,0,{expression}); -6 # MakeUni(_expr,var_IsList) <-- -[ - Local(result,item); - result:=expression; - ForEach(item,var) - [ - result:=MakeUni(result,item); - ]; - result; -]; - -10 # MakeUni(UniVariate(_var,_first,_coefs),_var) <-- - UniVariate(var,first,coefs); - -20 # MakeUni(UniVariate(_v,_first,_coefs),_var) <-- -[ - Local(reslist,item); - reslist:={}; - ForEach(item,expression[3]) - [ - If(IsFreeOf(var,item), - DestructiveAppend(reslist,item), - DestructiveAppend(reslist,MakeUni(item,var)) - ); - ]; - UniVariate(expression[1],expression[2],reslist); -]; - - -LocalSymbols(a,b,var,expression) -[ - 20 # MakeUni(expression_IsFreeOf(var),_var) - <-- UniVariate(var,0,{expression}); - 30 # MakeUni(_var,_var) <-- UniVariate(var,1,{1}); - 30 # MakeUni(_a + _b,_var) <-- MakeUni(a,var) + MakeUni(b,var); - 30 # MakeUni(_a - _b,_var) <-- MakeUni(a,var) - MakeUni(b,var); - 30 # MakeUni( - _b,_var) <-- - MakeUni(b,var); - 30 # MakeUni(_a * _b,_var) <-- MakeUni(a,var) * MakeUni(b,var); - 1 # MakeUni(_a ^ n_IsInteger,_var) <-- MakeUni(a,var) ^ n; - 30 # MakeUni(_a / (b_IsFreeOf(var)),_var) <-- MakeUni(a,var) * (1/b); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Monic.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Monic.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/Monic.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/Monic.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -%mathpiper,def="Monic" - -10 # Monic(UniVariate(_var,_first,_coefs)) <-- -[ - DropEndZeroes(coefs); - UniVariate(var,first,coefs/coefs[Length(coefs)]); -]; -20 # Monic(poly_CanBeUni) <-- NormalForm(Monic(MakeUni(poly))); - -30 # Monic(_poly,_var)_CanBeUni(poly,var) <-- NormalForm(Monic(MakeUni(poly,var))); - -%/mathpiper - - - -%mathpiper_docs,name="Monic",categories="User Functions;Polynomials (Operations)" -*CMD Monic --- monic part of a polynomial -*STD -*CALL - Monic(poly) - Monic(poly, var) - -*PARMS - -{poly} -- a polynomial - -{var} -- a variable - -*DESC - -This function returns the monic part of "poly", regarded as a -polynomial in the variable "var". The monic part of a polynomial is -the quotient of this polynomial by its leading coefficient. So the -leading coefficient of the monic part is always one. If only one -variable appears in the expression "poly", it is obvious that it -should be regarded as a polynomial in this variable and the first -calling sequence may be used. - -*E.G. - - In> poly := 2*x^2 + 4*x; - Out> 2*x^2+4*x; - In> lc := LeadingCoef(poly); - Out> 2; - In> m := Monic(poly); - Out> x^2+2*x; - In> Expand(lc*m); - Out> 2*x^2+4*x; - - In> Monic(2*a^2 + 3*a*b^2 + 5, a); - Out> a^2+(a*3*b^2)/2+5/2; - In> Monic(2*a^2 + 3*a*b^2 + 5, b); - Out> b^2+(2*a^2+5)/(3*a); - -*SEE LeadingCoef -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/NormalForm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/NormalForm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/NormalForm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/NormalForm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -%mathpiper,def="" - -/* -Note:tk:since this version of NormalForm is only used in univariate functions, and since - the standard version of NormalForm is published as a def in standard.mrw, -I am not publishing it as a def here. -*/ - -0 # NormalForm(UniVariate(_var,_first,_coefs)) <-- - ExpandUniVariate(var,first,coefs); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/PrimitivePart.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/PrimitivePart.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/PrimitivePart.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/PrimitivePart.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="PrimitivePart" - -10 # PrimitivePart(UniVariate(_var,_first,_coefs)) <-- - UniVariate(var,0,coefs/Gcd(coefs)); -20 # PrimitivePart(poly_CanBeUni) <-- NormalForm(PrimitivePart(MakeUni(poly))); - -%/mathpiper - - - -%mathpiper_docs,name="PrimitivePart",categories="User Functions;Polynomials (Operations)" -*CMD PrimitivePart --- primitive part of a univariate polynomial -*STD -*CALL - PrimitivePart(expr) - -*PARMS - -{expr} -- univariate polynomial - -*DESC - -This command determines the primitive part of a univariate -polynomial. The primitive part is what remains after the content (the -greatest common divisor of all the terms) is divided out. So the -product of the content and the primitive part equals the original -polynomial. - -*E.G. - - In> poly := 2*x^2 + 4*x; - Out> 2*x^2+4*x; - In> c := Content(poly); - Out> 2*x; - In> pp := PrimitivePart(poly); - Out> x+2; - In> Expand(pp*c); - Out> 2*x^2+4*x; - -*SEE Content -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/PSolve.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/PSolve.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/PSolve.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/PSolve.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -%mathpiper,def="PSolve" - -RuleBase("PSolve",{uni}); - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 1) - -Coef(uni,0)/Coef(uni,1); - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 2) - [ - Local(a,b,c,d); - c:=Coef(uni,0); - b:=Coef(uni,1); - a:=Coef(uni,2); - d:=b*b-4*a*c; - {(-b+Sqrt(d))/(2*a),(-b-Sqrt(d))/(2*a)}; - ]; - - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 3 ) - [ - Local(p,q,r,w,ww,a,b); - Local(coef0,coef1,coef3,adjust); - -/* Get coefficients for a new polynomial, such that the coefficient of - degree 2 is zero: - Take f(x)=a0+a1*x+a2*x^2+a3*x^3 and substitute x = x' + adjust - This gives g(x) = b0+b1*x+b2*x^2+b3*x^3 where - b3 = a3; - b2 = 0 => adjust = (-a2)/(3*a3); - b1 = 2*a2*adjust+3*a3*adjust^2+a1; - b0 = a2*adjust^2+a3*adjust^3+adjust*a1+a0; - - After solving g(x') = 0, return x = x' + adjust. -*/ - - adjust := (-Coef(uni,2))/(3*Coef(uni,3)); - coef3 := Coef(uni,3); - coef1 := 2*Coef(uni,2)*adjust+3*Coef(uni,3)*adjust^2+Coef(uni,1); - coef0 := Coef(uni,2)*adjust^2+Coef(uni,3)*adjust^3+ - adjust*Coef(uni,1)+Coef(uni,0); - - p:=coef3; - q:=coef1/p; - r:=coef0/p; - w:=Complex(-1/2,Sqrt(3/4)); - ww:=Complex(-1/2,-Sqrt(3/4)); - -/* Equation is xxx + qx + r = 0 */ -/* Let x = a + b - a^3 + b^3 + 3(aab + bba) + q(a + b) + r = 0 - a^3 + b^3 + (3ab+q)x + r = 0 - - Let 3ab+q = 0. This is permissible, for we can still find a+b == x - - a^3 + b^3 = -r - (ab)^3 = -q^3/27 - - So a^3 and b^3 are the roots of t^2 + rt - q^3/27 = 0 - - Let - a^3 = -r/2 + Sqrt(q^3/27+ rr/4) - b^3 = -r/2 - Sqrt(q^3/27+ rr/4) - Therefore there are three values for each of a and b. - Clearly if ab = -q/3 is true then (wa)(wwb) == (wb)(wwa) == -q/3 -*/ - - a:=(-r/2 + Sqrt(q^3/27+ r*r/4))^(1/3); - b:=(-r/2 - Sqrt(q^3/27+ r*r/4))^(1/3); - - {a+b+adjust,w*a+ww*b+adjust,ww*a+w*b+adjust}; -]; - -/* -How to solve the quartic equation? - -The equation is x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = 0. -The idea is to write the left-hand side as the difference of two -squares: (x^2 + p x + q)^2 - (s x + t)^2. -Eliminating the parentheses and equation coefficients yields four -equations for the four unknowns p, q, s and t: - a1 = 2p (1) - a2 = p^2 + 2q - s^2 (2) - a3 = 2pq - 2st (3) - a4 = q^2 - t^2 (4) -From the first equation, we find that p = a1/2. Substituting this in -the other three equations and rearranging gives - s^2 = a1^2/4 - a2 + 2q (5) - 2st = a1 q - a3 (6) - t^2 = q^2 - a4 (7) -We now take the square (6) and substitute (5) and (7): - 4 (a1^2/4 - a2 + 2q) (q^2 - a4) = (a1 q - a3)^2 <==> - 8 q^3 - 4 a2 q^2 + (2 a1 a3 - 8 a4) q + 4 a2 a4 - a1^2 a4 - a3^2 = 0. -Miraculously, we got a cubic equation for q. Suppose we can solve this -equation. We can then compute t from (7): t = sqrt(q^2 - a4). If t is -nonzero, we can compute s from (6). Note that we cannot compute s from -(5), since we introduced an extra solution when squaring (6). However, -if t is zero, then no extra solution was introduced and we can safely -use (5). Having found the values of p, q, s and t, we can factor the -difference of squares and solve the quartic: - x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = (x^2 + p x + q)^2 - (s x + t)^2 - = (x^2 + p x + q + s x + t) (x^2 + p x + q - sx - t). -The four roots of the quartic are the two roots of the first quadratic -factor plus the two roots of the second quadratic factor. -*/ - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 4 ) -[ - Local(coef4,a1,a2,a3,a4,y,y1,z,t,s); - - coef4:=Coef(uni,4); - a1:=Coef(uni,3)/coef4; - a2:=Coef(uni,2)/coef4; - a3:=Coef(uni,1)/coef4; - a4:=Coef(uni,0)/coef4; - - /* y1 = 2q, with q as above. */ - y1:=First(PSolve(y^3-a2*y^2+(a1*a3-4*a4)*y+(4*a2*a4-a3^2-a1^2*a4),y)); - t := Sqrt(y1^2/4-a4); - If(t=0, s:=Sqrt(y1+a1^2/4-a2), s:=(a1*y1-2*a3)/(4*t)); - Concat(PSolve(z^2+(a1/2+s)*z+y1/2+t,z), - PSolve(z^2+(a1/2-s)*z+y1/2-t,z)); -]; - -Function("PSolve",{uni,var}) - [ - PSolve(MakeUni(uni,var)); - ]; - -%/mathpiper - - - -%mathpiper_docs,name="PSolve",categories="User Functions;Solvers (Symbolic)" -*CMD PSolve --- solve a polynomial equation -*STD -*CALL - PSolve(poly, var) - -*PARMS - -{poly} -- a polynomial in "var" - -{var} -- a variable - -*DESC - -This commands returns a list containing the roots of "poly", -considered as a polynomial in the variable "var". If there is only -one root, it is not returned as a one-entry list but just by -itself. A double root occurs twice in the result, and similarly for -roots of higher multiplicity. All polynomials of degree up to 4 are -handled. - -*E.G. - - In> PSolve(b*x+a,x) - Out> -a/b; - In> PSolve(c*x^2+b*x+a,x) - Out> {(Sqrt(b^2-4*c*a)-b)/(2*c),(-(b+ - Sqrt(b^2-4*c*a)))/(2*c)}; - -*SEE Solve, Factor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/RepeatedSquaresMultiply.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/RepeatedSquaresMultiply.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/RepeatedSquaresMultiply.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/RepeatedSquaresMultiply.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -%mathpiper,def="RepeatedSquaresMultiply",scope="private" - -/* Repeated squares multiplication - TODO put somewhere else!!! - */ -10 # RepeatedSquaresMultiply(_a,- (n_IsInteger)) <-- 1/RepeatedSquaresMultiply(a,n); - -15 # RepeatedSquaresMultiply(UniVariate(_var,_first,{_coef}),(n_IsInteger)) <-- - UniVariate(var,first*n,{coef^n}); -20 # RepeatedSquaresMultiply(_a,n_IsInteger) <-- -[ - Local(m,b); - Set(m,1); - Set(b,1); - While(m<=n) Set(m,(ShiftLeft(m,1))); - Set(m, ShiftRight(m,1)); - While(m>0) - [ - Set(b,b*b); - If (Not(Equals(BitAnd(m,n), 0)),Set(b,b*a)); - Set(m, ShiftRight(m,1)); - ]; - b; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/SetOrder.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/SetOrder.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/SetOrder.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/SetOrder.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -%mathpiper,def="" - -//Not implemented in scripts. todo:tk. - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/AddTerm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/AddTerm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/AddTerm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/AddTerm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -%mathpiper,def="AddTerm" - -/* -Note:tk:I am publishing this function as a def because -but it seems like it was meant to be a published function. -*/ - -// Add a term into a termlist: this function assumes that -// 1) the list of terms is sorted in decreasing order of exponents -// 2) there are not two terms with the same exponent. -// 3) There is no term with cero coefficient -// This assumptions are preserved. - -// The parameter begining tell us where to begin the search -// (it is used for increasing the efficency of the algorithms!) -// The function returns the position at which the new term is added plus 1. -// (to be used as begining for sucesive AddTerm calls - -Function("AddTerm",{termlist,term,begining}) -[ - Local(l,i); - l := Length(termlist); - If(term[2]!=0, - [ - i:=begining; -// Fix-me: search by using binary search ? - If (l>=1, While ((i<=l) And (term[1]l, [DestructiveAppend(termlist,term);i++;], - If (term[1]=termlist[i][1], - [ Local(nc); - nc:=termlist[i][2]+term[2]; - If(nc!=0,DestructiveReplace(termlist,i,{term[1],nc}), - [DestructiveDelete(termlist,i);i--;]); - ], DestructiveInsert(termlist,i,term)) - ); - ] - ); - i+1; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/AddTerms.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/AddTerms.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/AddTerms.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/AddTerms.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="AddTerms" - -/* -Note:tk:I am publishing this function as a def because -but it seems like it was meant to be a published function. -*/ - -Function("AddTerms",{terms1,terms2}) -[ - Local(result,begining,t); - begining :=1; - ForEach (t,terms2) - begining :=AddTerm(terms1,t,begining); - terms1; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/DivTermList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/DivTermList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/DivTermList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/DivTermList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="DivTermList" - -// Implements the division of polynomials! - -Function("DivTermList",{a,b}) -[ - Local(q,nq,t,c,begining); - q := {}; - // a[1][1] is the degree of a, b[1][1] is the degree of b - While ((a!={}) And a[1][1]>=b[1][1]) - [ - begining := 1; - If(InVerboseMode(),Echo("degree=",a[1][1])); - nq := {a[1][1]-b[1][1],a[1][2]/b[1][2]}; // a new term of the quotient - DestructiveAppend(q,nq); - // We compute a:= a - nq* b - ForEach (t,b) - begining := AddTerm(a,{t[1]+nq[1],-t[2]*nq[2]},begining); - ]; - // a is the rest at the end - q; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/ExpandSparseUniVar.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/ExpandSparseUniVar.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/ExpandSparseUniVar.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/ExpandSparseUniVar.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -%mathpiper,def="ExpandSparseUniVar" - -Function("ExpandSparseUniVar",{s}) -[ - Local(result,t,var,termlist); - result :=0; - var := s[1]; - termlist := s[2]; - ForEach (t,termlist) - [ - Local(term); - term := NormalForm(t[2]*var^t[1]); - result := result + term; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/MultiplySingleTerm.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/MultiplySingleTerm.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/MultiplySingleTerm.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/MultiplySingleTerm.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -%mathpiper,def="MultiplySingleTerm" - -/* -Note:tk:I am publishing this function as a def because -but it seems like it was meant to be a published function. -*/ - -// Multiply a list of terms by a Single term. - -Function("MultiplySingleTerm",{termlist,term}) -[ - Local(result,t); - result:={}; - If(term[2]!=0, - ForEach (t,termlist) - DestructiveAppend(result,{t[1]+term[1],t[2]*term[2]}) ); - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/MultiplyTerms.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/MultiplyTerms.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/MultiplyTerms.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/MultiplyTerms.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -%mathpiper,def="MultiplyTerms" - -Function("MultiplyTerms",{terms1,terms2}) -[ - Local(result,t1,t2,begining); - result:={}; - ForEach (t1,terms1) - [ - begining :=1; - ForEach (t2,terms2) - begining := AddTerm(result,{t1[1]+t2[1],t1[2]*t2[2]},1); - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/SparseUniVar.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/SparseUniVar.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/SparseUniVar.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/SparseUniVar.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -%mathpiper,def="SparseUniVar" - -/* -Note:tk:I am publishing this function as a def because -but it seems like it was meant to be a published function. -*/ - -// SparceUniVariate(variable,termlist) implements an internal representation -// for univariate polynomials -// termlist is the list of terms in the form {exponent,coeficient} - -RuleBase("SparseUniVar",{var,termlist}); - -300 # SparseUniVar(_var,_terms1) * SparseUniVar(_var,_terms2) <-- -SparseUniVar(var, MultiplyTerms(terms1,terms2)); - -300 # SparseUniVar(_var,_terms1) + SparseUniVar(_var,_terms2) <-- -SparseUniVar(var, AddTerms(terms1,terms2)); - -300 # SparseUniVar(_var,_terms1) - SparseUniVar(_var,_terms2) <-- -SparseUniVar(var, SubstractTerms(terms1,terms2)); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/SubstractTerms.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/SubstractTerms.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sparse/SubstractTerms.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sparse/SubstractTerms.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -%mathpiper,def="SubstractTerms" - -/* -Note:tk:I am publishing this function as a def because -but it seems like it was meant to be a published function. -*/ - -Function("SubstractTerms",{terms1,terms2}) -[ - Local(result,t); - begining :=1 ; - ForEach (t,terms2) - begining := AddTerm(terms1,{t[1],-t[2]},1); - terms1; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/BoundRealRoots.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/BoundRealRoots.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/BoundRealRoots.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/BoundRealRoots.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -%mathpiper,def="BoundRealRoots" - -BoundRealRoots(_p) <-- -[ - BoundRealRoots(p,MinimumBound(p),MaximumBound(p)); -]; - -BoundRealRoots(_p,_Mmin,_Mmax) <-- -[ - Local(S,N,work,result,Vmin,Vmax,a,b,Va,Vb,c,Vc,x); - - result:={}; - if (IsZero(p Where x==0)) - [ - p:=Simplify(p/x); - result:={{0,0}}; - ]; - S:=SturmSequence(p); - Vmin := SturmVariations(S,-Infinity); - Vmax := SturmVariations(S,Infinity); - -//Echo("Vmin,Vmax = ",Vmin,Vmax); - - N:=Vmin - Vmax; - -//Echo("N = ",N); - -//Echo("Mmin,Mmax = ",Mmin,Mmax); - work:={}; - if (N=1) - [ - result:={{-Mmax,Mmax}}; - ]; - if (N>1) - [ - work := - { - {-Mmax,-Mmin,Vmin,SturmVariations(S,-Mmin)}, - { Mmin, Mmax,SturmVariations(S, Mmin),Vmax} - }; - ]; - -//Echo("Work start = ",work); - While(work != {}) - [ - {a,b,Va,Vb} := First(work); - work := Rest(work); - c:=(a+b)/2; -//Echo(a,b,c); - Vc := SturmVariations(S,c); - if (IsZero(p Where x == c)) - [ - Local(M,Vcmin,Vcplus,pnew); - pnew := Simplify((p Where x == x+c)/x); - M:=MinimumBound(pnew); -//Echo("Mi = ",M); - Vcmin := SturmVariations(S, c-M); - Vcplus := SturmVariations(S, c+M); - result:=Concat(result,{{c,c}}); - - if (Va = Vcmin+1) - [ - result:=Concat(result,{{a,c-M}}); - ]; - if (Va > Vcmin+1) - [ - work:=Concat(work,{{a,c-M,Va,Vcmin}}); - ]; - if (Vb = Vcplus-1) - [ - result:=Concat(result,{{c+M,b}}); - ]; - if (Vb < Vcplus-1) - [ - work:=Concat(work,{{c+M,b,Vcplus,Vb}}); - ]; - ] - else - [ - if (Va = Vc+1) - [ - result:=Concat(result,{{a,c}}); - ]; - if (Va > Vc+1) - [ - work:=Concat(work,{{a,c,Va,Vc}}); - ]; - if (Vb = Vc-1) - [ - result:=Concat(result,{{c,b}}); - ]; - if (Vb < Vc-1) - [ - work:=Concat(work,{{c,b,Vc,Vb}}); - ]; - ]; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/FindRealRoots.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/FindRealRoots.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/FindRealRoots.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/FindRealRoots.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -%mathpiper,def="FindRealRoots" - -FindRealRoots(_p) <-- -[ -//Echo("0..."); -//Echo("0..."); - p:=SquareFree(Rationalize(p)); -//Echo("1..."); -//Echo("2...",MinimumBound(p)); -//Echo("3...",MaximumBound(p)); - FindRealRoots(p,MinimumBound(p),MaximumBound(p)); -]; - -FindRealRoots(_p,_Mmin,_Mmax) <-- -[ - Local(bounds,result,i,prec,requiredPrec); -//Echo("bounds1"); - bounds := BoundRealRoots(p,Mmin,Mmax); -//Echo("bounds2"); - result:=FillList(0,Length(bounds)); - requiredPrec := BuiltinPrecisionGet(); - BuiltinPrecisionSet(BuiltinPrecisionGet()+2); - prec:=10^-(requiredPrec+1); - - For(i:=1,i<=Length(bounds),i++) - [ - Local(a,b,c,r); - {a,b} := bounds[i]; - c:=N(Eval((a+b)/2)); -//Echo(a,b,c); - r := Fail; -//Echo("newton1",`Hold(Newton(@p,x,@c,@prec,@a,@b))); - if (a != b) [r := `Newton(@p,x,@c,prec,a,b);]; -//Echo("newton2",r," ",CurrentFile(),CurrentLine()); - if (r = Fail) - [ - Local(c,cold,pa,pb,pc); - pa:=(p Where x==a); - pb:=(p Where x==b); - c:=((a+b)/2); - cold := a; - While (Abs(cold-c)>prec) - [ - pc:=(p Where x==c); -//Echo(a,b,c); - if (Abs(pc) < prec) - [ - a:=c; - b:=c; - ] - else if (pa*pc < 0) - [ - b:=c; - pb:=pc; - ] - else - [ - a:=c; - pa:=pc; - ]; - cold:=c; - c:=((a+b)/2); - ]; - r:=c; - ]; - result[i] := N(Eval((r/10)*(10)),requiredPrec); - ]; - BuiltinPrecisionSet(requiredPrec); - result; -]; - -%/mathpiper - - - -%mathpiper_docs,name="FindRealRoots",categories="User Functions;Solvers (Numeric)" -*CMD FindRealRoots --- find the real roots of a polynomial -*STD -*CALL - FindRealRoots(p) - -*PARMS - -{p} - a polynomial in {x} - -*DESC - -Return a list with the real roots of $ p $. It tries to find the real-valued -roots, and thus requires numeric floating point calculations. The precision -of the result can be improved by increasing the calculation precision. - -*E.G. notest - - In> p:=Expand((x+3.1)^5*(x-6.23)) - Out> x^6+9.27*x^5-0.465*x^4-300.793*x^3- - 1394.2188*x^2-2590.476405*x-1783.5961073; - In> FindRealRoots(p) - Out> {-3.1,6.23}; - -*SEE SquareFree, NumRealRoots, MinimumBound, MaximumBound, Factor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/MaximumBound.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/MaximumBound.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/MaximumBound.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/MaximumBound.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -%mathpiper,def="MaximumBound" - -/** Maximum bound on the absolute value of the roots of a - polynomial p in variable x, according to Knuth: - - Max( Abs(a[n-1]/a[n]) , Abs(a[n-2]/a[n])^(1/2), ... , Abs(a[0]/a[n])^(1/n) ) - - As described in Davenport. - */ - 5 # MaximumBound(_p)_(IsZero(p Where x==0)) <-- MaximumBound(Simplify(p/x)); -10 # MaximumBound(_p)_(Degree(p)>0) <-- -[ - Local(an); - an:=Coef(p,(Degree(p)-1) .. 0)/Coef(p,Degree(p)); - an := N(Eval(Abs(an)^(1/(1 .. Degree(p))))); - Rationalize(2*Max(an)); -]; - -20 # MaximumBound(_p) <-- Infinity; - -%/mathpiper - - - -%mathpiper_docs,name="MaximumBound",categories="User Functions;Solvers (Numeric)" -*CMD MaximumBound --- return upper bounds on the absolute values of real roots of a polynomial -*STD -*CALL - MaximumBound(p) - -*PARMS - -{p} - a polynomial in $x$ - -*DESC - -Return maximum bounds for the absolute values of the real -roots of a polynomial {p}. The polynomial has to be converted to one with -rational coefficients first, and be made square-free. -The polynomial must use the variable {x}. - -*E.G. - - In> p:=SquareFree(Rationalize((x-3.1)*(x+6.23))) - Out> (-40000*x^2-125200*x+772520)/870489; - In> MaximumBound(p) - Out> 10986639613/1250000000; - In> N(%) - Out> 8.7893116904; - -*SEE MinimumBound, SquareFree, NumRealRoots, FindRealRoots, Factor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/MinimumBound.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/MinimumBound.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/MinimumBound.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/MinimumBound.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%mathpiper,def="MinimumBound" - -10 # MinimumBound(_p)_(IsZero(p Where x==0)) <-- 0; - -20 # MinimumBound(_p)_(Degree(p)>0) <-- -[ - Local(an,result); - an:=Coef(p,1 .. (Degree(p)))/Coef(p,0); - an := N(Eval(Abs(an)^(1/(1 .. Degree(p))))); - - result:=0; - an:=2*Max(an); - if(Not IsZero(an)) [result := 1/an;]; - Simplify(Rationalize(result)); -]; -30 # MinimumBound(_p) <-- -Infinity; - -%/mathpiper - - - -%mathpiper_docs,name="MinimumBound",categories="User Functions;Solvers (Numeric) -*CMD MinimumBound --- return lower bounds on the absolute values of real roots of a polynomial -*STD -*CALL - MinimumBound(p) - -*PARMS - -{p} - a polynomial in $x$ - -*DESC - -Return minimum bounds for the absolute values of the real -roots of a polynomial {p}. The polynomial has to be converted to one with -rational coefficients first, and be made square-free. -The polynomial must use the variable {x}. - -*E.G. - - In> p:=SquareFree(Rationalize((x-3.1)*(x+6.23))) - Out> (-40000*x^2-125200*x+772520)/870489; - In> MinimumBound(p) - Out> 5000000000/2275491039; - In> N(%) - Out> 2.1973279236; - -*SEE MaximumBound, SquareFree, NumRealRoots, FindRealRoots, Factor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/NumRealRoots.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/NumRealRoots.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/NumRealRoots.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/NumRealRoots.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -%mathpiper,def="NumRealRoots" - -NumRealRoots(_p) <-- -[ - Local(S); - p:=SquareFree(Rationalize(p)); - S:=SturmSequence(p); - SturmVariations(S,-Infinity)-SturmVariations(S,Infinity); -]; - -%/mathpiper - - - -%mathpiper_docs,name="NumRealRoots",categories="User Functions;Solvers (Numeric)" -*CMD NumRealRoots --- return the number of real roots of a polynomial -*STD -*CALL - NumRealRoots(p) - -*PARMS - -{p} - a polynomial in {x} - -*DESC - -Returns the number of real roots of a polynomial $ p $. -The polynomial must use the variable {x} and no other variables. - -*E.G. - - In> NumRealRoots(x^2-1) - Out> 2; - In> NumRealRoots(x^2+1) - Out> 0; - -*SEE FindRealRoots, SquareFree, MinimumBound, MaximumBound, Factor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/SquareFree.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/SquareFree.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/SquareFree.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/SquareFree.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -%mathpiper,def="SquareFree" - -SquareFree(_p) <-- -[ - Local(dp,gcd); -//Echo("1..."); - dp:=MakeMultiNomial(`(D(x)(@p)),{x}); -// dp:=dp/MultiLeadingCoef(dp); - -//Echo("2...",dp); - p:=MakeMultiNomial(p,{x}); -//Echo(NormalForm(p)); -//Echo(NormalForm(dp)); - gcd:=MultiGcd(p,dp); -//Echo(NormalForm(gcd)); -//Echo(NormalForm(MultiDivide(p,{gcd})[1][1])); - NormalForm(MultiDivide(p,{gcd})[1][1]); -// Div(p,Gcd(p,Monic(`(D(x)(@p))))); -]; - -%/mathpiper - - - -%mathpiper_docs,name="SquareFree",categories="User Functions;Polynomials (Operations)" -*CMD SquareFree --- return the square-free part of polynomial -*STD -*CALL - SquareFree(p) - -*PARMS - -{p} - a polynomial in {x} - -*DESC - -Given a polynomial -$$ p = p[1]^n[1]* ... * p[m]^n[m] $$ -with irreducible polynomials $ p[i] $, -return the square-free version part (with all the factors having -multiplicity 1): -$$ p[1]* ... * p[m] $$ - -*E.G. - - In> Expand((x+1)^5) - Out> x^5+5*x^4+10*x^3+10*x^2+5*x+1; - In> SquareFree(%) - Out> (x+1)/5; - In> Monic(%) - Out> x+1; - -*SEE FindRealRoots, NumRealRoots, MinimumBound, MaximumBound, Factor -%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/SturmSequence.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/SturmSequence.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/SturmSequence.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/SturmSequence.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -%mathpiper,def="SturmSequence" - -/** SturmSequence(p) : generate a Sturm sequence for a polynomial in x. - */ -SturmSequence(_p) <-- -[ - Local(result,i,deg,nt); - result:={p,`D(@x)(@p)}; - deg:=Degree(p); - For(i:=3,i<=deg+1,i++) - [ - nt := -NormalForm(MultiDivide(MM(result[i-2],{x}),{MM(result[i-1],{x})})[2]); - DestructiveAppend(result,nt); - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/SturmVariations.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/SturmVariations.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/sturm/SturmVariations.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/sturm/SturmVariations.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -%mathpiper,def="SturmVariations" - -10 # SturmVariations(_S,Infinity) <-- -[ - Local(i,s); - s:=FillList(0,Length(S)); - For(i:=1,i<=Length(S),i++) - [ - s[i] := LeadingCoef(S[i]); - ]; - SturmVariations(s); -]; - -10 # SturmVariations(_S,-Infinity) <-- -[ - Local(i,s); - s:=FillList(0,Length(S)); - For(i:=1,i<=Length(S),i++) - [ - s[i] := ((-1)^Degree(S[i]))*LeadingCoef(S[i]); - ]; - SturmVariations(s); -]; - -20 # SturmVariations(_S,_x) <-- SturmVariations(Eval(S)); -SturmVariations(_S) <-- -[ - Local(result,prev); -//Echo("S = ",S); - result:=0; - While(Length(S)>0 And IsZero(S[1])) S:=Rest(S); -//Echo("S = ",S); - if (Length(S)>0) - [ - prev:=S[1]; - ForEach(item,Rest(S)) - [ - if(Not IsZero(item)) - [ - if (prev*item < 0) [result++;]; - prev:=item; - ]; - ]; - ]; - result; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniDivide.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniDivide.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniDivide.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniDivide.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -%mathpiper,def="UniDivide" - -/* division algo: (for zero-base univariates:) */ -Function("UniDivide",{u,v}) -[ - Local(m,n,q,r,k,j); - m := Length(u)-1; - n := Length(v)-1; - While (m>0 And IsZero(u[m+1])) m--; - While (n>0 And IsZero(v[n+1])) n--; - q := ZeroVector(m-n+1); - r := FlatCopy(u); /* (m should be >= n) */ - For(k:=m-n,k>=0,k--) - [ - q[k+1] := r[n+k+1]/v[n+1]; - For (j:=n+k-1,j>=k,j--) - [ - r[j+1] := r[j+1] - q[k+1]*v[j-k+1]; - ]; - ]; - Local(end); - end:=Length(r); - While (end>n) - [ - DestructiveDelete(r,end); - end:=end-1; - ]; - - {q,r}; -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniGCD.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniGCD.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniGCD.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniGCD.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -%mathpiper,def="UniGcd" - -Function("UniGcd",{u,v}) -[ - Local(l,div,mod,m); - - DropEndZeroes(u); - DropEndZeroes(v); -/* - If(Length(v)>Length(u), - [ - Locap(swap); - swap:=u; - u:=v; - v:=swap; - ] ); - If(Length(u)=Length(v) And v[Length(v)] > u[Length(u)], - [ - Locap(swap); - swap:=u; - u:=v; - v:=swap; - ] ); - */ - - - l:=UniDivide(u,v); - - div:=l[1]; - mod:=l[2]; - - DropEndZeroes(mod); - m := Length(mod); - -/* Echo({"v,mod = ",v,mod}); */ -/* If(m <= 1, */ - If(m = 0, - v, -/* v/v[Length(v)], */ - UniGcd(v,mod)); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniTaylor.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniTaylor.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniTaylor.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniTaylor.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -%mathpiper,def="UniTaylor" - -Function("UniTaylor",{taylorfunction,taylorvariable,taylorat,taylororder}) -[ - Local(n,result,dif,polf); - result:={}; - [ - MacroLocal(taylorvariable); - MacroSet(taylorvariable,taylorat); - DestructiveAppend(result,Eval(taylorfunction)); - ]; - dif:=taylorfunction; - polf:=(taylorvariable-taylorat); - For(n:=1,n<=taylororder,n++) - [ - dif:= Deriv(taylorvariable) dif; - MacroLocal(taylorvariable); - MacroSet(taylorvariable,taylorat); - DestructiveAppend(result,(Eval(dif)/n!)); - ]; - UniVariate(taylorvariable,0,result); -]; - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniVariate.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniVariate.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniVariate.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniVariate.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -%mathpiper,def="UniVariate" - -//Auxiliary function. -ShiftUniVar(UniVariate(_var,_first,_coefs),_fact,_shift) - <-- - [ -//Echo("fact, coefs = ",fact,coefs); - UniVariate(var,first+shift,fact*coefs); - ]; - - - -RuleBase("UniVariate",{var,first,coefs}); - -Rule("UniVariate",3,10,Length(coefs)>0 And coefs[1]=0) - UniVariate(var,first+1,Rest(coefs)); -Rule("UniVariate",3,1000,IsComplex(var) Or IsList(var)) - ExpandUniVariate(var,first,coefs); - -500 # UniVariate(_var,_f1,_c1) + UniVariate(_var,_f2,_c2) <-- -[ - Local(from,result); - Local(curl,curr,left,right); - - Set(curl, f1); - Set(curr, f2); - Set(left, c1); - Set(right, c2); - Set(result, {}); - Set(from, Min(curl,curr)); - - While(And(LessThan(curl,curr),left != {})) - [ - DestructiveAppend(result,First(left)); - Set(left,Rest(left)); - Set(curl,AddN(curl,1)); - ]; - While(LessThan(curl,curr)) - [ - DestructiveAppend(result,0); - Set(curl,AddN(curl,1)); - ]; - While(And(LessThan(curr,curl), right != {})) - [ - DestructiveAppend(result,First(right)); - Set(right,Rest(right)); - Set(curr,AddN(curr,1)); - ]; - While(LessThan(curr,curl)) - [ - DestructiveAppend(result,0); - Set(curr,AddN(curr,1)); - ]; - While(And(left != {}, right != {})) - [ - DestructiveAppend(result,First(left)+First(right)); - Set(left, Rest(left)); - Set(right, Rest(right)); - ]; - While(left != {}) - [ - DestructiveAppend(result,First(left)); - Set(left, Rest(left)); - ]; - While(right != {}) - [ - DestructiveAppend(result,First(right)); - Set(right, Rest(right)); - ]; - - UniVariate(var,from,result); -]; - - -200 # UniVariate(_var,_first,_coefs) + a_IsNumber <-- - UniVariate(var,first,coefs) + UniVariate(var,0,{a}); -200 # a_IsNumber + UniVariate(_var,_first,_coefs) <-- - UniVariate(var,first,coefs) + UniVariate(var,0,{a}); - - -200 # - UniVariate(_var,_first,_coefs) <-- UniVariate(var,first,-coefs); - - -200 # (_factor * UniVariate(_var,_first,_coefs))_((IsFreeOf(var,factor))) <-- - UniVariate(var,first,coefs*factor); - -200 # (UniVariate(_var,_first,_coefs)/_factor)_((IsFreeOf(var,factor))) <-- - UniVariate(var,first,coefs/factor); - - - -200 # UniVariate(_var,_f1,_c1) * UniVariate(_var,_f2,_c2) <-- -[ - Local(i,j,n,shifted,result); - Set(result,MakeUni(0,var)); -//Echo("c1 = ",var,f1,c1); -//Echo("c2 = ",var,f2,c2); - Set(n,Length(c1)); - For(i:=1,i<=n,i++) - [ -//Echo("before = ",result); -//Echo("parms = ",var,c1,c2,f1,f2,f1+i-1); - Set(result,result+ShiftUniVar(UniVariate(var,f2,c2),MathNth(c1,i),f1+i-1)); -//Echo("after = ",result); - ]; -//Echo("result = ",result); - result; -]; - - - - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniVarList.mrw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniVarList.mrw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts3/univar/UniVarList.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts3/univar/UniVarList.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -%mathpiper,def="UniVarList" - -//Note:tk:since this is used in more than one univariate function, I am publishing it as a def. - -UniVarList(expr) := VarList(expr); - -%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/array/ArrayCreateFromList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/array/ArrayCreateFromList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/array/ArrayCreateFromList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/array/ArrayCreateFromList.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,32 @@ + +%mathpiper,def="ArrayCreateFromList" + +ArrayCreateFromList(list):= +[ + Local(result,i); + result:=ArrayCreate(Length(list),0); + i:=1; + While (list != {}) + [ + result[i]:=First(list); + i++; + list:=Rest(list); + ]; + result; +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="ArrayCreateFromList",categories="Programmer Functions;Native Objects" +*CMD ArrayCreateFromList --- convert list to array +*CALL + ArrayCreateFromList(list) + +*DESC +Creates an array from the contents of the list passed in. + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/array/ArrayToList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/array/ArrayToList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/array/ArrayToList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/array/ArrayToList.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,19 @@ +%mathpiper,def="ArrayToList" + +ArrayToList(array):= (array[1 .. ArraySize(array) ]); + +%/mathpiper + + + + +%mathpiper_docs,name="ArrayToList",categories="Programmer Functions;Native Objects" +*CMD ArrayToList --- convert array to list +*CORE +*CALL + ArrayToList(array) + +*DESC +Creates a list from the contents of the array passed in. + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/AssocDelete.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/AssocDelete.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/AssocDelete.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/AssocDelete.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,95 @@ +%mathpiper,def="AssocDelete" + +/// Delete an element of an associative list. +LocalSymbols(hash, key, element, hash'expr) +[ + +/// AssocDelete(hash,{"key", value}) +10 # AssocDelete(hash_IsList, element_IsList) <-- +[ + Local(index); + index := Find(hash, element); + If( + index > 0, + DestructiveDelete(hash, index) + ); + index>0; // return False if nothing found + +]; + + +/// AssocDelete(hash, "key") +20 # AssocDelete(hash_IsList, key_IsString) <-- +[ + AssocDelete(hash, Builtin'Assoc(key, hash)); +]; + +30 # AssocDelete(hash_IsList, Empty) <-- False; + +//HoldArgument("AssocDelete", hash); +//UnFence("AssocDelete", 1); +//UnFence("AssocDelete", 2); + +]; // LocalSymbols(hash, ...) + +%/mathpiper + + + +%mathpiper_docs,name="AssocDelete",categories="User Functions;Lists (Operations)" +*CMD AssocDelete --- delete an entry in an association list +*STD +*CALL + AssocDelete(alist, "key") + AssocDelete(alist, {key, value}) + +*PARMS + +{alist} -- association list + +{"key"} -- string, association key + +{value} -- value of the key to be deleted + +*DESC + +The key {"key"} in the association list {alist} is deleted. (The list itself is modified.) If the key was found and successfully deleted, returns {True}, otherwise if the given key was not found, the function returns {False}. + +The second, longer form of the function deletes the entry that has both the +specified key and the specified value. It can be used for two purposes: +* 1. to make sure that we are deleting the right value; +* 2. if several values are stored on the same key, to delete the specified entry (see the last example). + +At most one entry is deleted. + +*E.G. + +In> writer := {}; +Result: {}; +In> writer["Iliad"] := "Homer"; +Result: True; +In> writer["Henry IV"] := "Shakespeare"; +Result: True; +In> writer["Ulysses"] := "James Joyce"; +Result: True; +In> AssocDelete(writer, "Henry IV") +Result: True; +In> AssocDelete(writer, "Henry XII") +Result: False; +In> writer +Result: {{"Ulysses","James Joyce"}, + {"Iliad","Homer"}}; +In> DestructiveAppend(writer, + {"Ulysses", "Dublin"}); +Result: {{"Iliad","Homer"},{"Ulysses","James Joyce"}, + {"Ulysses","Dublin"}}; +In> writer["Ulysses"]; +Result: "James Joyce"; +In> AssocDelete(writer,{"Ulysses","James Joyce"}); +Result: True; +In> writer +Result: {{"Iliad","Homer"},{"Ulysses","Dublin"}}; + + +*SEE Assoc, AssocIndices, AssocValues +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/AssocIndices.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/AssocIndices.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/AssocIndices.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/AssocIndices.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="AssocIndices" + +AssocIndices(associndiceslist_IsList) <-- + DestructiveReverse(MapSingle("First",associndiceslist)); + +%/mathpiper + + + +%mathpiper_docs,name="AssocIndices",categories="User Functions;Lists (Operations)" +*CMD AssocIndices --- return the keys in an association list +*STD +*CALL + AssocIndices(alist) + +*PARMS + +{alist} -- association list to examine + +*DESC + +All the keys in the association list "alist" are assembled in a list +and this list is returned. + +*E.G. + +In> writer := {}; +Result: {}; +In> writer["Iliad"] := "Homer"; +Result: True; +In> writer["Henry IV"] := "Shakespeare"; +Result: True; +In> writer["Ulysses"] := "James Joyce"; +Result: True; +In> AssocIndices(writer); +Result: {"Iliad","Henry IV","Ulysses"}; + +*SEE Assoc, AssocDelete, AssocValues +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/Assoc.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/Assoc.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/Assoc.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/Assoc.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="Assoc" + +/* Assoc : given an assoc list like for example l:={{a,2},{b,3}}, + Assoc(b,l) will return {b,3}. if the key is not in the list, + it will return the atom Empty. +*/ + +Function("Assoc",{key,list}) Builtin'Assoc(key,list); + +%/mathpiper + + + +%mathpiper_docs,name="Assoc",categories="User Functions;Lists (Operations)" +*CMD Assoc --- return element stored in association list +*STD +*CALL + Assoc(key, alist) + +*PARMS + +{key} -- string, key under which element is stored + +{alist} -- association list to examine + +*DESC + +The association list "alist" is searched for an entry stored with +index "key". If such an entry is found, it is returned. Otherwise +the atom {Empty} is returned. + +Association lists are represented as a list of two-entry lists. The +first element in the two-entry list is the key, the second element is +the value stored under this key. + +The call {Assoc(key, alist)} can (probably more +intuitively) be accessed as {alist[key]}. + +*E.G. + +In> writer := {}; +Result: {}; +In> writer["Iliad"] := "Homer"; +Result: True; +In> writer["Henry IV"] := "Shakespeare"; +Result: True; +In> writer["Ulysses"] := "James Joyce"; +Result: True; +In> Assoc("Henry IV", writer); +Result: {"Henry IV","Shakespeare"}; +In> Assoc("War and Peace", writer); +Result: Empty; + +*SEE AssocIndices, [], :=, AssocDelete, AssocValues +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/AssocValues.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/AssocValues.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/assoc/AssocValues.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/assoc/AssocValues.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="AssocValues" + +AssocValues(assocvalueslist_IsList) <-- + DestructiveReverse(MapSingle(Lambda({x},First(Rest(x))),assocvalueslist)); + +%/mathpiper + + + +%mathpiper_docs,name="AssocValues",categories="User Functions;Lists (Operations)",access="experimental" +*CMD AssocValues --- return the values in an association list +*STD +*CALL + AssocValues(alist) + +*PARMS + +{alist} -- association list to examine + +*DESC + +All the values in the association list "alist" are assembled in a list +and this list is returned. + +*E.G. + +In> writer := {}; +Result: {}; +In> writer["Iliad"] := "Homer"; +Result: True; +In> writer["Henry IV"] := "Shakespeare"; +Result: True; +In> writer["Ulysses"] := "James Joyce"; +Result: True; +In> AssocIndices(writer); +Result: {"Homer","ShakespeareJames Joyce"}; + +*SEE Assoc, AssocDelete, AssocIndices +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/CosN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/CosN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/CosN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/CosN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="CosN" + +Defun("CosN",{x})Trigonometry(x,0.0,1.0,1.0); + +%/mathpiper + + + + + +%mathpiper_docs,name="CosN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD CosN --- cosine (arbitrary-precision math function) +*CALL + CosN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/ExpN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/ExpN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/ExpN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/ExpN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="ExpN" + +/// ExpN(x). Algorithm: for x<0, divide 1 by ExpN(-x); for x>1, compute ExpN(x/2)^2 recursively; for 0must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathExpDoubling.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathExpDoubling.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathExpDoubling.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathExpDoubling.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="MathExpDoubling" + +/// Identity transformation, compute Exp(x) from value=Exp(x/2^n) by squaring the value n times +Defun("MathExpDoubling", {value, n}) +[ + Local(shift, result); + Bind(shift, n); + Bind(result, value); + While (IsGreaterThan(shift,0)) // will lose 'shift' bits of precision here + [ + Bind(result, MultiplyN(result, result)); + Bind(shift, AddN(shift,MathNegate(1))); + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathExpTaylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathExpTaylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathExpTaylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathExpTaylor.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,30 @@ +%mathpiper,def="MathExpTaylor" + +// simple Taylor expansion, use only for 0<=x<1 +Defun("MathExpTaylor0",{x}) +[ + Local(i,aResult,term,eps); + // Exp(x)=Sum(i=0 to Inf) x^(i) /(i)! + // Which incrementally becomes the algorithm: + // + // i <- 0 + Bind(i,0); + // sum <- 1 + Bind(aResult,1.0); + // term <- 1 + Bind(term,1.0); + Bind(eps,MathIntPower(10,MathNegate(BuiltinPrecisionGet()))); + // While (term>epsilon) + While(IsGreaterThan(AbsN(term),eps)) + [ + // i <- i+1 + Bind(i,AddN(i,1)); + // term <- term*x/(i) + Bind(term,DivideN(MultiplyN(term,x),i)); + // sum <- sum+term + Bind(aResult,AddN(aResult,term)); + ]; + aResult; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathFloatPower.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathFloatPower.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathFloatPower.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathFloatPower.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="MathFloatPower" + +// power function for non-integer argument y -- use ExpN and LogN +/* Serge, I disabled this one for now, until we get a compiled version of LogN that does not hang in + an infinite loop. The C++ version of LogN never terminates, so I mapped LogN to your Internal'LnNum + which of course does a much better job of it. Corollary is that this function can be defined when we also + have Internal'LnNum in this file. +Defun("MathFloatPower", {x,y}) + If(IsInteger(y), False, ExpN(MultiplyN(y,LogN(x)))); +*/ + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathIntPower.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathIntPower.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathIntPower.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathIntPower.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,14 @@ +%mathpiper,def="MathIntPower" + +// power x^y only for integer y (perhaps negative) +Defun("MathIntPower", {x,y}) + If(IsEqual(x,0),0,If(IsEqual(x,1),1, + If(IsInteger(y),If(IsLessThan(y,0), // negative power, need to convert x to float to save time, since x^(-n) is never going to be integer anyway + DivideN(1, PositiveIntPower(AddN(x,0.),MathNegate(y))), + // now the positive integer y calculation - note that x might still be integer + PositiveIntPower(x,y) + ), // floating-point calculation is absent, return False + False) + )); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathMul2Exp.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathMul2Exp.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathMul2Exp.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathMul2Exp.mpw 2010-01-06 00:54:57.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper,def="MathMul2Exp" + +// MathMul2Exp: multiply x by 2^n quickly (for integer n) +// this should really be implemented in the core as a call to BigNumber::ShiftRight or ShiftLeft +Defun("MathMul2Exp", {x,n}) // avoid roundoff by not calculating 1/2^n separately + If(IsGreaterThan(n,0), MultiplyN(x, MathIntPower(2,n)), DivideN(x, MathIntPower(2,MathNegate(n)))); +// this doesn't work because ShiftLeft/Right don't yet work on floats +// If(IsGreaterThan(n,0), ShiftLeft(x,n), ShiftRight(x,n) +// ); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathPi.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathPi.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/MathPi.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/MathPi.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="MathPi" + +Defun("MathPi",{}) +[ + // Newton's method for finding pi: + // x[0] := 3.1415926 + // x[n+1] := x[n] + Sin(x[n]) + Local(initialPrec,curPrec,result,aPrecision); + Bind(aPrecision,BuiltinPrecisionGet()); + Bind(initialPrec, aPrecision); // target precision of first iteration, will be computed below + Bind(curPrec, 40); // precision of the initial guess + Bind(result, 3.141592653589793238462643383279502884197169399); // initial guess + + // optimize precision sequence + While (IsGreaterThan(initialPrec, MultiplyN(curPrec,3))) + [ + Bind(initialPrec, FloorN(DivideN(AddN(initialPrec,2),3))); + ]; + Bind(curPrec, initialPrec); + While (Not(IsGreaterThan(curPrec, aPrecision))) + [ + // start of iteration code + // Get Sin(result) + BuiltinPrecisionSet(curPrec); + Bind(result,AddN(result,SinN(result))); + // Calculate new result: result := result + Sin(result); + // end of iteration code + // decide whether we are at end of loop now + If (IsEqual(curPrec, aPrecision), // if we are exactly at full precision, it's the last iteration + [ + Bind(curPrec, AddN(aPrecision,1)); // terminate loop + ], + [ + Bind(curPrec, MultiplyN(curPrec,3)); // precision triples at each iteration + // need to guard against overshooting precision + If (IsGreaterThan(curPrec, aPrecision), + [ + Bind(curPrec, aPrecision); // next will be the last iteration + ]); + ]); + ]; + BuiltinPrecisionSet(aPrecision); + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/PositiveIntPower.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/PositiveIntPower.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/PositiveIntPower.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/PositiveIntPower.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="PositiveIntPower" + +// first define the binary exponentiation algorithm, MathIntPower. +// Later, the PowerN function will be defined through IntPower and MathLn/ExpN. Note that ExpN uses IntPower. + +// power x^n only for non-negative integer n +Defun("PositiveIntPower", {x,n}) +[ + Local(result,unit); + If(IsLessThan(n,0), False, + [ + Bind(unit,1); // this is a constant, initial value of the power + Bind(result, unit); + If(IsEqual(n,0),unit, + If(IsEqual(n,1),x, + [ + While(IsGreaterThan(n,0)) + [ + If( + IsEqual(BitAnd(n,1), 1), +// If( +// IsEqual(result,unit), // if result is already assigned +// Bind(result, x), // avoid multiplication + Bind(result, MultiplyN(result,x)) +// ) + ); + Bind(x, MultiplyN(x,x)); + Bind(n,ShiftRight(n,1)); + ]; + result; + ] + ) + ); + ]); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/PowerN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/PowerN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/PowerN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/PowerN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="PowerN" + +// power function that works for all real x, y +/// FIXME: No precision tracking yet. + +/* Serge, as MathFloatPower cannot be defined yet, I made the "avoid PowerN(num,float) explicit :-) +*/ +Defun("PowerN", {x,y}) +// avoid PowerN(0,float) + If(IsEqual(x,0),0, If(IsEqual(x,1),1, + If(IsInteger(y), MathIntPower(x,y), False/*MathFloatPower(x,y)*/) + )); + +%/mathpiper + + + + + +%mathpiper_docs,name="PowerN",categories="User Functions;Numeric" +*CMD PowerN --- power x^y (arbitrary-precision math function) +*CALL + PowerN(x,y) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> BuiltinPrecisionSet(10) +Result: True +In> PowerN(2,3) +Result: 8 +In> PowerN(2,-3) +Result: 0.125 + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/SinN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/SinN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/SinN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/SinN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="SinN" + +Defun("SinN",{x})Trigonometry(x,1.0,x,x); + +%/mathpiper + + + + + +%mathpiper_docs,name="SinN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD SinN --- sine (arbitrary-precision math function) +*CALL + SinN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/TanN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/TanN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/TanN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/TanN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="TanN" + +Defun("TanN",{x})DivideN(SinN(x),CosN(x)); + +%/mathpiper + + + + + +%mathpiper_docs,name="TanN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD TanN --- tangent (arbitrary-precision math function) +*CALL + TanN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/Trigonometry.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/Trigonometry.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/base/Trigonometry.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/base/Trigonometry.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,26 @@ +%mathpiper,def="Trigonometry" + +Defun("Trigonometry",{x,i,sum,term}) +[ + Local(x2,orig,eps,previousPrec,newPrec); + Bind(previousPrec,BuiltinPrecisionGet()); + Bind(newPrec,AddN(BuiltinPrecisionGet(),2)); + Bind(x2,MultiplyN(x,x)); + BuiltinPrecisionSet(newPrec); + Bind(eps,MathIntPower(10,MathNegate(previousPrec))); + While(IsGreaterThan(AbsN(term),eps)) + [ + Bind(term,MultiplyN(term,x2)); + Bind(i,AddN(i,1.0)); + Bind(term,DivideN(term,i)); + Bind(i,AddN(i,1.0)); + Bind(term,DivideN(MathNegate(term),i)); + BuiltinPrecisionSet(previousPrec); + Bind(sum, AddN(sum, term)); + BuiltinPrecisionSet(newPrec); + ]; + BuiltinPrecisionSet(previousPrec); + sum; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/calendar/Easter.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/calendar/Easter.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/calendar/Easter.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/calendar/Easter.mpw 2011-04-21 19:13:30.000000000 +0000 @@ -0,0 +1,54 @@ +%mathpiper,def="Easter" + +// http://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm +Easter(year) := [ + + Check(IsPositiveInteger(year), "Argument", "The argument must be a positive integer"); + + Local(a,b,c,d,e,f,g,h,i,k,L,m,month,day); + + a := Modulo(year, 19); + b := Quotient(year, 100); + c := Modulo(year, 100); + d := Quotient(b, 4); + e := Modulo(b, 4); + f := Quotient(b + 8, 25); + g := Quotient(b - f + 1, 3); + h := Modulo(19*a + b - d - g + 15, 30); + i := Quotient(c, 4); + k := Modulo(c, 4); + L := Modulo(32 + 2*e + 2*i - h - k, 7); + m := Quotient(a + 11*h + 22*L, 451); + month := Quotient(h + L - 7*m + 114, 31); + day := Modulo(h + L - 7*m + 114, 31) + 1; + + { month, day }; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Easter",categories="User Functions" +*CMD Easter --- solve an equation +*CALL + Easter(year) + +*PARMS + +{year} -- year + +*DESC + +Calculates the date of Easter in the Gregorian calendar. + +*E.G. notest + +In> Easter(2011); +Result: {4,24} + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/combinatorics/Combinations.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/combinatorics/Combinations.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/combinatorics/Combinations.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/combinatorics/Combinations.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,54 @@ +%mathpiper,def="Combinations;BinomialCoefficient" + +/* Binomials -- now using partial factorial for speed */ +// BinomialCoefficient(n,m) = BinomialCoefficient(n, n-m) +10 # BinomialCoefficient(0,0) <-- 1; +10 # BinomialCoefficient(n_IsPositiveInteger,m_IsNonNegativeInteger)_(2*m <= n) <-- ((n-m+1) *** n) / m!; +15 # BinomialCoefficient(n_IsPositiveInteger,m_IsNonNegativeInteger)_(2*m > n And m <= n) <-- BinomialCoefficient(n, n-m); +20 # BinomialCoefficient(n_IsInteger,m_IsInteger) <-- 0; + +Combinations(n,m) := BinomialCoefficient(n,m); + +%/mathpiper + + + +%mathpiper_docs,name="Combinations;BinomialCoefficient",categories="User Functions;Combinatorics" +*CMD Combinations/BinomialCoefficient --- combinations/ binomial coefficient +*STD +*CALL + Combinations(n, r) + BinomialCoefficient(n, r) + +*PARMS + +{n} -- integer - total number of objects +{r} -- integer - number of objects chosen + +*DESC + +These functions are actually two names for a single function. + +In combinatorics, the function is thought of as being the number of ways +to choose "r" objects out of a total of "n" objects if order is +not taken into account. + +In mathematics the function is called the binomial coefficient function +and it is thought of as the coefficient of the x^r term in the polynomial expansion +of the binomial power (1 + x)^n. + +The binomial coefficient is defined to be zero +if "r" is negative or greater than "n"; {BinomialCoefficient(0,0)}=1. + + +*E.G. + +In> Combinations(10, 4) +Result: 210; + +In> BinomialCoefficient(10, 4) +Result: 210; + + +*SEE CombinationsList, Permutations, PermutationsList, !, Eulerian +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/combinatorics/PermutationsList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/combinatorics/PermutationsList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/combinatorics/PermutationsList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/combinatorics/PermutationsList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,59 @@ +%mathpiper,def="PermutationsList" + +Function("PermutationsList",{result,list}) +[ + If(Length(list) = 0, + [ + result; + ], + [ + Local(head); + Local(newresult); + Local(i); + head:=list[1]; + newresult:={}; + ForEach(item,result) + [ + For(i:=Length(item)+1,i>0,i--) + [ + DestructiveInsert(newresult,1,Insert(item,i,head)); + ]; + ]; + newresult:=DestructiveReverse(newresult); + PermutationsList(newresult,Rest(list)); + ]); +]; + + +Function("PermutationsList",{list}) +[ + PermutationsList({{}},list); +]; + +%/mathpiper + + + +%mathpiper_docs,name="PermutationsList",categories="User Functions;Combinatorics" +*CMD PermutationsList --- return all permutations of a list +*STD +*CALL + PermutationsList(list) + +*PARMS + +{list} -- a list of elements + +*DESC + +PermutationsList returns a list which contains all the permutations of +the elements in the original list. + +*E.G. + +In> PermutationsList({a,b,c}) +Result: {{a,b,c},{a,c,b},{c,a,b},{b,a,c}, + {b,c,a},{c,b,a}}; + +*SEE Permutations, Combinations, CombinationsList, LeviCivita +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Arg.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Arg.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Arg.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Arg.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="Arg" + +10 # Arg(Complex(Cos(_x),Sin(_x))) <-- x; +10 # Arg(x_IsZero) <-- Undefined; +15 # Arg(x_IsPositiveReal) <-- 0; +15 # Arg(x_IsNegativeReal) <-- Pi; +20 # Arg(Complex(r_IsZero,i_IsConstant)) <-- Sign(i)*Pi/2; +30 # Arg(Complex(r_IsPositiveReal,i_IsConstant)) <-- ArcTan(i/r); +40 # Arg(Complex(r_IsNegativeReal,i_IsPositiveReal)) <-- Pi+ArcTan(i/r); +50 # Arg(Complex(r_IsNegativeReal,i_IsNegativeReal)) <-- ArcTan(i/r)-Pi; + +%/mathpiper + + + +%mathpiper_docs,name="Arg",categories="User Functions;Numbers (Complex)" +*CMD Arg --- argument of a complex number +*STD +*CALL + Arg(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function returns the argument of "x". The argument is the angle +with the positive real axis in the Argand diagram, or the angle +"phi" in the polar representation $r * Exp(I*phi)$ of "x". The +result is in the range ($-Pi$, $Pi$], that is, excluding $-Pi$ but including $Pi$. The +argument of 0 is {Undefined}. + +*E.G. + +In> Arg(2) +Result: 0; +In> Arg(-1) +Result: Pi; +In> Arg(1+I) +Result: Pi/4; + +*SEE Abs, Sign +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Complex.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Complex.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Complex.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Complex.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,140 @@ +%mathpiper,def="Complex" + +0 # Complex(_r,i_IsZero) <-- r; +2 # Complex(Complex(_r1,_i1),_i2) <-- Complex(r1,i1+i2); +2 # Complex(_r1,Complex(_r2,_i2)) <-- Complex(r1-i2,r2); + +6 # Complex(Undefined,_x) <-- Undefined; +6 # Complex(_x,Undefined) <-- Undefined; + + +/* Addition */ + +110 # Complex(_r1,_i1) + Complex(_r2,_i2) <-- Complex(r1+r2,i1+i2); +300 # Complex(_r,_i) + x_IsConstant <-- Complex(r+x,i); +300 # x_IsConstant + Complex(_r,_i) <-- Complex(r+x,i); + +110 # - Complex(_r,_i) <-- Complex(-r,-i); + +300 # Complex(_r,_i) - x_IsConstant <-- Complex(r-x,i); +300 # x_IsConstant - Complex(_r,_i) <-- Complex((-r)+x,-i); +111 # Complex(_r1,_i1) - Complex(_r2,_i2) <-- Complex(r1-r2,i1-i2); + +/* Multiplication */ +110 # Complex(_r1,_i1) * Complex(_r2,_i2) <-- Complex(r1*r2-i1*i2,r1*i2+r2*i1); +/* right now this is slower than above +110 # Complex(_r1,_i1) * Complex(_r2,_i2) <-- +[ // the Karatsuba trick + Local(A,B); + A:=r1*r2; + B:=i1*i2; + Complex(A-B,(r1+i1)*(r2+i2)-A-B); +]; +*/ + + +// Multiplication in combination with complex numbers in the light of infinity +250 # Complex(r_IsZero,_i) * x_IsInfinity <-- Complex(0,i*x); +250 # Complex(_r,i_IsZero) * x_IsInfinity <-- Complex(r*x,0); +251 # Complex(_r,_i) * x_IsInfinity <-- Complex(r*x,i*x); + +250 # x_IsInfinity * Complex(r_IsZero,_i) <-- Complex(0,i*x); +250 # x_IsInfinity * Complex(_r,i_IsZero) <-- Complex(r*x,0); +251 # x_IsInfinity * Complex(_r,_i) <-- Complex(r*x,i*x); + + +300 # Complex(_r,_i) * y_IsConstant <-- Complex(r*y,i*y); +300 # y_IsConstant * Complex(_r,_i) <-- Complex(r*y,i*y); + +330 # Complex(_r,_i) * (y_IsConstant / _z) <-- (Complex(r*y,i*y))/z; +330 # (y_IsConstant / _z) * Complex(_r,_i) <-- (Complex(r*y,i*y))/z; + + +110 # x_IsConstant / Complex(_r,_i) <-- (x*Conjugate(Complex(r,i)))/(r^2+i^2); + + +300 # Complex(_r,_i) / y_IsConstant <-- Complex(r/y,i/y); + +110 # (_x ^ Complex(_r,_i)) <-- Exp(Complex(r,i)*Ln(x)); + +110 # Sqrt(Complex(_r,_i)) <-- Exp(Ln(Complex(r,i))/2); +110 # (Complex(_r,_i) ^ x_IsRationalOrNumber)_(Not(IsInteger(x))) <-- Exp(x*Ln(Complex(r,i))); + +// This is commented out because it used PowerN so (2*I)^(-10) became a floating-point number. Now everything is handled by binary algorithm below +//120 # Complex(r_IsZero,_i) ^ n_IsInteger <-- {1,I,-1,-I}[1+Modulo(n,4)] * i^n; + +123 # Complex(_r, _i) ^ n_IsNegativeInteger <-- 1/Complex(r, i)^(-n); + +124 # Complex(_r, _i) ^ (p_IsZero) <-- 1; // cannot have Complex(0,0) here + +125 # Complex(_r, _i) ^ n_IsPositiveInteger <-- +[ + // use binary method + Local(result, x); + x:=Complex(r,i); + result:=1; + While(n > 0) + [ + if ((n&1) = 1) + [ + result := result*x; + ]; + x := x*x; + n := n>>1; + ]; + result; +]; + + +/*[ // this method is disabled b/c it suffers from severe roundoff errors + Local(rr,ii,count,sign); + rr:=r^n; + ii:=0; + For(count:=1,count<=n,count:=count+2) [ + sign:=If(IsZero(Modulo(count-1,4)),1,-1); + ii:=ii+sign*BinomialCoefficient(n,count)*i^count*r^(n-count); + If(count I +Result: Complex(0,1); +In> 3+4*I +Result: Complex(3,4); +In> Complex(-2,0) +Result: -2; + +*SEE Re, Im, I, Abs, Arg +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Conjugate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Conjugate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Conjugate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Conjugate.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="Conjugate" + +LocalSymbols(a,x) +[ +Function("Conjugate",{a}) + Substitute(a,{{x},Type(x)="Complex"},{{x},Complex(x[1],-(x[2]))}); +]; // LocalSymbols(a,x) + +%/mathpiper + + + +%mathpiper_docs,name="Conjugate",categories="User Functions;Numbers (Complex)" +*CMD Conjugate --- complex conjugate +*STD +*CALL + Conjugate(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function returns the complex conjugate of "x". The complex +conjugate of $a + I*b$ is $a - I*b$. This function assumes that all +unbound variables are real. + +*E.G. + +In> Conjugate(2) +Result: 2; +In> Conjugate(Complex(a,b)) +Result: Complex(a,-b); + +*SEE Complex, Re, Im +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/II.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/II.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/II.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/II.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="II" + +// +// II is the imaginary number Sqrt(-1), and remains that way. +// The difference is it isn't converted to the form Complex(x,y). +// + +10 # II^n_IsNegativeInteger <-- (-II)^(-n); +20 # (II^_n)_(IsEven(n) = True) <-- (-1)^(n>>1); +20 # (II^_n)_(IsOdd(n) = True) <-- II*(-1)^(n>>1); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/ImII.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/ImII.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/ImII.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/ImII.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="ImII" + +ImII(_c) <-- NN(c)[2]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Im.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Im.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Im.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Im.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="Im" + +/* Imaginary parts */ +110 # Im(Complex(_r,_i)) <-- i; +120 # Im(Undefined) <-- Undefined; +300 # Im(_x) <-- 0; + +%/mathpiper + + + +%mathpiper_docs,name="Im",categories="User Functions;Numbers (Complex)" +*CMD Im --- imaginary part of a complex number +*STD +*CALL + Im(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function returns the imaginary part of the complex number "x". + +*E.G. + +In> Im(5) +Result: 0; +In> Im(I) +Result: 1; +In> Im(Complex(3,4)) +Result: 4; + +*SEE Complex, Re +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/IsComplexII.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/IsComplexII.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/IsComplexII.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/IsComplexII.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="IsComplexII" + +IsComplexII(_c) <-- (ImII(c) != 0); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/IsComplex.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/IsComplex.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/IsComplex.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/IsComplex.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,8 @@ +%mathpiper,def="IsComplex" + +/* All things you can request a real and imaginary part for are complex */ +1 # IsComplex(x_IsRationalOrNumber) <-- True; +2 # IsComplex(Complex(_r,_i)) <-- True; +3 # IsComplex(_x) <-- False; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/IsNotComplex.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/IsNotComplex.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/IsNotComplex.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/IsNotComplex.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="IsNotComplex" + +IsNotComplex(x) := Not(IsComplex(x)); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Magnitude.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Magnitude.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Magnitude.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Magnitude.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Magnitude" + +Function("Magnitude",{x}) [ + Sqrt(Re(x)^2 + Im(x)^2); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/NN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/NN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/NN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/NN.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,21 @@ +%mathpiper,def="NN" + +LocalSymbols(complexReduce) [ + + Bind(complexReduce, + Hold( + { + Exp(x_IsComplexII) <- Exp(ReII(x))*(Cos(ImII(x))+II*Sin(ImII(x))) + })); + + NN(_c) <-- + [ + Local(result); + c := (c /:: complexReduce); + result := Coef(Expand(c,II),II,{0,1}); + result; + ]; + +]; //LocalSymbols(complexReduce) + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/om/om.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper,def="" + +// From code.mpi.def: +OMDef( "Complex" , "complex1","complex_cartesian" ); +OMDef( "Re" , "complex1","real" ); +OMDef( "Im" , "complex1","imaginary" ); +OMDef( "Conjugate", "complex1","conjugate" ); +OMDef( "Arg" , "complex1","argument" ); +OMDef( "IsComplex", mathpiper,"is_complex" ); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/ReII.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/ReII.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/ReII.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/ReII.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="ReII" + +ReII(_c) <-- NN(c)[1]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Re.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Re.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/complex/Re.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/complex/Re.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="Re" + +/*Real parts */ +110 # Re(Complex(_r,_i)) <-- r; +120 # Re(Undefined) <-- Undefined; +300 # Re(_x) <-- x; + +%/mathpiper + + + +%mathpiper_docs,name="Re",categories="User Functions;Numbers (Complex)" +*CMD Re --- real part of a complex number +*STD +*CALL + Re(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function returns the real part of the complex number "x". + +*E.G. + +In> Re(5) +Result: 5; +In> Re(I) +Result: 0; +In> Re(Complex(3,4)) +Result: 3; + +*SEE Complex, Im +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/constants/constants.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/constants/constants.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/constants/constants.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/constants/constants.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,363 @@ +%mathpiper,def="I;CachedConstant;AssignCachedConstants;ClearCachedConstants" + +/* def file definitions. +I +CachedConstant +AssignCachedConstants +ClearCachedConstants +*/ + +/* Definition of constants. */ + +/* TODO: + * There is a problem with defining I this way: if I is used, but the + * file "complex" has not been loaded, the interpreter can not deal + * with "Complex". + * + * Note:tk:10/9/09: Perhaps use SetGlobalLazyVariable(I,Hold(Complex(0,1))); + */ + +SetGlobalLazyVariable(I,Complex(0,1)); + +////////////////////////////////////////////////// +/// Cached constants support and definition of Pi +////////////////////////////////////////////////// + +//TODO: here we wrap the entire file in LocalSymbols, this is inefficient in that it slows loading of this file. Needs optimization. +LocalSymbols(CacheOfConstantsN) [ + +/// declare a new cached constant C'atom and its associated function C'atom(). +/// C'atom() will call C'func() at current precision to evaluate C'atom if it has not yet been cached at that precision. (note: any arguments to C'func() must be included) +Rulebase("CachedConstant", {C'cache, C'atom, C'func}); +UnFence("CachedConstant", 3); // not sure if this is useful +HoldArgument("CachedConstant", C'func); +HoldArgument("CachedConstant", C'cache); // name of the cache +// check syntax: must be called on an atom and a function +Rule("CachedConstant", 3, 10, And(IsAtom(C'atom), IsFunction(C'func))) +[ + Local(C'name,C'functionName); + Bind(C'name, ToString(C'atom)); // this is for later conveniences + Bind(C'functionName,ConcatStrings("Internal'",C'name)); + + If( // create the cache it if it does not already exist + IsAtom(Eval(C'cache)), + MacroBind(Eval(C'cache), {}) + ); +// Write({"debug step 0: ", C'cache, Eval(C'cache), C'atom, C'func, C'name}); + // check that the constant is not already defined + If( + IsEqual(Builtin'Assoc(C'name, Eval(C'cache)), Empty), // the constant is not already defined, so need to define "C'atom" and the corresponding function "C'atom"() + [ // e.g. C'atom evaluates to Pi, C'cache to a name e.g. CacheOfConstantsN, which is bound to a hash + MacroUnbind(C'atom); +// Write({"debug step 1: ", Cache'name, C'cache, Eval(C'cache)}); + // add the new constant to the cache +// MacroBind(Cache'name, Insert(Eval(C'cache), 1, {C'name, 0, 0})); + DestructiveInsert(Eval(C'cache), 1, {C'name, 0, 0}); +// Write({"debug step 2: ", Cache'name, C'cache, Eval(C'cache)}); + // define the new function "C'atom"() + // note: this should not use N() because it may be called from inside N() itself + + MacroRulebase(C'functionName, {}); + `( Rule(@C'functionName, 0, 1024, True) + [ + Local(new'prec, new'C, cached'C); + Bind(new'prec, BuiltinPrecisionGet()); + // fetch the cache entry for this constant + // note that this procedure will store the name of the cache here in this statement as Eval(C'cache) + Bind(cached'C, Builtin'Assoc(@C'name, @C'cache)); + If( MathNth(cached'C, 2) != new'prec, + [ // need to recalculate at current precision + If(IsEqual(InVerboseMode(),True), Echo("CachedConstant: Info: constant ", @C'name, " is being recalculated at precision ", new'prec)); + Bind(new'C, RoundTo(Eval(@C'func),new'prec)); + DestructiveReplace(cached'C, 2, new'prec); + DestructiveReplace(cached'C, 3, new'C); + new'C; + ], + // return cached value of C'atom + MathNth(cached'C, 3) + ); + ]); + + // calculate C'atom at current precision for the first time +// Eval(ListToFunction({C'atom})); // "C'name"(); + // we do not need this until the constant is used; it will just slow us down + ], + // the constant is defined + Echo("CachedConstant: Warning: constant ", C'atom, " already defined") + ); +]; + +Rule("CachedConstant", 3, 20, True) + Echo("CachedConstant: Error: ", C'atom, " must be an atom and ", C'func, " must be a function."); + +/// assign numerical values to all cached constants: using fixed cache "CacheOfConstantsN" +// this is called from N() +Function("AssignCachedConstantsN", {}) +[ + Local(var,fname); + ForEach(var, AssocIndices(CacheOfConstantsN)) + [ + MacroUnbind(ToAtom(var)); + Bind(fname,ConcatStrings("Internal'",var)); + Bind(var,ToAtom(var)); + // this way the routine Internal'Pi() will be actually called only when the variable 'Pi' is used, etcetera. + `SetGlobalLazyVariable((@var), ListToFunction({ToAtom(fname)})); + ]; +]; +UnFence("AssignCachedConstantsN", 0); + +/// clear values from all cached constants: using fixed cache "CacheOfConstantsN" +// this is called from N() +Function("ClearCachedConstantsN", {}) +[ + Local(c'entry); + ForEach(c'entry, CacheOfConstantsN) + MacroUnbind(ToAtom(c'entry[1])); +]; +UnFence("ClearCachedConstantsN", 0); + +/// declare some constants now +CachedConstant(CacheOfConstantsN, Pi, +[// it seems necessary to precompute Pi to a few more digits +// so that Cos(0.5*Pi)=0 at precision 10 +// FIXME: find a better solution + Local(result,old'prec); + Bind(old'prec,BuiltinPrecisionGet()); +If(IsEqual(InVerboseMode(),True), Echo("Recalculating Pi at precision ",old'prec+5)); + BuiltinPrecisionSet(BuiltinPrecisionGet()+5); + result := MathPi(); +If(IsEqual(InVerboseMode(),True),Echo("Switching back to precision ",old'prec)); + BuiltinPrecisionSet(old'prec); + result; +] +); +CachedConstant(CacheOfConstantsN, gamma, GammaConstNum()); +CachedConstant(CacheOfConstantsN, GoldenRatio, N( (1+Sqrt(5))/2 ) ); +CachedConstant(CacheOfConstantsN, Catalan, CatalanConstNum() ); + +]; // LocalSymbols(CacheOfConstantsN) + +%/mathpiper + + + + + +%mathpiper_docs,name="I",categories="User Functions;Constants (Mathematical);Numbers (Complex)" +*CMD I --- imaginary unit +*STD +*CALL + I + +*DESC + +This symbol represents the imaginary unit, which equals the square +root of -1. It evaluates to {Complex(0,1)}. + +*E.G. + +In> I +Result: Complex(0,1); +In> I = Sqrt(-1) +Result: True; + +*SEE Complex +%/mathpiper_docs + + + +%mathpiper_docs,name="Pi",categories="User Functions;Constants (Mathematical)" +*CMD Pi --- mathematical constant $pi$ + +*STD +*CALL + Pi + +*DESC + +Pi symbolically represents the exact value of $pi$. When the {N()} function is +used, {Pi} evaluates to a numerical value according to the current precision. +It is better to use {Pi} than {N(Pi)} except in numerical calculations, because exact +simplification will be possible. + +This is a "cached constant" which is recalculated only when precision is increased. + +*E.G. + +In> Sin(3*Pi/2) +Result: -1; +In> Pi+1 +Result: Pi+1; +In> N(Pi) +Result: 3.14159265358979323846; + +*SEE Sin, Cos, N, CachedConstant +%/mathpiper_docs + + + +%mathpiper_docs,name="GoldenRatio",categories="User Functions;Constants (Mathematical)" +*CMD GoldenRatio --- the Golden Ratio +*STD +*CALL + GoldenRatio + +*DESC + +These functions compute the "golden ratio" +$$phi <=> 1.6180339887 <=> (1+Sqrt(5))/2 $$. + +The ancient Greeks defined the "golden ratio" as follows: +If one divides a length 1 into two pieces $x$ and $1-x$, such that the ratio of 1 to $x$ is the same as the ratio of $x$ to $1-x$, then $1/x <=> 1.618$... is the "golden ratio". + + +The constant is available symbolically as {GoldenRatio} or numerically through {N(GoldenRatio)}. +This is a "cached constant" which is recalculated only when precision is increased. +The numerical value of the constant can also be obtained as {N(GoldenRatio)}. + + +*E.G. + +In> x:=GoldenRatio - 1 +Result: GoldenRatio-1; +In> N(x) +Result: 0.6180339887; +In> N(1/GoldenRatio) +Result: 0.6180339887; +In> V(N(GoldenRatio,20)); + + CachedConstant: Info: constant GoldenRatio is + being recalculated at precision 20 +Result: 1.6180339887498948482; + + +*SEE N, CachedConstant +%/mathpiper_docs + + + +%mathpiper_docs,name="Catalan",categories="User Functions;Constants (Mathematical)" +*CMD Catalan --- Catalan's Constant +*STD +*CALL + Catalan + +*DESC + +These functions compute Catalan's Constant $Catalan<=>0.9159655941$. + +The constant is available symbolically as {Catalan} or numerically through {N(Catalan)} with {N(...)} the usual operator used to try to coerce an expression in to a numeric approximation of that expression. +This is a "cached constant" which is recalculated only when precision is increased. +The numerical value of the constant can also be obtained as {N(Catalan)}. +The low-level numerical computations are performed by the routine {CatalanConstNum}. + + +*E.G. + +In> N(Catalan) +Result: 0.9159655941; +In> DirichletBeta(2) +Result: Catalan; +In> V(N(Catalan,20)) + + CachedConstant: Info: constant Catalan is + being recalculated at precision 20 +Result: 0.91596559417721901505; + + +*SEE N, CachedConstant +%/mathpiper_docs + + + +%mathpiper_docs,name="gamma",categories="User Functions;Constants (Mathematical)" +*CMD gamma --- Euler's constant $gamma$ +*STD +*CALL + gamma + +*DESC + +These functions compute Euler's constant $gamma<=>0.57722$... + +The constant is available symbolically as {gamma} or numerically through using the usual function {N(...)} to get a numeric result, {N(gamma)}. +This is a "cached constant" which is recalculated only when precision is increased. +The numerical value of the constant can also be obtained as {N(gamma)}. +The low-level numerical computations are performed by the routine {GammaConstNum}. + +Note that Euler's Gamma function $Gamma(x)$ is the capitalized {Gamma} in MathPiper. + +*E.G. + +In> gamma+Pi +Result: gamma+Pi; +In> N(gamma+Pi) +Result: 3.7188083184; +In> V(N(gamma,20)) + + CachedConstant: Info: constant gamma is being + recalculated at precision 20 + GammaConstNum: Info: used 56 iterations at + working precision 24 +Result: 0.57721566490153286061; + +*SEE Gamma, N, CachedConstant +%/mathpiper_docs + + + +%mathpiper_docs,name="CachedConstant",categories="User Functions;Constants (Mathematical)" +*CMD CachedConstant --- precompute multiple-precision constants +*STD +*CALL + CachedConstant(cache, Cname, Cfunc) + +*PARMS +{cache} -- atom, name of the cache + +{Cname} -- atom, name of the constant + +{Cfunc} -- expression that evaluates the constant + +*DESC + +This function is used to create precomputed multiple-precision values of +constants. Caching these values will save time if they are frequently used. + +The call to {CachedConstant} defines a new function named {Cname()} that +returns the value of the constant at given precision. If the precision is +changed, the value will be recalculated as necessary, otherwise calling {Cname()} will take very little time. + +The parameter {Cfunc} must be an expression that can be evaluated and returns +the value of the desired constant at the current precision. (Most arbitrary-precision mathematical functions do this by default.) + +The associative list {cache} contains elements of the form {{Cname, prec, value}}, as illustrated in the example. If this list does not exist, it will be created. + +This mechanism is currently used by {N()} to precompute the values of $Pi$ and $gamma$ (and the golden ratio through {GoldenRatio}, and {Catalan}). +The name of the cache for {N()} is {CacheOfConstantsN}. +The code in the function {N()} assigns unevaluated calls to {Internal'Pi()} and {Internal'gamma()} to the atoms {Pi} and {gamma} and declares them to be lazy global variables through {SetGlobalLazyVariable} (with equivalent functions assigned to other constants that are added to the list of cached constants). + +The result is that the constants will be recalculated only when they are used in the expression under {N()}. +In other words, the code in {N()} does the equivalent of + + SetGlobalLazyVariable(mypi,Hold(Internal'Pi())); + SetGlobalLazyVariable(mygamma,Hold(Internal'gamma())); + +After this, evaluating an expression such as {1/2+gamma} will call the function {Internal'gamma()} but not the function {Internal'Pi()}. + +*E.G. notest + +In> CachedConstant( my'cache, Ln2, Internal'LnNum(2) ) +Result: True; +In> Internal'Ln2() +Result: 0.6931471806; +In> V(N(Internal'Ln2(),20)) + CachedConstant: Info: constant Ln2 is being + recalculated at precision 20 +Result: 0.69314718055994530942; +In> my'cache +Result: {{"Ln2",20,0.69314718055994530942}}; + + +*SEE N, BuiltinPrecisionSet, Pi, GoldenRatio, Catalan, gamma +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/constants/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/constants/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/constants/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/constants/om/om.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="" + +//From code.mpi.def: +OMDef( "I", "nums1", "i" ); +OMDef( "CachedConstant", mathpiper, "CachedConstant" ); +OMDef( "AssignCachedConstants", mathpiper, "AssignCachedConstants" ); +OMDef( "ClearCachedConstants", mathpiper, "ClearCachedConstants" ); +OMDef( "Pi", "nums1", "pi" ); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/else.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/else.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/else.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/else.mpw 2010-01-09 00:07:57.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="else" + +Rulebase("else",{ifthen,otherwise}); + +0 # (if (_predicate) _body else _otherwise)_(Eval(predicate) = True) <-- Eval(body); + +0 # (if (_predicate) _body else _otherwise)_(Eval(predicate) = False) <-- Eval(otherwise); + +1 # (if (_predicate) _body else _otherwise) <-- + ListToFunction({ToAtom("else"), + ListToFunction({ToAtom("if"), (Eval(predicate)), body}), + otherwise}); + +HoldArgument("else",ifthen); + +HoldArgument("else",otherwise); + +UnFence("else",2); + +%/mathpiper + + + + +%mathpiper_docs,name="else",categories="User Functions;Control Flow" +*CMD else --- branch point +*STD +*CALL + if(predicate) body else otherwise) + +*PARMS + +{predicate} -- predicate to test + +{body} -- expression to evaluate if the predicate is {True}. + +{otherwise} -- expression to evaluate if the predicate if {False}. + +*DESC + +(This description under in development.) + + +*SEE If, if +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/ForEachExperimental.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/ForEachExperimental.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/ForEachExperimental.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/ForEachExperimental.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,66 @@ +%mathpiper,def="",public="todo" + +/* + * TODO This was an experiment to try to get to using a new ForEach that works the + * same on lists and arrays. For some odd reason all sorts of places in the scripts + * break if we use this version of ForEach. We need to look into this still! I want + * a ForEach that works on lists as well as arrays. + +Macro()(ForEachRest(i,L,B)); + +LocalSymbols(foreachtail) +[ + 10 # ForEachRest(_i,L_IsFunction,_B) <-- + [ + Local(foreachtail); + Local(@i); + Bind(foreachtail,@L); + While(Not(IsEqual(foreachtail,{}))) + [ + Bind(@i,First(foreachtail)); + @B; + Bind(foreachtail,Rest(foreachtail)); + ]; + ]; +]; + +LocalSymbols(index,nr) +[ + 20 # ForEachRest(_i,_A,_B)_( And( + IsEqual(IsGeneric(A),True), + IsEqual(GenericTypeName(A),"Array") + )) <-- + [ + Local(index,nr); + Local(@i); + Bind(index,1); + Bind(nr,Length(@A)); + While(index<=nr) + [ + Bind(@i,(@A)[index]); + @B; + Bind(index,AddN(index,1)); + ]; + ]; +]; + +Macro()(ForEach(i,L)(B)); + +LocalSymbols(itm,lst,bd) +[ + (ForEach(_i,_L)(_B)) <-- + [ + Local(itm,lst,bd); +//CurrentFile(),CurrentLine(),,Hold(@B) +//Echo(CurrentFile(),CurrentLine()); +// Echo("ForEach(",Hold(@i),", ",Hold(@L),", ) "); + itm:=Hold(@i); + lst:= (@L); + bd:=Hold(@B); +//Echo("1...",itm); + `ForEachRest(@itm,@lst,@bd); + ]; +]; +*/ + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/ForEachInArray.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/ForEachInArray.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/ForEachInArray.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/ForEachInArray.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="ForEachInArray" + +LocalSymbols(i,nr) +[ + TemplateFunction("ForEachInArray",{item,list,body}) + [ + Local(i,nr); + MacroLocal(item); + Bind(i,1); + Bind(nr,Length(list)); + While(i<=nr) + [ + MacroBind(item,list[i]); + Eval(body); + Bind(i,AddN(i,1)); + ]; + ]; +]; + +UnFence("ForEachInArray",3); +HoldArgumentNumber("ForEachInArray",3,1); +HoldArgumentNumber("ForEachInArray",3,3); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/ForEach.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/ForEach.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/ForEach.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/ForEach.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,101 @@ +%mathpiper,def="ForEach" + +//Retract("ForEach" , *); + +/*TODO remove? Not yet. If the code above (ForEachExperimental) can be made to work we can do away with this version. */ +TemplateFunction("ForEach",{item,listOrString,body}) +[ + If(And(IsEqual(IsGeneric(listOrString),True), + IsEqual(GenericTypeName(listOrString),"Array") + ), + `ForEachInArray(@item,listOrString,@body), + [ + + MacroLocal(item); + + If(IsString(listOrString), + [ + + Local(index, stringLength); + + stringLength := Length(listOrString); + + index := 1; + While(index <= stringLength ) + [ + MacroBind(item,listOrString[index] ); + + Eval(body); + + index++; + ]; + + ], + [ + Local(foreachtail); + Bind(foreachtail,listOrString); + While(Not(IsEqual(foreachtail,{}))) + [ + MacroBind(item,First(foreachtail)); + Eval(body); + Bind(foreachtail,Rest(foreachtail)); + ]; + ]); + ]); +]; +UnFence("ForEach",3); +HoldArgumentNumber("ForEach",3,1); +HoldArgumentNumber("ForEach",3,3); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="ForEach",categories="User Functions;Control Flow" +*CMD ForEach --- loop over all entries in a list or a string +*STD +*CALL + ForEach(var, list_or_string) body + +*PARMS + +{var} -- looping variable + +{list} -- list of values or string of characters to assign to "var" + +{body} -- expression to evaluate with different values of "var" + +*DESC + +The expression "body" is evaluated multiple times. The first time, +"var" has the value of the first element of "list" or the first +character in "string", then it gets +the value of the second element and so on. {ForEach} +returns {True}. + +*E.G. notest + +In> ForEach(i,{2,3,5,7,11}) Echo({i, i!}); +2 2 +3 6 +5 120 +7 5040 +11 39916800 +Result: True; + + +In> ForEach(i,"Hello") Echo(i) +Result: True +Side Effects: +H +e +l +l +o + +*SEE For, While, Until, Break, Continue +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/For.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/For.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/For.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/For.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,72 @@ +%mathpiper,def="For" + +/* Defining a For function */ +TemplateFunction("For",{start,predicate,increment,body}) +[ + Eval(start); + While (IsEqual(Eval(predicate),True)) + [ + Eval(body); + Eval(increment); + ]; +]; +UnFence("For",4); +HoldArgumentNumber("For",4,1); +HoldArgumentNumber("For",4,2); +HoldArgumentNumber("For",4,3); +HoldArgumentNumber("For",4,4); + +%/mathpiper + + + +%mathpiper_docs,name="For",categories="User Functions;Control Flow" +*CMD For --- C-style {for} loop +*STD +*CALL + For(init, pred, incr) body + +*PARMS + +{init} -- expression for performing the initialization + +{pred} -- predicate deciding whether to continue the loop + +{incr} -- expression to increment the counter + +{body} -- expression to loop over + +*DESC + +This commands implements a C style {for} loop. First +of all, the expression "init" is evaluated. Then the predicate +"pred" is evaluated, which should return {True} or +{False}. Next the loop is executed as long as the +predicate yields {True}. One traversal of the loop +consists of the subsequent evaluations of "body", "incr", and +"pred". Finally, the value {True} is returned. + +This command is most often used in a form such as {For(i=1, i<=10, i++) body}, which evaluates {body} with +{i} subsequently set to 1, 2, 3, 4, 5, 6, 7, 8, 9, +and 10. + +The expression {For(init, pred, incr) body} is +equivalent to {init; While(pred) [body; incr;]}. + +*E.G. notest + +In> For (i:=1, i<=10, i++) Echo({i, i!}); + 1 1 + 2 2 + 3 6 + 4 24 + 5 120 + 6 720 + 7 5040 + 8 40320 + 9 362880 + 10 3628800 +Result: True; + +*SEE While, Until, ForEach, Break, Continue +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/if.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/if.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/if.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/if.mpw 2010-01-09 00:07:57.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="if" + +Rulebase("if",{predicate,body}); + +(if(True) _body) <-- Eval(body); + +HoldArgument("if",body); + +UnFence("if",2); + +%/mathpiper + + + + +%mathpiper_docs,name="if",categories="User Functions;Control Flow" +*CMD if --- branch point +*STD +*CALL + if(predicate)body + +*PARMS + +{predicate} -- predicate to test + +{body} -- expression to evaluate if the predicate is true + +*DESC + +(This description is in development.) + + +*SEE If, else +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/Lambda.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/Lambda.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/Lambda.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/Lambda.mpw 2010-07-23 05:26:16.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="Lambda" + +/* Lambda was introduced as a form of pure function that can be passed on to the function Apply as a first argument. + * The original method, passing it in as a list, had the disadvantage that the list was evaluated, which caused the + * arguments to be evaluated too. This resulted in unwanted behaviour sometimes (expressions being prematurely evaluated + * in the body of the pure function). The arguments to Lambda are not evaluated. + */ +DefMacroRulebase("Lambda",{args,body}); + +%/mathpiper + + + + +%mathpiper_docs,name="Lambda",categories="User Functions;Control Flow" +*CMD Lambda --- a form of pure function that can be passed to functions like Apply and Select +*STD +*CALL + Lambda(arglist, function body) + +*PARMS + +{arglist} -- list of arguments + +*DESC + +Lambda functions are unnamed pure functions which can be used in places where a small function +is needed and creating a normal function is either inconvenient or impossible. + +*E.G. +In> Apply(Lambda({x,y}, x-y^2), {Cos(a), Sin(a)}); +Result: Cos(a)-Sin(a)^2 + +In> Lambda({x,y}, x-y^2) @ {Cos(a), Sin(a)} +Result: Cos(a)-Sin(a)^2 + + +/%mathpiper + +list := {1,-3,2,-6,-4,3}; + +Select(list, Lambda({i}, i > 0 )); + +/%/mathpiper + + /%output,preserve="false" + Result: {1,2,3} +. /%/output + +*SEE Apply, @, Select +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/Until.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/Until.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/contolflow/Until.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/contolflow/Until.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="Until" + +TemplateFunction("Until",{predicate,body}) +[ + Eval(body); + While (IsEqual(Eval(predicate),False)) + [ + Eval(body); + ]; + True; +]; +UnFence("Until",2); +HoldArgumentNumber("Until",2,1); +HoldArgumentNumber("Until",2,2); + +%/mathpiper + + + +%mathpiper_docs,name="Until",categories="User Functions;Control Flow" +*CMD Until --- loop until a condition is met +*STD +*CALL + Until(pred) body + +*PARMS + +{pred} -- predicate deciding whether to stop + +{body} -- expression to loop over + +*DESC + +Keep on evaluating "body" until "pred" becomes {True}. More precisely, {Until} first +evaluates the expression "body". Then the predicate "pred" is +evaluated, which should yield either {True} or {False}. In the latter case, the expressions "body" +and "pred" are again evaluated and this continues as long as +"pred" is {False}. As soon as "pred" yields {True}, the loop terminates and {Until} returns {True}. + +The main difference with {While} is that {Until} always evaluates the body at least once, but {While} may not evaluate the body at all. Besides, the +meaning of the predicate is reversed: {While} stops +if "pred" is {False} while {Until} stops if "pred" is {True}. +The command +{Until(pred) body;} is equivalent to {pred; While(Not pred) body;}. In fact, the +implementation of {Until} is based on the internal +command {While}. The {Until} +command can be compared to the {do ... while} +construct in the programming language C. + +*E.G. notest + +In> x := 0; +Result: 0; +In> Until (x! > 10^6) \ + [ Echo({x, x!}); x++; ]; + 0 1 + 1 1 + 2 2 + 3 6 + 4 24 + 5 120 + 6 720 + 7 5040 + 8 40320 + 9 362880 +Result: True; + +*SEE While, For, ForEach, Break, Continue +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/debug/debug.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/debug/debug.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/debug/debug.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/debug/debug.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,346 @@ +%mathpiper,def="TraceExp;Debug;Profile;DebugRun;DebugStep;DebugStepOver;DebugBreakAt;DebugRemoveBreakAt;DebugStop;DebugVerbose;DebugAddBreakpoint;BreakpointsClear;DebugCallstack;DebugBreakIf;DebugLocals;EchoTime;DebugShowCode" + +/* def file definitions +TraceExp +Debug +Profile +DebugRun +DebugStep +DebugStepOver +DebugBreakAt +DebugRemoveBreakAt +DebugStop +DebugVerbose +DebugAddBreakpoint +BreakpointsClear +DebugCallstack +DebugBreakIf +DebugLocals +EchoTime +DebugShowCode +*/ + +LocalSymbols(TraceStart,TraceEnter,TraceLeave,DebugStart,DebugEnter, + DebugLeave,ProfileStart,ProfileEnter,result, + WriteLines,ClearScreenString,Debug'FileLoaded, Debug'FileLines, Debug'NrLines, + debugstepoverfile, debugstepoverline) [ + +TraceStart() := [indent := 0;]; +TraceEnter() := +[ + indent++; + Space(2*indent); + Echo("Enter ",CustomEval'Expression()); +]; +TraceLeave() := +[ + Space(2*indent); + Echo("Leave ",CustomEval'Result()); + indent--; +]; +Macro(TraceExp,{expression}) +[ + TraceStart(); + CustomEval(TraceEnter(),TraceLeave(),CustomEval'Stop(),@expression); +]; + + + +DebugStart():= +[ + debugging:=True; + debugstopdepth := -1; + breakpoints:={}; + filebreakpoints := {}; + debugstopped:=False; + debugverbose:=False; + debugcallstack:={}; + breakpredicate:=False; +]; +DebugRun():= [debugging:=False;True;]; +DebugStep():=[debugging:=False;nextdebugging:=True;]; + +DebugStepOver():= +[ + debugging:=False; + debugstepoverfile := DebugFile(CustomEval'Expression()); + debugstepoverline := DebugLine(CustomEval'Expression()); + debugstopdepth := Length(debugcallstack); +]; +DebugBreakAt(file,line):= +[ + Check(InDebugMode(), "Mode", "DebugBreakAt only supported in the debug build of MathPiper"); + If(filebreakpoints[file] = Empty,filebreakpoints[file]:={}); + DestructiveAppend(filebreakpoints[file],line); +]; +DebugRemoveBreakAt(file,line):= +[ + Check(InDebugMode(), "Mode", "DebugRemoveBreakAt only supported in the debug build of MathPiper"); + If(filebreakpoints[file] = Empty,filebreakpoints[file]:={}); + filebreakpoints[file] := Difference(filebreakpoints[file],{line}); +]; + + +DebugStop():=[debugging:=False;debugstopped:=True;CustomEval'Stop();]; +DebugVerbose(verbose):=[debugverbose:=verbose;]; +DebugAddBreakpoint(fname_IsString) <-- [ breakpoints := fname:breakpoints;]; +Macro(DebugBreakIf,{predicate}) +[ + breakpredicate:= Hold(@predicate); +]; + +BreakpointsClear() <-- +[ + breakpredicate:=False; + breakpoints := {}; +]; +Macro(DebugLocals,{}) +[ + Echo(""); + Echo("*************** Current locals on the stack ****************"); + ForEach(item,CustomEval'Locals()) + [ + Echo(" ",item," : ",Eval(item)); + ]; + Echo(""); +]; +DebugCallstack() <-- +[ + Echo(""); + Echo("*************** Function call stack ****************"); + ForEach(item,debugcallstack) + [ + if(IsFunction(item)) + Echo(" Function ",Type(item)," : ",item) + else + Echo(" Variable ",item); + ]; + Echo(""); +]; + +Macro(DebugEnter,{}) +[ + debugcallstack := CustomEval'Expression():debugcallstack; + // custom breakpoint (custom predicate thought up by the programmer) + If(debugging = False And + Eval(breakpredicate) = True, + [ + breakpredicate:=False; + debugging:=True; + ]); + + If(debugging = False And InDebugMode(), + [ + Local(file,line); + file := DebugFile(CustomEval'Expression()); + If(filebreakpoints[file] != Empty, + [ + line := DebugLine(CustomEval'Expression()); + If(Not(file = debugstepoverfile And line = debugstepoverline) And + Contains(filebreakpoints[file],line), + [ + debugging:=True; + ] + ); + ]); + ]); + + + // the standard breakpoint + If(debugging = False And + IsFunction(CustomEval'Expression()) And + Contains(breakpoints,Type(CustomEval'Expression())), debugging:=True); + nextdebugging:=False; + If (debugging, + [ + If(InDebugMode(),DebugShowCode()); + Echo(">>> ",CustomEval'Expression()); + While(debugging) + [ + Echo("DebugResult: ",Eval(PipeFromString(ReadCmdLineString("Debug> "):";")Read())); + // If(debugging,Echo("DebugResult: ",debugRes)); + If(IsExitRequested(),debugging:=False); + ]; + ]); + debugging:=nextdebugging; + + If(IsExitRequested(),debugstopped:=True); + +]; +Macro(DebugLeave,{}) +[ + If(debugging = False And debugstopdepth >= 0 And Length(debugcallstack) = debugstopdepth, + [ + debugstepoverline := -1; + debugging := True; + debugstopdepth := -1; + ]); + + debugcallstack := Rest(debugcallstack); + If(debugverbose,Echo(CustomEval'Result()," <-- ",CustomEval'Expression())); +]; +Macro(Debug,{expression}) +PipeToStdout() +[ + DebugStart(); + CustomEval(DebugEnter(),DebugLeave(),If(debugstopped,Check(False, "Debug", ""),[debugging:=True;debugcallstack := Rest(debugcallstack);]),@expression); +]; + + +ProfileStart():= +[ + profilefn:={}; +]; +10 # ProfileEnter()_(IsFunction(CustomEval'Expression())) <-- +[ + Local(fname); + fname:=Type(CustomEval'Expression()); + If(profilefn[fname]=Empty,profilefn[fname]:=0); + profilefn[fname] := profilefn[fname]+1; +]; +Macro(Profile,{expression}) +[ + ProfileStart(); + CustomEval(ProfileEnter(),True,CustomEval'Stop(),@expression); + ForEach(item,profilefn) + Echo("Function ",item[1]," called ",item[2]," times"); +]; + +/// Measure the time taken by evaluation and print results. +Macro(EchoTime,{expression}) +[ + Local(result); + Echo(Time()Bind(result, @expression), "seconds taken."); + result; +]; + + + +// ClearScreenString : the ascii escape codes to clear the screen +ClearScreenString := UnicodeToString(27):"[2J":UnicodeToString(27):"[1;1H"; + +// WriteLines: do the actual outputting of lines of a file to screen +WriteLines(filename,lines,from,nrlines,breakpoints,current):= +[ + Local(i,nr); + nr:=Length(lines); + WriteString(ClearScreenString); + Echo("File ",filename," at line ",current); + For(i:=from,i") + else + WriteString(" "); + if (Contains(breakpoints,i)) + WriteString("*") + else + WriteString(" "); + WriteString("| "); + Echo(lines[i][1]); + ]; +]; +Debug'FileLoaded := ""; +Debug'FileLines := {}; +Debug'NrLines:=20; + +// +// DebugShowCode: show the part of the file we are currently executing (based on the +// value returned by CustomEval'Expression() ). +// +// Currently unimplemented, should we remove? +// +DebugShowCode():= +[ + False; +]; + +]; //LocalSymbols + + +%/mathpiper + + + + +%mathpiper_docs,name="TraceExp",categories="User Functions;Control Flow",access="private" +*CMD TraceExp --- evaluate with tracing enabled +*CORE +*CALL + TraceExp(expr) + +*PARMS + +{expr} -- expression to trace + +*DESC + +The expression "expr" is evaluated with the tracing facility turned +on. This means that every subexpression, which is evaluated, is shown +before and after evaluation. Before evaluation, it is shown in the +form {TrEnter(x)}, where {x} +denotes the subexpression being evaluated. After the evaluation the +line {TrLeave(x,y)} is printed, where {y} is the result of the evaluation. The indentation +shows the nesting level. + +Note that this command usually generates huge amounts of output. A +more specific form of tracing (eg. {TraceRule}) is +probably more useful for all but very simple expressions. + +*E.G. notest + +In> TraceExp(2+3); + TrEnter(2+3); + TrEnter(2); + TrLeave(2, 2); + TrEnter(3); + TrLeave(3, 3); + TrEnter(IsNumber(x)); + TrEnter(x); + TrLeave(x, 2); + TrLeave(IsNumber(x),True); + TrEnter(IsNumber(y)); + TrEnter(y); + TrLeave(y, 3); + TrLeave(IsNumber(y),True); + TrEnter(True); + TrLeave(True, True); + TrEnter(MathAdd(x,y)); + TrEnter(x); + TrLeave(x, 2); + TrEnter(y); + TrLeave(y, 3); + TrLeave(MathAdd(x,y),5); + TrLeave(2+3, 5); +Result: 5; + +*SEE TraceStack, TraceRule +%/mathpiper_docs + + + + +%mathpiper_docs,name="EchoTime",categories="User Functions;Input/Output" +*CMD EchoTime --- measure the time taken by a function and echos it +*STD +*CALL + EchoTime()expr +*PARMS +{expr} -- any expression +*DESC + +The function {EchoTime()expr} evaluates the expression {expr} and prints the time in seconds needed for the evaluation. +The time is printed to the current output stream. +The built-in function {Time} is used for timing. + +The result is the "user time" as reported by the OS, not the real ("wall clock") time. +Therefore, any CPU-intensive processes running alongside MathPiper will not significantly affect the result of {EchoTime}. + +*E.G. notest +In> EchoTime() N(MathLog(1000),40) + 0.34 seconds taken +Result: 6.9077552789821370520539743640530926228033; + +*SEE Time, SystemTimer +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/debug/verbose_mode.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/debug/verbose_mode.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/debug/verbose_mode.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/debug/verbose_mode.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,68 @@ +%mathpiper,def="V;InVerboseMode" + +LocalSymbols(Verbose) [ + + Bind(Verbose,False); + + + Function("V",{aNumberBody}) + [ + Local(prevVerbose,result); + Bind(prevVerbose,Verbose); + Bind(Verbose,True); + Bind(result,Eval(aNumberBody)); + Bind(Verbose,prevVerbose); + result; + ]; + + + Function("InVerboseMode",{}) Verbose; + +]; // LocalSymbols(Verbose) + +HoldArgument("V",aNumberBody); +UnFence("V",1); + +%/mathpiper + + + + + +%mathpiper_docs,name="V;InVerboseMode",categories="User Functions;Input/Output" +*CMD V, InVerboseMode --- set verbose output mode +*STD +*CALL + V(expression) + InVerboseMode() + +*PARMS + +{expression} -- expression to be evaluated in verbose mode + +*DESC + +The function {V(expression)} will evaluate the expression in +verbose mode. Various parts of MathPiper can show extra information +about the work done while doing a calculation when using {V}. + +In verbose mode, {InVerboseMode()} will return {True}, otherwise +it will return {False}. + +*E.G. notest + +In> OldSolve({x+2==0},{x}) +Result: {{-2}}; +In> V(OldSolve({x+2==0},{x})) + Entering OldSolve + From x+2==0 it follows that x = -2 + x+2==0 simplifies to True + Leaving OldSolve +Result: {{-2}}; +In> InVerboseMode() +Result: False +In> V(InVerboseMode()) +Result: True + +*SEE Echo, N, OldSolve +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/colon_equals_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/colon_equals_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/colon_equals_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/colon_equals_operator.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,283 @@ +%mathpiper,def=":=" + +/* := assignment. */ +Rulebase(":=",{aLeftAssign,aRightAssign}); +UnFence(":=",2); +HoldArgument(":=",aLeftAssign); +HoldArgument(":=",aRightAssign); + +/* := assignment. */ +// assign a variable +Rule(":=",2,0,IsAtom(aLeftAssign)) +[ + Check( Not IsNumber(aLeftAssign), "Argument", "Only a variable can be placed on the left side of an := operator." ); + + MacroBind(aLeftAssign,Eval(aRightAssign)); + + Eval(aLeftAssign); +]; + + + +// assign lists +Rule(":=",2,0,IsList(aLeftAssign)) +[ + Map(":=",{aLeftAssign,Eval(aRightAssign)}); +]; + +// auxiliary function to help assign arrays using := +Rulebase("AssignArray",{setlistterm,setlistindex,setlistresult}); +UnFence("AssignArray",3); +Rule("AssignArray",3,1,IsString(setlistindex)) +[ + Local(item); + item:=Assoc(setlistindex,setlistterm); + If(item = Empty, + DestructiveInsert(setlistterm,1,{setlistindex,setlistresult}), + DestructiveReplace(item,2,setlistresult) + ); + True; +]; +// assign generic arrays +Rule("AssignArray",3,1, + And( + IsEqual(IsGeneric(setlistterm),True), + IsEqual(GenericTypeName(setlistterm),"Array") + ) + ) +[ + ArraySet(setlistterm,setlistindex,setlistresult); +]; + + +Rule("AssignArray",3,2,True) +[ + DestructiveReplace(setlistterm ,setlistindex, setlistresult); + True; +]; + +// a[x] := ... assigns to an array element +Rule(":=",2,10,IsFunction(aLeftAssign) And (First(FunctionToList(aLeftAssign)) = Nth)) +[ + Local(frst,scnd); + + Local(lst); + Bind(lst,(FunctionToList(aLeftAssign))); + Bind(lst,Rest(lst)); + Bind(frst, Eval(First(lst))); + Bind(lst,Rest(lst)); + Bind(scnd, Eval(First(lst))); + + AssignArray(frst,scnd,Eval(aRightAssign)); +]; + +// f(x):=... defines a new function +Rule(":=",2,30,IsFunction(aLeftAssign) And Not(IsEqual(aLeftAssign[0], ToAtom(":="))) ) +[ + Check( Not IsEqual(aLeftAssign[0], ToAtom("/")), "Argument", "Only a variable can be placed on the left side of an := operator." ); + + Local(oper,args,arity); + Bind(oper,ToString(aLeftAssign[0])); + Bind(args,Rest(FunctionToList(aLeftAssign))); + If( + And(IsGreaterThan(Length(args), 1), IsEqual( MathNth(args, Length(args)), ToAtom("...") )), + // function with variable number of arguments + [ + DestructiveDelete(args,Length(args)); // remove trailing "..." + Bind(arity,Length(args)); + Retract(oper,arity); + MacroRulebaseListed(oper, args); + ], + // function with a fixed number of arguments + [ + Bind(arity,Length(args)); + Retract(oper,arity); + MacroRulebase(oper, args); + ] + ); + Unholdable(aRightAssign); + MacroRule(oper,arity,1025,True) aRightAssign; +]; + +%/mathpiper + + + +%mathpiper_docs,name=":=",categories="Operators" +*CMD := --- assign a variable or a list; define a function +*STD +*CALL + var := expr + {var1, var2, ...} := {expr1, expr2, ...} + var[i] := expr + fn(arg1, arg2, ...) := expr +Precedence: +*EVAL PrecedenceGet(":=") + +*PARMS + +{var} -- atom, variable which should be assigned + +{expr} -- expression to assign to the variable or body of function + +{i} -- index (can be integer or string) + +{fn} -- atom, name of a new function to define + +{arg1}, {arg2} -- atoms, names of arguments of the new function {fn} + +*DESC + +The {:=} operator can be used +in a number of ways. In all cases, some sort of assignment or definition takes +place. + +The first form is the most basic one. It evaluates the expression on +the right-hand side and assigns it to the variable named on the +left-hand side. The left-hand side is not evaluated. The evaluated +expression is also returned. + +The second form is a small extension, which allows one to do multiple +assignments. The first entry in the list on the right-hand side is +assigned to the first variable mentioned in the left-hand side, the +second entry on the right-hand side to the second variable on the +left-hand side, etc. The list on the right-hand side must have at +least as many entries as the list on the left-hand side. Any excess +entries are silently ignored. The result of the expression is the list +of values that have been assigned. + +The third form allows one to change an entry in the list. If the index +"i" is an integer, the "i"-th entry in the list is changed to the +expression on the right-hand side. It is assumed that the length of +the list is at least "i". If the index "i" is a string, then +"var" is considered to be an associative list (sometimes called hash +table), and the key "i" is paired with the value "exp". In both +cases, the right-hand side is evaluated before the assignment and the +result of the assignment is {True}. + +The last form defines a function. For example, the assignment {fn(x) := x^2} +removes any rules previously associated with {fn(x)} and defines the rule +{fn(_x) <-- x^2}. Note that the left-hand side may take a different form if +{fn} is defined to be a prefix, infix or bodied function. This case +is special since the right-hand side is not evaluated +immediately, but only when the function {fn} is used. If this takes +time, it may be better to force an immediate evaluation with {Eval} +(see the last example). If the expression on the right hand side begins +with {Eval()}, then it will be evaluated before defining the new function. + +A variant of the function definition can be used to make a function +accepting a variable number of arguments. + +*E.G. + +A simple assignment: + +In> a := Sin(x) + 3; +Result: Sin(x)+3; +In> a; +Result: Sin(x)+3; + +Multiple assignments: + +In> {a,b,c} := {1,2,3}; +Result: {1,2,3}; +In> a; +Result: 1; +In> b+c; +Result: 5; + +Assignment to a list: + +In> xs := { 1,2,3,4,5 }; +Result: {1,2,3,4,5}; +In> xs[3] := 15; +Result: True; +In> xs; +Result: {1,2,15,4,5}; + +Building an associative list: + +In> alist := {}; +Result: {}; +In> alist["cherry"] := "red"; +Result: True; +In> alist["banana"] := "yellow"; +Result: True; +In> alist["cherry"]; +Result: "red"; +In> alist; +Result: {{"banana","yellow"},{"cherry","red"}}; + +Defining a function: + +In> f(x) := x^2; +Result: True; +In> f(3); +Result: 9; +In> f(Sin(a)); +Result: Sin(a)^2; + +Defining a function with variable number of arguments: + +In> f(x, ...) := If(IsList(x),Sum(x),x); +Result: True; +In> f(2); +Result: 2; +In> f(1,2,3); +Result: 6; + +Defining a new infix operator: + +In> Infix("*&*",10); +Result: True; +In> x1 *&* x2 := x1/x2 + x2/x1; +Result: True; +In> Sin(a) *&* Cos(a); +Result: Tan(1)+Cos(1)/Sin(1); +In> Unbind(a); +Result: True; +In> Sin(a) *&* Exp(a); +Result: Sin(a)/Exp(a)+Exp(a)/Sin(a); + +In the following example, it may take some time to compute the Taylor +expansion. This has to be done every time the function {f} is called. + +In> f(a) := Taylor(x,0,25) Sin(x); +Result: True; +In> f(1); +Result: x-x^3/6+x^5/120-x^7/5040+x^9/362880- +x^11/39916800+x^13/6227020800-x^15/ +1307674368000+x^17/355687428096000-x^19/ +121645100408832000+x^21/51090942171709440000 +-x^23/25852016738884976640000+x^25 +/15511210043330985984000000; +In> f(2); +Result: x-x^3/6+x^5/120-x^7/5040+x^9/362880- +x^11/39916800+x^13/6227020800-x^15 +/1307674368000+x^17/355687428096000-x^19/ +121645100408832000+x^21/51090942171709440000 +-x^23/25852016738884976640000+x^25/ +15511210043330985984000000; + +The remedy is to evaluate the Taylor expansion immediately. Now the +expansion is computed only once. + +In> f(a) := Eval(Taylor(x,0,25) Sin(x)); +Result: True; +In> f(1); +Result: x-x^3/6+x^5/120-x^7/5040+x^9/362880- +x^11/39916800+x^13/6227020800-x^15/ +1307674368000+x^17/355687428096000-x^19/ +121645100408832000+x^21/51090942171709440000 +-x^23/25852016738884976640000+x^25 +/15511210043330985984000000; +In> f(2); +Result: x-x^3/6+x^5/120-x^7/5040+x^9/362880- +x^11/39916800+x^13/6227020800-x^15 +/1307674368000+x^17/355687428096000-x^19/ +121645100408832000+x^21/51090942171709440000 +-x^23/25852016738884976640000+x^25/ +15511210043330985984000000; + +*SEE <--, Bind, Unbind, [], Rule, Infix, Eval, Function +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/Function.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/Function.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/Function.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/Function.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,133 @@ +%mathpiper,def="Function" + +/* Defining a macro-like function that declares a function + * with only one rule. + */ +Rulebase("Function",{oper,args,body}); + + + +// function with variable number of arguments: Function("func",{x,y, ...})body; +Rule("Function",3,2047, + And(IsGreaterThan(Length(args), 1), IsEqual( MathNth(args, Length(args)), ToAtom("...") )) +) +[ + DestructiveDelete(args,Length(args)); // remove trailing "..." + Retract(oper,Length(args)); + MacroRulebaseListed(oper,args); + MacroRule(oper,Length(args),1025,True) body; // at precedence 1025, for flexibility +]; + +// function with a fixed number of arguments +Rule("Function",3,2048,True) +[ + Retract(oper,Length(args)); + MacroRulebase(oper,args); + MacroRule(oper,Length(args),1025,True) body; +]; + + +/// shorthand function declarations +Rulebase("Function",{oper}); +// function with variable number of arguments: Function() f(x,y, ...) +Rule("Function",1,2047, + And(IsFunction(oper), IsGreaterThan(Length(oper), 1), IsEqual( MathNth(oper, Length(oper)), ToAtom("...") )) +) +[ + Local(args); + Bind(args,Rest(FunctionToList(oper))); + DestructiveDelete(args,Length(args)); // remove trailing "..." + If(RulebaseDefined(Type(oper),Length(args)), + False, // do nothing + MacroRulebaseListed(Type(oper),args) + ); +]; + + +// function with a fixed number of arguments +Rule("Function",1,2048, + And(IsFunction(oper)) +) +[ + Local(args); + Bind(args,Rest(FunctionToList(oper))); + If(RulebaseDefined(Type(oper),Length(args)), + False, // do nothing + MacroRulebase(Type(oper),args) + ); +]; + + +HoldArgument("Function",oper); +HoldArgument("Function",args); +HoldArgument("Function",body); + +%/mathpiper + + + +%mathpiper_docs,name="Function",categories="Programmer Functions;Programming;Built In" +*CMD Function --- declare or define a function +*STD +*CALL + Function() func(arglist) + Function() func(arglist, ...) + Function("op", {arglist}) body + Function("op", {arglist, ...}) body + +*PARMS + +{func(args)} -- function declaration, e.g. {f(x,y)} + +{"op"} -- string, name of the function + +{{arglist}} -- list of atoms, formal arguments to the function + +{...} -- literal ellipsis symbol "{...}" used to denote a variable number of arguments + +{body} -- expression comprising the body of the function + +*DESC + +This command can be used to define a new function with named arguments. + + +The number of arguments of the new function and their names are determined by the list {arglist}. If the ellipsis "{...}" follows the last atom in {arglist}, a function with a variable number of arguments is declared (using {RulebaseListed}). Note that the ellipsis cannot be the only element of {arglist} and must be preceded by an atom. + +A function with variable number of arguments can take more arguments than elements in {arglist}; in this case, it obtains its last argument as a list containing all extra arguments. + +The short form of the {Function} call merely declares a {Rulebase} for the new function but does not define any function body. This is a convenient shorthand for {Rulebase} and {RulebaseListed}, when definitions of the function are to be supplied by rules. If the new function has been already declared with the same number of arguments (with or without variable arguments), {Function} returns false and does nothing. + +The second, longer form of the {Function} call declares a function and also defines a function body. It is equivalent to a +single rule such as {op(_arg1, _arg2) <-- body}. The rule will be declared at +precedence 1025. Any previous rules associated with {"op"} (with the same +arity) will be discarded. More complicated functions (with more than one body) +can be defined by adding more rules. + +*E.G. notest + +This will declare a new function with two or more arguments, but define no rules for it. This is equivalent to {Rulebase ("f1", {x, y, ...})}. +In> Function() f1(x,y,...); +Result: True; +In> Function() f1(x,y); +Result: False; + +This defines a function {FirstOf} which returns the +first element of a list. Equivalent definitions would be +{FirstOf(_list) <-- list[1]} or {FirstOf(list) := list[1]}. +In> Function("FirstOf", {list}) list[1]; +Result: True; +In> FirstOf({a,b,c}); +Result: a; + +The following function will print all arguments to a string: +In> Function("PrintAll",{x, ...}) If(IsList(x), + PrintList(x), PipeToString()Write(x)); +Result: True; +In> PrintAll(1): +Result: " 1"; +In> PrintAll(1,2,3); +Result: " 1 2 3"; + +*SEE TemplateFunction, Rule, Rulebase, RulebaseListed, :=, Retract +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/HoldArgumentNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/HoldArgumentNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/HoldArgumentNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/HoldArgumentNumber.mpw 2011-02-05 04:04:44.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="HoldArgumentNumber" + +Function("HoldArgumentNumber",{function,arity,index}) +[ + Local(args); + args:=RulebaseArgumentsList(function,arity); +/* Echo({"holdnr ",args}); */ + ApplyFast("HoldArgument",{function,args[index]}); +]; + +%/mathpiper + + + +%mathpiper_docs,name="HoldArgumentNumber",categories="Programmer Functions;Programming;Built In" +*CMD HoldArgumentNumber --- specify argument as not evaluated +*STD +*CALL + HoldArgumentNumber("function", arity, argNum) + +*PARMS +{"function"} -- string, function name + +{arity}, {argNum} -- positive integers + +*DESC + +Declares the argument numbered {argNum} of the function named {"function"} with +specified {arity} to be unevaluated ("held"). Useful if you don't know symbolic +names of parameters, for instance, when the function was not declared using an +explicit {Rulebase} call. Otherwise you could use {HoldArgument}. + +*SEE HoldArgument, Rulebase +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/Macro.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/Macro.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/Macro.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/Macro.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,118 @@ +%mathpiper,def="Macro" + +Rulebase("Macro",{oper,args,body}); +HoldArgument("Macro",oper); +HoldArgument("Macro",args); +HoldArgument("Macro",body); + +// macro with variable number of arguments: Macro("func",{x,y, ...})body; +Rule("Macro",3,2047, + And(IsGreaterThan(Length(args), 1), IsEqual( MathNth(args, Length(args)), ToAtom("...") )) +) +[ + DestructiveDelete(args,Length(args)); // remove trailing "..." + Retract(oper,Length(args)); + `DefMacroRulebaseListed(@oper,@args); + MacroRule(oper,Length(args),1025,True) body; // at precedence 1025, for flexibility +]; + +// macro with a fixed number of arguments +Rule("Macro",3,2048,True) +[ + Retract(oper,Length(args)); + `DefMacroRulebase(@oper,@args); + MacroRule(oper,Length(args),1025,True) body; +]; + +Rulebase("Macro",{oper}); +// macro with variable number of arguments: Macro() f(x,y, ...) +Rule("Macro",1,2047, + And(IsFunction(oper), IsGreaterThan(Length(oper), 1), IsEqual( MathNth(oper, Length(oper)), ToAtom("...") )) +) +[ + Local(args,name); + Bind(args,Rest(FunctionToList(oper))); + DestructiveDelete(args,Length(args)); // remove trailing "..." + Bind(name,Type(oper)); + If(RulebaseDefined(Type(oper),Length(args)), + False, // do nothing + `DefMacroRulebaseListed(@name,@args) + ); +]; +// macro with a fixed number of arguments +Rule("Macro",1,2048, + And(IsFunction(oper)) +) +[ + Local(args,name); + Bind(args,Rest(FunctionToList(oper))); + Bind(name,Type(oper)); + If(RulebaseDefined(Type(oper),Length(args)), + False, // do nothing + [ + `DefMacroRulebase(@name,@args); + ] + ); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Macro",categories="Programmer Functions;Programming;Built In" +*CMD Macro --- declare or define a macro +*STD +*CALL + Macro() func(arglist) + Macro() func(arglist, ...) + Macro("op", {arglist}) body + Macro("op", {arglist, ...}) body + +*PARMS + +{func(args)} -- function declaration, e.g. {f(x,y)} + +{"op"} -- string, name of the function + +{{arglist}} -- list of atoms, formal arguments to the function + +{...} -- literal ellipsis symbol "{...}" used to denote a variable number of arguments + +{body} -- expression comprising the body of the function + +*DESC + +This does the same as {Function}, but for macros. One can define a macro +easily with this function, in stead of having to use {DefMacroRulebase}. + +*E.G. notest + +the following example defines a looping function. + +In> Macro("myfor",{init,pred,inc,body}) [@init;While(@pred)[@body;@inc;];True;]; +Result: True; +In> a:=10 +Result: 10; + +Here this new macro {myfor} is used to loop, using a variable {a} from the +calling environment. + +In> myfor(i:=1,i<10,i++,Echo(a*i)) + 10 + 20 + 30 + 40 + 50 + 60 + 70 + 80 + 90 +Result: True; +In> i +Result: 10; + +*SEE Function, DefMacroRulebase +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/TemplateFunction.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/TemplateFunction.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/TemplateFunction.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/TemplateFunction.mpw 2011-02-05 04:04:44.000000000 +0000 @@ -0,0 +1,87 @@ +%mathpiper,def="TemplateFunction" + +Rulebase("TemplateFunction",{oper,args,body}); + +Bodied("TemplateFunction",60000); + +HoldArgument("TemplateFunction",oper); + +HoldArgument("TemplateFunction",args); + +HoldArgument("TemplateFunction",body); + +Rule("TemplateFunction",3,2047,True) +[ + Retract(oper,Length(args)); + Local(arglist); + arglist:=FlatCopy(args); + + DestructiveAppend(arglist,{args,ListToFunction({Hold,body})}); + arglist:=ApplyFast("LocalSymbols",arglist); + + MacroRulebase(oper,arglist[1]); + MacroRule(oper,Length(args),1025,True) arglist[2]; + +]; + +%/mathpiper + + + + +%mathpiper_docs,name="TemplateFunction",categories="Programmer Functions;Programming;Built In" +*CMD TemplateFunction --- defines a function +*CALL + TemplateFunction("operator",parameter) + +*PARMS +{"operator"} -- string, name of a function + +{parameter} -- atom, symbolic name of parameter + +*DESC +Defines a function. + +*E.G. +/%mathpiper +TemplateFunction("MyUntil",{predicate,body}) +[ + Eval(body); + While (IsEqual(Eval(predicate),False)) + [ + Eval(body); + ]; + True; +]; +UnFence("MyUntil",2); +HoldArgumentNumber("MyUntil",2,1); +HoldArgumentNumber("MyUntil",2,2); +Bodied("MyUntil",60000); + +/%/mathpiper + + + +/%mathpiper + +x := 1; + +MyUntil(x = 5) +[ + Echo(x); + x++; +]; + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + 1 + 2 + 3 + 4 + +. /%/output +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/Unholdable.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/Unholdable.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deffunc/Unholdable.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deffunc/Unholdable.mpw 2010-07-14 23:26:25.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="Unholdable" + + +Rulebase("Unholdable",{var}); + +HoldArgument("Unholdable",var); + +UnFence("Unholdable",1); + +Rule("Unholdable",1,10,IsEqual(Type(Eval(var)),"Eval")) +[ + MacroBind(var,Eval(Eval(var))); + //Echo({"unheld",var,Eval(var)}); +]; + + +Rule("Unholdable",1,20,True) +[ + //Echo({"held"}); + True; +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="Unholdable",categories="Programmer Functions;Programming;Built In" +*CMD Unholdable --- make a variable unholdable + +*CALL + Unholdable(var) + +*PARMS + +{var} -- a variable + +*DESC +This function makes a variable unholdable. It is used to make sure that an := +operator with an Eval() immediately to its right hand side evaluates its argument. +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Curl.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Curl.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Curl.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Curl.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="Curl" + +Rulebase("Curl", {aFunc, aBasis}); + +Rule("Curl", 2, 1, Length(aBasis)=Length(aFunc)) + { + Apply("Differentiate",{aBasis[2],aFunc[3]})-Apply("Differentiate",{aBasis[3],aFunc[2]}), + Apply("Differentiate",{aBasis[3],aFunc[1]})-Apply("Differentiate",{aBasis[1],aFunc[3]}), + Apply("Differentiate",{aBasis[1],aFunc[2]})-Apply("Differentiate",{aBasis[2],aFunc[1]}) + }; + +%/mathpiper + + + +%mathpiper_docs,name="Curl",categories="User Functions;Calculus Related (Symbolic)" +*CMD Curl --- curl of a vector field +*STD +*CALL + Curl(vector, basis) + +*PARMS + +{vector} -- vector field to take the curl of + +{basis} -- list of variables forming the basis + +*DESC + +This function takes the curl of the vector field "vector" with +respect to the variables "basis". The curl is defined in the usual way, + + Curl(f,x) = { + Differentiate(x[2]) f[3] - Differentiate(x[3]) f[2], + Differentiate(x[3]) f[1] - Differentiate(x[1]) f[3], + Differentiate(x[1]) f[2] - Differentiate(x[2]) f[1] + } +Both "vector" and "basis" should be lists of length 3. + +*E.G. + +In> Curl({x*y,x*y,x*y},{x,y,z}) +Result: {x,-y,y-x}; + +*SEE D, Diverge +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Deriv.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Deriv.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Deriv.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Deriv.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,93 @@ +%mathpiper,def="Deriv" + + +5 # (Deriv(_var,1)_func) <-- Deriv(var)func; +5 # (Deriv(_var,0)_func) <-- func; +10 # (Deriv(_var,n_IsPositiveInteger)_func) <-- Deriv(var)Deriv(var,n-1)func; +10 # (Deriv(_var,n_IsNegativeInteger)_func) <-- Check(0, "Math", "Negative derivative"); + + +// Need to clean out Sec(x) and friends +0 # (Deriv(_var) (_var)) <-- 1; +1 # (Deriv(_var)func_IsAtom) <-- 0; +2 # (Deriv(_var)_x + _y) <-- (Deriv(var)x) + (Deriv(var)y); +2 # (Deriv(_var)- (_x) ) <-- -Deriv(var)x; +2 # (Deriv(_var)_x - _y) <-- (Deriv(var)x) - (Deriv(var)y); +2 # (Deriv(_var)_x * _y) <-- (x*Deriv(var)y) + (Deriv(var)x)*y; +2 # (Deriv(_var)Sin(_x)) <-- (Deriv(var)x)*Cos(x); +2 # (Deriv(_var)Sinh(_x))<-- (Deriv(var)x)*Cosh(x); +2 # (Deriv(_var)Cosh(_x))<-- (Deriv(var)x)*Sinh(x); +2 # (Deriv(_var)Cos(_x)) <-- -(Deriv(var)x)*Sin(x); +2 # (Deriv(_var)Csc(_x)) <-- -(Deriv(var)x)*Csc(x)*Cot(x); +2 # (Deriv(_var)Csch(_x)) <-- -(Deriv(var)x)*Csch(x)*Coth(x); +2 # (Deriv(_var)Sec(_x)) <-- (Deriv(var)x)*Sec(x)*Tan(x); +2 # (Deriv(_var)Sech(_x)) <-- -(Deriv(var)x)*Sech(x)*Tanh(x); +2 # (Deriv(_var)Cot(_x)) <-- -(Deriv(var)x)*Csc(x)^2; +2 # (Deriv(_var)Coth(_x)) <-- (Deriv(var)x)*Csch(x)^2; + +2 # (Deriv(_var)Tan(_x)) <-- ((Deriv(var) x) / (Cos(x)^2)); +2 # (Deriv(_var)Tanh(_x)) <-- (Deriv(var)x)*Sech(x)^2; + +2 # (Deriv(_var)Exp(_x)) <-- (Deriv(var)x)*Exp(x); + +// When dividing by a constant, this is faster +2 # (Deriv(_var)(_x / _y))_(IsFreeOf(var,y)) <-- (Deriv(var) x) / y; +3 # (Deriv(_var)(_x / _y)) <-- + (y* (Deriv(var) x) - x* (Deriv(var) y))/ (y^2); + +2 # (Deriv(_var)Ln(_x)) <-- ((Deriv(var) x) / x); +2 # (Deriv(_var)(_x ^ _n))_(IsRationalOrNumber(n) Or IsFreeOf(var, n)) <-- + n * (Deriv(var) x) * (x ^ (n - 1)); + +//2 # (Deriv(_var)(Abs(_x))) <-- Sign(x)*(Deriv(var)x); +2 # (Deriv(_var)(Abs(_x))) <-- (x/Abs(x))*(Deriv(var)x); +2 # (Deriv(_var)(Sign(_x))) <-- 0; + +2 # (Deriv(_var)(if(_cond)(_body))) <-- + ListToFunction({ToAtom("if"),cond,Deriv(var)body}); +2 # (Deriv(_var)((_left) else (_right))) <-- + ListToFunction({ToAtom("else"), (Deriv(var)left), (Deriv(var)right) } ); + +3 # (Deriv(_var)(_x ^ _n)) <-- (x^n)*Deriv(var)(n*Ln(x)); + +2 # (Deriv(_var)ArcSin(_x)) <-- (Deriv(var) x)/Sqrt(1 - (x^2)); +2 # (Deriv(_var)ArcCos(_x)) <-- -(Deriv(var)x)/Sqrt(1 - (x^2)); +2 # (Deriv(_var)ArcTan(_x)) <-- (Deriv(var) x)/(1 + x^2); + +2 # (Deriv(_var)ArcSinh(_x)) <-- (Deriv(var) x)/Sqrt((x^2) + 1); +2 # (Deriv(_var)ArcCosh(_x)) <-- (Deriv(var) x)/Sqrt((x^2) - 1); +2 # (Deriv(_var)ArcTanh(_x)) <-- (Deriv(var) x)/(1 - x^2); + +2 # (Deriv(_var)Sqrt(_x)) <-- ((Deriv(var)x)/(2*Sqrt(x))); +2 # (Deriv(_var)Complex(_r,_i)) <-- Complex(Deriv(var)r,Deriv(var)i); + +LocalSymbols(var,var2,a,b,y)[ + 2 # (Deriv(_var)Integrate(_var)(_y)) <-- y; + 2 # (Deriv(_var)Integrate(_var2,_a,_b)(y_IsFreeOf(var))) <-- + (Deriv(var)b)*(y Where var2 == b) - + (Deriv(var)a)*(y Where var2 == a); + 3 # (Deriv(_var)Integrate(_var2,_a,_b)(_y)) <-- + (Deriv(var)b)*(y Where var2 == b) - + (Deriv(var)a)*(y Where var2 == a) + + Integrate(var2,a,b) Deriv(var) y; + ]; + + + +2 # (Deriv(_var)func_IsList)_(Not(IsList(var))) <-- + Map("Deriv",{FillList(var,Length(func)),func}); + + +2 # (Deriv(_var)UniVariate(_var,_first,_coefs)) <-- +[ + Local(result,m,i); + result:=FlatCopy(coefs); + m:=Length(result); + For(i:=1,i<=m,i++) + [ + result[i] := result[i] * (first+i-1); + ]; + UniVariate(var,first-1,result); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Differentiate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Differentiate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Differentiate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Differentiate.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,94 @@ +%mathpiper,def="Differentiate" + +Rulebase("Differentiate",{aVar,aFunc}); +Rulebase("Differentiate",{aVar,aCount,aFunc}); + +Rule("Differentiate",2,1,IsList(aVar) And Not(IsList(aFunc))) + Map("Differentiate",{aVar,FillList(aFunc, Length(aVar))}); +Rule("Differentiate",2,1,IsList(aVar) And IsList(aFunc)) + Map("Differentiate",{aVar,aFunc}); + +Rule("Differentiate",2,3,True) +[ + MacroLocal(aVar); + Apply("Deriv",{aVar,1,aFunc}); +]; + +Rule("Differentiate",3,1,IsList(aVar) And Not(IsList(aFunc))) + Map("Differentiate",{aVar, + FillList(aCount, Length(aVar)), + FillList(aFunc, Length(aVar))}); +Rule("Differentiate",3,1,IsList(aVar) And IsList(aFunc)) + Map("Differentiate",{aVar, + FillList(aCount, Length(aVar)), + aFunc}); +Rule("Differentiate",3,3,True) +[ + MacroLocal(aVar); + Apply("Deriv",{aVar,aCount,aFunc}); +]; + + +HoldArgument("Differentiate",aVar); +HoldArgument("Differentiate",aFunc); + +%/mathpiper + + + +%mathpiper_docs,name="Differentiate",categories="User Functions;Calculus Related (Symbolic)" +*CMD Differentiate --- take derivative of expression with respect to variable +*STD +*CALL + Differentiate(variable) expression + Differentiate(list) expression + Differentiate(variable,n) expression + +*PARMS + +{variable} -- variable + +{list} -- a list of variables + +{expression} -- expression to take derivatives of + +{n} -- order of derivative + +*DESC + +This function calculates the derivative of the expression {expr} with +respect to the variable {var} and returns it. If the third calling +format is used, the {n}-th derivative is determined. MathPiper knows +how to differentiate standard functions such as {Ln} +and {Sin}. + +The {D} operator is threaded in both {var} and +{expr}. This means that if either of them is a list, the function is +applied to each entry in the list. The results are collected in +another list which is returned. If both {var} and {expr} are a +list, their lengths should be equal. In this case, the first entry in +the list {expr} is differentiated with respect to the first entry in +the list {var}, the second entry in {expr} is differentiated with +respect to the second entry in {var}, and so on. + +The {D} operator returns the original function if $n=0$, a common +mathematical idiom that simplifies many formulae. + +*E.G. + +In> Differentiate(x)Sin(x*y) +Result: y*Cos(x*y); +In> Differentiate({x,y,z})Sin(x*y) +Result: {y*Cos(x*y),x*Cos(x*y),0}; +In> Differentiate(x,2)Sin(x*y) +Result: -Sin(x*y)*y^2; +In> Differentiate(x){Sin(x),Cos(x)} +Result: {Cos(x),-Sin(x)}; + +*SEE Integrate, Taylor, Diverge, Curl +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Diverge.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Diverge.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/deriv/Diverge.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/deriv/Diverge.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="Diverge" + +Rulebase("Diverge", {aFunc, aBasis}); +Rule("Diverge", 2, 1, IsList(aBasis) And IsList(aFunc) And Length(aBasis) = Length(aFunc)) + Add(Map("Differentiate", {aBasis,aFunc})); + +%/mathpiper + + + +%mathpiper_docs,name="Diverge",categories="User Functions;Calculus Related (Symbolic)" +*CMD Diverge --- divergence of a vector field +*STD +*CALL + Diverge(vector, basis) + +*PARMS + +{vector} -- vector field to calculate the divergence of + +{basis} -- list of variables forming the basis + +*DESC + +This function calculates the divergence of the vector field "vector" +with respect to the variables "basis". The divergence is defined as + + Diverge(f,x) = Differentiate(x[1]) f[1] + ... + + Differentiate(x[n]) f[n], +where {n} is the length of the lists "vector" and +"basis". These lists should have equal length. + +*E.G. + +In> Diverge({x*y,x*y,x*y},{x,y,z}) +Result: y+x; + +*SEE D, Curl +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/equations/EquationLeft.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/equations/EquationLeft.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/equations/EquationLeft.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/equations/EquationLeft.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="EquationLeft" + +EquationLeft(_symbolicEquation)_(Type(symbolicEquation) = "==") <-- +[ + Local(listForm); + + listForm := FunctionToList(symbolicEquation); + + listForm[2]; +]; +%/mathpiper + + + + +%mathpiper_docs,name="EquationLeft",categories="User Functions;Expression Manipulation" +*CMD EquationLeft --- return the left side of a symbolic equation +*STD +*CALL + EquationLeft(equation) + +*PARMS + +{equation} -- symbolic equation. + + +*DESC + +A symbolic equation is an equation which is defined using the == operator. This +function returns the left side of a symbolic equation. + +*E.G. + +In> equ := y^2 == 4*p*x +Result: y^2==4*p*x + +In> EquationLeft(equ) +Result: y^2 + +*SEE ==, EquationRight +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/equations/EquationRight.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/equations/EquationRight.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/equations/EquationRight.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/equations/EquationRight.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="EquationRight" + +EquationRight(_symbolicEquation)_(Type(symbolicEquation) = "==") <-- +[ + Local(listForm); + + listForm := FunctionToList(symbolicEquation); + + listForm[3]; +]; + +%/mathpiper + + + +%mathpiper_docs,name="EquationRight",categories="User Functions;Expression Manipulation" +*CMD EquationRight --- return the right side of a symbolic equation +*STD +*CALL + EquationRight(equation) + +*PARMS + +{equation} -- symbolic equation. + + +*DESC + +A symbolic equation is an equation which is defined using the == operator. This +function returns the right side of a symbolic equation. + +*E.G. + +In> equ := y^2 == 4*p*x +Result: y^2==4*p*x + +In> EquationRight(equ) +Result: 4*p*x + +*SEE ==, EquationLeft +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/example/Example.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/example/Example.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/example/Example.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/example/Example.mpw 2010-01-01 06:42:32.000000000 +0000 @@ -0,0 +1,101 @@ +%mathpiper,def="Example" + + + +examplelist:= +Hold( +{ + {40!, +"Simple factorial of a number. +" + }, + {Differentiate(x)Sin(x), +"Taking the derivative of a function (the derivative of Sin(x) with +respect to x in this case). +" + }, + {Taylor(x,0,5)Sin(x), +"Expanding a function into a taylor series. +" + }, + {Integrate(x,a,b)Sin(x), +"Integrate a function. +" + }, + {Solve(a+x*y==z,x), +"Solve a function for a variable. +" + }, + {Limit(x,0) Sin(x)/x, +"Take a limit. +" + }, + {Subst(x,Cos(a)) x+x, +"Substitute an expression with another in the main expression. +" + }, + {Expand((1+x)^3), +"Expand into a polynomial. +" + }, + {2^40, +"Big numbers. +" + }, + {1<<40, +"Bitwise operations +" + }, + {1 .. 4, +"Generating a list of numbers. +" + }, + {a:b:c:{}, +"Generating a list of items. +" + }, + {[Local(x);x:={a,b,c};Sin(x)^2;], +"Threading: Sin(..)^2 will be performed on all elements of the list +passed in. +" + }, + {[Local(list);list:={a,b,c,d,e,f}; list[2 .. 4];], +"Selecting a sublist from a list. +" + }, + {PermutationsList({a,b,c}), +"Generate all permutations of a list. +" + }, + {VarList(a+b*x), +"Show all variables that occur in an expression. +" + }, + {TrigSimpCombine(Cos(a)*Cos(a)+Sin(a)*Sin(a)), +"Convert factors between trigonometric functions to addition of +trigonometric functions. +" + } +} +); +exampleindex:=0; + +Example():= +[ + exampleindex++; + If (exampleindex>Length(examplelist),exampleindex:=1); + + Local(example); + example:=examplelist[exampleindex]; + WriteString("Current example : "); + Write(example[1]);WriteString(";");NewLine(); + NewLine(); + WriteString(example[2]); + NewLine(); + Eval(example[1]); +]; + + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/BinaryFactors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/BinaryFactors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/BinaryFactors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/BinaryFactors.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,298 @@ +%mathpiper,def="BinaryFactors",public="todo" + +LocalSymbols(lastcoef,OrdBuild, AddFoundSolutionSingle , AddFoundSolution, Fct, MkfactD,p) +[ + +LastCoef(_vector,_p) <-- +[ + Local(n); + n:=Length(vector); + Add(vector*p^(0 .. (n-1))); +]; + +/* +Ord(vector,q):= +[ + Local(n); + n:=Length(vector); + q*Coef(Simplify(LastCoef(vector,p+q)-LastCoef(vector,p)),q,1); +]; +*/ + +OrdBuild(vector,q):= +[ + Local(i,result,n); + Bind(i,2); + Bind(result, 0); + Bind(n, Length(vector)); + While (i<=n) + [ + Bind(result,result+(i-1)*vector[i]*p^(i-2)); + Bind(i, i+2); + ]; + q*result; +]; + + +Function(AddFoundSolutionSingle,{p}) +[ + Local(calc); +// If ( Not Contains(result,p), +// [ + Bind(calc, Eval(lastcoef)); + If (IsEqual(calc, 0), + [ + Local(newlist,count,root); + count:=0; + root := p; + Local(rem); + + rem:={-root,1}; + {testpoly,rem}:=MkfactD(testpoly,rem); + + rem:={-root,1}; + {newlist,rem}:=MkfactD(poly,rem); + While (rem = {}) + [ + count++; + Bind(poly,newlist); + rem:={-root,1}; + {newlist,rem}:=MkfactD(poly,rem); + ]; + + Local(lgcd,lc); + Bind(lgcd,Gcd({andiv,an,root})); + Bind(lc,Quotient(an,lgcd)); + Bind(result,{var+ (-(Quotient(root,lgcd)/lc)),count}:result); + Bind(andiv,Quotient(andiv,lgcd^count)); + Bind(anmul,anmul*lc^count); + +// factor:=(x-root); +// Bind(result,{factor,count}:result); + + Local(p,q); + Bind(lastcoef, LastCoef(testpoly,p)); + Bind(ord, OrdBuild(testpoly,q)); + ]); +// ]); +]; +UnFence(AddFoundSolutionSingle,1); + +Function(AddFoundSolution,{p}) +[ + AddFoundSolutionSingle(p); + AddFoundSolutionSingle(-2*q+p); +]; +UnFence(AddFoundSolution,1); + +Function(Fct,{poly,var}) +[ + Local(maxNrRoots,result,ord,p,q,accu,calc,twoq,mask); + + Local(gcd); + [ + Bind(gcd,Gcd(poly)); + If(poly[Length(poly)] < 0,Bind(gcd, gcd * -1)); + Bind(poly,poly/gcd); + ]; + + Local(unrat); + Bind(unrat,Lcm(MapSingle("Denominator",poly))); + Bind(poly,unrat*poly); + + Local(origdegree); + Bind(origdegree,Length(poly)-1); + + Local(an,andiv,anmul); + Bind(an,poly[Length(poly)]); + Bind(poly,poly* (an^((origdegree-1) .. -1))); + Bind(andiv,an^(origdegree-1)); + Bind(anmul,1); + + Local(leadingcoef,lowestcoef); + Bind(leadingcoef,poly[Length(poly)]); + [ + Local(i); + Bind(i,1); + Bind(lowestcoef,Abs(poly[i])); + While (lowestcoef = 0 And i<=Length(poly)) + [ + Bind(i,i+1); + Bind(lowestcoef,Abs(poly[i])); + ]; + ]; + // testpoly is the square-free version of the polynomial, used for finding + // the factors. the original polynomials is kept around to find the + // multiplicity of the factor. + Local(testpoly); +// Bind(testpoly,Mkc(Quotient(polynom,Monic(Gcd(polynom,Deriv(var)polynom))),var)); + Local(deriv); + // First determine a derivative of the original polynomial + deriv:=Rest(poly); + [ + Local(i); + For (i:=1,i<=Length(deriv),i++) + [ + deriv[i] := deriv[i]*i; + ]; +// Echo("POLY = ",poly); +// Echo("DERIV = ",deriv); + ]; + [ + Local(q,r,next); + q:=poly; + r:=deriv; + While(r != {}) + [ +//Echo(q,r); + next := MkfactD(q,r)[2]; + q:=r; + r:=next; + ]; + // now q is the gcd of the polynomial and its first derivative. + + // Make it monic + q:=q/q[Length(q)]; + testpoly:=MkfactD(poly,q)[1]; +//Echo("TESTPOLY = ",testpoly); + ]; + +// Bind(testpoly,poly); //@@@ + + Bind(maxNrRoots,Length(testpoly)-1); + Bind(result, {}); + + Bind(lastcoef, LastCoef(testpoly,p)); + Bind(ord, OrdBuild(testpoly,q)); + + Bind(accu,{}); + Bind(q,1); + Bind(twoq,MultiplyN(q,2)); + Bind(mask,AddN(twoq,MathNegate(1))); + if (IsEven(testpoly[1])) + [ + Bind(accu,0:accu); + AddFoundSolutionSingle(0); + ]; + Bind(p,1); + Bind(calc, Eval(lastcoef)); + If (IsEven(calc), + [ + Bind(accu,1:accu); + AddFoundSolution(1); + ]); + Bind(q,twoq); + Bind(twoq,MultiplyN(q,2)); + Bind(mask,AddN(twoq,MathNegate(1))); + While(Length(result)0 And q<=Abs(testpoly[1])) + [ + Local(newaccu); + Bind(newaccu,{}); + ForEach(p,accu) + [ + Bind(calc,Eval(lastcoef)); + If (IsLessThan(calc,0), + Bind(calc, AddN(calc,MultiplyN(twoq,QuotientN(AddN(MathNegate(calc),twoq),twoq)))) + ); + Bind(calc, BitAnd(calc, mask)); + If ( IsEqual(calc, 0), + [ + Bind(newaccu, p:newaccu); + AddFoundSolutionSingle(-2*q+p); + ]); + Bind(calc, AddN(calc, Eval(ord))); + If (IsLessThan(calc,0), + Bind(calc, AddN(calc,MultiplyN(twoq,QuotientN(AddN(MathNegate(calc),twoq),twoq)))) + ); + Bind(calc, BitAnd(calc, mask)); + If ( IsEqual(calc, 0), + [ + Bind(newaccu, AddN(p,q):newaccu); + AddFoundSolution(AddN(p,q)); + ]); + ]; + Bind(accu, newaccu); + Bind(q,twoq); + Bind(twoq,MultiplyN(q,2)); + Bind(mask,AddN(twoq,MathNegate(1))); + +//Echo("q = ",q); +//Echo("Length is",Length(accu),"accu = ",accu); +//Echo("result = ",result); + ]; + + // If the polynom is not one, it is a polynomial which is not reducible any further + // with this algorithm, return as is. + Bind(poly,poly*an^(0 .. (Length(poly)-1))); + Bind(poly,gcd*anmul*poly); + //TODO had to add this if statement, what was andiv again, and why would it become zero? This happens with for example Factor(2*x^2) + If(Not IsZero(unrat * andiv ),Bind(poly,poly/(unrat * andiv ))); + If(poly != {1}, + [ + result:={(Add(poly*var^(0 .. (Length(poly)-1)))),1}:result; + ]); + result; +]; + + + +BinaryFactors(expr):= +[ + Local(result,uni,coefs); + uni:=MakeUni(expr,VarList(expr)[1]); + uni:=FunctionToList(uni); + coefs:=uni[4]; + coefs:=Concat(ZeroVector(uni[3]),coefs); + result:=Fct(coefs,uni[2]); +// Echo(result,list); +// Echo((Add(list*x^(0 .. (Length(list)-1))))); +// Product(x-result)*(Add(list*x^(0 .. (Length(list)-1)))); + result; +]; + + + +MkfactD(numer,denom):= +[ + Local(q,r,i,j,ln,ld,nq); + DropEndZeroes(numer); + DropEndZeroes(denom); + Bind(numer,Reverse(numer)); + Bind(denom,Reverse(denom)); + Bind(ln,Length(numer)); + Bind(ld,Length(denom)); + Bind(q,FillList(0,ln)); + Bind(r,FillList(0,ln)); + + Bind(i,1); + If(ld>0, + [ + While(Length(numer)>=Length(denom)) + [ + Bind(nq,numer[1]/denom[1]); + q[ln-(Length(numer)-ld)] := nq; + For(j:=1,j<=Length(denom),j++) + [ + numer[j] := (numer[j] - nq*denom[j]); + ]; + r[i] := r[1] + numer[1]; + + Bind(numer, Rest(numer)); + i++; + ]; + ]); + For(j:=0,j 0, DestructiveAppend(newn,{f,k}) ); + If( k < 0, DestructiveAppend(newd,{f,-k}) ); + ], + [ + k := 1; + DestructiveAppend(newn,{f,k}); + ] + ); + ]; + If(InVerboseMode(),Tell(" ",{newn,newd})); + FW(newn)/FW(newd); +]; + +20 # FactorCancel( _p ) <-- Factor(p); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +. + + + +%mathpiper_docs,name="FactorCancel",categories="User Functions;Polynomials (Operations)" + +*CMD FactorCancel -- Factors a Rational Function and cancels where possible + +*CALL +FactorCancel( expr ) + +*PARMS +{expr} -- A function which is a quotient of two polynomials + +*DESC +A quotient of two polynomials P(z) and Q(z), + R(z)=(P(z))/(Q(z)), +is called a rational function, or sometimes a rational polynomial function. + +By convention, the {Domain} of the function {excludes} any points which are +zeros of the denominator, even though some of these may be cancelable by +equivalent zeros in the numerator. Therefore, the function {Factor}, when +applied to such a function, retains all the factors of both numerator and +denominator, whether or not they might subsequently cancel. + +But sometimes a user might want to see the factored function in the form which +results when such cancellation has been performed. {FactorCancel} performs +this operation. + +*E.G. + +In> P:=Expand(x^2-1) +Result: x^2-1 + +In> Q:=Expand((x+1)^2) +Result: x^2+2*x+1 + +In> F:=P/Q +Result: (x^2-1)/(x^2+2*x+1) + +In> Factor(F) +Result: ((x-1)*(x+1))/(x+1)^2 + +In> FactorCancel(F) +Result: (x-1)/(x+1) + + +*SEE Factor,Factors + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorizeInt.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorizeInt.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorizeInt.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorizeInt.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="FactorizeInt" + +// numbers + +/// Middle level function: returns a list of prime factors and their powers. +/// E.g. FactorizeInt(50) returns {{2, 1}, {5, 2}}. +1# FactorizeInt(0) <-- {}; +1# FactorizeInt(1) <-- {}; + +3# FactorizeInt(n_IsInteger) <-- +[ + Local(small'powers); + n := Abs(n); // just in case we are given a negative number + // first, find powers of 2, 3, ..., p with p=257 currently -- this speeds up PollardRho and should avoids its worst-case performance + // do a quick check first - this will save us time especially if we want to move 257 up a lot + If( + Gcd(ProductPrimesTo257(), n) > 1, // if this is > 1, we need to separate some factors. Gcd() is very fast + small'powers := TrialFactorize(n, 257), // value is {n1, {p1,q1}, {p2,q2}, ...} and n1=1 if completely factorized into these factors, and the remainder otherwise + small'powers := {n} // pretend we had run TrialFactorize without success + ); + n := small'powers[1]; // remainder + If(n=1, Rest(small'powers), + // if n!=1, need to factorize the remainder with Pollard Rho algorithm + [ + //If(InVerboseMode(), Echo({"FactorizeInt: Info: remaining number ", n})); + SortFactorList( + PollardCombineLists(Rest(small'powers), PollardRhoFactorize(n)) + ); + ] + ); +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Factor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Factor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Factor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Factor.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,189 @@ +%mathpiper,def="Factor" + +//Retract("Factor",*); + +10 # Factor( p_IsRational )_(Denominator(p) != 1) <-- +[ + If(InVerboseMode(),Tell("Factor_ratNum",p)); + Local(fs,num,den,dent,n,d); + fs := Factors(p); + If(InVerboseMode(),Tell(" ",fs)); + num := Select(fs,Lambda({X},X[2]>=0)); + den := Select(fs,Lambda({X},X[2]<0)); + If(InVerboseMode(),Tell(" ",{num,den})); + dent := Transpose(den); + dent[2] := -1 * dent[2]; + den := Transpose(dent); + If(InVerboseMode(),Tell(" ",{num,den})); + n := FW(num); + d := FW(den); + n/d; + +]; + + +12 # Factor( p_CanBeUni ) <-- +[ + If(InVerboseMode(),Tell("Factor_uni",p)); + Local(facList); + facList := Factors(p); + If(InVerboseMode(),[Tell(" ",facList);]); + FW(facList); +]; + + +20 # Factor( p_IsRationalFunction ) <-- +[ + If(InVerboseMode(),Tell("Factor_ratFunc",p)); + Local(fs,num,den,dent,n,d); + fs := Factors( p ); + If(InVerboseMode(),Tell(" ",fs)); + num := Select(fs,Lambda({X},X[2]>=0)); + den := Select(fs,Lambda({X},X[2]<0)); + If(InVerboseMode(),Tell(" ",{num,den})); + dent := Transpose(den); + dent[2] := -1 * dent[2]; + den := Transpose(dent); + If(InVerboseMode(),Tell(" ",{num,den})); + n := FW(num); + d := FW(den); + n/d; +]; + + +30 # Factor( L_IsList ) <-- +[ + Local (result,x,f); + result := {}; + ForEach(x,L) + [ + f := Factors(x); + If( f = {}, f := 0, f := FW(f) ); + DestructiveAppend(result,f); + ]; + result; +]; + + + +40 # Factor( _expr ) <-- expr; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="Factor",categories="User Functions;Polynomials (Operations);Number Theory" +*CMD Factor -- Factorization of almost anything factorable +*CALL +Factor( expr ) +*PARMS +{expr} -- An Integer, Rational number, Gaussian Integer, Polynomial, or Rational Function +*DESC +This function decomposes an integer number {expr} into a product of its prime factors. + +If {expr} is a Rational number (quotient of integers), it is decomposed into a +quotient of prime factors divided by prime factors, in lowest terms. + +If {expr} is a Gaussian integer (complex number whose Re and Im parts are integers), +it is decomposed into a product of Gaussian primes. + +If {expr} is a univariate polynomial, it is decomposed into a product of +irreducible polynomials. If the coefficients of {expr} are all Integers, the +factors will be irreducible over the Integers. If the coefficients of {expr} +are Rational numbers, the factors will be irreducible over the Rationals. +If any of the coefficients are in {R} but not in {Z} or {Q}, they will be +converted to approximate Rationals before factoring. + +If {expr} is a multivariate polynomial, it may or may not be factorized by this +function. In general, {bivariate binomials} and {homogeneous bivariate polynomials} +will be factored correctly. Factoring of other types of multivariate polynomials +is not yet fully implemented. + +If {expr} is a Rational {function} (quotient of polynomials), it is decomposed into a +quotient of irreducible factors divided by irreducible factors, but not in lowest terms. + +*E.G. +In> n:=2*2*5*7*11^2 +Result: 16940 + +In> Factor(n) +Result: 2^2*5*7*11^2 + +In> m:=3*7*11 +Result: 231 + +In> Factor(n/m) +Result: (2^2*5*11)/3 + +In> g:=Expand((-2+3*I)*(5-6*I)) +Result: Complex(8,27) + +In> Factor(g) +Result: Complex(-2,3)*Complex(-5,6) + +In> f:=Expand(5*x*(x-2)^2*(x^2+x+1)*(x^2-x+1)) +Result: 5*x^7-20*x^6+25*x^5-20*x^4+25*x^3-20*x^2+20*x + +In> Factor(f) +Result: 5*x*(x-2)^2*(x^2-x+1)*(x^2+x+1) + +In> P:=Expand(x^2-1) +Result: x^2-1 + +In> Q:=Expand((x+1)^2) +Result: x^2+2*x+1 + +In> F:=P/Q +Result: (x^2-1)/(x^2+2*x+1) + +In> Factor(F) +Result: ((x-1)*(x+1))/(x+1)^2 + +In> f:=Expand((2*x)^6-(3)^6) +Result: 64*x^6-729 + +In> Factor(f) +Result: (2*x+3)*(4*x^2-6*x+9)*(2*x-3)*(4*x^2+6*x+9) + +In> f:=Expand((2*x)^6-(3*y)^6) +Result: 64*x^6-729*y^6 + +In> Factor(f) +Result: (3*y+2*x)*(9*y^2-6*y*x+4*x^2)*(2*x-3*y)*(9*y^2+6*y*x+4*x^2) + +In> f:=Expand((2*x-5*y)^2*(7*x+3*y)) +Result: 28*x^3-128*y*x^2+115*y^2*x+75*y^3 + +In> Factor(f) +Result: (2*x-5*y)^2*(7*x+3*y) + +In> f:=(a*x-a*y)/a +Result: (a*x-a*y)/a + +In> Factor(f) +Result: ((-1)*a*(y-x))/a + +NOTE: If you want the result of Factor on a rational function to express +the answer in lowest terms (i.e., with cancellation), then use the function +FactorCancel() instead. + +In> FactorCancel(f) +Result: x-y + + +*SEE FactorCancel,Factors + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorQS.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorQS.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorQS.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorQS.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,18 @@ +%mathpiper,def="FactorQS" + +// numbers + +// The bud of an Quadratic Seive algorithm +// congruence solving code must be written first +Function("FactorQS",{n})[ + Local(x,k,fb,j); + // optimal number of primes in factor base + // according to Fundamental Number Theory with Applications - Mollin, p130 + k:=Round(N(Sqrt(Exp(Sqrt(Ln(n)*Ln(Ln(n))))))); + fb:=ZeroVector(k); + For(j:=1,j<=k,j++)[ + fb[j]:=NextPrime(j); + ]; +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsBinomials.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsBinomials.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsBinomials.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsBinomials.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,title="FactorsBinomials" + +//Retract("FactorsBinomials",*); + +10 # FactorsBinomials( _x + y_IsFreeOf(x) ) <-- {x+y,1}; + +10 # FactorsBinomials( _x - y_IsFreeOf(x) ) <-- {x-y,1}; + +10 # FactorsBinomials( c_IsConstant * _x + y_IsFreeOf(x) ) <-- {c*x+y,1}; + +10 # FactorsBinomials( c_IsConstant * _x - y_IsFreeOf(x) ) <-- {c*x-y,1}; + +10 # FactorsBinomials( _x^m_IsOdd + _y ) <-- +[ + If(InVerboseMode(),Tell("FactorsBinomialssum",{x,m,y})); + Local(nn,qq); + nn := (m-1)/2; + qq := (y^(1/m)); + If(InVerboseMode(),Tell(" FBinsum1",{nn,qq})); + r := {{x+qq,1},{Sum(k,0,m-1,(-1)^k*qq^k*x^(m-1-k)),1}}; +]; + + +12 # FactorsBinomials( c_IsConstant * _x^m_IsOdd + _y ) <-- +[ + If(InVerboseMode(),Tell("FactorsBinomialssum",{c,x,m,y})); + Local(nn,qq); + nn := (m-1)/2; + qq := ((y/c)^(1/m)); + If(InVerboseMode(),Tell(" FBinsum.1b",{nn,qq})); + If( c=1, + r := {{x+qq,1},{Sum(k,0,m-1,(-1)^k*qq^k*x^(m-1-k)),1}}, + r := {{c,1},{x+qq,1},{Sum(k,0,m-1,(-1)^k*qq^k*x^(m-1-k)),1}} + ); +]; + + +10 # FactorsBinomials( _x^m_IsInteger - _y ) <-- +[ + If(InVerboseMode(),Tell("FactorsBinomialsdif",{x,m,y})); + Local(pp,qq,r,L); + pp := m-1; + qq := (y^(1/m)); + If(IsNumber(y),qq:=GuessRational(N(qq))); + If(InVerboseMode(),Tell(" FBindif.1",{pp,qq})); + + if (m = 2) + [ + L := FunctionToList(y); + If(And(L[1]=ToAtom("^"),L[3]=2),qq:=L[2]); + r := {{x+qq,1},{x-qq,1}}; + ] + else if (m = 4) + [r := {{x+qq,1},{x-qq,1},{x^2+qq^2,1}};] + else if (m = 6) + [r := {{x+qq,1},{x-qq,1},{x^2+x*qq+qq^2,1},{x^2-x*qq+qq^2,1}};] + else + [r := {{x-qq,1},{Sum(k,0,pp,qq^k*x^(pp-k)),1}};]; + r; +]; + + +12 # xFactorsBinomials( c_IsConstant * _x^m_IsInteger - _y ) <-- +[ + If(InVerboseMode(),Tell("FactorsBinomialsdif",{c,x,m,y})); + Local(aa,bb,c0,r); + aa := c^(1/m); + bb := ((y)^(1/m)); + If(IsNumber(y),bb:=GuessRational(N(bb))); + If(InVerboseMode(),Tell(" FBindif.1b",{aa,bb})); + r := FactorsBinomials( (aa*x)^m - bb^m ); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsMonomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsMonomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsMonomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsMonomial.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,94 @@ +%mathpiper,def="FactorsMonomial" + +//Retract("FactorsMonomial",*); + +10 # FactorsMonomial(expr_IsMonomial) <-- +[ + If(InVerboseMode(),Tell("FactorsMonomial",expr)); + Local(den,num,Ns,flat,prod,quot,result,f,ff); + If( IsRationalFunction(expr), + [ + den := Denominator(expr); + num := Flatten(Numerator(expr),"*"); + ], + [ + den := 1; + num := Flatten(expr,"*"); + ] + ); + If(InVerboseMode(),Tell(" ",{num,den})); + Ns := Select(num, "IsComplex"); + If(InVerboseMode(),Tell(" ",Ns)); + If( Ns = {}, + If( den != 1, DestructiveInsert(num,1,1/den)), + DestructiveReplace(num,Find(num,Ns[1]),Ns[1]/den) + ); + If(InVerboseMode(),Tell(" ",num)); + result := {}; + ForEach(f,num) + [ + If( IsComplex(f), + DestructiveAppend(result,{(f),1}), + If( IsAtom(f), + DestructiveAppend(result,{f,1}), + DestructiveAppend(result,DestructiveDelete(FunctionToList(f),1)) + ) + ); + ]; + result; +]; + +%/mathpiper + + + + + + +%mathpiper_docs,name="FactorsMonomial",categories="User Functions;Number Theory" +*CMD FactorsMonomial --- factorization of a monomial expression +*STD +*CALL + FactorsMonomial(expr) + +*PARMS + +{expr} -- an expression representing a Monomial + +*DESC + +This function decomposes the {expr} into a product of numbers and variables +raised to various powers. + +The factorization is returned as a list of pairs. The first member of +each pair is the factor (a number or a variable name), while the second +member is an integer denoting the power to which this factor should be +raised. + +Thus, the factorization +$expr = p1^n1 * ... * p9^n9$ +is returned as {{(p1,n1), ..., (p9,n9)}}. + +If {expr} is not a monomial, the function returns unevaluated. + +NOTE: numerical factors are not decomposed into their prime factorization. + +*E.G. + +In> FactorsMonomial(24) +Result: {{24,1}} + +In> FactorsMonomial(24/15) +Result: {{8/5,1}} + +In> FactorsMonomial(24*a*x^2*y^3) +Result: {{24,1},{a,1},{x,2},{y,3}} + +In> FactorsMonomial(24*a*x^2*y^3/15) +Result: {{8/5,1},{a,1},{x,2},{y,3}} + +In> FactorsMonomial(24*a*x^2*y^3/15+1) +Result: FactorsMonomial((24*a*x^2*y^3)/15+1) + +%/mathpiper_docs + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Factors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Factors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Factors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Factors.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,185 @@ +%mathpiper,def="Factors" + +/*------------------------------------------------------------------------ + * Started 091222 + * revised 100108-22 + * revised 100215 + * major refactoring 100425 + * convert polynomial factoring to use JAS library 100511 + * Another major refactoring -- 100529 + * Ready for initial commit 100610 + * Modifications 100727 + *------------------------------------------------------------------------*/ + +//Retract("Factors",*); + + +/* -------------- LISTS ---------------*/ + +10 # Factors( L_IsList ) <-- nFactors /@ L; + + +/* ------------- NUMBERS --------------*/ + + +10 # Factors(n_IsPositiveInteger) <-- +[ + If( n < 1600, FactorsSmallInteger(n), FactorizeInt(n) ); +]; + + + +15 # Factors(n_IsNegativeInteger) <-- +[ + If(InVerboseMode(),Tell("Factors_negInt",n)); + Local(en,ans); + en := -n; + ans := {-1,1}:If( en < 1600, FactorsSmallInteger(en), FactorizeInt(en) ); +]; + + +20 # Factors(p_IsRational)_(Denominator(p) != 1) <-- +[ + If(InVerboseMode(),Tell("Factors_ratNum",p)); + Local(sgn,num,den,fn,fd,f,ans); + sgn := 1; + If(p < 0, [p := -p; sgn := -1;]); + num := Numerator(p); + den := Denominator(p); + fn := FactorizeInt(num); + If(sgn < 0, fn := {-1,1}:fn ); + fd := FactorizeInt(den); + If(InVerboseMode(),Tell(" ",{fn,fd})); + ForEach(f,fd) + [ + DestructiveReplace(f,2,-f[2]); + DestructiveAppend(fn,f); + ]; + ans := fn; +]; + + +25 # Factors(p_IsGaussianInteger) <-- GaussianFactors(p); + + +30 # Factors(_p)_(Length(VarList(p))=0) <-- {{p,1}}; + + +//40 # Factors(p_IsRationalFunction) <-- +//[ +// If(InVerboseMode(),Tell("Factors_ratFunc",p)); +// jFactorsRationalFunc(p); +//]; + + +50 # Factors( p_CanBeUni ) <-- +[ + If(InVerboseMode(),Tell("Factors_uni",p)); + Local(res,len,newRes,ii,accum,n); + res := jFactorsPoly(p); + // + // Now, do a bit of fix-up for factors of (-1)^n + // + len := Length(res); + newRes := {}; + accum := 1; // initialize number accumulator + + ForEach(r,res) + [ + If(InVerboseMode(),Tell(" ",r)); + If( IsNumber(Eval(r[1])), + [ + n := r[1]^r[2]; + If(InVerboseMode(),Tell(" ",n)); + accum := accum * n; + ], + DestructiveAppend(newRes,r) + ); + ]; + If(InVerboseMode(),Tell(" ",{newRes,accum})); + If(accum != 1, DestructiveInsert(newRes,1,{accum,1})); + newRes; +]; + + +60 # Factors( p_IsRationalFunction ) <-- +[ + If(InVerboseMode(),Tell("Factors_ratFunc",p)); + Local(num,den,fn,fd,f); + num := Numerator(p); + den := Denominator(p); + If(InVerboseMode(),Tell(" ",{num,den})); + fn := Factors(num); + fd := Factors(den); + If(Not IsListOfLists(fd), fd := {fd}); + If(InVerboseMode(),Tell(" r ",{fn,fd})); + ForEach(f,fd) + [ + DestructiveReplace(f,2,-f[2]); + DestructiveAppend(fn,f); + ]; + fn; +]; + +100 # Factors( _p ) <-- +[ + Tell("Factors__Fall-Through_cases",p); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + %output,preserve="false" + Processing... +. %/output + + %output,preserve="false" + Processing... +. %/output + + + + + +%mathpiper_docs,name="Factors",categories="User Functions;Number Theory" +*CMD Factors --- factorization +*STD +*CALL + Factors(x) + +*PARMS + +{x} -- integer or univariate polynomial + +*DESC + +This function decomposes the integer number {x} into a product of +numbers. +Alternatively, if {x} is a univariate polynomial, it is +decomposed into irreducible polynomials. If {x} is a polynomial +"over the integers", the irreducible polynomial factors will also +be returned in the (unique) form with integer coefficients. + +The factorization is returned as a list of pairs. The first member of +each pair is the factor, while the second member denotes the power to +which this factor should be raised. So the factorization +$x = p1^n1 * ... * p9^n9$ +is returned as {{{p1,n1}, ..., {p9,n9}}}. + +Programmer: Yacas Team + Sherm Ostrowsky + +*E.G. +In> Factors(24) +Result: {{2,3},{3,1}} + +In> Factors(32*x^3+32*x^2-70*x-75) +Result: {{4*x+5,2},{2*x-3,1}} + +*SEE Factor, IsPrime, GaussianFactors +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsPolynomialOverIntegers.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsPolynomialOverIntegers.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsPolynomialOverIntegers.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsPolynomialOverIntegers.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,205 @@ +%mathpiper,def="FactorsPolynomialOverIntegers" + +//Retract("FactorsPolynomialOverIntegers",*); +//Retract("TryToReduceSpecialPolynomial",*); + +//--------------------------------------------------------------------------- + +10 # FactorsPolynomialOverIntegers(_expr)_IsPolynomialOverIntegers(expr) <-- +[ + Local(x); + x := VarList(expr)[1]; + FactorsPolynomialOverIntegers(expr,x); + +]; + +15 # FactorsPolynomialOverIntegers(_expr) <-- expr; + + +10 # FactorsPolynomialOverIntegers(_expr,_var)_(IsPolynomialOverIntegers(expr,var)) <-- +[ + Local(factorsList,factListTransp,factrs,multiplicities,factrsUnMonic); + Local(polyFactors,normalizations,normDivisor,polyFactors,factList); + Local(n,result,newResult,gtotal,r,rr,d,g); + factorsList := BinaryFactors(expr); + /* + * BinaryFactors is the internal MathPiper function that + * creates a double list of factors and their multiplicities + */ + + // By transposing factorsList (which has the form of a list of + // lists, hence a matrix), we convert it into a form which has + // a list of all the factors first, followed by a list of all + // the corresponding multiplicities. + + factListTransp := Transpose(factorsList); + factrs := factListTransp[1]; + multiplicities := factListTransp[2]; + + // Now, these factors are probably all in "monic" form, with the + // coefficient of the highest power of x in each factor being + // equal to 1, and all the "normalizing" factors being combined + // into a new leading numeric factor. We want to undo this + // monic-ization. The function Together() will accomplish this + // for each separate factor, while leaving untouched factors + // which do not need changing. + + factrsUnMonic := MapSingle("Together",factrs); + + // The result of this step is that each factor which had been + // "normalized" to a monic has now be un-normalized into a + // rational function consisting of a non-monic polynomial + // divided by a number. Now we just collect all the non-monic + // polynomials into one list, and all the normalizing denominators + // into another. + + {polyFactors,normalizations}:=Transpose(MapSingle("GetNumerDenom",factrsUnMonic)); + + // The next step is to make sure that each of the normalizing + // numbers is raised to the power of its corresponding + // multiplicity. Then all these powers of numbers are + // multiplied together, to form the overall normilizing + // divisor which must be used to remove the extra factor (if + // any) introduced during the monic-ization process. All this + // is condensed into one line of Functional code + + normDivisor := Product(Map("^",{normalizations,multiplicities})); + + // Notice that normDivisors is exactly equal in value to the + // 'extra' numeric factor introduced by the monic-ization, if + // any was indeed so introduced (it doesn't happen under all + // circumstances). I believe this will always be true, but I + // have not taken the time to prove it. So I proceed in a + // more general way. + + polyFactors[1] := Simplify(polyFactors[1]/normDivisor); + + // We can now replace the first sub-list in factListTransp by + // the un-monic-ized version + + factListTransp[1] := polyFactors; + factList := Transpose(factListTransp); + + + // .... and that is (supposedly) the answer. + result := factList; + + // However, let's find out if any of the factors needs more treatment. + Local(newResult,gtotal,d,g,rr); + newResult := {}; + gtotal := 1; + ForEach(r,result) [ + d := Degree(r[1],var); + g := Gcd(Coef(r[1],var,0 .. d)); + If( g > 1, // need to remove common numerical factor + [ gtotal:=g*gtotal; + r[1]:=Simplify(r[1]/g); + ] + ); + If(d > 2, + [ + // polynomial is NOT irreducible, but can we reduce it? + rr := TryToReduceSpecialPolynomial(r[1]); + If( IsList(rr),newResult := Concat(newResult,rr) ); + ], + If( r != {1,1}, newResult := r:newResult ) + ); + ]; + If(gtotal>1,newResult:={gtotal,1}:newResult); + newResult; +]; + + +//--------------------------------------------------------------------------- +// S P E C I A L C A S E S +//--------------------------------------------------------------------------- +/* + * Given an unreduced polynomial over the integers, of degree > 2, + * which was found as one of the "factors" of a polynomial over + * the integers, we know that it is factorable into irreducible + * quadratics. This function tries to find such quadratic factors. + * Lacking a good general attack on this problem, we will turn + * to special cases which we happen to be able to solve. + */ + +10 # TryToReduceSpecialPolynomial(_x^4+_x^2+1) <-- {{x^2+x+1,1},{x^2-x+1,1}}; + +10 # TryToReduceSpecialPolynomial(_x^6-1) <-- {{x+1,1},{x-1,1},{x^2+x+1,1},{x^2-x+1,1}}; + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="FactorsPolynomialOverIntegers",categories="User Functions;Number Theory",access="experimental" +*CMD Factors --- factorization of univariate polynomials over the integers +*STD +*CALL + FactorsPolynomialOverIntegers(poly,x) + +*PARMS + +{poly} -- a polynomial which is univariate w.r.t. variable x +{x} -- variable of the polynomial + +*DESC + +This function decomposes the polynomial {poly}, considered as univariate +in the variable {x}, into a product of irreducible polynomials. + +This function is specialized for polynomials in {x} whose coefficients +are all integers. In such a case, it is often customary to expect the +irreducible polynomial factors to be given in a form which also has +only integer coefficients. However, the standard MathPiper function +Factors() follows a different convention, which returns the constituant +polynomial factors in a {monic} form. This means that the results may +have rational, rather than integer, coefficients. + +The present function offers an alternative which is guaranted to return +polynomial factors with integer coefficients. But it works only for +input {polynomials}, not {numbers}, and only for polynomials all of whose +coefficients are integers. For any other input, this function will simply +return the input expression unevaluated. + +The factorization is returned as a list of pairs. The first member of +each pair is the factor, while the second member denotes the power to +which this factor should be raised. So the factorization +$poly = p1^n1 * ... * p9^n9$ +is returned as {{{p1,n1}, ..., {p9,n9}}}. + +NOTE: If you want the factorization to be expressed in the nominal +form $poly = p1^n1 * ... * p9^n9$, +just apply the function FW() to the result returned by the present +function. + +Programmer: Sherm Ostrowsky + +*E.G. + +In> u:=Expand((2*x-3)^2*(3*x+5)^3) +Result: 108*x^5+216*x^4-477*x^3-985*x^2+525*x+1125 + +In> FactorsPolynomialOverIntegers(u,x) +Result: {{2*x-3,2},{3*x+5,3}} + +In> FW(%) +Result: (2*x-3)^2*(3*x+5)^3 + +In> FactorsPolynomialOverIntegers(y^2-4) +Result: {{y+2,1},{y-2,1}} + +In> FactorsPolynomialOverIntegers(x^4+x^2+1) +Result: {{x^2+x+1,1},{x^2-x+1,1}} + +*SEE Factor, Factors, FW +%/mathpiper_docs + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsSmallInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsSmallInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FactorsSmallInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FactorsSmallInteger.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,67 @@ +%mathpiper,def="FactorsSmallInteger" + +//Retract("FactorsSmallInteger",*); + +10 # FactorsSmallInteger( N_IsInteger ) <-- +[ + Local(n, power, prime, result, limit); + n := Abs(N); // make sure its positive + limit := Ceil(SqrtN(n)); // upper bound for largest possible factor + prime := 2; // first prime + result := {}; + While( prime <= limit And n > 1 And prime*prime <= n ) + [ // find the max power of prime which divides n + {n, power} := FindPrimeFactor(n, prime); + If( power > 0, DestructiveAppend(result, {prime,power}) ); + prime := NextPseudoPrime(prime); // faster than NextPrime and we don't need real primes here + ]; + // Add the last prime (with multiplicity 1) to end of list + If( n > 1, DestructiveAppend(result, {n,1}) ); + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="FactorsSmallInteger",categories="User Functions;Number Theory" +*CMD FactorsSmallInteger --- factorization for small integers +*STD +*CALL + FactorsSmallInteger(x) + +*PARMS + +{x} -- a small integer + +*DESC + +This function decomposes the integer number {x} into its prime factors. +The method used is not suitable for large integers, although it will work. +This function is best reserved for integers less than, say, 10,000 or so. + +The factorization is returned as a list of pairs. The first member of +each pair is the factor, while the second member denotes the power to +which this factor should be raised. So the factorization +$x = p1^n1 * ... * p9^n9$ +is returned as {{{p1,n1}, ..., {p9,n9}}}. + +Programmer: Yacas Team + Sherm Ostrowsky + +*E.G. +In> FactorsSmallInteger(24) +Result: {{2,3},{3,1}} + +*SEE Factors, IsPrime, FactorizeInt +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FindPrimeFactor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FindPrimeFactor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FindPrimeFactor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FindPrimeFactor.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="FindPrimeFactor" + +// numbers + +/// Auxiliary function. Return the power of a given prime contained in a given integer and remaining integer. +/// E.g. FindPrimeFactor(63, 3) returns {7, 2} and FindPrimeFactor(42,17) returns {42, 0} +// use variable step loops, like in IntLog() +FindPrimeFactor(n, prime) := +[ + Local(power, factor, old'factor, step); + power := 1; + old'factor := 1; // in case the power should be 0 + factor := prime; + // first loop: increase step + While(Modulo(n, factor)=0) // avoid division, just compute Modulo() + [ + old'factor := factor; // save old value here, avoid sqrt + factor := factor^2; + power := power*2; + ]; + power := Quotient(power,2); + factor := old'factor; + n := Quotient(n, factor); + // second loop: decrease step + step := Quotient(power,2); + While(step>0 And n > 1) + [ + factor := prime^step; + If( + Modulo(n, factor)=0, + [ + n := Quotient(n, factor); + power := power + step; + ] + ); + step := Quotient(step, 2); + ]; + {n, power}; +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FindPrimeFactorSimple.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FindPrimeFactorSimple.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FindPrimeFactorSimple.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FindPrimeFactorSimple.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,19 @@ +%mathpiper,def="FindPrimeFactorSimple" + +// numbers + +/* simpler method but slower on worstcase such as p^n or n! */ +FindPrimeFactorSimple(n, prime) := +[ + Local(power, factor); + power := 0; + factor := prime; + While(Modulo(n, factor)=0) + [ + factor := factor*prime; + power++; + ]; + {n/(factor/prime), power}; +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FWatom.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FWatom.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FWatom.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FWatom.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,6 @@ +%mathpiper,def="FWatom" + +10 # FWatom({_a,1}) <-- a; +20 # FWatom({_a,_n}) <-- ListToFunction({ToAtom("^"),a, n}); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FW.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FW.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/FW.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/FW.mpw 2010-01-05 20:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +%mathpiper,def="FW" + +/* FW: pass FW the result of Factors, and it will show it in the + * form of p0^n0*p1^n1*... + */ + + +5 # FW(_list)_(Length(list) = 0) <-- 1; +10 # FW(_list)_(Length(list) = 1) <-- FWatom(list[1]); +20 # FW(_list) <-- +[ + Local(result); + result:=FWatom(First(list)); + ForEach(item,Rest(list)) + [ + result := ListToFunction({ ToAtom("*"),result,FWatom(item)}); + ]; + result; +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/jasFactorsInt.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/jasFactorsInt.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/jasFactorsInt.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/jasFactorsInt.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,62 @@ +%mathpiper,title="jasFactorsInt" + +//Retract("jasFactorsInt",*); + +jasFactorsInt(poly_IsPolynomial) <-- +[ + If(InVerboseMode(),Tell(jasFactorsInt,poly)); + Local(polyStr,vars,strVars,ns,ringDescription,defaultPoly,jasI); + + // --- get Java class JFactorsPolyInt into MathPiper form + polyStr := ExpressionToString(poly); // polynomial as string + vars := VarList(poly); + strVars := ExpressionToString( vars ); // variables as string + ns := Length(strVars); + strVars := strVars[2 .. ns-1]; // remove enclosing braces + + jasI := JavaNew("org.mathpiper.builtin.library.jas.JFactorsPolyInt",polyStr,strVars); + If(InVerboseMode(),[Tell(" ",jasI);]); + + // --- at last, we're ready to do some factoring + Local(resultSet,entrySet,iterator,result,mult,fact); + // the result returned by the factors() method is a Java SortedMap + // In order to iterate through this Map, we need its first set and + // an iterator. + resultSet := JavaCall(jasI,"factors"); + entrySet := JavaCall(resultSet,"entrySet"); + iterator := JavaCall(entrySet,"iterator"); + // now we can iterate through the Map and make a MathPiper List whose + // elements are {factor,multiplicity} pairs + result := {}; + While ( JavaAccess(iterator,"hasNext")=True) + [ + entrySet := JavaCall(iterator,"next"); + mult := JavaAccess(entrySet,"getValue"); + fact := ToString(JavaAccess(JavaCall(entrySet,"getKey"),"toScript")); + // convert factor string from "**" to "^" exponent notation + Local(lst,ii,factor); + lst := StringToList(fact); + For(ii:=1,ii0,{content,pp}:={pp,content}); + If( Length(VarList(pp))=0, result := {{pp*content,1}}, + [ + //If(InVerboseMode(),Tell(" ",{content,pp})); + vars := VarList(pp); + nvars := Length(vars); + disassem := DisassembleExpression(pp); + nterms := Length(disassem[3]); + degrees := {}; + allCoeffs := disassem[3]; + allPowers := Flatten(disassem[2],"List"); + If(nvars > 0, + [ + ForEach(v,vars) + [ DestructiveAppend(degrees,Degree(pp,v)); ]; + isHomogeneous := [ + // A polynomial is homogeneous of degree n + // if all terms have degree n. + Local(sd,cmp); + sd := Sum /@ disassem[2]; + cmp := FillList(sd[1],Length(sd)); + IsZeroVector(sd - cmp); + ]; + ] + ); + + If(InVerboseMode() And moreDetails, + [ + Tell(" ",vars); + Tell(" ",nvars); + Tell(" ",nterms); + Tell(" ",degrees); + Tell(" ",disassem); + Tell(" ",allCoeffs); + Tell(" ",allPowers); + Tell(" ",isHomogeneous); + NewLine(); + ] + ); + + // Does the Content have factors? If so, get them. + //If(InVerboseMode(),NewLine()); + monomialFactors := FactorsMonomial(content); + If(InVerboseMode(),Tell(" ",monomialFactors)); + + // OK. Now factor the PrimitivePart + ppFactors := jFactorsPrimitivePart( pp ); + If(InVerboseMode(),Tell(" ",ppFactors)); + If( Not IsListOfLists(ppFactors), + [ + Local(L,op,var,exp); + L := If(IsAtom(ppFactors[1]), ppFactors, FunctionToList(ppFactors[1]) ); + If(InVerboseMode(),Tell(" ",L)); + If( L[1] = ^, ppFactors := {L[2],L[3]} ); + ppFactors := {ppFactors}; + ] + ); + If(InVerboseMode(),Tell(" ",ppFactors)); + + // Next, include the factors of the Content, if any + If( monomialFactors[1][1] = 1, + result := ppFactors, + //result := Concat(monomialFactors,{ppFactors}) // hso 100801 + result := Concat(monomialFactors,ppFactors) // hso 100803 + ); + ] + ); + + If(InVerboseMode(), + [ + NewLine(); + Tell(" ",monomialFactors); + Tell(" ",ppFactors); + Tell(" final ",result); + ] + ); + result; +]; +UnFence("jFactorsPoly",1); + + + +// ----------------- FACTOR PRIMITIVE PART ----------------- + + // special case: binomials +60 # jFactorsPrimitivePart( _pp )_(isHomogeneous And nterms=2 And nvars=2) <-- +[ + If(InVerboseMode(),Tell("Bivariate Binomial",pp)); + Local(ppFactors,isDiagonal); + isDiagonal := IsDiagonal(disassem[2]); // mod hso 10-11-25 + ppFactors := If(isDiagonal,jFactorsBivariateBinomial(pp),jasFactorsInt(pp) ); +]; +UnFence("jFactorsPrimitivePart",1); + + + // special case: homogeneous bivariates +65 # jFactorsPrimitivePart( _pp )_(isHomogeneous And nterms>1 And nvars=2) <-- +[ + If(InVerboseMode(),Tell("Homogeneous and Bivariate")); + Local(ppFactors); + ppFactors := jFactorsHomogeneousBivariate(disassem); +]; +UnFence("jFactorsPrimitivePart",1); + + + // special case: no variables in pp! +70 # jFactorsPrimitivePart( _pp )_(nvars=0) <-- +[ + Local(ppFactors); + ppfactors := {}; +]; + + + // general case +100 # jFactorsPrimitivePart( _pp ) <-- +[ + If(InVerboseMode(),Tell("jFactorsPrimitivePart_usingJAS",pp)); + Local(answer); + answer := If(IsMonomial(pp),{pp,1},jasFactorsInt(pp)); + If(InVerboseMode(),Tell(" ",answer)); + answer; +]; +UnFence("jFactorsPrimitivePart",1); + +// ------------------ HOMOGENEOUS BIVARIATE ------------------ + +10 # jFactorsHomogeneousBivariate( dis_IsList ) <-- +[ + If(InVerboseMode(),[NewLine();Tell("jFactorsHomogeneousBivariate",dis);]); + Local(dis1,f,dis2,poly1,ppFactors,residuals); + Local(ii,lst,f,preassem); + dis1 := {{xi},{{X},{X[1]}} /@ dis[2],dis[3]}; + If(InVerboseMode(),Tell(" ",dis1)); + poly1 := Sum(ReassembleListTerms(dis1)); + If(InVerboseMode(),Tell(" ",poly1)); + ppFactors := BinaryFactors(poly1); + {ppFactors,residuals} := FixUpMonicFactors(ppFactors); + For(ii:=1,ii<=Length(ppFactors),ii++) + [ + f := ppFactors[ii]; + If(InVerboseMode(),Tell(" ",f[1])); + lst := DisassembleExpression(f[1]); + If(InVerboseMode(), + [ + Tell(" ",lst); + Tell(" ",dis[1]); + ] + ); + DestructiveReplace(lst,1,dis[1]); + DestructiveAppend(lst[2][1],0); + DestructiveAppend(lst[2][2],1); + If(Length(lst[2])=3, DestructiveAppend(lst[2][3],2)); + If(InVerboseMode(),Tell(" ",lst)); + preassem := Sum(ReassembleListTerms(lst)) ; + If(InVerboseMode(),Tell(" ",preassem)); + ppFactors[ii][1] := preassem; + ]; + If(InVerboseMode(),[Tell(" ",ppFactors); Tell(" ",residuals);NewLine();] ); + ppFactors; +]; +UnFence("jFactorsHomogeneousBivariate",1); + +// --------------------- OTHER STUFF ------------------------ + +10 # RealToRationalConvert( poly_IsPolynomial ) <-- +[ + // If the polynomial has REAL coefficients, convert them to + // approximate RATIONALS + If(InVerboseMode(),[NewLine();Tell(" REAL",poly);]); + Local(coeffs,gcd,lcm); + coeffs := Rationalize /@ (allCoeffs); + If(InVerboseMode(),[Tell(" to-Q",coeffs);Tell(" to-Z",coeffs);]); + Local(gcd,lcm); + gcd := Gcd(Numerator /@ coeffs); + lcm := Lcm(Denominator /@ coeffs); + If(InVerboseMode(),[Tell(" ",gcd);Tell(" ",lcm);]); + disassem[3] := coeffs; + allCoeffs := coeffs; + poly := Sum(ReassembleListTerms(disassem)); + If(InVerboseMode(),Tell(" new",poly)); + poly; +]; +UnFence("RealToRationalConvert",1); + + +10 # RationalToIntegerConvert( poly_IsPolynomial ) <-- +[ + // If the polynomial has RATIONAL coefficients, convert to + // approximate INTEGER + Local(coeffs,gcd,lcm); + coeffs := allCoeffs; + If(InVerboseMode(),Tell(" ",coeffs)); + lcm := Lcm(Denominator /@ coeffs); + extraFactor := lcm; + If(InVerboseMode(),[Tell(" ",extraFactor);]); + poly := Simplify(extraFactor*poly); + If(InVerboseMode(),Tell(" new ",poly)); + poly; +]; +UnFence("RationalToIntegerConvert",1); + + +100 # CombineNumericalFactors( factrs_IsList ) <-- +[ + If( InVerboseMode(), Tell("Combine",factrs) ); + Local(q,a,b,t,f,ff,err); + err := False; + t := 1; + f := {}; + ForEach(q,factrs) + [ + If( InVerboseMode(), Tell(1,q) ); + If( IsList(q) And Length(q)=2, + [ + {a,b} := q; + If( InVerboseMode(), Echo(" ",{a,b}) ); + If( IsNumericList( {a,b} ), + t := t * a^b, + f := {a,b}:f + ); + ], + err := True + ); + ]; + If( InVerboseMode(), + [ + Echo(" t = ",t); + Echo(" f = ",f); + Echo(" err = ",err); + ] + ); + ff := If(Not err And t != 1, {t,1}:Reverse(f), factrs); + ff := Select(Lambda({x},x!={1,1}),ff); + If(ff[1]<0,ff[1]:=-ff[1]); +]; + + +// ---------------- RATIONAL POLYNOMIALS ----------------- + +150 # jFactors( expr_IsRationalFunction )_ + (IsPolynomial(Numerator(expr)) And IsPolynomial(Denominator(expr))) <-- +[ + If(InVerboseMode(),[NewLine();Tell("jFactors_Rational_Function",expr);]); + Local(Numer,Denom,fNumer,fDenom); + Numer := Numerator(expr); + Denom := Denominator(expr); + fNumer := jFactors(Numer); + fDenom := jFactors(Denom); + If(InVerboseMode(),[Tell(" ",fNumer); Tell(" ",fDenom);]); + fNumer/fDenom; +]; + + +152 # jFactors( expr_IsRationalFunction )_ + (IsConstant(Numerator(expr)) And IsPolynomial(Denominator(expr))) <-- +[ + If(InVerboseMode(),[NewLine();Tell("jFactors_Rational_Denom",expr);]); + Local(Numer,Denom,fNumer,fDenom); + Numer := Numerator(expr); + Denom := Denominator(expr); + fNumer := jFactors(Numer); + fDenom := jFactors(Denom); + If(InVerboseMode(),[Tell(" ",fNumer); Tell(" ",fDenom);]); + fNumer/fDenom; +]; + + +// ---------- POSSIBLE NON-INTEGER EXPONENTS ---------- + +200 # jFactors( _expr )_(Length(VarList(expr)) = 1) <-- +[ + If(InVerboseMode(),[NewLine();Tell("Some other kind of expression",expr);]); + Local(dis,X,pows); + dis := DisassembleExpression(expr); + X := VarList(expr)[1]; + pows := matchPower /@ dis[1]; + rats := NearRational /@ pows; + dis[1] := x^rats; + p := Sum(ReassembleListTerms(dis)); + If(InVerboseMode(),Tell(" new ",p)); + jFactors(p); +]; + + + +/*------------------------------------------------------------------- + * Factoring Binomial expressions of the form A X^n � B Y^n, + * Uses JAS library, but converts to univariate equivalent + * before factoring. (JAS is inefficient for multivariate + * factoring when degree is large.) + *-------------------------------------------------------------------*/ + +10 # jFactorsBivariateBinomial( poly_IsPolynomial )_(Length(VarList(poly))=2) <-- +[ + If(InVerboseMode(),Tell(jFactorsBivariateBinomial,poly)); + Local(dis,n,X,Y,vars,A,B,s,Ar,Br,Arr,Brr,DAr,DBr,result); + dis := DisassembleExpression(poly); + If(InVerboseMode(),Tell(" ",dis)); + n := Maximum(dis[2])[1]; + X := dis[1][1]; + Y := dis[1][2]; + vars := dis[1]; + A := Abs(dis[3][1]); + B := Abs(dis[3][2]); + s := Sign(dis[3][1]*dis[3][2]); + //Ar := NearRational(N(A^(1/n))); + //Br := NearRational(N(B^(1/n))); + Ar := N(A^(1/n)); Arr := Round(Ar); DAr := Abs(Ar-Arr); + Br := N(B^(1/n)); Brr := Round(Br); DBr := Abs(Br-Brr); + If(InVerboseMode(), + [ + Tell(" ",{n,X,Y}); + Tell(" ",{vars,A,B}); + Tell(" ",{Ar,Br,s}); + Tell(" ",{Arr,Brr}); + Tell(" ",{DAr,DBr}); + Tell(" ",dis); + ] + ); + result := If( DAr < 10^(-9) And DBr < 10^(-9), jFB(dis), {{poly,1}} ); + result; +]; +UnFence("jFactorsBivariateBinomial",1); + + +50 # jFB( dis_IsList )_(Length(dis)=3 And Length(dis[3])=2) <-- +[ + If(InVerboseMode(),[NewLine();Tell("jFB",dis);]); + Local(ns,ii,fn,mx,my,fac); + If(InVerboseMode(), + [ + Tell(" ",n); + Tell(" ",{X,Y}); + Tell(" ",{A,B,s}); + Tell(" ",{Ar,Br}); + ] + ); + X := Arr*X; + Y := Brr*Y; + If(InVerboseMode(),Tell(" ",{X,Y})); + + fac := jFac( X/Y,n,s); // factor using JAS and normalized variable + If(InVerboseMode(), + [ + NewLine(); + Tell(" ",X/Y); + Tell(" ",fac); + ] + ); + + // now convert factorization back to actual variables if required + If( Y != 1, + [ + Local(f,d,fs); + For(ii:=1,ii<=Length(fac),ii++) + [ + f := fac[ii][1]; + d := Degree(f,x); + If(InVerboseMode(),Tell(" ",{ii,f,d})); + fs := Subst(x,X/Y) f; + If(InVerboseMode(),Tell(" ",{fs,d})); + fac[ii][1] := Simplify(Simplify(Y^d*fs)); + ]; + ] + ); + fac; +]; +UnFence("jFB",1); + + + +60 # jFac( _var, n_IsPositiveInteger, s_IsInteger ) <-- +[ + // Uses JAS to factor polynomial of form x^n � 1. + If(InVerboseMode(),[NewLine();Tell("jFac",{var,n,s});]); + Local(x,poly,result); + poly := x^n+s; + If(InVerboseMode(),Tell(" ",poly)); + result := jasFactorsInt(poly); +]; +UnFence("jFac",3); + + +10 # IsPureRational( N_IsRational )_(Not IsInteger(N)) <-- True; + +12 # IsPureRational( _N ) <-- False; + +10 # HasRealCoefficients( poly_IsPolynomial ) <-- +[ + Local(disassem); + disassem := DisassembleExpression(poly); + (Length(Select(disassem[3],"IsDecimal")) > 0); +]; + +10 # HasRealCoefficients( poly_IsMonomial ) <-- +[ + Local(disassem); + disassem := DisassembleExpression(poly); + (Length(Select(disassem[3],"IsDecimal")) > 0); +]; + + +10 # HasRationalCoefficients( poly_IsPolynomial ) <-- +[ + Local(disassem,answer); + If(InVerboseMode(),Tell(" HasRationalCoefficients",poly)); + disassem := DisassembleExpression(poly); + //Tell(" ",disassem); + answer := (Length(Select(disassem[3],"IsPureRational")) > 0); + If(InVerboseMode(),Tell(" ",answer)); + answer; +]; + +10 # HasRationalCoefficients( poly_IsMonomial) <-- +[ + Local(disassem); + disassem := DisassembleExpression(poly); + (Length(Select(disassem[3],"IsPureRational")) > 0); +]; + + +10 # FixUpMonicFactors( factrs_IsList ) <-- +[ + If(InVerboseMode(),[ NewLine(); Tell(" doing monic fixup"); ] ); + Local(factrsnew,residuals,f,uni,); + factrsnew := {}; + residuals := {}; + ForEach(f,factrs) + [ + If(InVerboseMode(),Tell(" ",f)); + uni := MakeUni(f[1]); + If(InVerboseMode(),Tell(" ",uni)); + If( Degree(f[1])=1, + [ + Local(cc,lcm,fnew); + If(InVerboseMode(),Tell(" ",Degree(f[1]))); + cc := Coef(f[1],uni[1],0 .. 1); + //Tell(" ",cc); + lcm := Lcm( Denominator /@ cc ); + uni[3] := lcm * cc; + fnew := NormalForm(uni); + If( hasRationalCoefficients, + [ + DestructiveAppend(factrsnew,f); + ], + [ + DestructiveAppend(factrsnew,{fnew,f[2]}); + ] + ); + ] + ); + If( Degree(f[1])=2, + [ + If(InVerboseMode(),Tell(" ",Degree(f[1]))); + Local(pq); + pq := PrimitivePart(f[1]); + DestructiveAppend(factrsnew,{pq,f[2]}); + ] + ); + // If any factors have degree >=3, store them in a 'residuals' array + // for further analysis + If( Degree(f[1]) > 2, + [ + If(InVerboseMode(),Tell(" ",Degree(f[1]))); + Local(pq); + pq := PrimitivePart(f[1]); + DestructiveAppend(residuals,{pq,f[2]}); + If(InVerboseMode(),Tell(" appending to residuals",pq)); + ] + ); + ]; + {factrsnew,residuals}; +]; +UnFence("FixUpMonicFactors",1); + + +//10 # matchPower(_Z^n_IsNumber) <-- n; + +//15 # matchPower(_Z) <-- 1; + + +//======================================================================== + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Monomials.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Monomials.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Monomials.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Monomials.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,147 @@ +%mathpiper,def="Monomials" + +//Retract("CanBeMonomial",*); +//Retract("IsMonomial",*); +//Retract("FactorsMonomial",*); + +10 # CanBeMonomial(_expr)<--Not (HasFunc(expr,ToAtom("+")) Or HasFunc(expr,ToAtom("-"))); + +10 # IsMonomial(expr_CanBeMonomial) <-- +[ + Local(r); + If( IsRationalFunction(expr), + r := (VarList(Denominator(expr)) = {}), + r := True + ); +]; + +15 # IsMonomial(_expr) <-- False; + + +10 # FactorsMonomial(expr_IsMonomial) <-- +[ + If(InVerboseMode(),Tell("FactorsMonomial",expr)); + Local(den,num,Ns,flat,prod,quot,result,f,ff); + If( IsRationalFunction(expr), + [ + den := Denominator(expr); + num := Flatten(Numerator(expr),"*"); + ], + [ + den := 1; + num := Flatten(expr,"*"); + ] + ); + If(InVerboseMode(),Tell(" ",{num,den})); + Ns := Select(num, "IsComplex"); + If(InVerboseMode(),Tell(" ",Ns)); + If( Ns = {}, + If( den != 1, DestructiveInsert(num,1,1/den)), + DestructiveReplace(num,Find(num,Ns[1]),Ns[1]/den) + ); + If(InVerboseMode(),Tell(" ",num)); + result := {}; + ForEach(f,num) + [ + If( IsComplex(f), + DestructiveAppend(result,{(f),1}), + If( IsAtom(f), + DestructiveAppend(result,{f,1}), + DestructiveAppend(result,DestructiveDelete(FunctionToList(f),1)) + ) + ); + ]; + result; +]; + +%/mathpiper + + + + + + + +%mathpiper_docs,name="IsMonomial",categories="User Functions;Predicates" +*CMD IsMonomial --- determine if {expr} is a Monomial +*STD +*CALL + IsMonomial(expr) + +*PARMS + +{expr} -- an expression + +*DESC + +This function returns {True} if {expr} satisfies the definition of a {Monomial}. +Otherwise, {False}. +A {Monomial} is defined to be a single term, consisting of a product of numbers +and variables. + +*E.G. +In> IsMonomial(24) +Result: True + +In> IsMonomial(24*a*x^2*y^3) +Result: True + +In> IsMonomial(24*a*x^2*y^3/15) +Result: True + +In> IsMonomial(24*a*x^2*y^3/15+1) +Result: False + +%/mathpiper_docs + + + +%mathpiper_docs,name="FactorsMonomial",categories="User Functions;Polynomials (Operations)" +*CMD FactorsMonomial --- factorization of a monomial expression +*STD +*CALL + FactorsMonomial(expr) + +*PARMS + +{expr} -- an expression representing a Monomial + +*DESC + +This function decomposes the {expr} into a product of numbers and variables +raised to various powers. + +The factorization is returned as a list of pairs. The first member of +each pair is the factor (a number or a variable name), while the second +member is an integer denoting the power to which this factor should be +raised. + +Thus, the factorization +$expr = p1^n1 * ... * p9^n9$ +is returned as {{(p1,n1), ..., (p9,n9)}}. + +If {expr} is not a monomial, the function returns unevaluated. + +NOTE: numerical factors are not decomposed into their prime factorization. + +*E.G. + +In> FactorsMonomial(24) +Result: {{24,1}} + +In> FactorsMonomial(24/15) +Result: {{8/5,1}} + +In> FactorsMonomial(24*a*x^2*y^3) +Result: {{24,1},{a,1},{x,2},{y,3}} + +In> FactorsMonomial(24*a*x^2*y^3/15) +Result: {{8/5,1},{a,1},{x,2},{y,3}} + +In> FactorsMonomial(24*a*x^2*y^3/15+1) +Result: FactorsMonomial((24*a*x^2*y^3)/15+1) + +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/pollardrho/PollardCombineLists.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/pollardrho/PollardCombineLists.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/pollardrho/PollardCombineLists.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/pollardrho/PollardCombineLists.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,15 @@ +%mathpiper,def="PollardCombineLists" +/* PollardCombineLists combines two assoc lists used for factoring. + the first element in each item list is the factor, and the second + the exponent. Thus, an assoc list of {{2,3},{3,5}} means 2^3*3^5. +*/ +PollardCombineLists(_left,_right) <-- +[ + ForEach(item,right) + [ + PollardMerge(left,item); + ]; + left; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/pollardrho/PollardMerge.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/pollardrho/PollardMerge.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/pollardrho/PollardMerge.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/pollardrho/PollardMerge.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,14 @@ +%mathpiper,def="PollardMerge" + +5 # PollardMerge(_list,{1,_n}) <-- True; +10 # PollardMerge(_list,_item)_(Assoc(item[1],list) = Empty) <-- + DestructiveInsert(list,1,item); + +20 # PollardMerge(_list,_item) <-- +[ + Local(assoc); + assoc := Assoc(item[1],list); + assoc[2]:=assoc[2]+item[2]; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/pollardrho/PollardRhoFactorize.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/pollardrho/PollardRhoFactorize.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/pollardrho/PollardRhoFactorize.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/pollardrho/PollardRhoFactorize.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,73 @@ +%mathpiper,def="PollardRhoFactorize" + +/* This is Pollard's Rho method of factorizing, as described in + * "Modern Computer Algebra". It is a rather fast algorithm for + * factoring, but doesn't scale to polynomials regrettably. + * + * It acts 'by chance'. This is the Floyd cycle detection trick, where + * you move x(i+1) = f(x(i)) and y(i+1) = f(f(y(i))), so the y goes twice + * as fast as x, and for a certain i x(i) will be equal to y(i). + * + * "Modern Computer Algebra" reasons that if f(x) = (x^2+1) mod n for + * the value n to be factored, then chances are good that gcd(x-y,n) + * is a factor of n. The function x^2+1 is arbitrary, a higher order + * polynomial could have been chosen also. + * + */ + +/* +Warning: The Pollard Rho algorithm cannot factor some numbers, e.g. 703, and +can enter an infinite loop. This currently results in an error message: "failed to factorize". +Hopefully the TrialFactorize() step will avoid these situations by excluding +small prime factors. +This problem could also be circumvented by trying a different random initial value for x when a loop is encountered -- hopefully another initial value will not get into a loop. (currently this is not implemented) +*/ + + + + +/// Polynomial for the Pollard Rho iteration +PollardRhoPolynomial(_x) <-- x^2+1; + +2# PollardRhoFactorize(n_IsPrimePower) <-- {GetPrimePower(n)}; +3# PollardRhoFactorize(_n) <-- +[ + Local(x,y,restarts,gcd,repeat); + gcd:=1; + restarts := 100; // allow at most this many restartings of the algorithm + While(gcd = 1 And restarts>=0) // outer loop: this will be typically executed only once but it is needed to restart the iteration if it "stalls" + [ + restarts--; + /* Pick a random value between 1 and n-1 */ + x:= RandomInteger(n-1); + + /* Initialize loop */ + gcd:=1; y:=x; + repeat := 4; // allow at most this many repetitions +// Echo({"debug PollardRho: entering gcd loop, n=", n}); + + /* loop until failure or success found */ + While(gcd = 1 And repeat>=0) + [ + x:= Modulo( PollardRhoPolynomial(x), n); + y:= Modulo( PollardRhoPolynomial( + Modulo( PollardRhoPolynomial(y), n) // this is faster for large numbers + ), n); + If(x-y = 0, + [ + gcd := 1; + repeat--; // guard against "stalling" in an infinite loop but allow a few repetitions + ], + gcd:=Gcd(x-y,n) + ); +// Echo({"debug PollardRho: gcd=",gcd," x=", x," y=", y}); + ]; + If(InVerboseMode() And repeat<=0, Echo({"PollardRhoFactorize: Warning: stalled while factorizing ", n, "; counters ", x, y})); + ]; + Check(restarts>0, "Math", "PollardRhoFactorize: Error: failed to factorize " : ToString(n)); + If(InVerboseMode() And gcd > 1, Echo({"PollardRhoFactorize: Info: while factorizing ", n, " found factor ", gcd})); + /* Return result found */ + PollardCombineLists(PollardRhoFactorize(gcd), PollardRhoFactorize(Quotient(n,gcd))); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Roots.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Roots.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/Roots.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/Roots.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,26 @@ +%mathpiper,def="Roots" + +// polynomials + +10 # Roots(poly_CanBeUni) <-- +[ + Local(factors,result,uni,root,i,deg); + factors:=Factors(poly); + result:={}; + ForEach(item,factors) + [ + uni:=MakeUni(item[1]); + deg:=Degree(uni); + If(deg > 0 And deg < 3, + [ + root:= PSolve(uni); + If(Not IsList(root),root:={root}); + For(i:=0,i 0 And deg < 3, + [ + root:= PSolve(uni); + If(Not IsList(root),root:={root}); + For(i:=1,i<=Length(root),i++) + result:= Concat({{root[i],item[2]}}, result); + ] + ); + ]; + result; +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/SortFactorList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/SortFactorList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/SortFactorList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/SortFactorList.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="SortFactorList" + +/// Sort the list of prime factors using HeapSort() +LocalSymbols(a,b, list) [ + +SortFactorList(list) := HeapSort(list, {{a,b}, a[1] 1,000,000. +/// Try all prime factors up to Sqrt(n). +/// Resulting factors are automatically sorted. +/// This function is not used any more. +/* +2# TrialFactorize(n_IsPrimePower) <-- {GetPrimePower(n)}; +3# TrialFactorize(n_IsInteger) <-- +[ + Local(factorization); + factorization := TrialFactorize(n, n); // TrialFactorize will limit to Sqrt(n) automatically + If( + First(factorization) = 1, // all factors were smaller than Sqrt(n) + Rest(factorization), + // the first element needs to be replaced + Concat(Rest(factorization), {{First(factorization),1}}) + ); +]; +*/ + + +/// Auxiliary function. Factorizes by trials. Return prime factors up to given limit and the remaining number. +/// E.g. TrialFactorize(42, 2) returns {21, {{2, 1}}} and TrialFactorize(37, 4) returns {37} +TrialFactorize(n, limit) := +[ + Local(power, prime, result); + result := {n}; // first element of result will be replaced by the final value of n + prime := 2; // first prime + While(prime <= limit And n>1 And prime*prime <= n) + [ // find the max power of prime which divides n + {n, power} := FindPrimeFactor(n, prime); + If( + power>0, + DestructiveAppend(result, {prime,power}) + ); + prime := NextPseudoPrime(prime); // faster than NextPrime and we don't need real primes here + ]; + // replace the first element which was n by the new n + DestructiveReplace(result, 1, n); +]; + + + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xContent.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xContent.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xContent.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xContent.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,def="xContent" + +/*------------------------------------------------------------------------ + * Finds the Content of a univariate or multivariate polynomial + * mod 100727 by hso: conform to majority definition of "Content" + *------------------------------------------------------------------------*/ + +//Retract("xContent",*); + + +//10 # xContent( poly_IsPolynomial ) <-- +10 # xContent( poly_CanBeUni ) <-- +[ + Local(disassem,gcdCoefs,lc,minExpts); + disassem := DisassembleExpression(poly); + gcdCoefs := Gcd(disassem[3]); + lc := LeadingCoef(poly); + If(IsNegativeNumber(lc) And gcdCoefs > 0, gcdCoefs:=-gcdCoefs); + //minExpts := Minimum /@ Transpose(disassem[2]); + //gcdCoefs * Product(disassem[1]^minExpts); + gcdCoefs; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="xContent",categories="User Functions;Number Theory" +*CMD Content --- content of a polynomial +*STD +*CALL + Content(expr) + +*PARMS + +{expr} -- a univariate or multivariate polynomial + +*DESC + +This is an experimental version of the existing function Contact(), +with extended features. It is provided primarily for testing purposes, +until it is ready to replace the older version. + +This command determines the {content} of a polynomial. +The {content} is the greatest common divisor of all the terms in the +polynomial. + +For a {univariate} polynomial, the {content} will consist of a number +or the product of a number and the lowest power of the variable (if not 0). + +For a {multivariate} polynomial, the {content} will consist of a number +or the product of a number and the lowest power of each variable present +in all terms. + +Every polynomial can be written as the product of its {content} +and its {primitive part} (q.v.). This representation is usually +the first step in any attempt to factor the polynomial. + +*E.G. + +In> poly2:=2*a*x^2+4*a*x +Result: 2*a*x^2+4*a*x + +In> cx:=xContent(poly2) +Result: 2*a*x + +In> ppx := xPrimitivePart(poly2) +Result: x+2 + +In> Expand(ppx*cx) +Result: 2*a*x^2+4*a*x + +*SEE Content, PrimitivePart, Gcd, xPrimitivePart +%/mathpiper_docs + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactor.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="xFactor" + +//Retract("xFactor",*); + +10 # xFactor( p_CanBeUni ) <-- FW(xFactors(p)); + + +10 # xFactor( p_IsRationalFunction ) <-- +[ + Local(fs,n,d); + fs := xFactors( p ); + n := FW(Numerator(fs)); + d := FW(Denominator(fs)); + n/d; +]; + + +10 # xFactor( L_IsList ) <-- +[ + Local (result,x,f); + result := {}; + ForEach(x,L) + [ + f := xFactors(x); + If( f = {}, f := 0, f := FW(f) ); + DestructiveAppend(result,f); + ]; + result; +]; + + + +20 # xFactor( _expr ) <-- expr; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactorsBinomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactorsBinomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactorsBinomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactorsBinomial.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,329 @@ +%mathpiper,title="xFactorsBinomial" + +/*----------------------------------------------------------------- + * Factoring Binomial expressions of the form A X^n � B Y^n, + *-----------------------------------------------------------------*/ + +//Retract("xFactorsBinomial",*); +//Retract("xFB1",*); +//Retract("xFB2",*); +//Retract("IsPowerOf2",*); + + +10 # xFactorsBinomial( poly_IsPolynomial )_(Length(VarList(poly))=1) <-- +[ + If(InVerboseMode(),Tell(xFactorsBinomial,poly)); + Local(dis,n,X,var,A,B,s,Ar,Br); + dis := DisassembleExpression(poly); + If(InVerboseMode(),Tell(" ",dis)); + n := Maximum(dis[2])[1]; + X := dis[1][1]; + var := dis[1][1]; + A := Abs(dis[3][1]); + B := Abs(dis[3][2]); + s := Sign(dis[3][1]*dis[3][2]); + Ar := NearRational(N(A^(1/n),20)); + Br := NearRational(N(B^(1/n),20)); + If(InVerboseMode(),[Tell(" ",{n,X,var,A,B}); Tell(" ",{Ar,Br,s});]); + If( IsInteger(Ar) And IsInteger(Br), xFB1(dis), {{poly,1}} ); +]; + + +10 # xFactorsBinomial( poly_IsPolynomial )_(Length(VarList(poly))=2) <-- +[ + If(InVerboseMode(),Tell(xFactorsBinomial,poly)); + Local(dis,n,X,Y,vars,A,B,s,Ar,Br); + dis := DisassembleExpression(poly); + If(InVerboseMode(),Tell(" ",dis)); + n := Maximum(dis[2])[1]; + X := dis[1][1]; + Y := dis[1][2]; + vars := dis[1]; + A := Abs(dis[3][1]); + B := Abs(dis[3][2]); + s := Sign(dis[3][1]*dis[3][2]); + Ar := NearRational(N(A^(1/n))); + Br := NearRational(N(B^(1/n))); + If(InVerboseMode(), + [ + Tell(" ",{n,X,Y}); + Tell(" ",{vars,A,B}); + Tell(" ",{Ar,Br,s}); + ] + ); + If( IsInteger(Ar) And IsInteger(Br), xFB2(dis), {{poly,1}} ); +]; + + +12 # xFB1( dis_IsList )_(Length(dis)=3 And Length(dis[3])=2) <-- +[ + If(InVerboseMode(),[NewLine();Tell("xFB1",dis);]); + Local(Y,y,ii,fac1); + X := Ar*X; Y := Br; + Unbind(y); + y := 1; + If(InVerboseMode(), Tell(" ",{X,Y})); + fac1 := xFB1( X/Y,n,s); // factor using normalized variable + + If( InVerboseMode(),Tell(" ",fac1)); + + // now convert factorization back to actual variable if required + If( Y != 1, + [ + Local(f,d); + For(ii:=1,ii<=Length(fac1),ii++) + [ + f := fac1[ii][1]; + d := Degree(f,var); + If(InVerboseMode(),Tell(" ",{ii,f,d})); + fac1[ii][1] := Simplify(Y^d*f); + ]; + ] + ); + fac1; +]; +UnFence("xFB1",1); + + +15 # xFB1(_X,n_IsSmallPrime,s_IsNotZero)_(IsOdd(n)) <-- +[ + Local(ans,k); + If(InVerboseMode(),[NewLine();Tell(" xFB1prime",{X,n,s});]); + ans := {{X+s,1}}; + If( n > 1, ans := Concat(ans,{{Sum(k,0,n-1,(-s)^k*X^(n-1-k)),1}}) ); + If(InVerboseMode(),Tell(" ",ans)); + ans; +]; +UnFence("xFB1",3); + + +20 # xFB1(_X, n_IsOdd, s_IsPositiveInteger) <-- +[ + Local(ans,ans1); + If(InVerboseMode(),[NewLine(); Tell(" xFB1oddsum",{X,Y,n});]); + if ( n = 9 ) + [ ans := {{X+1,1},{X^2-X+1,1},{X^6-X^3+1,1}}; ] + else if ( n = 15 ) + [ ans := {{X+1,1},{X^2-X+1,1},{X^4-X^3+X^2-X+1,1},{X^8+X^7-X^5-X^4-X^3+X+1,1}}; ] + else if ( n = 21 ) + [ ans := {{X+1,1},{X^2-X+1,1},{X^6-X^5+X^4-X^3+X^2-X+1,1},{X^12+X^11-X^9-X^8+X^6-X^4-X^3+X+1,1}}; ] + else if ( n = 25 ) + [ ans := {{X+1,1},{X^4-X^3+X^2-X+1,1},{X^20-X^15+X^10-X^5+1,1}}; ] + else if ( n = 35 ) + [ ans := {{X+1,1},{X^4-X^3+X^2-X+1,1},{X^6-X^5+X^4-X^3+X^2-X+1,1},{X^24+X^23-X^19-X^18-X^17-X^16+X^14+X^13+X^12+X^11+X^10-X^8-X^7-X^6-X^5+X+1,1}}; ] + else if ( n = 45 ) + [ ans := {{X+1,1},{X^2-X+1,1},{X^4-X^3+X^2-X+1,1},{X^6-X^3+1,1},{X^8+X^7-X^5-X^4-X^3+X+1,1},{X^24+X^21-X^15-X^12-X^9+X^3+1,1}}; ] + else + [ ans := BinaryFactors(X^n+1); ]; // may take a long time, and not be complete + ans; +]; + + +25 # xFB1(_X,n_IsOdd, s_IsNegativeInteger) <-- +[ + Local(ans); + If(InVerboseMode(),[NewLine(); Tell(" xFB1odddif",{X,n});]); + if ( n = 9 ) + [ ans := {{X-1,1},{X^2+X+1,1},{X^6+X^3+1,1}}; ] + else if ( n = 15 ) + [ ans := {{X-1,1},{X^2+X+1,1},{X^4+X^3+X^2+X+1,1},{X^8-X^7+X^5-X^4+X^3-X+1,1}}; ] + else if ( n = 21 ) + [ ans := {{X-1,1},{X^2+X+1,1},{X^6+X^5+X^4+X^3+X^2+X+1,1},{X^12-X^11+X^9-X^8+X^6-X^4+X^3-X+1,1}}; ] + else if ( n = 25 ) + [ ans := {{X-1,1},{X^4+X^3+X^2+X+1,1},{X^20+X^15+X^10+X^5+1,1}}; ] + else if ( n = 35 ) + [ ans := {{X-1,1},{X^4+X^3+X^2+X+1,1},{X^6+X^5+X^4+X^3+X^2+X+1,1},{X^24-X^23+X^19-X^18+X^17-X^16+X^14-X^13+X^12-X^11+X^10-X^8+X^7-X^6+X^5-X+1,1}}; ] + else if ( n = 45 ) + [ ans := {{X-1,1},{X^2+X+1,1},{X^4+X^3+X^2+X+1,1},{X^6+X^3+1,1},{X^8-X^7+X^5-X^4+X^3-X+1,1},{X^24-X^21+X^15-X^12+X^9-X^3+1,1}}; ] + else + [ ans := BinaryFactors(X^n-1); ]; // may take a long time, and not be complete + ans; + If(InVerboseMode(),Tell(" ",ans)); + ans; +]; + + +30 # xFB1(_X, n_IsEven, s_IsPositiveInteger) <-- +[ + Local(ans,fn,mx,my); + If(InVerboseMode(),[NewLine(); Tell(" xFB1evensum",{X,n});]); + fn := {{1,1}}; + If( n > 1, fn := FactorsSmallInteger(n) ); + If(Length(fn)=1 And IsOdd(fn[1][1]), mx:= fn[1][1]^(fn[1][2]-1)); + If(Length(fn)>1, + ForEach(f,fn) [ If( IsOdd(f[1]), mx := f[1]^f[2] ); ]); + my := n/mx; + If(InVerboseMode(),Tell(" ",{mx,my})); + + If( IsPowerOf2(n), + [ + // is power of 2, so does not factor + ans := {{X^n+1,1}}; + ], + [ + // is not power of 2 -- check further + if ( n = 6 ) + [ ans := {{X^2+1,1},{X^4-X^2+1,1}}; ] + else if ( n = 10 ) + [ ans := {{X^2+1,1},{X^8-X^6+X^4-X^2+1,1}}; ] + else if ( n = 20 ) + [ ans := {{X^4+1,1},{X^16-X^12+X^8-X^4+1,1}}; ] + else if ( n = 30 ) + [ ans := {{X^2+1,1},{X^4-x^2+1,1},{X^8-X^6+X^4-X^2+1,1},{X^16+X^14-X^10-X^8-X^6+X^2+1,1}}; ] + else if ( n = 40 ) + [ ans := {{X^8+1,1},{X^32-X^24+X^16-X^8+1,1}}; ] + else if ( n = 50 ) + [ ans := {{X^2+1,1},{X^8-X^6+X^4-X^2+1,1},{X^40-X^30+X^20-X^10+1,1}}; ] + else if ( n = 100 ) + [ ans := {{X^4+1,1},{X^16-X^12+X^8-X^4+1,1},{X^80-X^60+X^40-X^20+1,1}}; ] + else + [ ans := {{X^my+1,1},{Sum(k,0,mx-1,X^(n-my-k*my)*(-1)^k),1}}; ]; + ] + ); + If(InVerboseMode(),Tell(" ",ans)); + ans; +]; + + +35 # xFB1(_X, n_IsEven, s_IsNegativeInteger) <-- +[ + Local(ans); + If(InVerboseMode(),[NewLine(); Tell(" xFB1evendif",{X,n});]); + if ( n = 2 ) + [ ans := {{X-1,1},{X+1,1}}; ] + else if ( n = 10 ) + [ ans := {{X-1,1},{X+1,1},{X^4+X^3+X^2+X+1,1},{X^4-X^3+X^2-X+1,1}}; ] + else if ( n = 20 ) + [ ans := {{X-1,1},{X+1,1},{X^2+1,1},{X^4+X^3+X^2+X+1,1},{X^4-X^3+X^2-X+1,1},{X^8-X^6+X^4-X^2+1,1}}; ] + else if ( n = 30 ) + [ ans := {{X-1,1},{X+1,1},{X^2+X+1,1},{X^2-X+1,1},{X^4+X^3+x^2+X+1,1},{X^4-X^3+x^2-X+1,1},{X^8-X^7+X^5-X^4+X^3-X+1,1},{X^8+X^7-X^5-X^4-X^3+X+1,1}}; ] + else if ( n = 40 ) + [ ans := {{X-1,1},{X+1,1},{X^2+1,1},{X^4+1,1},{X^4+X^3+X^2+X+1,1},{X^4-X^3+X^2-X+1,1},{X^8-X^6+X^4-X^2+1,1},{X^16-X^12+X^8-X^4+1,1}}; ] + else if ( n = 50 ) + [ ans := {{X-1,1},{X+1,1},{X^4+X^3+X^2+X+1,1},{X^4-X^3+X^2-X+1,1},{X^20+X^15+X^10+X^5+1,1},{X^20-X^15+X^10-X^5+1,1}}; ] + else if ( n = 100 ) + [ ans := {{X-1,1},{X+1,1},{X^2+1,1},{X^4+X^3+X^2+X+1,1},{X^4-X^3+X^2-X+1,1},{X^8-X^6+X^4-X^2+1,1},{X^20+X^15+X^10+X^5+1,1},{X^20-X^15+X^10-X^5+1,1},{X^40-X^30+X^20-X^10+1,1}};] + else + [ ans := Concat( xFB1(X,n/2,1), xFB1(X,n/2,-1) ); ]; + + If(InVerboseMode(),Tell(" ",ans)); + ans; +]; + + + +50 # xFB2( dis_IsList )_(Length(dis)=3 And Length(dis[3])=2) <-- +[ + If(InVerboseMode(),[NewLine();Tell("xFB2",dis);]); + Local(ns,ii,fn,mx,my,fac2); + If(InVerboseMode(), + [ + Tell(" ",n); + Tell(" ",{X,Y}); + Tell(" ",{A,B,s}); + Tell(" ",{Ar,Br}); + ] + ); + X := Ar*X; + Y := Br*Y; + If(InVerboseMode(),Tell(" ",{X,Y})); + + fac2 := xFB1( X/Y,n,s); // factor using normalized variable + If(InVerboseMode(),Tell(" ",fac2)); + + // now convert factorization back to actual variables if required + + If( Y != 1, + [ + Local(f,d); + For(ii:=1,ii<=Length(fac2),ii++) + [ + f := fac2[ii][1]; + d := Degree(f,vars[1]); + If(InVerboseMode(),Tell(" ",{ii,f,d})); + fac2[ii][1] := Simplify(Simplify(Y^d*f)); + ]; + ] + ); + fac2; +]; +UnFence("xFB2",1); + + +IsPowerOf2( n_IsPositiveInteger ) <-- [ Count(StringToList(ToBase(2,n)),"1") = 1; ]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper,title="testing" + +//Retract("TestPlus1",*); +//Retract("TestMinus1",*); + + +1000 # TestMinus1() <-- +[ + Local(n,poly,a,b,result,prod,ok); + NewLine(1); + Tell("Test Binomial Dif, 1 Variable"); + a := 2; + b := 3; + For(n:=2,n<=12,n++) + [ + poly := ExpandBrackets(a^n*x^n-b^n); + result := xFactorsBinomial(poly); + prod := ExpandBrackets(FW(result)); + ok := Verify(a^n*x^n-b^n,prod); + NewLine(1); + Tell(" ",poly); + If(InVerboseMode(), + [ + Tell(" ",result); + Tell(" ",prod); + ] + ); + Tell(" ",ok); + ]; +]; + + +1000 # TestPlus1() <-- +[ + Local(n,poly,a,b,result,prod,ok); + NewLine(1); + Tell("Test Binomial Sum, 1 Variable"); + a := 2; + b := 3; + For(n:=2,n<=12,n++) + [ + poly := ExpandBrackets(a^n*x^n+b^n); + result := xFactorsBinomial(poly); + prod := ExpandBrackets(FW(result)); + ok := Verify(a^n*x^n+b^n,prod); + NewLine(1); + Tell(" ",poly); + If(InVerboseMode(), + [ + Tell(" ",result); + Tell(" ",prod); + ] + ); + Tell(" ",ok); + ]; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactors.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,582 @@ +%mathpiper,def="xFactors" + +/*------------------------------------------------------------------------ + * PENULTIMATE VERSION + * Started 091222 + * revised 100108-22 + * revised 100215 + * revised 100301 + *------------------------------------------------------------------------*/ + +//Retract("xFactors",*); +//Retract("xFactorsPrimitivePart",*); +//Retract("xFactorsUnivariate",*); +//Retract("xFactorsMultivariate",*); +//Retract("xFactorsHomogeneousBivariate",*); +//Retract("CheckForSpecialForms",*); + +//Retract("ApproximateRealCoefficients",*); +//Retract("FixUpMonicFactors",*); +//Retract("CombineNumericalFactors",*); +//Retract("IsPureRational",*); +//Retract("HasRealCoefficients",*); +//Retract("HasRationalCoefficients",*); +//Retract("matchPower",*); +//Retract("IsIrreducible",*); // NOT YET OPERATIONAL + + +/* -------------- LISTS ---------------*/ + +10 # xFactors( L_IsList ) <-- xFactors /@ L; + + +/* ------------- NUMBERS --------------*/ + + +10 # xFactors(p_IsPositiveInteger) <-- +[ + If( p < 1600, FactorsSmallInteger(p), FactorizeInt(p) ); +]; + + +12 # xFactors(p_IsNegativeInteger) <-- xFactors(-p); + + +14 # xFactors(p_IsRational)_(Denominator(p) != 1) <-- + { {xFactor(Numerator(p)) / xFactor(Denominator(p) ) , 1} }; + + +16 # xFactors(p_IsGaussianInteger) <-- GaussianFactors(p); + + +18 # xFactors(_p)_(Length(VarList(p))=0) <-- {{p,1}}; + + + +/* ------------- POLYNOMIALS -- CAN BE UNI --------------*/ + +21 # xFactors( poly_CanBeUni ) <-- +[ + If(InVerboseMode(),Tell("xFactors_can_be_uni_100122",poly)); + Local(content,pp,ppFactors,monomialFactors,result); + Local(vars,nvars,disassem,degrees,mpoly,nterms,allCoeffs,allPowers); + Local(hasRealCoefficients,hasRationalCoefficients,isHomogeneous); + + // First, check to see if the polynomial has any REAL coefficients. + // If so, convert to approximate integers (with divisor). + hasRealCoefficients := HasRealCoefficients(poly); + If( hasRealCoefficients, + [ + Local(realPoly); + realPoly := poly; // just in case -- save original form + disassem := DisassembleExpression(poly); + allCoeffs := disassem[3]; + allPowers := Flatten(disassem[2],"List"); + poly := ApproximateRealCoefficients(poly); + ] + ); + + // Also, check to see if the polynomial has Rational coeffs + hasRationalCoefficients := HasRationalCoefficients(poly); + + // Now: get Content and Primitive Part + content := xContent( poly ); + pp := xPrimitivePart( poly, content ); + If(InVerboseMode(),Tell(" ",{content,pp})); + vars := VarList(pp); + nvars := Length(vars); + disassem := DisassembleExpression(pp); + nterms := Length(disassem[3]); + degrees := {}; + allCoeffs := disassem[3]; + allPowers := Flatten(disassem[2],"List"); + If(nvars > 0, + [ + ForEach(v,vars) + [ DestructiveAppend(degrees,Degree(pp,v)); ]; + isHomogeneous := [ + // A polynomial is homogeneous of degree n + // if all terms have degree n. + Local(sd,cmp); + sd := Sum /@ disassem[2]; + cmp := FillList(sd[1],Length(sd)); + IsZeroVector(sd - cmp); + ]; + ] + ); + + // Experimental: + // Attach a set of Meta-Keys to pp, describing + // some of the above information + pp := MetaSet(pp,"nvars",nvars); + pp := MetaSet(pp,"nterms",nterms); + pp := MetaSet(pp,"degrees",degrees); + pp := MetaSet(pp,"isHomogeneous",isHomogeneous); + + If(InVerboseMode(), + [ + Tell(" ",vars); + Tell(" ",nvars); + Tell(" ",nterms); + Tell(" ",degrees); + Tell(" ",disassem); + Tell(" ",allCoeffs); + Tell(" ",allPowers); + Tell(" ",isHomogeneous); + NewLine(); + ] + ); + + // OK. Now factor the PrimitivePart + ppFactors := xFactorsPrimitivePart( pp ); + + If(InVerboseMode(),[NewLine();Tell(" ",ppFactors);]); + + // Next, include the factors of the Content, if any + If(InVerboseMode(),NewLine()); + monomialFactors := FactorsMonomial(content); + If(InVerboseMode(),[Tell(" ",monomialFactors);]); + If( monomialFactors[1][1] = 1, + result := ppFactors, + result := Concat(monomialFactors,ppFactors) + ); + + If(InVerboseMode(),[NewLine();Tell(" final ",result);]); + result; +]; + + + +// ----------------- FACTOR PRIMITIVE PART ----------------- + + // special case: binomials +10 # xFactorsPrimitivePart( _pp )_(nterms=2) <-- +[ + If(InVerboseMode(),Tell("Binomial")); + Local(ppFactors); + ppFactors := xFactorsBinomial(pp); +]; +UnFence("xFactorsPrimitivePart",1); + + + // special case: homogeneous bivariates +12 # xFactorsPrimitivePart( _pp )_(isHomogeneous And nvars=2) <-- +[ + If(InVerboseMode(),Tell("Homogeneous and Bivariate")); + Local(ppFactors); + ppFactors := xFactorsHomogeneousBivariate(disassem); +]; +UnFence("xFactorsPrimitivePart",1); + + + // special case: no variables in pp! +14 # xFactorsPrimitivePart( _pp )_(nvars=0) <-- +[ + Local(ppFactors); + ppfactors := {}; +]; + + + // general case: univariate +16 # xFactorsPrimitivePart( _pp )_(nvars=1) <-- xFactorsUnivariate(pp); +UnFence("xFactorsPrimitivePart",1); + + + // general case: multivariate +18 # xFactorsPrimitivePart( _pp )_(nvars>1) <-- xFactorsMultivariate(pp); +UnFence("xFactorsPrimitivePart",1); + + + // catch-all: represents an ERROR CONDITION +20 # xFactorsPrimitivePart( _pp ) <-- Tell("Should never get here!"); +UnFence("xFactorsPrimitivePart",1); + + + +// ---------------------- UNIVARIATE POLYNOMIALS ----------------------- + +30 # xFactorsUnivariate( poly_CanBeUni )_(Length(VarList(poly))=1) <-- +[ + Local(factrs,coeffs,deg,X,residuals,factrsnew); + + If(InVerboseMode(), + [ + NewLine(); + Tell("xFactorsUnivariate",poly); + Tell(" ",allCoeffs); + ] + ); + + // OK, First, send it through MathPiper's basic factoring function + // for univariate polynomials + + factrs := BinaryFactors(poly); + If(InVerboseMode(),Tell(" output of BinaryFactors",factrs)); + + // Now fix-up the (monic) factors found above, to express them + // as linear in x with integer coefficients. + // Also, separate out any 'residual' factors -- defined here as + // factors of degree > 2. + + {factrsnew,residuals} := FixUpMonicFactors(factrs); + + // See if we can do something with the residuals + Local(residOut); + residOut := {}; + If(Length(residuals) > 0, residOut := xFactorsResiduals( residuals ) ); + + If(InVerboseMode(), + [ + NewLine(); + Tell(" just before end of univariate factoring"); + Tell(" ",factrs); + Tell(" ",factrsnew); + Tell(" ",residOut); + ] + ); + // Finally, the output -------- + Local(final); + If(Length(Union(factrsnew,residOut)) > 0, + final := Concat(factrsnew,residOut), + final := factrs + ); + CheckForSpecialForms( final ); +]; // xFactorsUnivariate +UnFence("xFactorsUnivariate",1); + + +// ---------------- MULTIVARIATE POLYNOMIALS ----------------- + +40 # xFactorsMultivariate( poly_CanBeUni )_(Length(VarList(poly))>1) <-- +[ + Local(factrs); + + If(InVerboseMode(),[NewLine();Tell("xFactorsMultivariate",poly);]); + If( nterms = 2, + [ + If(InVerboseMode(),Tell(" Is Binomial")); + factrs := xFactorsBinomial(poly); + ], + [ + If(InVerboseMode(),Tell(" Has more than 2 terms")); + ] + ); + factrs; +]; +UnFence("xFactorsMultivariate",1); + + +// ------------------ HOMOGENEOUS BIVARIATE ------------------ + +10 # xFactorsHomogeneousBivariate( dis_IsList ) <-- +[ + If(InVerboseMode(),[NewLine();Tell("xFactorsHomogeneousBivariate",dis);]); + Local(dis1,f,lst,dis2,poly1,ppFactors,residuals,ii,preassem); + dis1 := {{xi},{{X},{X[1]}} /@ dis[2],dis[3]}; + If(InVerboseMode(),Tell(" ",dis1)); + poly1 := Sum(ReassembleListTerms(dis1)); + If(InVerboseMode(),Tell(" ",poly1)); + ppFactors := BinaryFactors(poly1); + {ppFactors,residuals} := FixUpMonicFactors(ppFactors); + For(ii:=1,ii<=Length(ppFactors),ii++) + [ + f := ppFactors[ii]; + If(InVerboseMode(),Tell(" ",f[1])); + lst := DisassembleExpression(f[1]); + If(InVerboseMode(), + [ + Tell(" ",lst); + Tell(" ",dis[1]); + ] + ); + DestructiveReplace(lst,1,dis[1]); + DestructiveAppend(lst[2][1],0); + DestructiveAppend(lst[2][2],1); + If(InVerboseMode(),Tell(" ",lst)); + preassem := Sum(ReassembleListTerms(lst)) ; + If(InVerboseMode(),Tell(" ",preassem)); + ppFactors[ii][1] := preassem; + ]; + If(InVerboseMode(),[Tell(" ",ppFactors); Tell(" ",residuals);NewLine();] ); + ppFactors; +]; +UnFence("xFactorsHomogeneousBivariate",1); + + +// ------------------ SPECIAL FORMS ------------------ + +10 # CheckForSpecialForms( final_IsList ) <-- +[ + If(InVerboseMode(),[NewLine();Tell("CheckForSpecialForms",final);]); + Local(LL,ii,fact,mult,dis,new); + new := {}; + LL := Length(final); + For(ii:=1,ii<=LL,ii++) + [ + fact := final[ii][1]; + mult := final[ii][2]; + If(InVerboseMode(),Tell(" ",{fact,mult})); + dis := DisassembleExpression( fact ); + If(InVerboseMode(),Tell(" ",dis)); + Local(var); + var := dis[1][1]; + if ( dis[2]={{4},{2},{0}} And dis[3]={1,1,1} ) + [ + Local(new1,new2); + new1 := {var^2-var+1,mult}; + new2 := {var^2+var+1,mult}; + DestructiveAppend(new,new1); + DestructiveAppend(new,new2); + If(InVerboseMode(),Tell(" ",new)); + ] + else + [ + If(InVerboseMode(),Tell(" no special form")); + DestructiveAppend(new,{fact,mult}); + ]; + ); + ]; + new; +]; + + +// --------------------- OTHER STUFF ------------------------ + + +10 # ApproximateRealCoefficients( poly_IsPolynomial ) <-- +[ + // If the polynomial has REAL coefficients, convert them to + // approximate integers + If(InVerboseMode(),[NewLine();Tell(" REAL",poly);]); + Local(coeffs,gcd,lcm); + coeffs := Rationalize /@ (allCoeffs); + If(InVerboseMode(),[Tell(" to-Q",coeffs);Tell(" to-Z",coeffs);]); + Local(gcd,lcm); + gcd := Gcd(Numerator /@ coeffs); + lcm := Lcm(Denominator /@ coeffs); + If(InVerboseMode(),[Tell(" ",gcd);Tell(" ",lcm);]); + disassem[3] := coeffs; + allCoeffs := coeffs; + poly := Sum(ReassembleListTerms(disassem)); + If(InVerboseMode(),Tell(" new",poly)); + poly; +]; +UnFence("ApproximateRealCoefficients",1); + + +100 # CombineNumericalFactors( factrs_IsList ) <-- +[ + If( InVerboseMode(), Tell("Combine",factrs) ); + Local(q,a,b,t,f,ff,err); + err := False; + t := 1; + f := {}; + ForEach(q,factrs) + [ + If( InVerboseMode(), Tell(1,q) ); + If( IsList(q) And Length(q)=2, + [ + {a,b} := q; + If( InVerboseMode(), Echo(" ",{a,b}) ); + If( IsNumericList( {a,b} ), + t := t * a^b, + f := {a,b}:f + ); + ], + err := True + ); + ]; + If( InVerboseMode(), + [ + Echo(" t = ",t); + Echo(" f = ",f); + Echo(" err = ",err); + ] + ); + ff := If(Not err And t != 1, {t,1}:Reverse(f), factrs); + ff := Select(Lambda({x},x!={1,1}),ff); + If(ff[1]<0,ff[1]:=-ff[1]); +]; + + +// ---------------- RATIONAL POLYNOMIALS ----------------- + +150 # xFactors( expr_IsRationalFunction )_ + (IsPolynomial(Numerator(expr)) And IsPolynomial(Denominator(expr))) <-- +[ + If(InVerboseMode(),[NewLine();Tell("xFactors_Rational_Function",expr);]); + Local(Numer,Denom,fNumer,fDenom); + Numer := Numerator(expr); + Denom := Denominator(expr); + fNumer := xFactors(Numer); + fDenom := xFactors(Denom); + If(InVerboseMode(),[Tell(" ",fNumer); Tell(" ",fDenom);]); + fNumer/fDenom; +]; + + +152 # xFactors( expr_IsRationalFunction )_ + (IsConstant(Numerator(expr)) And IsPolynomial(Denominator(expr))) <-- +[ + If(InVerboseMode(),[NewLine();Tell("xFactors_Rational_Denom",expr);]); + Local(Numer,Denom,fNumer,fDenom); + Numer := Numerator(expr); + Denom := Denominator(expr); + fNumer := xFactors(Numer); + fDenom := xFactors(Denom); + If(InVerboseMode(),[Tell(" ",fNumer); Tell(" ",fDenom);]); + fNumer/fDenom; +]; + + +// ---------- POSSIBLE NON-INTEGER EXPONENTS ---------- + +200 # xFactors( _expr )_(Length(VarList(expr)) = 1) <-- +[ + If(InVerboseMode(),[NewLine();Tell("Some other kind of expression",expr);]); + Local(dis,X,pows); + dis := DisassembleExpression(expr); + X := VarList(expr)[1]; + pows := matchPower /@ dis[1]; + rats := NearRational /@ pows; + dis[1] := x^rats; + p := Sum(ReassembleListTerms(dis)); + If(InVerboseMode(),Tell(" new ",p)); + xFactors(p); +]; + + + + +10 # IsPureRational( N_IsRational )_(Not IsInteger(N)) <-- True; + +12 # IsPureRational( _N ) <-- False; + + +10 # HasRealCoefficients( poly_IsPolynomial ) <-- +[ + Local(disassem); + disassem := DisassembleExpression(poly); + (Length(Select(disassem[3],"IsDecimal")) > 0); +]; + +10 # HasRealCoefficients( poly_IsMonomial ) <-- +[ + Local(disassem); + disassem := DisassembleExpression(poly); + (Length(Select(disassem[3],"IsDecimal")) > 0); +]; + + +10 # HasRationalCoefficients( poly_IsPolynomial ) <-- +[ + Local(disassem); + disassem := DisassembleExpression(poly); + //Tell(" ",disassem); + (Length(Select(disassem[3],"IsPureRational")) > 0); +]; + +10 # HasRationalCoefficients( poly_IsMonomial) <-- +[ + Local(disassem); + disassem := DisassembleExpression(poly); + (Length(Select(disassem[3],"IsPureRational")) > 0); +]; + + +10 # FixUpMonicFactors( factrs_IsList ) <-- +[ + If(InVerboseMode(),[ NewLine(); Tell(" doing monic fixup"); ] ); + Local(factrsnew,residuals,uni); + factrsnew := {}; + residuals := {}; + ForEach(f,factrs) + [ + If(InVerboseMode(),Tell(" ",f)); + uni := MakeUni(f[1]); + If(InVerboseMode(),Tell(" ",uni)); + If( Degree(f[1])=1, + [ + Local(cc,lcm,fnew); + If(InVerboseMode(),Tell(" ",Degree(f[1]))); + cc := Coef(f[1],uni[1],0 .. 1); + //Tell(" ",cc); + lcm := Lcm( Denominator /@ cc ); + uni[3] := lcm * cc; + fnew := NormalForm(uni); + If( hasRationalCoefficients, + [ + DestructiveAppend(factrsnew,f); + ], + [ + DestructiveAppend(factrsnew,{fnew,f[2]}); + ] + ); + ] + ); + If( Degree(f[1])=2, + [ + If(InVerboseMode(),Tell(" ",Degree(f[1]))); + Local(pq); + pq := PrimitivePart(f[1]); + DestructiveAppend(factrsnew,{pq,f[2]}); + ] + ); + // If any factors have degree >=3, store them in a 'residuals' array + // for further analysis + If( Degree(f[1]) > 2, + [ + If(InVerboseMode(),Tell(" ",Degree(f[1]))); + Local(pq); + pq := PrimitivePart(f[1]); + DestructiveAppend(residuals,{pq,f[2]}); + If(InVerboseMode(),Tell(" appending to residuals",pq)); + ] + ); + ]; + {factrsnew,residuals}; +]; +UnFence("FixUpMonicFactors",1); + +10 # IsIrreducible( poly_IsPolynomial )_(Length(VarList(poly))=1) <-- +[ + // If these tests return True, the polynomial IS irreducible.. + // If they return False, the reducibility of the polynomial is + // not established, one way or the other. + // + // ---- THIS FUNCTION IS NOT YET COMPLETE OR USEABLE --- + If(InVerboseMode(),Tell("IsIrreducible",poly)); + Local(var,deg,coeffs,num1); + var := VarList(poly)[1]; + deg := Degree(poly); + coeffs := Coef(poly,var,deg .. 0); + If(InVerboseMode(),Tell(" ",deg)); + Local(ii,res,nprimes); + nprimes := 0; + For(ii:=-3*deg,ii<=3*deg,ii:=ii+3) + [ + res := N(Subst(x,ii) poly); + //Tell(" ",{ii,res,IsPrime(res)}); + If(Abs(res)=1 Or IsPrime(res), nprimes := nprimes + 1, ); + ]; + Tell(" ",nprimes); + If(nprimes > 2*deg, True, False ); +]; + + +10 # matchPower(_Z^n_IsNumber) <-- n; + +15 # matchPower(_Z) <-- 1; + + +//======================================================================== + +%/mathpiper + + + + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactorsResiduals.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactorsResiduals.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xFactorsResiduals.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xFactorsResiduals.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,271 @@ +%mathpiper,def="xFactorsResiduals" + +//Retract("xFactorsResiduals",*); +//Retract("trySQF",*); +//Retract("tryRealRoots",*); +//Retract("processRealRoots",*); + +10 # xFactorsResiduals( residualList_IsList ) <-- +[ + If(InVerboseMode(),[NewLine(); Tell("Residuals",residualList);]); + If(InVerboseMode(),Tell(" --",content)); + If(InVerboseMode(),Tell(" --",factrs)); + If(InVerboseMode(),Tell(" --",factrsnew)); + If(InVerboseMode(),Tell(" --",residuals)); + If(InVerboseMode(),Tell(" -- original ",degrees)); + Local(resid,sqf,sqfGood,rrGood); + + // --- see if Square-Free factoring can find some factors + + residualList := trySQF(residualList); // hso + + If(InVerboseMode(), + [ + Tell(" after trying SQF on all residuals"); + Tell(" ",sqfGood); + Tell(" ",factrsnew); + Tell(" ",residualList); + NewLine(); + ] + ); + + // --- see if there are any REAL roots to help with factoring + + tryRealRoots(residualList); + + If(InVerboseMode(), + [ + Tell(" after trying for REAL roots on all residuals"); + Tell(" ",rrGood); + Tell(" ",factrsnew); + Tell(" ",residuals); + Tell(" ",residualList); + NewLine(); + ] + ); + + residOut; +]; +UnFence("xFactorsResiduals",1); + + + +10 # trySQF( residualList_IsList ) <-- +[ + //--- First, try SquareFree factorization on these residuals + Local(resid,sqf); + If(InVerboseMode(),[NewLine(); Tell("trySQF",residualList);]); + ForEach(resid,residualList) + [ + If(InVerboseMode(),Tell(" ",resid)); + + sqf := SquareFree(resid[1]); + If(InVerboseMode(), + [ + Tell(" trying SQF"); + Tell(" ",resid[1]); + Tell(" ",sqf); + ] + ); + If(Degree(sqf) < Degree(resid[1]), + [ + If(InVerboseMode(),Tell(" sqf helps factor resid")); + sqfGood := True; + Local(f1,f2); + f1 := sqf; + f2 := Simplify(resid[1]/sqf); + If( f2 = f1, + factrsnew := Concat({{f1,2*resid[2]}},factrsnew), + factrsnew := Concat({{f1,resid[2]},{f2,resid[2]}},factrsnew) + ); + //HSO experimental + residuals := Difference(residuals,{resid}); + If(InVerboseMode(),Tell(" new",residuals)); + residualList := residuals; + ], + [ + If(InVerboseMode(), + [ + Tell(" sqf DOES NOT HELP factor resid"); + sqfGood := False; + ] + ); + ] + ); + If(InVerboseMode(),Tell(" after sqf ",factrsnew)); + If(InVerboseMode(),Tell(" ",residuals)); + If(InVerboseMode(),Tell(" ",residualList)); // hso + ]; + residualList; // hso +]; +UnFence("trySQF",1); + + + +10 # tryRealRoots(residualList_IsList)_(Length(residualList)>0) <-- +[ + //--- See if there are any REAL roots to factor out + If(InVerboseMode(),[NewLine(); Tell("tryRealRoots",residualList);]); + ForEach(resid,residualList) + [ + Local(nrr,rr,ptry,uptry); + nrr := RealRootsCount(resid[1]); + If(InVerboseMode(), + [ Tell(" this ",resid[1]); Tell(" ",nrr); ] + ); + If( nrr > 0, rr := FindRealRoots(resid[1]), rr := {} ); + processRealRoots(rr); + + If( nrr = 2, + [ + If( nrr = 0, + [ + // OhOh - no real solutions -- have to try something else + If(InVerboseMode(), + [ + NewLine(); + Tell(" NO real solutions"); + Tell(" try something else"); + ] + ); + // Here go some ad-hoc solutions that can be useful.... + Local(u,X); + u := MakeUni(resid[1]); + X := u[1]; + If( u[2]=0 And u[3]={1,0,1,0,1}, + [ + DestructiveAppend(residOut,{X^2-X+1,1}); + DestructiveAppend(residOut,{X^2+X+1,1}); + If(InVerboseMode(), + [ + Tell(" found ",factrsnew); + Tell(" ",resid); + Tell(" ",factrs); + Tell(" ",residOut); + ] + ); + ] + ); + ], + [ + // more than 2 real solutions -- have to do a bit more work + rr := FindRealRoots(resid[1]); + If(InVerboseMode(),Tell(" ",rr)); + // try them pairwise + goodptry := {}; + For(ii:=1,ii 0, + [ + ForEach(pt,goodptry) + [ DestructiveAppend(residOut,{pt,1}); ]; + ] + ); + ] + ); // if nrr=0 + ] + ); // if nrr=2 + ]; +]; +UnFence("tryRealRoots",1); + + +10 # processRealRoots( rr_IsNumericList )_(Length(rr) = 1) <-- +[ + // Only one real root, so it will probably be of no help + // in factoring, unless it is integer or small rational + If(InVerboseMode(),Tell(" Only 1 real root",rr)); + Local(root); + root := rr[1]; + rrGood := False; + If(IsInteger(root), + [ + If(InVerboseMode(),Tell(" integer ",root)); + rrGood := True; + ], + [ + Local(rroot); + rroot := NearRational(root); + If(InVerboseMode(),Tell(" rational ",rroot)); + If(Denominator(rroot) < 100, [root := rroot; rrGood:=True;] ); + ] + ); + +]; +UnFence("processRealRoots",1); + + +10 # processRealRoots( rr_IsNumericList )_(Length(rr) = 2) <-- +[ + // a pair of real solutions -- probably form a quadratic + ptry := Expand((x-rr[1])*(x-rr[2])); + If(InVerboseMode(),[Tell(" ",rr);Tell(" ",ptry);]); + uptry := MakeUni(ptry); + uptry[3] := "NearRational" /@ uptry[3]; + ptry := NormalForm(uptry); + If(InVerboseMode(),Tell(" ",ptry)); + If( Abs(Lcm(uptry[3])) < 100, + [ + // looks OK -- try to use it + Local(f1,f2,new); + f1 := ptry; + f2 := Simplify(resid[1]/f1); + new := {{f1,resid[2]},{f2,resid[2]}}; + If(InVerboseMode(),Tell(" ",new)); + resid := new; + residOut := new; + If(InVerboseMode(),Tell(" ",residOut)); + ] + ); +]; +UnFence("processRealRoots",1); + + + +10 # processRealRoots( rr_IsNumericList )_(Length(rr) >= 4) <-- +[ + // more than 2 real solutions -- have to do a bit more work + If(InVerboseMode(),Tell(" ",rr)); + // try them pairwise + goodptry := {}; + For(ii:=1,ii 0, + [ + ForEach(pt,goodptry) + [ DestructiveAppend(residOut,{pt,1}); ]; + ] + ); + ]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xPrimitivePart.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xPrimitivePart.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/xPrimitivePart.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/xPrimitivePart.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,115 @@ +%mathpiper,def="xPrimitivePart" + +//Retract("xPrimitivePart",*); + +10 # xPrimitivePart(poly_CanBeUni) <-- +[ + Local(cont,pp); + If(InVerboseMode(),Tell(" xPrimitivePart1",poly)); + cont := xContent(poly); + pp := poly / cont; + //pp := Simplify(Simplify(pp)); +]; + + +Macro("xPrimitivePart",{poly,xcont}) +[ + Local(pp); + If(InVerboseMode(),Tell(" xPrimitivePart2",{poly,xcont})); + + If( IsBound(@xcont), + [ + pp := Eval(@poly) / Eval(@xcont); + ], + [ + Local(xCont); + xCont := xContent(Eval(@poly)); + @xcont := xCont; + pp := Eval(@poly) / xCont; + ] + ); + pp; + //pp := Simplify(Simplify(pp)); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="xPrimitivePart",categories="User Functions;Number Theory" +*CMD xPrimitivePart --- primitive part of a polynomial +*STD +*CALL + PrimitivePart(expr) + PrimitivePart(expr,cont) + +*PARMS + +{expr} -- a univariate or multivariate polynomial +{cont} -- the Content of this polynomial + +*DESC + +This is an experimental version of the existing function PrimitivePart(), +with extended features. It is provided primarily for testing purposes, +until it is ready to replace the older version. + +This command determines the {primitive part} of a polynomial. +The {primitive part} is what remains after the content (the +greatest common divisor of all the terms) is divided out. + +Every polynomial can be written as the product of its {content} (q.v.) +and its {primitive part}. This representation is usually the +first step in any attempt to factor the polynomial. + +NOTE: If the first calling sequence is used ('arity' = 1), the function +computes xContent(expr) internally, but returns only the primitive part. + + If the second calling sequence is used ('arity' = 2), then +(a) If the second argument contains a previously-computed value of + xContent(expr), that value will be used in computing the primitive + part, thereby saving some work. +(b) If the second argument is not bound to any value, the function will + compute xContent(expr) internally, AND return it in the second argument! + +*E.G. +In> Unbind(a,b,xCont) +Result: True + +In> poly:=2*a*x^2*y-8*a*y +Result: 2*a*x^2*y-8*a*y + +In>Time() xCont := xContent(poly) +Result: 0.427442564 +In> xCont +Result: 2*a*y + +In> Time() xpp1:=xPrimitivePart(poly) +Result: 0.697451928 +In> xpp1 +Result: x^2-4 + +In> Time() xpp2:=xPrimitivePart(poly,xCont) +Result: 0.392679832 +In> xpp2 +Result: x^2-4 + +In> Unbind(cont) +Result: True + +In> Time() xpp3:=xPrimitivePart(poly,cont) +Result: 0.735463317 +In> xpp3 +Result: x^2-4 +In> cont +Result: 2*a*y + +*SEE Content, PrimitivePart, Gcd, xContent +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/YacasFactor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/YacasFactor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/YacasFactor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/YacasFactor.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="YacasFactor" + +// This is so YacasFactor(Sin(x)) doesn't return FWatom(Sin(x)) +//YacasFactor(_p) <-- FW(YacasFactors(p)); +10 # YacasFactor(p_CanBeUni) <-- FW(YacasFactors(p)); + +%/mathpiper + + + +%mathpiper_docs,name="YacasFactor",categories="User Functions;Number Theory" +*CMD Factor --- factorization (in pretty form) +*STD +*CALL + YacasFactor(x) + +*PARMS + +{x} -- integer or univariate polynomial + +*DESC + +This is the original Yacas version of the Factor() function. It has +b een superceeded in MathPiper by the function xFactor(). + +This function factorizes "x", similarly to {YacasFactors}, but +it shows the result in a more human-readable format. + +*E.G. + +In> PrettyForm(YacasFactor(24)); + + 3 + 2 * 3 + +Result: True; +In> PrettyForm(YacasFactor(2*x^3 + 3*x^2 - 1)); + + 2 / 1 \ + 2 * ( x + 1 ) * | x - - | + \ 2 / + +Result: True; + +*SEE YacasFactors, xFactor, IsPrime, PrettyForm +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/YacasFactors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/YacasFactors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/factors/YacasFactors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/factors/YacasFactors.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,246 @@ +%mathpiper,def="YacasFactors" + +//Retract("YacasFactors",*); +//Retract("FactorsMultivariateSpecialCases",*); +//Retract("FactorsSomethingElse",*); +//Retract("CombineNumericalFactors",*); + +/* + * This is the fundamental factorization algorithm as created for Yacas, with + * a few improvements. + * It works for integers, rational numbers, Gaussian integers, and polynomials + * When the argument is an integer, FactorizeInt() does the heavy lifting. + * When the argument is a polynomial, BinaryFactors() is the workhorse. + */ + + +10 # YacasFactors(p_IsPositiveInteger) <-- FactorizeInt(p); + +11 # YacasFactors(p_IsInteger) <-- FactorizeInt(p); + +12 # YacasFactors(p_IsRational)_(Denominator(p) != 1) <-- {{YacasFactor(Numerator(p)) /YacasFactor(Denominator(p)) , 1}}; + //Added to handle rational numbers with denominators that are not 1 + +14 # YacasFactors(p_IsGaussianInteger) <-- GaussianFactors(p); + +20 # YacasFactors(p_CanBeUni)_(Length(VarList(p)) = 1) <-- +[ + Local(x,d,coeffs,nterms,factorsList,result); + x := VarList(p)[1]; + d := Degree(p,x); + /* p is the polynomial, x is its (only) variable. It IS Univariate */ + /* Let's find out how many terms this polynomial has. */ + coeffs := Coef(p,x,0 .. Degree(p,x)); + nterms := Length(Select(coeffs, "IsNotZero")); + /* If nterms = 2, it is a binomial, and might be most easily + * factored by some special-purpose algorithms */ + If( nterms = 2 And d > 2, + [ result := FactorsBinomials(p); ], + [ // nterms != 2, so try other techniques + factorsList := BinaryFactors(p); + // BinaryFactors is the internal MathPiper function that + // creates a double list of factors and their multiplicities + /* + * Now we check whether the input polynomial is "over the + * integers", by examining all its coefficients + */ + If( AllSatisfy("IsInteger",coeffs), + [ + // Yes -- all integer coefficients + result := FactorsPolynomialOverIntegers(p,x); + ], + [ + // No -- at least one non-integer coefficient + // Check for FLOAT or RATIONAL coefficients + Local(notInt,rat,dd,lcm,newCoeffs,NewPoly,facs); + notInt := Select(coeffs, Lambda({i},Not IsInteger(i))); + rat := Rationalize(coeffs); + dd := MapSingle("Denominator",rat); + lcm := Lcm(dd); + newCoeffs := lcm * rat; + newPoly := NormalForm(UniVariate(x,0,newCoeffs)); + facs := FactorsPolynomialOverIntegers(newPoly); + If( InVerboseMode(), [ + Echo("coeffs ",coeffs); + Echo("notInt ",notInt); + Echo("rat ",rat); + Echo("dd ",dd); + Echo("lcm ",lcm); + Echo("newCoeffs ",newCoeffs); + Echo("newPoly ",newPoly); + Echo("facs ",facs); + ] + ); + result := {(1/lcm),1}:facs; + //NOT FINISHED YET + ] + ); + ] + ); + CombineNumericalFactors( result ); +]; + + +30 # YacasFactors(p_CanBeUni) <-- +[ + /* + * This may be a multi-variate polynomial, or it may be something else. + * Original YT function Factors() did not attempt to factor such. + * If it is a multivariate polynomial, we will try certain + * Special cases which we can relatively easily factor. + * If it is "something else", we will have to check, on a + * case-by-case basis. + */ + Local(vl,nvars,coeffs,result); + vl := VarList(p); + nvars := Length(vl); + coeffs := Coef(p,x,0 .. 8); + If(InVerboseMode(),Tell("CBU",{vl,nvars,coeffs})); + If (nvars > 1, + [ + If( InVerboseMode(), Echo(" special ",p)); + result := FactorsMultivariateSpecialCases(p); + ], + result := FactorsSomethingElse(p) + ); + CombineNumericalFactors( result ); +]; + + +40 # YacasFactors(_p) <-- +[ + /* + * This may may be a polynomial with non-integer exponents. Let's check. + */ + If( InVerboseMode(), Echo("Possibly trying to factor polynomial with non-integral exponents") ); + Local( result); + //Echo(40,p); + // NOT IMPLEMENTED YET + result := {{p,1}}; + CombineNumericalFactors( result ); + +]; + +//------------------------------------------------------------------------ +// S P E C I A L C A S E S +//------------------------------------------------------------------------ + +10 # FactorsMultivariateSpecialCases(-_expr) <-- {-1,1}:FactorsMultivariateSpecialCases(expr); + +10 # FactorsMultivariateSpecialCases(x_IsAtom + y_IsAtom) <-- [If(InVerboseMode(),Tell(1));{{x+y,1}};]; + +10 # FactorsMultivariateSpecialCases(x_IsAtom - y_IsAtom) <-- [If(InVerboseMode(),Tell(2));{{x-y,1}};]; + +10 # FactorsMultivariateSpecialCases(_n*_x^p_IsInteger + _n*_y) <-- [If(InVerboseMode(),Tell(3));{n,1}:FactorsMultivariateSpecialCases(x+y);]; + +10 # FactorsMultivariateSpecialCases(_n*_x^p_IsInteger - _n*_y) <-- [If(InVerboseMode(),Tell(4));{n,1}:FactorsMultivariateSpecialCases(x-y);]; + +10 # FactorsMultivariateSpecialCases(n_IsInteger*_x + m_IsInteger*_y)_(Gcd(n,m)>1) <-- {{Gcd(n,m),1},{(Simplify((n*x+m*y)/Gcd(n,m))),1}}; + +10 # FactorsMultivariateSpecialCases(n_IsInteger*_x - m_IsInteger*_y)_(Gcd(n,m)>1) <-- {{Gcd(n,m),1},{(Simplify((n*x-m*y)/Gcd(n,m))),1}}; + +10 # FactorsMultivariateSpecialCases(_n*_x + _n*_y) <-- {n,1}:FactorsMultivariateSpecialCases(x+y); + +10 # FactorsMultivariateSpecialCases(_n*_x - _n*_y) <-- {n,1}:FactorsMultivariateSpecialCases(x-y); + +10 # FactorsMultivariateSpecialCases(_x^n_IsInteger - _y) <-- FactorsBinomials(x^n - y); + +10 # FactorsMultivariateSpecialCases(_x^n_IsInteger + _y) <-- FactorsBinomials(x^n + y); + +20 # FactorsSomethingElse(_p) <-- + [ + If( InVerboseMode(), + [ + ECHO(" *** FactorsSomethingElse: NOT IMPLEMENTED YET ***"); + ] + ); + p; + ]; + +//------------------------------------------------------------------------ + + +10 # CombineNumericalFactors( factrs_IsList ) <-- + [ + If( InVerboseMode(), Tell("Combine",factrs) ); + Local(q,a,b,t,f,err); + err := False; + t := 1; + f := {}; + ForEach(q,factrs) + [ + If( InVerboseMode(), Tell(1,q) ); + If( IsList(q) And Length(q)=2, + [ + {a,b} := q; + If( InVerboseMode(), Echo(" ",{a,b}) ); + If( IsNumericList( {a,b} ), + t := t * a^b, + f := {a,b}:f + ); + ], + err := True + ); + ]; + If( InVerboseMode(), + [ + Echo(" t = ",t); + Echo(" f = ",f); + Echo(" err = ",err); + ] + ); + If(Not err And t != 1, {t,1}:Reverse(f), factrs); + ]; + +%/mathpiper + + + + + +%mathpiper_docs,name="YacasFactors",categories="User Functions;Number Theory" +*CMD YacasFactors --- factorization +*STD +*CALL + YacasFactors(x) + +*PARMS + +{x} -- integer or univariate polynomial + +*DESC + +This is mostly the original Yacas version of the function Factors(), +slightly modified for Mathpiper to improve some of its capabilities. +It has now been superceeded in MathPiper by the function xFactors(), +which has a large number of improvements. + +This function decomposes the integer number {x} into a product of +numbers. +Alternatively, if {x} is a univariate polynomial, it is +decomposed into irreducible polynomials. If {x} is a polynomial +"over the integers", the irreducible polynomial factors will also +be returned in the (unique) form with integer coefficients. + +The factorization is returned as a list of pairs. The first member of +each pair is the factor, while the second member denotes the power to +which this factor should be raised. So the factorization +$x = p1^n1 * ... * p9^n9$ +is returned as {{{p1,n1}, ..., {p9,n9}}}. + +Programmer: Yacas Team + Sherm Ostrowsky + +*E.G. +In> YacasFactors(24) +Result: {{2,3},{3,1}} + +In> YacasFactors(32*x^3+32*x^2-70*x-75) +Result: {{4*x+5,2},{2*x-3,1}} + +*SEE YacasFactor, xFactors, IsPrime, GaussianFactors +%/mathpiper_docs + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/Apply.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/Apply.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/Apply.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/Apply.mpw 2011-02-05 04:21:42.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="Apply" + +10 # Apply(_applyoper,_applyargs) _ (Or(IsString(applyoper), IsList(applyoper))) <-- ApplyFast(applyoper,applyargs); +20 # Apply(applyoper_IsAtom,_applyargs) <-- ApplyFast(ToString(applyoper),applyargs); + +30 # Apply(Lambda(_args,_body),_applyargs) <-- `ApplyFast(Hold({@args,@body}),applyargs); +UnFence("Apply",2); + +%/mathpiper + + + +%mathpiper_docs,name="Apply",categories="User Functions;Functional Operators" +*CMD Apply --- apply a function to arguments +*STD +*CALL + Apply(fn, arglist) + +*PARMS + +{fn} -- function to apply + +{arglist} -- list of arguments + +*DESC + +This function applies the function "fn" to the arguments in +"arglist" and returns the result. The first parameter "fn" can +either be a string containing the name of a function or a pure +function. Pure functions, modeled after lambda-expressions, have the +form "{varlist,body}", where "varlist" is the list of formal +parameters. Upon application, the formal parameters are assigned the +values in "arglist" (the second parameter of {Apply}) and the "body" is evaluated. + +Another way to define a pure function is with the Lambda construct. +Here, instead of passing in "{varlist,body}", one can pass in +"Lambda(varlist,body)". Lambda has the advantage that its arguments +are not evaluated (using lists can have undesirable effects because +lists are evaluated). Lambda can be used everywhere a pure function +is expected, in principle, because the function Apply is the only function +dealing with pure functions. So all places where a pure function can +be passed in will also accept Lambda. + +An shorthand for {Apply} is provided by the {@} operator. + +*E.G. +In> Apply("+", {5,9}); +Result: 14; + +In> Apply({{x,y}, x-y^2}, {Cos(a), Sin(a)}); +Result: Cos(a)-Sin(a)^2; + +In> Apply(Lambda({x,y}, x-y^2), {Cos(a), Sin(a)}); +Result: Cos(a)-Sin(a)^2 + +In> Lambda({x,y}, x-y^2) @ {Cos(a), Sin(a)} +Result: Cos(a)-Sin(a)^2 + +*SEE Map, MapSingle, @, Lambda +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/atsign_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/atsign_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/atsign_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/atsign_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="@" + +Rulebase("@",{func,arg}); +Rule("@",2,1,IsList(arg)) Apply(func,arg); +Rule("@",2,2,True ) Apply(func,{arg}); + +%/mathpiper + + + +%mathpiper_docs,name="@",categories="Operators" +*CMD @ --- apply a function +*STD +*CALL + fn @ arglist +Precedence: +*EVAL PrecedenceGet("@") + +*PARMS + +{fn} -- function to apply + +{arglist} -- single argument, or a list of arguments + +*DESC + +This function is a shorthand for {Apply}. It applies the +function "fn" to the argument(s) in "arglist" and returns the +result. The first parameter "fn" can either be a string containing +the name of a function or a pure function. + +This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. + +*E.G. + +In> "Sin" @ a +Result: Sin(a); +In> {{a},Sin(a)} @ a +Result: Sin(a); +In> "f" @ {a,b} +Result: f(a,b); + +*SEE Apply +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/colon_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/colon_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/colon_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/colon_operator.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,78 @@ +%mathpiper,def=":" + +/* Operators for functional programming. todo:tk:move some of this documentation into the proper function's .mpw files. + * Examples: + * a:b:c:{} -> {a,b,c} + * "Sin" @ a -> Sin(a) + * "Sin" @ {a,b} -> Sin(a,b) + * "Sin" /@ {a,b} -> {Sin(a),Sin(b)} + * 1 .. 4 -> {1,2,3,4} + */ + + +/* a : b will now return unevaluated (rather than cause error of invalid argument in Concat) if neither a nor b is a list and if one of them is not a string +*/ +Rulebase(":",{head,tail}); +Rule(":",2,20,IsList(head) And Not IsList(tail) ) Concat(head,{tail}); +Rule(":",2,30,IsList(tail) ) Concat({head},tail); +Rule(":",2,10,IsString(tail) And IsString(head)) ConcatStrings(head,tail); +UnFence(":",2); + +%/mathpiper + + + +%mathpiper_docs,name=":",categories="Operators" +*CMD : --- append one item to a list or prepend one or more items to a list or concatenate strings +*STD +*CALL + list : item + item : list + item : item : list + string1 : string2 + +Precedence = 70 + +*PARMS +{item} -- an item to append or prepend to a list + +{list} -- a list + +{string1} -- a string + +{string2} -- a string + +*DESC + +The first form appends a single "item" to "list". The second form +prepends one or more "items" to "list" +The third form concatenates the strings "string1" and +"string2". + +This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. + +*E.G. + +In> {}:a +Result: {a} + +In> {a,b}:c +Result: {a,b,c} + +In> a:b:c:{} +Result: {a,b,c}; + +In> a:b:{c}:d +Result: {a,b,c,d} + +In> "This":"Is":"A":"String" +Result: "ThisIsAString"; + +*SEE Concat, ConcatStrings +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/dot_dot_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/dot_dot_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/dot_dot_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/dot_dot_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def=".." + +/* +.. operator is implemented with the Table function. +*/ +10 # (count'from_IsInteger .. count'to_IsInteger)_(count'from <= count'to) + <-- Table(i,i,count'from,count'to,1); +20 # (count'from_IsInteger .. count'to_IsInteger) + <-- Table(i,i,count'from,count'to,-1); + +%/mathpiper + + + +%mathpiper_docs,name="..",categories="Operators" +*CMD .. --- construct a list of consecutive integers + +*STD + +*CALL + n .. m + +*PARMS + +{n} -- integer. the first entry in the list + +{m} -- integer, the last entry in the list + +*DESC + +This command returns the list {{n, n+1, n+2, ..., m}}. If {m} is +smaller than {n}, the empty list is returned. Note that the +{..} operator should be surrounded by spaces to keep the +parser happy, if "n" is a number. So one should write "{1 .. 4}" instead of "{1..4}". + +This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. + +*E.G. + +In> 1 .. 4 +Result: {1,2,3,4}; + +*SEE Table +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/NFunction.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/NFunction.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/NFunction.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/NFunction.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,97 @@ +%mathpiper,def="NFunction" + +/* NFunction("new'func", "old'func" {arg'list}) will define a wrapper function +around "old'func", called "new'func", which will return "old'func(arg'list)" +only when all arguments are numbers and will return unevaluated +"new'func(arg'list)" otherwise. */ +LocalSymbols(NFunction'Numberize) +[ +NFunction(new'name_IsString, old'name_IsString, arg'list_IsList) <-- [ + MacroRulebase(new'name, arg'list); + MacroRule(new'name, Length(arg'list), 0, // check whether all args are numeric + ListToFunction({IsNumericList, arg'list}) + ) + + /* this is the rule defined for the new function. + // this expression should evaluate to the body of the rule. + // the body looks like this: + // NFunction'Numberize(old'name(arg'list)) + */ + NFunction'Numberize(ListToFunction({ToAtom("@"), old'name, arg'list})); + // cannot use bare '@' b/c get a syntax error + +]; + +// this function is local to NFunction. +// special handling for numerical errors: return Undefined unless given a number. +10 # NFunction'Numberize(x_IsNumber) <-- x; +20 # NFunction'Numberize(x_IsAtom) <-- Undefined; +// do nothing unless given an atom + +]; // LocalSymbols() + +%/mathpiper + + + +%mathpiper_docs,name="NFunction",categories="User Functions;Functional Operators" +*CMD NFunction --- make wrapper for numeric functions +*STD +*CALL + NFunction("newname","funcname", {arglist}) + +*PARMS +{"newname"} -- name of new function + +{"funcname"} -- name of an existing function + +{arglist} -- symbolic list of arguments + +*DESC +This function will define a function named "newname" +with the same arguments as an existing function named "funcname". The new function will evaluate and return the expression "funcname(arglist)" only when +all items in the argument list {arglist} are numbers, and return unevaluated otherwise. + +This can be useful when plotting functions defined through other MathPiper routines that cannot return unevaluated. + +If the numerical calculation does not return a number (for example, +it might return the atom {nan}, "not a number", for some arguments), +then the new function will return {Undefined}. + +This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. + + +*E.G. notest +In> f(x) := N(Sin(x)); +Result: True; +In> NFunction("f1", "f", {x}); +Result: True; +In> f1(a); +Result: f1(a); +In> f1(0); +Result: 0; +Suppose we need to define a complicated function {t(x)} which cannot be evaluated unless {x} is a number: + +In> t(x) := If(x<=0.5, 2*x, 2*(1-x)); +Result: True; +In> t(0.2); +Result: 0.4; +In> t(x); + In function "If" : + bad argument number 1 (counting from 1) + CommandLine(1) : Invalid argument +Then, we can use {NFunction()} to define a wrapper {t1(x)} around {t(x)} which will not try to evaluate {t(x)} unless {x} is a number. + +In> NFunction("t1", "t", {x}) +Result: True; +In> t1(x); +Result: t1(x); +In> t1(0.2); +Result: 0.4; +Now we can plot the function. + +In> Plot2D(t1(x), -0.1: 1.1) +Result: True; + +*SEE MacroRule +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/om/om.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="" + +// From code.mpi.def: +OMDef( ":" , "mathpiper","prepend" ); +OMDef( "@" , "mathpiper","apply" ); +OMDef( "/@" , "mathpiper","list_apply" ); +OMDef( ".." , "interval1","integer_interval" ); +OMDef( "NFunction", "mathpiper","NFunction" ); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/slash_atsign_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/slash_atsign_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/functional/slash_atsign_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/functional/slash_atsign_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="/@" + +Function("/@",{func,lst}) Apply("MapSingle",{func,lst}); + +%/mathpiper + + + +%mathpiper_docs,name="/@",categories="Operators" +*CMD /@ --- apply a function to all entries in a list +*STD +*CALL + fn /@ list +Precedence: +*EVAL PrecedenceGet("/@") + +*PARMS + +{fn} -- function to apply + +{list} -- list of arguments + +*DESC +This function is a shorthand for {MapSingle}. It +successively applies the function "fn" to all the entries in +"list" and returns a list contains the results. The parameter "fn" +can either be a string containing the name of a function or a pure +function. + +This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. + +*E.G. + +In> "Sin" /@ {a,b} +Result: {Sin(a),Sin(b)}; +In> {{a},Sin(a)*a} /@ {a,b} +Result: {Sin(a)*a,Sin(b)*b}; + +*SEE MapSingle, Map, MapArgs +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/html/html.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/html/html.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/html/html.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/html/html.mpw 2010-01-05 20:11:09.000000000 +0000 @@ -0,0 +1,252 @@ +%mathpiper,def="HtmlNewParagraph;HtmlAnchor;HtmlLink;HtmlTable;HtmlCaption;HtmlTitle;HtmlFrameSetRows;HtmlFrameSetCols;HtmlFrame;HtmlTag;HtmlForm;Bullets;Bullet;HtmlTextArea;HtmlTextField;HtmlSubmitButton;SetHtmlDirectory;HtmlFile;ClearSite;LoadSite;SaveSite;MySQLQuery" + +/* def file definitions +HtmlNewParagraph +HtmlAnchor +HtmlLink +HtmlTable +HtmlCaption +HtmlTitle +HtmlFrameSetRows +HtmlFrameSetCols +HtmlFrame +HtmlTag +HtmlForm +Bullets +Bullet +HtmlTextArea +HtmlTextField +HtmlSubmitButton +SetHtmlDirectory +HtmlFile +ClearSite +LoadSite +SaveSite +MySQLQuery +*/ + + +/* code to generate html */ + + +/* Global defines */ +anchor:={}; +anchor["0"]:="a"; +anchor["name"]:=""; + +link:={}; +link["0"]:="a"; +link["href"]:=""; + +frameset:={}; +frameset["0"]:="frameset"; +frameset["border"]:="0"; + +frame:={}; +frame["0"]:="frame"; + +caption:={}; +caption["0"]:="caption"; + +table:={}; +table["0"]:="table"; + +form:={}; +form["0"]:="form"; + +textarea:={}; +textarea["0"]:="textarea"; + +textfield:={}; +textfield["0"]:="input"; +textfield["TYPE"]:="text"; + +button:={}; +button["0"]:="input"; +button["TYPE"]:="submit"; + +bullets:={}; +bullets["0"]:="ul"; + +bullet:={}; +bullet["0"]:="li"; + +newline:=" +"; +Gt():=">"; +Lt():="<"; + + + + +HtmlNewParagraph():= (newline : "

    " : newline); + +HtmlTitle(title):= +[ +" + " : title : " + +"; +]; + +HtmlAnchor(name):= +[ + anchor["name"]:=name; + HtmlTag(anchor,""); +]; +Bodied("HtmlAnchor",60000); + +HtmlTable(cellpadding,width,body):= +[ + table["cellpadding"]:=ToString(cellpadding); + table["width"]:=width; + HtmlTag(table,body); +]; + +Bullets(list):=HtmlTag(bullets,list); +Bullet (list):=HtmlTag(bullet ,list); + + +HtmlCaption(title):= +[ + HtmlTag(caption,title); +]; + +HtmlForm(action,body):= +[ + form["method"]:="get"; + form["action"]:=action; + HtmlTag(form,body); +]; + + +HtmlTextArea(name,width,height,body) := +[ + textarea["name"]:=name; + textarea["cols"]:=ToString(width); + textarea["rows"]:=ToString(height); + HtmlTag(textarea,body); +]; + +HtmlTextField(name,size,value):= +[ + textfield["name"]:=name; + textfield["size"]:=ToString(size); + textfield["value"]:=value; + HtmlTag(textfield,""); +]; + +HtmlSubmitButton(name,value):= +[ + button["name"]:=name; + button["value"]:=value; + HtmlTag(button,""); +]; + + +HtmlLink(description,file,tag,target):= +[ + If(tag != "", + link["href"]:= file : "#" : tag, + link["href"]:= file); + + If(target != "",link["target"] :=target); + HtmlTag(link,description); +]; + +HtmlFrameSetRows(columns,body):= +[ + frameset["cols"]:=""; + frameset["rows"]:=columns; + HtmlTag(frameset,body); +]; + +HtmlFrameSetCols(columns,body):= +[ + frameset["cols"]:=columns; + frameset["rows"]:=""; + HtmlTag(frameset,body); +]; + +HtmlFrame(source,name):= +[ + frame["src"]:=source; + frame["name"]:=name; + HtmlTag(frame,""); +]; + + +/* export a html tag type, using the specifications in the + tags assoc list. + */ +HtmlTag(tags,content):= +[ + Local(result,tag,analytics); + result:="<" : tags["0"]; + ForEach(tag,AssocIndices(tags)) + [ + If (tag != "0" And tags[tag] != "", + result:= result : " " : tag : "=" : "\"" : tags[tag] : "\"" + ); + ]; + + analytics:=""; + If(tags["0"] = "body", + analytics:=" + +"); + + + result:= result : ">" : newline : + content : newline : + analytics : "" : newline; + + result; +]; + +/* output directory management */ +htmldir:=""; +SetHtmlDirectory(dir):= [htmldir:=dir;]; +HtmlFile(file) := [htmldir : file;]; + + +/* loading and saving site info */ +site:={}; +ClearSite() := [site:={};]; +LoadSite():= +[ + PipeFromFile("siteall") + [ + site:=Read(); + ]; +]; + +SaveSite():= +[ + PipeToFile("siteall") + [ + Write(site); + WriteString(";"); + ]; +]; + +MySQLQuery(pidstr,string):= +[ + Local(result); + PipeToFile("sqlin":pidstr) WriteString(string); + SystemCall("mysql mysql < ":"sqlin":pidstr:" > sqlout":pidstr); + SystemCall(FindFile("tools/mysqlstubs"):" sqlout":pidstr:" sqlout_":pidstr); + result:= PipeFromFile("sqlout_":pidstr)Read(); + SystemCall("rm -rf sqlin":pidstr); + SystemCall("rm -rf sqlout":pidstr); + SystemCall("rm -rf sqlout_":pidstr); + result; +]; + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/mathpiperinit/mathpiperinit.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/mathpiperinit/mathpiperinit.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/mathpiperinit/mathpiperinit.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/mathpiperinit/mathpiperinit.mpw 2010-12-31 06:20:30.000000000 +0000 @@ -0,0 +1,77 @@ +%mathpiper,def="" + + + +/* This is the basic initialization file for MathPiper. It gets loaded + * each time MathPiper is started. All the basic files are loaded. + */ + +/* Set up drivers, configurable in the .mpiperrc + * Bind(MultiNomialDriver,"multivar.rep/sparsenomial.mpi"); + * or + * Bind(MultiNomialDriver,"multivar.rep/partialdensenomial.mpi"); + */ + +/* The truly required files (MathPiper NEEDS to load). */ +// syntax must be loaded first +LoadScriptOnce("initialization.rep/stdopers.mpi"); + +/* Set of functions to define very simple functions. There are scripts that can + be compiled to plugins. So MathPiper either loads the plugin, or loads the + scripts at this point. The functions in these plugins need to be defined with + these "Defun" functions. + */ +DefMacroRulebase("Defun",{func,args,body}); +Rule("Defun",3,0,True) +[ + Local(nrargs); + Bind(nrargs,Length(@args)); + Retract(@func, `(@nrargs)); + Rulebase(@func,@args); + Local(fn,bd); + Bind(fn,Hold(@func)); Bind(bd,Hold(@body)); + `Rule(@fn, @nrargs, 0,True)(@bd); +]; + +//TODO remove? LoadScriptOnce("base.rep/math.mpi"); + +LoadScriptOnce("patterns.rep/code.mpi"); +// at this point <-- can be used + +LoadScriptOnce("deffunc.rep/code.mpi"); + +// at this point := and Function() can be used + +LoadScriptOnce("constants.rep/code.mpi"); +LoadScriptOnce("initialization.rep/standard.mpi"); +LoadScriptOnce("initialization.rep/stdarith.mpi"); + +// at this point arithmetic can be used + +/* Load the def files for the other modules. The def files contain lists + * of functions defined in that file. So, in solve.def you can find the + * functions defined in the file solve. Each time a function is invoked + * for which the interpreter can not find a definition, the file is loaded. + */ + +Rulebase(LoadPackages,{packages}); +Rule(LoadPackages, 1, 1, True) +[ + If(IsEqual(packages,{}), True, + [ + DefLoad(First(packages)); + LoadPackages(Rest(packages)); + ]); +]; + +LoadScriptOnce("initialization.rep/packages.mpi"); +LoadPackages(DefFileList()); + +// The multivar routines are not all properly initialized until the first time +// one of them is called. This may come too late for some operations that try +// to use them before they have been initialized. The following call should +// take care of this problem. +LoadScriptOnce("multivar.rep/code.mpi"); + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/miscdocs/miscellaneousdocs.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/miscdocs/miscellaneousdocs.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/miscdocs/miscellaneousdocs.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/miscdocs/miscellaneousdocs.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,221 @@ + + +%mathpiper_docs,name="quit;restart",categories="User Functions;Built In" +*CMD quit --- stop MathPiper from running (from the command line) +*CMD restart --- restart MathPiper (to start with a clean slate) +*CORE +*CALL + quit + restart + +*DESC + +Type {quit} or {restart} at the MathPiper prompt to exit or to restart the interpreter. + +The directives {quit} and {restart} are not reserved words or variable names. +They take effect only when typed as first characters at a prompt. + +Pressing {Ctrl-C} will stop the currently running calculation. +If there is no currently running calculation, {Ctrl-C} will quit the interpreter. + +When the interpreter quits, it saves the command history +(so quitting by {Ctrl-C} does not mean a "crash"). + +This command is not a function but a special directive that only applies while running MathPiper interactively. It should not be used in scripts. + +*E.G. + +To be effective, the directive must be typed immediately after the prompt: +In> quit + Quitting... +We can use variables named {quit}: +In> 1+quit +Result: quit+1; +There is no effect if we type some spaces first: +In> restart +Result: restart; + +*SEE Exit +%/mathpiper_docs + + + + +%mathpiper_docs,name="%_v2",categories="Operators" +*CMD % --- previous result +*CORE +*CALL + % + +*DESC + +{%} evaluates to the previous result on the command line. {%} is a global +variable that is bound to the previous result from the command line. +Using {%} will evaluate the previous result. (This uses the functionality +offered by the {SetGlobalLazyVariable} command). + +Typical examples are {Simplify(%)} and {PrettyForm(%)} to simplify and show the result in a nice +form respectively. + +*E.G. + +In> Taylor(x,0,5)Sin(x) +Result: x-x^3/6+x^5/120; +In> PrettyForm(%) + + 3 5 + x x + x - -- + --- + 6 120 + + + +*SEE SetGlobalLazyVariable +%/mathpiper_docs + + + + + + +%mathpiper_docs,name="True;False",categories="User Functions;Constants (System)" +*CMD True --- boolean constant representing true +*CMD False --- boolean constant representing false +*CORE +*CALL + True + False + +*DESC + +{True} and {False} are typically a result +of boolean expressions such as {2 < 3} or {True And False}. + +*SEE And, Or, Not +%/mathpiper_docs + + + + + + +%mathpiper_docs,name="EndOfFile",categories="User Functions;Constants (System)" +*CMD EndOfFile --- end-of-file marker +*CORE +*CALL + EndOfFile + +*DESC + +End of file marker when reading from file. If a file +contains the expression {EndOfFile;} the +operation will stop reading the file at that point. +%/mathpiper_docs + + + + + +%mathpiper_docs,name="Infinity",categories="User Functions;Constants (Mathematical)" + +*CMD Infinity --- constant representing mathematical infinity +*STD +*CALL + Infinity + +*DESC + +Infinity represents infinitely large values. It can be the result of certain +calculations. + +Note that for most analytic functions MathPiper understands {Infinity} as a positive number. +Thus {Infinity*2} will return {Infinity}, and {a < Infinity} will evaluate to {True}. + +*E.G. + +In> 2*Infinity +Result: Infinity; +In> 2 2*Infinity +Result: Infinity; +In> 0*Infinity +Result: Undefined; +In> Sin(Infinity); +Result: Undefined; +In> Undefined+2*Exp(Undefined); +Result: Undefined; + +*SEE Infinity +%/mathpiper_docs + + + + +%mathpiper_docs,name="/*;*/;//",categories="Operators" +*CMD /* --- Start of comment +*CMD */ --- end of comment +*CMD // --- Beginning of one-line comment +*CORE +*CALL + /* comment */ + // comment + +*DESC + +Introduce a comment block in a source file, similar to C++ comments. +{//} makes everything until the end of the line a comment, while {/*} and {*/} may delimit a multi-line comment. + +*E.G. + + a+b; // get result + a + /* add them */ b; +%/mathpiper_docs + + + + +%mathpiper_docs,name="[;]",categories="Operators" +*CMD [ --- beginning of block of statements +*CMD ] --- end of block of statements +*CORE +*CALL + + [ statement1; statement2; ... ] + +*PARMS + +{statement1}, {statement2} -- expressions + +*DESC + +The {Prog} and the {[ ... ]} construct have the same effect: they evaluate all +arguments in order and return the result of the last evaluated expression. + +{Prog(a,b);} is the same as typing {[a;b;];} and is very useful for writing out +function bodies. The {[ ... ]} construct is a syntactically nicer version of the +{Prog} call; it is converted into {Prog(...)} during the parsing stage. + +*SEE Prog +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/ampersand_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/ampersand_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/ampersand_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/ampersand_operator.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="&" + +a_IsNonNegativeInteger & b_IsNonNegativeInteger <-- BitAnd(a,b); + +%/mathpiper + + + + +%mathpiper_docs,name="&",categories="Operators" +*CMD --- bitwise AND operator +*STD +*CALL + a & b + +*PARMS + +{a} -- non negative integer + +{b} -- non negative integer + +*DESC + +This operator performs a bitwise AND on two integers. + +*E.G. + +In> 15 & 4 +Result: 4 + +*SEE | +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/A_Nth.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/A_Nth.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/A_Nth.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/A_Nth.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,100 @@ +%mathpiper,def="Nth" + +/* Implementation of Nth that allows extending. */ +Rulebase("Nth",{alist,aindex}); +Rule("Nth",2,10, + And(IsEqual(IsFunction(alist),True), + IsEqual(IsInteger(aindex),True), + Not(IsEqual(First(FunctionToList(alist)),Nth)) + )) + MathNth(alist,aindex); + + + + +Rule("Nth",2,14, + And(IsEqual(IsString(alist),True),IsList(aindex)) + ) +[ + Local(result); + result:=""; + ForEach(i,aindex) [ result := result : StringMidGet(i,1,alist); ]; + result; +]; + +Rule("Nth",2,15,IsEqual(IsString(alist),True)) +[ + StringMidGet(aindex,1,alist); +]; + + +Rule("Nth",2,20,IsEqual(IsList(aindex),True)) +[ + Map({{ii},alist[ii]},{aindex}); +]; + +Rule("Nth",2,30, + And( + IsEqual(IsGeneric(alist),True), + IsEqual(GenericTypeName(alist),"Array"), + IsEqual(IsInteger(aindex),True) + ) + ) +[ + ArrayGet(alist,aindex); +]; + + + +Rule("Nth",2,40,IsEqual(IsString(aindex),True)) +[ + Local(as); + as := Assoc(aindex,alist); + If (Not(IsEqual(as,Empty)),Bind(as,Nth(as,2))); + as; +]; + + +%/mathpiper + + + +%mathpiper_docs,name="Nth",categories="User Functions;Lists (Operations)" +*CMD Nth --- return the $n$-th element of a list +*CORE +*CALL + Nth(list, n) + +*PARMS + +{list} -- list to choose from + +{n} -- index of entry to pick + +*DESC + +The entry with index "n" from "list" is returned. The first entry +has index 1. It is possible to pick several entries of the list by +taking "n" to be a list of indices. + +More generally, {Nth} returns the n-th operand of the +expression passed as first argument. + +An alternative but equivalent form of {Nth(list, n)} is +{list[n]}. + +*E.G. + +In> lst := {a,b,c,13,19}; +Result: {a,b,c,13,19}; +In> Nth(lst, 3); +Result: c; +In> lst[3]; +Result: c; +In> Nth(lst, {3,4,1}); +Result: {c,13,a}; +In> Nth(b*(a+c), 2); +Result: a+c; + +*SEE Select, Nth +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/ArgumentsCount.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/ArgumentsCount.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/ArgumentsCount.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/ArgumentsCount.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="ArgumentsCount" + +Function("ArgumentsCount",{aLeft}) Length(FunctionToList(aLeft))-1; + +%/mathpiper + + + + +%mathpiper_docs,name="ArgumentsCount",categories="Programmer Functions;Programming" +*CMD ArgumentsCount --- return number of top-level arguments +*STD +*CALL + ArgumentsCount(expr) + +*PARMS + +{expr} -- expression to examine + +*DESC + +This function evaluates to the number of top-level arguments of the +expression "expr". The argument "expr" may not be an atom, since +that would lead to an error. + +*E.G. + +In> ArgumentsCount(f(a,b,c)) +Result: 3; +In> ArgumentsCount(Sin(x)); +Result: 1; +In> ArgumentsCount(a*(b+c)); +Result: 2; + +*SEE Type, Length +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/Denominator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/Denominator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/Denominator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/Denominator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="Denominator" + +//Retract("Denominator",*); + +1 # Denominator(_x / _y) <-- y; +1 # Denominator(-_x/ _y) <-- y; +2 # Denominator(x_IsNumber) <-- 1; + +%/mathpiper + + + + +%mathpiper_docs,name="Denominator",categories="User Functions;Numbers (Operations)" +*CMD Denominator --- denominator of an expression +*STD +*CALL + Denominator(expr) + +*PARMS + +{expr} -- expression to determine denominator of + +*DESC + +This function determines the denominator of the rational expression +"expr" and returns it. As a special case, if its argument is numeric +but not rational, it returns {1}. If "expr" is +neither rational nor numeric, the function returns unevaluated. + +*E.G. + +In> Denominator(2/7) +Result: 7; +In> Denominator(a / x^2) +Result: x^2; +In> Denominator(-a / x^2) +Result: x^2 +In> Denominator(5) +Result: 1; + +*SEE Numerator, IsRational, IsNumber +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/equals_equals_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/equals_equals_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/equals_equals_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/equals_equals_operator.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="==" + +Rulebase("==",{left,right}); + +%/mathpiper + + + + +%mathpiper_docs,name="==",categories="Operators" +*CMD == --- symbolic equality operator +*STD +*CALL + expression == expression + +*PARMS + +{expression} -- an expression + +*DESC + +This operator is used to symbolically represent the equality +of two expressions as opposed to the = operator which performs +a comparison operation on two expressions. + +*E.G. + +In> Solve(y == m*x + b, x) +Result: {x==(y-b)/m} + +*SEE !== +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/exclamationpoint_equals_equals_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/exclamationpoint_equals_equals_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/exclamationpoint_equals_equals_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/exclamationpoint_equals_equals_operator.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,28 @@ +%mathpiper,def="!==" + +Rulebase("!==",{left,right}); + +%/mathpiper + + + + +%mathpiper_docs,name="!==",categories="Operators" +*CMD !== --- symbolic inequality operator +*STD +*CALL + expression !== expression + +*PARMS + +{expression} -- an expression + +*DESC + +This operator is used to symbolically represent the inequality +of two expressions as opposed to the != operator which performs +a comparison operation on two expressions. + + +*SEE == +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/IsNonObject.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/IsNonObject.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/IsNonObject.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/IsNonObject.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsNonObject" + +10 # IsNonObject(Object(_x)) <-- False; +20 # IsNonObject(_x) <-- True; + +%/mathpiper + + + + + +%mathpiper_docs,name="IsNonObject",categories="User Functions;Predicates" +*CMD IsNonObject --- test whether argument is not an {Object()} +*STD +*CALL + IsNonObject(expr) + +*PARMS + +{expr} -- the expression to examine + +*DESC + +This function returns {True} if "expr" is not of +the form {Object(...)} and {False} +otherwise. + +*HEAD Bugs + +In fact, the result is always {True}. + +*SEE Object +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/minus_minus_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/minus_minus_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/minus_minus_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/minus_minus_operator.mpw 2010-09-05 02:05:18.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="--" + +Function("--",{aVar}) +[ + MacroBind(aVar,SubtractN(Eval(aVar),1)); + + Eval(aVar); +]; + +UnFence("--",1); + +HoldArgument("--",aVar); + +%/mathpiper + + + + +%mathpiper_docs,name="--",categories="Operators" +*CMD -- --- decrement variable +*STD +*CALL + var-- + +*PARMS + +{var} -- variable to decrement + +*DESC + +The variable with name "var" is decremented, i.e. the number 1 is +subtracted from it. The expression {x--} is +equivalent to the assignment {x := x - 1}. + +*E.G. +In> x := 5; +Result: 5; + +In> x--; +Result: 4; + +In> x; +Result: 4; + +*SEE ++, := +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/NormalForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/NormalForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/NormalForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/NormalForm.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,26 @@ +%mathpiper,def="NormalForm" + +Rulebase("NormalForm",{expression}); +Rule("NormalForm",1,1000,True) expression; + +%/mathpiper + + + + +%mathpiper_docs,name="NormalForm",categories="User Functions;Lists (Operations)" +*CMD NormalForm --- return expression in normal form +*STD +*CALL + NormalForm(expression) + +*PARMS + +{expression} -- an expression + +*DESC + +This function returns an expression in normal form. + + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/Numerator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/Numerator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/Numerator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/Numerator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="Numerator" + +//Retract("Numerator",*); + +1 # Numerator(_x / _y) <-- x; +1 # Numerator(-_x/ _y) <-- -x; +2 # Numerator(x_IsNumber) <-- x; + +%/mathpiper + + + + + +%mathpiper_docs,name="Numerator",categories="User Functions;Numbers (Operations)" +*CMD Numerator --- numerator of an expression +*STD +*CALL + Numerator(expr) + +*PARMS + +{expr} -- expression to determine numerator of + +*DESC + +This function determines the numerator of the rational expression +"expr" and returns it. As a special case, if its argument is numeric +but not rational, it returns this number. If "expr" is neither +rational nor numeric, the function returns unevaluated. + +*E.G. + +In> Numerator(2/7) +Result: 2; +In> Numerator(a / x^2) +Result: a; +In> Numerator(-a / x^2) +Result: -a; +In> Numerator(5) +Result: 5; + +*SEE Denominator, IsRational, IsNumber +%/mathpiper_docs + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/numeric.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/numeric.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/numeric.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/numeric.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,215 @@ +%mathpiper,def="N;NonN;InNumericMode" + +//"+-;/-;*-;^-;:=-;:=+" These were in the def list. + +/* See the documentation on the assignment of the precedence of the rules. + */ + +/* Some very basic functions that are used always any way... */ + +/* Implementation of numeric mode */ + +//Retract("N",*); + +LocalSymbols(numericMode) +[ + + numericMode := False; + + // N function: evaluate numerically with given precision. + LocalSymbols(previousNumericMode, previousPrecision, numericResult) + Macro("N",{expression, precision}) + [ + //If(InVerboseMode(), + // [Tell("N",{expression,precision}); Tell(" ",{@expression,@precision});] + //); + + // we were in non-numeric mode + Local(previousNumericMode, previousPrecision, numericResult, exception); + + previousPrecision := BuiltinPrecisionGet(); + //If(InVerboseMode(),Tell(" ",previousPrecision)); + BuiltinPrecisionSet(@precision+5); + + AssignCachedConstantsN(); + + previousNumericMode := numericMode; + numericMode := True; + exception := False; + + //ExceptionCatch(Bind(numericResult, Eval(@expression)),Bind(exception,ExceptionGet())); + + ExceptionCatch( numericResult:=Eval(@expression), exception := ExceptionGet() ); + //If(InVerboseMode(),Tell(" 1",numericResult)); + + If(IsDecimal(numericResult), numericResult := RoundToN(numericResult, @precision)); + //If(InVerboseMode(),Tell(" 2",numericResult)); + + numericMode := previousNumericMode; + + If(Not numericMode, [ ClearCachedConstantsN(); ] ); + + BuiltinPrecisionSet(previousPrecision); + + Check(exception = False, exception["type"], exception["message"]); + + numericResult; + + ]; + + + + + // N function: evaluate numerically with default precision. + LocalSymbols(precision,heldExpression) + Macro("N",{expression}) + [ + Local(precision, heldExpression); + precision := BuiltinPrecisionGet(); + heldExpression := Hold(@expression); + + `N(@heldExpression, @precision); + ]; + + + // NoN function. + LocalSymbols(result) + Macro("NonN",{expression}) + [ + Local(result); + GlobalPush(numericMode); + numericMode := False; + result := (@expression); + numericMode := GlobalPop(); + result; + ]; + + + // InNumericMode function. + Function("InNumericMode",{}) numericMode; + +]; //LocalSymbols(numericMode) + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="N",categories="User Functions;Numbers (Operations)" +*CMD N --- try to determine an numerical approximation of expression + +*CALL + N(expression) + N(expression, precision) +*PARMS + +{expression} -- expression to evaluate + +{precision} -- integer, precision to use + +*DESC + +The function {N} instructs {MathPiper} to try to coerce an expression in to a numerical approximation to the +expression {expr}, using {prec} digits precision if the second calling +sequence is used, and the default precision otherwise. This overrides the normal +behaviour, in which expressions are kept in symbolic form (eg. {Sqrt(2)} instead of {1.41421}). + +Application of the {N} operator will make MathPiper +calculate floating point representations of functions whenever +possible. In addition, the variable {Pi} is bound to +the value of $Pi$ calculated at the current precision. +(This value is a "cached constant", so it is not recalculated each time {N} is used, unless the precision is increased.) + + +{N} is a macro. Its argument {expr} will only +be evaluated after switching to numeric mode. + +*E.G. +In> 1/2 +Result: 1/2; +In> N(1/2) +Result: 0.5; +In> Sin(1) +Result: Sin(1); +In> N(Sin(1),10) +Result: 0.8414709848; +In> Pi +Result: Pi; +In> N(Pi,20) +Result: 3.1415926535897932385 + +*SEE Pi, InNumericMode, NonN +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + + +%mathpiper_docs,name="InNumericMode",categories="User Functions;Predicates" +*CMD InNumericMode --- determine if currently in numeric mode + +*CALL + InNumericMode() + +*DESC + +When in numeric mode, {InNumericMode()} will return {True}, else it will +return {False}. {MathPiper} is in numeric mode when evaluating an expression +with the function {N}. Thus when calling {N(expr)}, {InNumericMode()} will +return {True} while {expr} is being evaluated. + +{InNumericMode()} would typically be used to define a transformation rule +that defines how to get a numeric approximation of some expression. One +could define a transformation rule + + f(_x)_InNumericMode() <- [... some code to get a numeric approximation of f(x) ... ]; + +{InNumericMode()} usually returns {False}, so transformation rules that check for this +predicate are usually left alone. + + +*E.G. +In> InNumericMode() +Result: False +In> N(InNumericMode()) +Result: True + +*SEE N, BuiltinPrecisionSet, BuiltinPrecisionGet, Pi, CachedConstant +%/mathpiper_docs + + + + + +%mathpiper_docs,name="NonN",categories="User Functions;Numbers (Operations)" +*CMD NonN --- calculate part in non-numeric mode + +*CALL + NonN(expr) + +*PARMS +{expr} -- expression to evaluate + +*DESC +When in numeric mode, {NonN} can be called to switch back to non-numeric +mode temporarily. + +{NonN} is a macro. Its argument {expr} will only +be evaluated after the numeric mode has been set appropriately. + +*E.G. +In> N(NonN(InNumericMode())) +Result: False + +*SEE N, BuiltinPrecisionSet, BuiltinPrecisionGet, Pi, CachedConstant +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/percent_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/percent_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/percent_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/percent_operator.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="%" + +a_IsNonNegativeInteger % b_IsPositiveInteger <-- Modulo(a,b); + +%/mathpiper + + + + +%mathpiper_docs,name="%_v1",categories="Operators" +*CMD % --- modulus operator +*STD +*CALL + a % b + +*PARMS + +{a} -- non negative integer + +{b} -- non negative integer + +*DESC + +Divides a by b and returns the remainder of the division. + +*E.G. +In> 8 % 5 +Result: 3 + +*SEE / +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/plus_plus_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/plus_plus_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/plus_plus_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/plus_plus_operator.mpw 2010-09-05 02:05:18.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="++" + +Function("++",{aVar}) +[ + MacroBind(aVar,AddN(Eval(aVar),1)); + + Eval(aVar); +]; + +UnFence("++",1); + +HoldArgument("++",aVar); + +%/mathpiper + + + + +%mathpiper_docs,name="++",categories="Operators" +*CMD ++ --- increment variable +*STD +*CALL + var++ + +*PARMS + +{var} -- variable to increment + +*DESC + +The variable with name "var" is incremented, i.e. the number 1 is +added to it. The expression {x++} is equivalent to +the assignment {x := x + 1}. + +*E.G. +In> x := 5; +Result: 5; + +In> x++; +Result: 6; + +In> x; +Result: 6; + +*SEE --, := +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/vertical_bar_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/vertical_bar_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/standard/vertical_bar_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/standard/vertical_bar_operator.mpw 2009-12-29 02:45:11.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="|" + +a_IsNonNegativeInteger | b_IsNonNegativeInteger <-- BitOr(a,b); + +%/mathpiper + + + + +%mathpiper_docs,name="|",categories="Operators" +*CMD --- bitwise OR operator +*STD +*CALL + a | b + +*PARMS + +{a} -- non negative integer + +{b} -- non negative integer + +*DESC + +This operator performs a bitwise OR on two integers. + +*E.G. + +In> 3 | 4 +Result: 7 + +*SEE & +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/asterisk_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/asterisk_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/asterisk_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/asterisk_operator.mpw 2011-04-14 15:40:21.000000000 +0000 @@ -0,0 +1,134 @@ +%mathpiper,def="*" + +/* Multiplication */ + +50 # x_IsNumber * y_IsNumber <-- MultiplyN(x,y); +100 # 1 * _x <-- x; +100 # _x * 1 <-- x; +100 # (_f * _x)_(f= -1) <-- -x; +100 # (_x * _f)_(f= -1) <-- -x; +105 # (f_IsNegativeNumber * _x) <-- -(-f)*x; +105 # (_x * f_IsNegativeNumber) <-- -(-f)*x; + +95 # x_IsMatrix * y_IsMatrix <-- +[ + Local(i,j,k,row,result); + result:=ZeroMatrix(Length(x),Length(y[1])); + For(i:=1,i<=Length(x),i++) + For(j:=1,j<=Length(y),j++) + For(k:=1,k<=Length(y[1]),k++) + [ + row:=result[i]; + row[k]:= row[k]+x[i][j]*y[j][k]; + ]; + result; +]; + + +96 # x_IsMatrix * y_IsList <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=Length(x),i++) + [ DestructiveInsert(result,i,Dot(x[i], y)); ]; + result; +]; + + +97 # (x_IsList * y_IsNonObject)_Not(IsList(y)) <-- y*x; +98 # (x_IsNonObject * y_IsList)_Not(IsList(x)) <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=Length(y),i++) + [ DestructiveInsert(result,i,x * y[i]); ]; + result; +]; + + +50 # _x * Undefined <-- Undefined; +50 # Undefined * _y <-- Undefined; + + +100 # 0 * y_IsInfinity <-- Undefined; +100 # x_IsInfinity * 0 <-- Undefined; + +101 # 0 * (_x) <-- 0; +101 # (_x) * 0 <-- 0; + +100 # x_IsNumber * (y_IsNumber * _z) <-- (x*y)*z; +100 # x_IsNumber * (_y * z_IsNumber) <-- (x*z)*y; + +100 # (_x * _y) * _y <-- x * y^2; +100 # (_x * _y) * _x <-- y * x^2; +100 # _y * (_x * _y) <-- x * y^2; +100 # _x * (_x * _y) <-- y * x^2; +100 # _x * (_y / _z) <-- (x*y)/z; +// fractions +100 # (_y / _z) * _x <-- (x*y)/z; +100 # (_x * y_IsNumber)_Not(IsNumber(x)) <-- y*x; + +100 # (_x) * (_x) ^ (n_IsConstant) <-- x^(n+1); +100 # (_x) ^ (n_IsConstant) * (_x) <-- x^(n+1); +100 # (_x * _y)* _x ^ n_IsConstant <-- y * x^(n+1); +100 # (_y * _x)* _x ^ n_IsConstant <-- y * x^(n+1); +100 # Sqrt(_x) * (_x) ^ (n_IsConstant) <-- x^(n+1/2); +100 # (_x) ^ (n_IsConstant) * Sqrt(_x) <-- x^(n+1/2); +100 # Sqrt(_x) * (_x) <-- x^(3/2); +100 # (_x) * Sqrt(_x) <-- x^(3/2); + +105 # x_IsNumber * -(_y) <-- (-x)*y; +105 # (-(_x)) * (y_IsNumber) <-- (-y)*x; + +106 # _x * -(_y) <-- -(x*y); +106 # (- _x) * _y <-- -(x*y); + +107 # -( (-(_x))/(_y)) <-- x/y; +107 # -( (_x)/(-(_y))) <-- x/y; + + +250 # x_IsNumber * y_IsInfinity <-- Sign(x)*y; +250 # x_IsInfinity * y_IsNumber <-- Sign(y)*x; + + +/* Note: this rule MUST be past all the transformations on + * matrices, since they are lists also. + */ +230 # (aLeft_IsList * aRight_IsList)_(Length(aLeft)=Length(aRight)) <-- + Map("*",{aLeft,aRight}); +// fractions +242 # (x_IsInteger / y_IsInteger) * (v_IsInteger / w_IsInteger) <-- (x*v)/(y*w); +243 # x_IsInteger * (y_IsInteger / z_IsInteger) <-- (x*y)/z; +243 # (y_IsInteger / z_IsInteger) * x_IsInteger <-- (x*y)/z; + +400 # (_x) * (_x) <-- x^2; + +%/mathpiper + + +%mathpiper_docs,name="*",categories="Operators" +*CMD * --- arithmetic multiplication +*STD +*CALL + + x*y +Precedence: +*EVAL PrecedenceGet("*") + +*PARMS + +{x} and {y} -- objects for which arithmetic multiplication is defined + +*DESC + +The multiplication operator can work on integers, +rational numbers, complex numbers, vectors, matrices and lists. + +This operator is implemented in the standard math library (as opposed +to being built-in). This means that they can be extended by the user. + +*E.G. + +In> 2*3 +Result: 6; +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/caret_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/caret_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/caret_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/caret_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,118 @@ +%mathpiper,def="^" + +/* Faster version of raising power to 0.5 */ +50 # _x ^ (1/2) <-- Sqrt(x); +50 # (x_IsPositiveNumber ^ (1/2))_IsInteger(SqrtN(x)) <-- SqrtN(x); +58 # 1 ^ n_IsInfinity <-- Undefined; +59 # _x ^ 1 <-- x; +59 # 1 ^ _n <-- 1; +59 # x_IsZero ^ y_IsZero <-- Undefined; +60 # (x_IsZero ^ n_IsRationalOrNumber)_(n>0) <-- 0; +60 # (x_IsZero ^ n_IsRationalOrNumber)_(n<0) <-- Infinity; +// This is to fix: +// In> 0.0000^2 +// Result: 0.0000^2; +// In> 0.0^2/2 +// Result: 0.0^2/2; +//60 # (x_IsNumber ^ n_IsRationalOrNumber)_(x+1=1) <-- 0; + +59 # _x ^ Undefined <-- Undefined; +59 # Undefined ^ _x <-- Undefined; + +/* Regular raising to the power. */ +61 # Infinity ^ (y_IsNegativeNumber) <-- 0; +61 # (-Infinity) ^ (y_IsNegativeNumber) <-- 0; +//61 # x_IsPositiveNumber ^ y_IsPositiveNumber <-- PowerN(x,y); +//61 # x_IsPositiveNumber ^ y_IsNegativeNumber <-- (1/PowerN(x,-y)); +// integer powers are very fast +61 # x_IsPositiveNumber ^ y_IsPositiveInteger <-- MathIntPower(x,y); +61 # x_IsPositiveNumber ^ y_IsNegativeInteger <-- 1/MathIntPower(x,-y); +65 # (x_IsPositiveNumber ^ y_IsNumber)_InNumericMode() <-- Exp(y*Ln(x)); + +90 # (-_x)^m_IsEven <-- x^m; +91 # (x_IsConstant ^ (m_IsOdd / p_IsOdd))_(IsNegativeNumber(Re(N(Eval(x))))) <-- + -((-x)^(m/p)); +92 # (x_IsNegativeNumber ^ y_IsNumber)_InNumericMode() <-- Exp(y*Ln(x)); + + +70 # (_x ^ m_IsRationalOrNumber) ^ n_IsRationalOrNumber <-- x^(n*m); + +80 # (x_IsNumber/y_IsNumber) ^ n_IsPositiveInteger <-- x^n/y^n; +80 # (x_IsNumber/y_IsNumber) ^ n_IsNegativeInteger <-- y^(-n)/x^(-n); +80 # x_IsNegativeNumber ^ n_IsEven <-- (-x)^n; +80 # x_IsNegativeNumber ^ n_IsOdd <-- -((-x)^n); + + +100 # ((_x)*(_x ^ _m)) <-- x^(m+1); +100 # ((_x ^ _m)*(_x)) <-- x^(m+1); +100 # ((_x ^ _n)*(_x ^ _m)) <-- x^(m+n); + +100 # ((x_IsNumber)^(n_IsInteger/(_m)))_(n>1) <-- MathIntPower(x,n)^(1/m); + +100 # Sqrt(_n)^(m_IsEven) <-- n^(m/2); + +100 # Abs(_a)^n_IsEven <-- a^n; +100 # Abs(_a)^n_IsOdd <-- Sign(a)*a^n; + + +200 # x_IsMatrix ^ n_IsPositiveInteger <-- x*(x^(n-1)); +204 # (xlist_IsList ^ nlist_IsList)_(Length(xlist)=Length(nlist)) <-- + Map("^",{xlist,nlist}); +205 # (xlist_IsList ^ n_IsConstant)_(Not(IsList(n))) <-- + Map({{xx},xx^n},{xlist}); +206 # (_x ^ n_IsList)_(Not(IsList(x))) <-- Map({{xx},x^xx},{n}); +249 # x_IsInfinity ^ 0 <-- Undefined; +250 # Infinity ^ (_n) <-- Infinity; +250 # Infinity ^ (_x_IsComplex) <-- Infinity; +250 # ((-Infinity) ^ (n_IsNumber))_(IsEven(n)) <-- Infinity; +250 # ((-Infinity) ^ (n_IsNumber))_(IsOdd(n)) <-- -Infinity; + +250 # (x_IsNumber ^ Infinity)_(x> -1 And x < 1) <-- 0; +250 # (x_IsNumber ^ Infinity)_(x> 1) <-- Infinity; + +// these Magnitude(x)s should probably be changed to Abs(x)s + +250 # (x_IsComplex ^ Infinity)_(Magnitude(x) > 1) <-- Infinity; +250 # (x_IsComplex ^ Infinity)_(Magnitude(x) < -1) <-- -Infinity; +250 # (x_IsComplex ^ Infinity)_(Magnitude(x) > -1 And Magnitude(x) < 1) <-- 0; + +250 # (x_IsNumber ^ -Infinity)_(x> -1 And x < 1) <-- Infinity; +250 # (x_IsNumber ^ -Infinity)_(x< -1) <-- 0; +250 # (x_IsNumber ^ -Infinity)_(x> 1) <-- 0; + +255 # (x_IsComplex ^ Infinity)_(Abs(x) = 1) <-- Undefined; +255 # (x_IsComplex ^ -Infinity)_(Abs(x) = 1) <-- Undefined; + + + +400 # _x ^ 0 <-- 1; + +%/mathpiper + + +%mathpiper_docs,name="^",categories="Operators" +*CMD ^ --- arithmetic power +*STD +*CALL + + x^y +Precedence: +*EVAL PrecedenceGet("^") + +*PARMS + +{x} and {y} -- objects for which arithmetic operations are defined + +*DESC + +These are the basic arithmetic operations. They can work on integers, +rational numbers, complex numbers, vectors, matrices and lists. + +These operators are implemented in the standard math library (as opposed +to being built-in). This means that they can be extended by the user. + +*E.G. + +In> 2^3 +Result: 8; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/minus_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/minus_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/minus_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/minus_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,105 @@ +%mathpiper,def="-" + +/* Subtraction arity 1 */ + +//50 # -0 <-- 0; +51 # -Undefined <-- Undefined; +54 # - (- _x) <-- x; +55 # (- (x_IsNumber)) <-- SubtractN(0,x); +100 # _x - n_IsConstant*(_x) <-- (1-n)*x; +100 # n_IsConstant*(_x) - _x <-- (n-1)*x; + +110 # - (_x - _y) <-- y-x; +111 # - (x_IsNumber / _y) <-- (-x)/y; +LocalSymbols(x) +[ + 200 # - (x_IsList) <-- MapSingle("-",x); +]; + +/* Subtraction arity 2 */ +50 # x_IsNumber - y_IsNumber <-- SubtractN(x,y); +50 # x_IsNumber - y_IsNumber <-- SubtractN(x,y); +60 # Infinity - Infinity <-- Undefined; +100 # 0 - _x <-- -x; +100 # _x - 0 <-- x; +100 # _x - _x <-- 0; + +110 # _x - (- _y) <-- x + y; +110 # _x - (y_IsNegativeNumber) <-- x + (-y); +111 # (_x + _y)- _x <-- y; +111 # (_x + _y)- _y <-- x; +112 # _x - (_x + _y) <-- - y; +112 # _y - (_x + _y) <-- - x; +113 # (- _x) - _y <-- -(x+y); +113 # (x_IsNegativeNumber) - _y <-- -((-x)+y); +113 # (x_IsNegativeNumber)/_y - _z <-- -((-x)/y+z); + + +/* TODO move to this precedence everywhere? */ +LocalSymbols(x,y,xarg,yarg) +[ + 10 # ((x_IsList) - (y_IsList))_(Length(x)=Length(y)) <-- + [ + Map({{xarg,yarg},xarg-yarg},{x,y}); + ]; +]; + +240 # (x_IsList - y_IsNonObject)_Not(IsList(y)) <-- -(y-x); + +241 # (x_IsNonObject - y_IsList)_Not(IsList(x)) <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=Length(y),i++) + [ DestructiveInsert(result,i,x - y[i]); ]; + result; +]; + +250 # z_IsInfinity - Complex(_x,_y) <-- Complex(-x+z,-y); +250 # Complex(_x,_y) - z_IsInfinity <-- Complex(x-z,y); + +251 # z_IsInfinity - _x <-- z; +251 # _x - z_IsInfinity <-- -z; + +250 # Undefined - _y <-- Undefined; +250 # _x - Undefined <-- Undefined; +// fractions +210 # x_IsNumber - (y_IsNumber / z_IsNumber) <--(x*z-y)/z; +210 # (y_IsNumber / z_IsNumber) - x_IsNumber <--(y-x*z)/z; +210 # (x_IsNumber / v_IsNumber) - (y_IsNumber / z_IsNumber) <--(x*z-y*v)/(v*z); + +%/mathpiper + + +%mathpiper_docs,name="-",categories="Operators" +*CMD - --- arithmetic subtraction or negation +*STD +*CALL + + x-y +Precedence: left-side: +*EVAL PrecedenceGet("-") +, right-side: +*EVAL RightPrecedenceGet("-") + + -x + +*PARMS + +{x} and {y} -- objects for which subtraction is defined + +*DESC + +The subtraction operators can work on integers, +rational numbers, complex numbers, vectors, matrices and lists. + +These operators are implemented in the standard math library (as opposed +to being built-in). This means that they can be extended by the user. + +*E.G. + +In> 2-3 +Result: -1; +In> - 3 +Result: -3; +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/plus_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/plus_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/plus_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/plus_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,101 @@ +%mathpiper,def="+" + +/* Addition */ + +100 # + _x <-- x; + +50 # x_IsNumber + y_IsNumber <-- AddN(x,y); + +100 # 0 + _x <-- x; +100 # _x + 0 <-- x; +100 # _x + _x <-- 2*x; +100 # _x + n_IsConstant*(_x) <-- (n+1)*x; +100 # n_IsConstant*(_x) + _x <-- (n+1)*x; +101 # _x + - _y <-- x-y; +101 # _x + (- _y)/(_z) <-- x-(y/z); +101 # (- _y)/(_z) + _x <-- x-(y/z); +101 # (- _x) + _y <-- y-x; +102 # _x + y_IsNegativeNumber <-- x-(-y); +102 # _x + y_IsNegativeNumber * _z <-- x-((-y)*z); +102 # _x + (y_IsNegativeNumber)/(_z) <-- x-((-y)/z); +102 # (y_IsNegativeNumber)/(_z) + _x <-- x-((-y)/z); +102 # (x_IsNegativeNumber) + _y <-- y-(-x); +// fractions +150 # _n1 / _d + _n2 / _d <-- (n1+n2)/d; + +200 # (x_IsNumber + _y)_Not(IsNumber(y)) <-- y+x; +200 # ((_y + x_IsNumber) + _z)_Not(IsNumber(y) Or IsNumber(z)) <-- (y+z)+x; +200 # ((x_IsNumber + _y) + z_IsNumber)_Not(IsNumber(y)) <-- y+(x+z); +200 # ((_x + y_IsNumber) + z_IsNumber)_Not(IsNumber(x)) <-- x+(y+z); +// fractions +210 # x_IsNumber + (y_IsNumber / z_IsNumber) <--(x*z+y)/z; +210 # (y_IsNumber / z_IsNumber) + x_IsNumber <--(x*z+y)/z; +210 # (x_IsNumber / v_IsNumber) + (y_IsNumber / z_IsNumber) <--(x*z+y*v)/(v*z); + + +// 220 # + x_IsList <-- MapSingle("+",x); // this rule is never active + +220 # (xlist_IsList + ylist_IsList)_(Length(xlist)=Length(ylist)) <-- Map("+",{xlist,ylist}); + +SumListSide(_x, y_IsList) <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=Length(y),i++) + [ DestructiveInsert(result,i,x + y[i]); ]; + result; +]; + +240 # (x_IsList + _y)_Not(IsList(y)) <-- SumListSide(y,x); +241 # (_x + y_IsList)_Not(IsList(x)) <-- SumListSide(x,y); + +250 # z_IsInfinity + Complex(_x,_y) <-- Complex(x+z,y); +250 # Complex(_x,_y) + z_IsInfinity <-- Complex(x+z,y); + +251 # z_IsInfinity + _x <-- z; +251 # _x + z_IsInfinity <-- z; + + +250 # Undefined + _y <-- Undefined; +250 # _x + Undefined <-- Undefined; + +%/mathpiper + + + + +%mathpiper,scope="nobuild",subtype="test_suite" +//This fold is used to test the + operator. + Verify(3 + 2 , 5); +%/mathpiper + + + +%mathpiper_docs,name="+",categories="Operators" +*CMD + --- arithmetic addition +*STD +*CALL + + x+y + +x +Precedence: +*EVAL PrecedenceGet("+") + +*PARMS + +{x} and {y} -- objects for which arithmetic addition is defined + + +*DESC + +The addition operators can work on integers, +rational numbers, complex numbers, vectors, matrices and lists. + +These operators are implemented in the standard math library (as opposed +to being built-in). This means that they can be extended by the user. + +*E.G. + +In> 2+3 +Result: 5; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/slash_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/slash_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdarith/slash_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdarith/slash_operator.mpw 2011-04-14 16:07:08.000000000 +0000 @@ -0,0 +1,136 @@ +%mathpiper,def="/" + +/* Division */ + +50 # 0 / 0 <-- Undefined; + +52 # x_IsPositiveNumber / 0 <-- Infinity; +52 # x_IsNegativeNumber / 0 <-- -Infinity; +55 # (_x / y_IsNumber)_(IsZero(y)) <-- Undefined; +55 # 0 / _x <-- 0; +// unnecessary rule (see #100 below). TODO: REMOVE +//55 # x_IsNumber / y_IsNegativeNumber <-- (-x)/(-y); + +56 # (x_IsNonZeroInteger / y_IsNonZeroInteger)_(GcdN(x,y) > 1) <-- + [ + Local(gcd); + Bind(x,x); + Bind(y,y); + Bind(gcd,GcdN(x,y)); + QuotientN(x,gcd)/QuotientN(y,gcd); + ]; + +57 # ((x_IsNonZeroInteger * _expr) / y_IsNonZeroInteger)_(GcdN(x,y) > 1) <-- + [ + Local(gcd); + Bind(x,x); + Bind(y,y); + Bind(gcd,GcdN(x,y)); + (QuotientN(x,gcd)*expr)/QuotientN(y,gcd); + ]; + +57 # ((x_IsNonZeroInteger) / (y_IsNonZeroInteger * _expr))_(GcdN(x,y) > 1) <-- + [ + Local(gcd); + Bind(x,x); + Bind(y,y); + Bind(gcd,GcdN(x,y)); + QuotientN(x,gcd)/(QuotientN(y,gcd)*expr); + ]; + +57 # ((x_IsNonZeroInteger * _p) / (y_IsNonZeroInteger * _q))_(GcdN(x,y) > 1) <-- + [ + Local(gcd); + Bind(x,x); + Bind(y,y); + Bind(gcd,GcdN(x,y)); + (QuotientN(x,gcd)*p)/(QuotientN(y,gcd)*q); + ]; + +60 # (x_IsDecimal / y_IsNumber) <-- DivideN(x,y); +60 # (x_IsNumber / y_IsDecimal) <-- DivideN(x,y); +60 # (x_IsNumber / y_IsNumber)_(InNumericMode()) <-- DivideN(x,y); + + +90 # x_IsInfinity / y_IsInfinity <-- Undefined; +95 # x_IsInfinity / y_IsNumber <-- Sign(y)*x; +95 # x_IsInfinity / y_IsComplex <-- Infinity; + +90 # Undefined / _y <-- Undefined; +90 # _y / Undefined <-- Undefined; + + +100 # _x / _x <-- 1; +100 # _x / 1 <-- x; +100 # (_x / y_IsNegativeNumber) <-- -x/(-y); +100 # (_x / - _y) <-- -x/y; + +150 # (_x) / (_x) ^ (n_IsConstant) <-- x^(1-n); +150 # (_x) ^ (n_IsConstant) * (_x) <-- x^(n-1); +150 # Sqrt(_x) / (_x) ^ (n_IsConstant) <-- x^(1/2-n); +150 # (_x) ^ (n_IsConstant) / Sqrt(_x) <-- x^(n-1/2); +150 # (_x) / Sqrt(_x) <-- Sqrt(x); + +// fractions +200 # (_x / _y)/ _z <-- x/(y*z); +230 # _x / (_y / _z) <-- (x*z)/y; + +240 # (xlist_IsList / ylist_IsList)_(Length(xlist)=Length(ylist)) <-- + Map("/",{xlist,ylist}); + + +250 # (x_IsList / _y)_(Not(IsList(y))) <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=Length(x),i++) + [ DestructiveInsert(result,i,x[i] / y); ]; + result; +]; + +250 # (_x / y_IsList)_(Not(IsList(x))) <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=Length(y),i++) + [ DestructiveInsert(result,i,x/y[i]); ]; + result; +]; + +250 # _x / Infinity <-- 0; +250 # _x / (-Infinity) <-- 0; + + +400 # 0 / _x <-- 0; + +%/mathpiper + + +%mathpiper_docs,name="/",categories="Operators" +*CMD / --- arithmetic division +*STD +*CALL + + x/y +Precedence: +*EVAL PrecedenceGet("/") + +*PARMS + +{x} and {y} -- objects for which arithmetic division is defined + +*DESC + +The division operator can work on integers, +rational numbers, complex numbers, vectors, matrices and lists. + +This operator is implemented in the standard math library (as opposed +to being built-in). This means that they can be extended by the user. + +*E.G. + +In> 6/2 +Result: 3; + +*SEE %_v1 +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdopers/stdopers.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdopers/stdopers.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/initialization/stdopers/stdopers.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/initialization/stdopers/stdopers.mpw 2010-01-07 02:30:20.000000000 +0000 @@ -0,0 +1,122 @@ +%mathpiper,def="" + + +/* stdopers is loaded immediately after MathPiper is started. It contains + * the definitions of the infix operators, so the parser can already + * parse expressions containing these operators, even though the + * function hasn't been defined yet. + */ + +Infix("=",90); +Infix("And",1000); +RightAssociativeSet("And"); +Infix("Or", 1010); +Prefix("Not", 100); +Infix("<",90); +Infix(">",90); +Infix("<=",90); +Infix(">=",90); +Infix("!=",90); + +Infix(":=",10000); +RightAssociativeSet(":="); + +Infix("+",70); +Infix("-",70); +RightPrecedenceSet("-",40); +Infix("/",30); +Infix("*",40); +Infix("^",20); +LeftPrecedenceSet("^",19); //Added to make expressions like x^n^2 unambiguous. +RightAssociativeSet("^"); +Prefix("+",50); +Prefix("-",50); +RightPrecedenceSet("-",40); +Bodied("For",60000); +Bodied("Until",60000); +Postfix("++",5); +Postfix("--",5); +Bodied("ForEach",60000); +Infix("<<",10); +Infix(">>",10); +Bodied("Differentiate",60000); +Bodied("Deriv",60000); +Infix("X",30); +Infix(".",30); +Infix("o",30); +Postfix("!", 30); +Postfix("!!", 30); +Infix("***", 50); +Bodied("Integrate",60000); + +Bodied("Limit",60000); + +Bodied("EchoTime", 60000); + +Bodied("Repeat", 60000); + +Infix("->",600); + +/* functional operators */ +Infix(":",70); +RightAssociativeSet(":"); +Infix("@",600); +Infix("/@",600); +Infix("..",600); + +Bodied("Taylor",60000); +Bodied("Taylor1",60000); +Bodied("Taylor2",60000); +Bodied("Taylor3",60000); +Bodied("InverseTaylor",60000); + +Infix("<--",10000); +Infix("#",9900); + +Bodied("TSum",60000); +Bodied("TExplicitSum",60000); +Bodied("TD",5); /* Tell the MathPiper interpreter that TD is to be used as TD(i)f */ + +/* Operator to be used for non-evaluating comparisons */ +Infix("==",90); +Infix("!==",90); + +/* Operators needed for propositional logic theorem prover */ +Infix("=>",10000); /* implication, read as 'implies' */ + + +Bodied("if",5); +Infix("else",60000); +RightAssociativeSet("else"); +/* Bitwise operations we REALLY need. Perhaps we should define them + also as MathPiper operators? + */ +Infix("&",50); +Infix("|",50); +Infix("%",50); + +/* local pattern replacement operators */ +Infix("/:",20000); +Infix("/::",20000); +Infix("<-",10000); + +/* Operators used for manual layout */ +Infix("<>", PrecedenceGet("=")); +Infix("<=>", PrecedenceGet("=")); + +/* Operators for Solve: Where and AddTo */ +Infix("Where", 11000); +Infix("AddTo", 2000); + +Bodied("Function",60000); +Bodied("Macro",60000); + +Bodied(Assert, 60000); + +// Defining very simple functions, in scripts that can be converted to plugin. +Bodied("Defun",0); + + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/AntiDeriv.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/AntiDeriv.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/AntiDeriv.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/AntiDeriv.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,285 @@ +%mathpiper,def="AntiDeriv" + +//todo:tk:this file need to be broken down further. + +//tk:this code was moved here from Integrate.mpw because it was causing a +// "rulebase with this arity already defined" error. +//hso:but the Rulebase line causes hang when processing in fold +//Rulebase("IntegrateMultiplicative",{var,from,a,b}); + +//Retract("AntiDeriv",*); +//Retract("IntFunc",*); + + +//////////////////////////////////////////////// +// +// Anti-derivative of a univariate polynomial +// +//////////////////////////////////////////////// +5 # AntiDeriv(_var, poly_CanBeUni(var) ) + <-- NormalForm(AntiDeriv(var,`MakeUni(@poly,@var))); +5 # AntiDeriv(_var,UniVariate(_var,_first,_coefs)) <-- +[ + Local(result,i); + result:=FlatCopy(coefs); + For(i:=1,i<=Length(result),i++) + [ + result[i]:= result[i]/(first+i); + ]; + UniVariate(var,first+1,result); +]; + + +//////////////////////////////////////////////// +// +// Standard additive properties of integration. +// +//////////////////////////////////////////////// +10 # AntiDeriv(_var,_x + _y) <-- AntiDeriv(var,x) + AntiDeriv(var,y); +10 # AntiDeriv(_var,_x - _y) <-- AntiDeriv(var,x) - AntiDeriv(var,y); +10 # AntiDeriv(_var, - _y) <-- - AntiDeriv(var,y); + +10 # AntiDeriv(_var,_x/c_IsFreeOf(var) )_(HasExpr(x,var)) <-- AntiDeriv(var,x)/c; +10 # AntiDeriv(_var,c_IsFreeOf(var)/_x )_(HasExpr(x,var) And c!= 1) + <-- c*AntiDeriv(var,1/x); + + +//////////////////////////////////////////////// +// +// Multiplying a polynomial with another (integrable) +// function, Integrate by parts. +// +//////////////////////////////////////////////// +1570 # IntegrateMultiplicative(_var,(exy_CanBeUni(var)) * _exx,_dummy1,_dummy2) + <-- IntByParts(var,exy*exx,AntiDeriv(var,exx)); +1570 # IntegrateMultiplicative(_var,_exx * (exy_CanBeUni(var)),_dummy1,_dummy2) + <-- IntByParts(var,exy*exx,AntiDeriv(var,exx)); +10 # IntByParts(_var,_exy * _exx,Integrate(_var)(_something)) <-- + `Hold(AntiDeriv(@var,((@exy)*(@exx)))); +20 # IntByParts(_var,_exy * _exx,_anti)_(Not IsFreeOf(anti,exx)) <-- + `Hold(AntiDeriv(@var,((@exy)*(@exx)))); +30 # IntByParts(_var,_exy * _exx,_anti) <-- + [ + Local(cf); + cf:=anti*Deriv(var)exy; +// Echo({exy*anti,exy*exx,cf}); + exy*anti - `(AntiDeriv(@var,@cf)); + ]; + +//////////////////////////////////////////////// +// +// Rational functions: f(x)/g(x) where f and g are +// polynomials. +// +//////////////////////////////////////////////// +1570 # IntegrateMultiplicative(_var,(exy_CanBeUni(var)) / (exx_CanBeUni(var)),_dummy1,_dummy2) <-- + IntRat(var,exy/exx,MakeUni(exy,var),MakeUni(exx,var)); + +10 # IntRat(_var,_exy / _exx,_exyu,_exxu)_ + (Degree(exyu) > Degree(exxu) Or Degree(Gcd(exyu,exxu)) > 0) <-- + [ + Local(gcd); + gcd:=Gcd(exxu,exyu); + exyu:=Quotient(exyu,gcd); + exxu:=Quotient(exxu,gcd); + AntiDeriv(var,NormalForm(Quotient(exyu,exxu))) + + AntiDeriv(var,NormalForm(Modulo(exyu,exxu))/NormalForm(exxu)); + ]; + +11 # IntRat(_var,_exy / _exx,_exyu,_exxu)_ + (Degree(exxu,var) > 1 And LeadingCoef(exxu)=1 And + IsNumericList(Coef(exxu,var,0 .. Degree(exxu)))) <-- +[ + Local(ee); + ee:=Apart(exy/exx,var); + `AntiDeriv(@var,@ee); +]; + + +20 # IntRat(_var,_exy / _exx,_exyu,_exxu) <-- + `Hold(AntiDeriv(@var,((@exy)/(@exx)))); + + +30 # AntiDeriv(_var,Deriv(_var)(_expr)) <-- expr; + +//////////////////////////////////////////////// +// +// No simple form, try something else +// +//////////////////////////////////////////////// +100 # AntiDeriv(_var,_exp) <-- +[ + IntegrateMultiplicative(var,exp,a,b); +]; + + +//////////////////////////////////////////////// +// +// Special anti-derivatives can be added here. +// +//////////////////////////////////////////////// + +// integrating expressions containing if: +10 # IntegrateMultiplicative(_var,if(_cond)(_body),_a,_b) + <-- + [ + body := AntiDeriv(var,body); + `Hold(if(@cond)(@body)); + ]; +// integrating expressions containing else +10 # IntegrateMultiplicative(_var,(_left) else (_right),_a,_b) + <-- + [ + left := AntiDeriv(var,left); + right := AntiDeriv(var,right); + `Hold( (@left) else (@right) ); + ]; + + +//////////////////////////////////////////////// +// +// Could not find anti-derivative, return unsimplified +// +//////////////////////////////////////////////// +1600 # IntegrateMultiplicative(_var,_exp,_a,_b) <-- `Hold(Integrate(@var)(@exp)); + +//////////////////////////////////////////////// +// +// IntFunc declares the anti-derivative of a function +// that has one argument. +// Calling sequence: IntFunc(variable,from,to); +// Example: IntFunc(x,Cos(_x),Sin(x)); +// +//////////////////////////////////////////////// +LocalSymbols(intpred) +[ + intpred := 50; + IntFunc(_vr,_from,_to) <-- + [ + `((@intpred) # IntegrateMultiplicative(_var,@from,_dummy1,_dummy2)_MatchLinear(var,@vr) <-- (@to)/Matched'a()); + intpred++; + ]; +]; + + +IntPureSquare(_vr,_from,_sign2,_sign0,_to) <-- +[ + `(50 # IntegrateMultiplicative(_var,@from,_dummy1,_dummy2)_MatchPureSquared(var,@sign2,@sign0,@vr) <-- (@to)); +]; + + + + +//////////////////////////////////////////////// +// +// Declaration of the anti-derivatives of a few analytic functions +// +//////////////////////////////////////////////// + + +IntFunc(x,Sqrt(_x),(2*Sqrt(x)^(3))/3); +IntFunc(x,1/Sqrt(_x),2*Sqrt(x)); +IntFunc(x,1/_x^(_n),x^(1-n)/(1-n) ); +IntFunc(x,Sin(_x),-Cos(x)); +IntFunc(x,1/Sin(_x), Ln( 1/Sin(x) - Cos(x)/Sin(x) ) ); +IntFunc(x,Cos(_x),Sin(x)); +IntFunc(x,1/Cos(_x),Ln(1/Cos(x)+Tan(x))); +IntFunc(x,Tan(_x),-Ln(Cos(x))); +IntFunc(x,1/Tan(_x),Ln(Sin(x)) ); +IntFunc(x,Cos(_x)/Sin(_x),Ln(Sin(x))); +IntFunc(x,Exp(_x),Exp(x)); +IntFunc(x,(C_IsFreeOf(var))^(_x),C^x/Ln(C)); +// we don't need Ln(Abs(x)) +IntFunc(x,num_IsFreeOf(var) / (_x),num*Ln(x)); +IntFunc(x,Ln(_x),x*Ln(x)-x); +// where did these 1+1's come from? +IntFunc(x,(_x)*Ln(_x),(1/(1+1))*x^(1+1)*Ln(x) - (1/(1+1)^2)*x^(1+1) ); +IntFunc(x,Ln(_x)*(_x),(1/(1+1))*x^(1+1)*Ln(x) - (1/(1+1)^2)*x^(1+1) ); + +IntFunc(x,1/Sin(_x)^2,-Cos(x)/Sin(x) ); +IntFunc(x,1/Cos(_x)^2,Tan(x) ); +IntFunc(x,1/(Sin(_x)*Tan(_x)),-1/Sin(x)); +IntFunc(x,Tan(_x)/Cos(_x),1/Cos(x)); +IntFunc(x,1/Sinh(_x)^2,-1/Tanh(x)); +IntFunc(x,1/Cosh(_x)^2,Tanh(x)); +IntFunc(x,1/(Sinh(_x)*Tan(_x)),-1/Sinh(x)); +IntFunc(x,Tanh(_x)/Cosh(_x),-1/Cosh(x)); + +IntFunc(x,1/Sqrt(m_IsFreeOf(x)-_x^2),ArcSin(x/Sqrt(m)) ); + +IntFunc(x,Exp(n_IsNumber*_x)*Sin(m_IsNumber*_x),Exp(n*x)*(n*Sin(m*x)- m*Cos(m*x))/(m^2+n^2) ); + +// n>0 +IntFunc(x,Ln(_x)*(_x)^n_IsNumber,(1/(n+1))*x^(n+1)*Ln(x) - (1/(n+1)^2)*x^(n+1) ); + +// n>0 +IntFunc(x,Ln(A_IsNumber*_x)*(_x)^n_IsNumber,(1/(n+1))*x^(n+1)*Ln(A*x) - (1/(n+1)^2)*x^(n+1) ); + +IntFunc(x,Sin(Ln(_x)),x*Sin(Ln(x))/2 - x*Cos(Ln(x))/2 ); + + +//This is a bug fix which was posted on the Yacas list by Alberto González Palomo on 10/5/2009. +//IntFunc(x,Cos(Ln(_x)),x*Sin(Ln(x))/2 - x*Cos(Ln(x))/2 ); +IntFunc(x,Cos(Ln(_x)),x*Sin(Ln(x))/2 + x*Cos(Ln(x))/2 ); + +IntFunc(x,1/((_x)*Ln(_x)),Ln(Ln(x))); + +IntFunc(x,(_x)^(-1),Ln(x)); + +IntFunc(x,(_x)^(n_IsFreeOf(x)),x^(n+1)/(n+1)); +IntFunc(x,C_IsFreeOf(x)*(_x)^(n_IsFreeOf(x)),C*x^(n+1)/(n+1)); +IntFunc(x,C_IsFreeOf(x)/(D_IsFreeOf(x)*(_x)^(n_IsFreeOf(x))),(C/D)*x^(1-n)/(1-n)); +IntFunc(x,Sinh(_x),Cosh(x)); +IntFunc(x,Sinh(_x)^2,Sinh(2*x)/4 - x/2); +IntFunc(x,1/Sinh(_x),Ln(Tanh(x/2))); +IntFunc(x,Cosh(_x),Sinh(x)); +IntFunc(x,Cosh(_x)^2,Sinh(2*x)/4 + x/2); +IntFunc(x,1/Cosh(_x),ArcTan(Sinh(x))); +IntFunc(x,Tanh(_x),Ln(Cosh(x))); +IntFunc(x,Tanh(_x)/Cosh(_x),-1/Cosh(x)); +IntFunc(x,1/Cosh(_x)^2,Tanh(x)); +//IntFunc(x,1/Sech(_x)*Coth(_x),-1/Sinh(x)); +IntFunc(x,1/Tanh(_x),Ln(Sinh(x))); + +IntFunc(x,Abs(_x),Abs(x)*x/2); // not 2*a + +IntFunc(x,ArcTan(_x),x*ArcTan(x) - Ln(x^2 + 1)/2); +//IntFunc(x,ArcSin(_x),(x*ArcSin(x)) + Sqrt(1-x^2) ); +IntFunc(x,ArcCos(_x),x*ArcCos(x) - Sqrt(1-x^2) ); + +IntFunc(x,ArcTanh(_x),x*ArcTanh(x) + Ln(1-x^2)/2 ); +IntFunc(x,ArcSinh(_x),x*ArcSinh(x) - Sqrt(x^2 + 1) ); +IntFunc(x,ArcCosh(_x),x*ArcCosh(x) - Sqrt(x-1)*Sqrt(x+1) ); + + +// n^2 > x^2 +//IntFunc(x,num_IsFreeOf(var)/(-(_x)^2 + n_IsNumber),num*ArcTanh(x/Sqrt(n))/n); + +// x^2 > n^2 +//IntFunc(x,num_IsFreeOf(var)/((_x)^2 - n_IsNumber),num * -ArcCoth(x/Sqrt(n))/Sqrt(n)); + +// n^2 > x^2 +//IntFunc(x,num_IsFreeOf(var)/Sqrt(n_IsNumber - (_x)^2),num*ArcSin(x/Sqrt(n))); + +// previous code is killing this.... +IntFunc(x,num_IsFreeOf(var)/(A_IsNumber + B_IsNumber*(_x))^2,-num/(A*b + B^2*x)); + +// Code works now? +IntFunc(x,num_IsFreeOf(var)/(n_IsNumber + m_IsNumber*Exp(p_IsNumber*(_x))),num*x/n - num*Ln(n + m*Exp(p*x))/(n*p)); +IntFunc(x,num_IsFreeOf(var)/(m_IsNumber*Exp(p_IsNumber*(_x)) + n_IsNumber),num*x/n - num*Ln(n + m*Exp(p*x))/(n*p)); + +// note:hso: removed erroneous "a" in denominator of function below +IntPureSquare(x,num_IsFreeOf(var)/(_x),1,1,(num/(Sqrt(Matched'b()/Matched'a())))*ArcTan(var/Sqrt(Matched'b()/Matched'a()))); + +///// Integrating Special Functions +IntFunc(x,Erf(_x), x*Erf(x)+ 1/(Exp(x^2)*Sqrt(Pi)) ); + +UnFence("IntegrateMultiplicative",4); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/Integrate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/Integrate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/Integrate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/Integrate.mpw 2011-04-24 07:27:36.000000000 +0000 @@ -0,0 +1,192 @@ +%mathpiper,def="Integrate" + +//todo:tk:this file need to be broken down further. + + +10# (Integrate(_var)(expr_IsList)) + <-- Map("Integrate",{FillList(var,Length(expr)),expr}); +20 # (Integrate(_var)(_expr)) <-- IntSub(var,expr,AntiDeriv(var,IntClean(var,expr))); + +20 # (Integrate(_var, optionsList_IsList)(_expr)) <-- +[ + Local(result); + + optionsList := OptionsToAssociativeList(optionsList); + + result := Integrate(var) expr; + + If( optionsList["logAbs"] = "True", result := ( result /: {Ln(_x) <- Ln(Abs(x))}) ); + + result; +]; + + +10 # IntSub(_var,_expr,Integrate(_var)(_expr2)) <-- + `Hold(Integrate(@var)(@expr)); +20 # IntSub(_var,_expr,_result) <-- result; // + UniqueConstant(); + +//////////////////////////////////////////////// +// +// Integrate over a range +// +//////////////////////////////////////////////// +10# (Integrate(_var,_from,_to)(expr_IsList)) + <-- Map("Integrate",{FillList(var,Length(expr)), + FillList(from,Length(expr)), + FillList(to,Length(expr)), + expr}); + +20 # (Integrate(_var,_from,_to)(_expr)) + <-- defIntegrate(var,from,to,expr,a,b); + + +20 # (Integrate(_var,_from,_to,optionsList_IsList)(_expr)) <-- +[ + Local(result); + + optionsList := OptionsToAssociativeList(optionsList); + + result := Integrate(var,from,to) expr; + + If( optionsList["logAbs"] = "True", result := ( result /: {Ln(_x) <- Ln(Abs(x))}) ); + + result; +]; + +//////////////////////////////////////////////// +// +// separate rules can be added here for specific integrals +// to defIntegrate +// +//////////////////////////////////////////////// + +10 # defIntegrate(_var,_from,_to,_expr,_a,_b)_(from = -to And IsOddFunction(expr,var)) <-- 0; + +// We need to define this case (integrating from 0 to 0 over an even function) +// explicitly, otherwise the integration ends up going in to infinite recursion. +// Extended it a little bit more, since if you are integrating from A to A, +// then the result is obviously zero. There are perhaps situations where +// this does not work, where we need to simplify (to-from) first. A naive +// implementation caused a test to fail. + +10 # defIntegrate(_var,_from,_from,_expr,_a,_b) <-- 0; + +12 # defIntegrate(_var,_from,_to,_expr,_a,_b)_(from = -to And IsEvenFunction(expr,var)) + <-- 2*defIntegrate(var,0,to,expr,a,b); + +100 # defIntegrate(_var,_from,_to,_expr,_a,_b)_(Type(AntiDeriv(var,IntClean(var,expr))) != "AntiDeriv") + <-- IntegrateRange(var,expr,from,to,AntiDeriv(var,IntClean(var,expr))); + +101 # defIntegrate(_var,_from,_to,_expr,_a,_b) + <-- `Hold(Integrate(@var,@from,@to)(@expr)); +// <-- IntegrateRange(var,expr,from,to,AntiDeriv(var,expr)); + + +//////////////////////////////////////////////// +// +// No anti-derivative found, return unavaluated. +// +//////////////////////////////////////////////// +10 # IntegrateRange(_var,_expr,_from,_to,Integrate(_var)_expr2) + <-- `Hold(Integrate(@var,@from,@to)@expr); + +//////////////////////////////////////////////// +// +// Anti-derivative found, return result. +// +//////////////////////////////////////////////// +20 # IntegrateRange(_var,_expr,_from,_to,_antideriv) + <-- `(@antideriv Where @var == @to) - `(@antideriv Where @var == @from); + +//////////////////////////////////////////////// +// +// IntClean cleans up an expression before passing +// it on to integration. This function normalizes +// an expression in a way desirable for integration. +// TrigSimpCombine, for instance, expands expressions +// containing trigonometric functions so that they are +// additive as opposed to multiplicative. +// +// If the expression doesn't contain the variable, +// just return it as-is. This fixes: +// In> Integrate(x) z^100 +// +// If the expression can be considered to be a sum +// of terms in var, then avoid premature simplification. +//////////////////////////////////////////////// +10 # IntClean(_var,_expr) <-- +[ + if( IsFreeOf(var,expr) Or IsSumOfTerms(var,expr) )[ + expr; + ] else if ( HasFunc(expr,Sin) Or HasFunc(expr,Cos) )[ + Simplify(TrigSimpCombine(expr)); + ] else [ + Simplify(expr); + ]; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Integrate",categories="User Functions;Calculus Related (Symbolic)" +*CMD Integrate --- integration + +*STD +*CALL + Integrate(var, x1, x2) expr + Integrate(var) expr + Integrate(var, {optionsList}) expr + Integrate(var, x1, x2, {optionsList}) expr + +*PARMS + +{var} -- atom, variable to integrate over + +{optionsList} -- a list which contains options that affect integration + +{x1} -- first point of definite integration + +{x2} -- second point of definite integration + +{expr} -- expression to integrate + +*DESC + +This function integrates the expression {expr} with respect to the +variable {var}. The first calling format is used to perform +definite integration: the integration is carried out from $var=x1$ +to $var=x2$. The second form is for indefinite integration. + +Some simple integration rules have currently been +implemented. Polynomials, some quotients of polynomials, +trigonometric functions and their inverses, hyperbolic functions +and their inverses, {Exp}, and {Ln}, and products of these +functions with polynomials can be integrated. + + + +{Options}: + +{logAbs} -- For results which contain logs, the result is given in terms of Ln(Abs(...)) +if logAbs is True, but in terms of Ln(...) if logAbs is not set or is set to anything other than True. + + +*E.G. +In> Integrate(x,a,b) Cos(x) +Result: Sin(b)-Sin(a); + +In> Integrate(x) Cos(x) +Result: Sin(x); + +In> Integrate(x) 1/x; +Result> Ln(x) + +In> Integrate(x, {logAbs -> True}) 1/x; +Result> Ln(Abs(x)) + +In> Integrate(x, a, b, {logAbs -> True})1/x; +Result> Ln(Abs(b))-Ln(Abs(a)) + +*SEE Differentiate, UniqueConstant +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/MatchLinear.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/MatchLinear.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/MatchLinear.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/MatchLinear.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,114 @@ +%mathpiper,def="MatchLinear;MatchPureSquared" + +/* +todo:tk:MatchPureSquared() is in this file because it is grouped with MatchLinear in a +LocalSymbols() block. +*/ + +/* Def file definitions +MatchPureSquared +*/ + +/** MatchLinear(variable,expression) + */ +LocalSymbols(a,b)[ + +10 # MatchLinear(var_IsAtom,expr_CanBeUni(var)) <-- +[ + Bind(expr,MakeUni(expr,var)); + MatchLinear(expr); +]; +20 # MatchLinear(_var,_expr) <-- False; + +10 # MatchLinear(_expr)_(Degree(expr,var)<2) <-- +[ + Check(IsUniVar(expr), "Argument", PipeToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"})); + +//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way? +// Check(a = Hold(a), "Argument", PipeToString()(Echo({"Found bound variable a which should have been unbound, in MatchLinear: ", a, "=", Eval(a)}))); +// Check(b = Hold(b), "Argument", PipeToString()(Echo({"Found bound variable b which should have been unbound, in MatchLinear: ", b, "=", Eval(b)}))); + + a := Coef(expr,1); + b := Coef(expr,0); + True; +]; +20 # MatchLinear(_expr) <-- False; +UnFence("MatchLinear",1); +UnFence("MatchLinear",2); + +/** MatchPureSquared(variable,expression) - matches expressions + * of the form a*x^2+b. + */ +10 # MatchPureSquared(var_IsAtom,_sign2,_sign0,expr_CanBeUni(var)) <-- +[ + Bind(expr,MakeUni(expr,var)); + MatchPureSquared(expr,sign2,sign0); +]; +20 # MatchPureSquared(_var,_sign2,_sign0,_expr) <-- False; + +10 # MatchPureSquared(_expr,_sign2,_sign0)_(Degree(expr,var)=2 And + Coef(expr,1) = 0 And + IsNumber(Coef(expr,0)) And + IsNumber(Coef(expr,2)) And + Coef(expr,0)*sign0 > 0 And + Coef(expr,2)*sign2 > 0 + ) <-- +[ + Check(IsUniVar(expr), "Argument", PipeToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"})); +//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way? +// Check(a = Hold(a), "Invariant", "Found bound variable which should have been unbound, in MatchLinear"); +// Check(b = Hold(b), "Invariant", "Found bound variable which should have been unbound, in MatchLinear"); + a := Coef(expr,2); + b := Coef(expr,0); + True; +]; +20 # MatchPureSquared(_expr,_sign2,_sign0) <-- False; +UnFence("MatchPureSquared",3); +UnFence("MatchPureSquared",4); + +Matched'a() := a; +Matched'b() := b; + + + +]; // LocalSymbols a,b + + +%/mathpiper + + + +%mathpiper_docs,name="MatchLinear",categories="User Functions;Predicates" +*CMD MatchLinear --- match an expression to a polynomial of degree one in a variable +*STD +*CALL + MatchLinear(x,expr) + +*PARMS + +{x} -- variable to express the univariate polynomial in + +{expr} -- expression to match + +*DESC + +{MatchLinear} tries to match an expression to a linear (degree less than +two) polynomial. The function returns {True} if it could match, and +it stores the resulting coefficients in the variables "{a}" and "{b}" +as a side effect. The function calling this predicate should declare +local variables "{a}" and "{b}" for this purpose. +{MatchLinear} tries to match to constant coefficients which don't +depend on the variable passed in, trying to find a form "{a*x+b}" +with "{a}" and "{b}" not depending on {x} if {x} is given as the variable. + +*E.G. + +In> MatchLinear(x,(R+1)*x+(T-1)) +Result: True; +In> {a,b}; +Result: {R+1,T-1}; +In> MatchLinear(x,Sin(x)*x+(T-1)) +Result: False; + +*SEE Integrate +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/integrate/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/integrate/om/om.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper,def="" + +// From code.mpi.def: +OMDef( "Integrate", "calculus1","defint", // Same argument reordering as Sum. + { $, _2 .. _3, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }, + { $, _{2,2,1}, _{1,1}, _{1,2}, _{2,3} } + ); +OMDef( "AntiDeriv", mathpiper,"AntiDeriv" ); + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Assert.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Assert.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Assert.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Assert.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,99 @@ +%mathpiper,def="Assert" + +/// post an error if assertion fails +(Assert(_error'class, _error'object) _predicate) <-- +[ + CheckErrorTableau(); + If(IsEqual(predicate, True), // if it does not evaluate to True, it's an error + True, + [ // error occurred, need to post error'object + DestructiveAppend(GetErrorTableau(), {error'class, error'object}); + False; + ] + ); +]; + +/// interface +(Assert(_error'class) _predicate) <-- Assert(error'class, True) predicate; + +/// interface +(Assert() _predicate) <-- Assert("generic", True) predicate; + +%/mathpiper + + + +%mathpiper_docs,name="Assert",categories="Programmer Functions;Error Reporting",access="private" +*CMD Assert --- signal "soft" custom error +*STD +*CALL + Assert("str", expr) pred + Assert("str") pred + Assert() pred +Precedence: +*EVAL PrecedenceGet("Assert") + +*PARMS + +{pred} -- predicate to check + +{"str"} -- string to classify the error + +{expr} -- expression, error object + +*DESC + +{Assert} is a global error reporting mechanism. It can be used to check for +errors and report them. An error is considered to occur when the predicate +{pred} evaluates to anything except {True}. In this case, the function returns +{False} and an error object is created and posted to the global error tableau. +Otherwise the function returns {True}. + +Unlike the "hard" error function {Check}, the function {Assert} does not stop +the execution of the program. + +The error object consists of the string {"str"} and an arbitrary +expression {expr}. The string should be used to classify the kind of error that +has occurred, for example "domain" or "format". The error object can be any expression that might be useful for handling the error later; +for example, a list of erroneous values and explanations. +The association list of error objects is currently obtainable through +the function {GetErrorTableau()}. + +If the parameter {expr} is missing, {Assert} substitutes {True}. If both optional parameters {"str"} and {expr} are missing, {Assert} creates an error of class {"generic"}. + +Errors can be handled by a +custom error handler in the portion of the code that is able to handle a certain class of +errors. The functions {IsError}, {GetError} and {ClearError} can be used. + +Normally, all errors posted to the error tableau during evaluation of an expression should +be eventually printed to the screen. This is the behavior of prettyprinters +{DefaultPrint}, {Print}, {PrettyForm} and {TeXForm} (but not of the +inline prettyprinter, which is enabled by default); they call +{DumpErrors} after evaluating the expression. + +*E.G. + +In> Assert("bad value", "must be zero") 1=0 +Result: False; +In> Assert("bad value", "must be one") 1=1 +Result: True; +In> IsError() +Result: True; +In> IsError("bad value") +Result: True; +In> IsError("bad file") +Result: False; +In> GetError("bad value"); +Result: "must be zero"; +In> DumpErrors() + Error: bad value: must be zero +Result: True; +No more errors left: +In> IsError() +Result: False; +In> DumpErrors() +Result: True; + +*SEE IsError, DumpErrors, Check, GetError, ClearError, ClearErrors, GetErrorTableau + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/DefaultPrint.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/DefaultPrint.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/DefaultPrint.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/DefaultPrint.mpw 2010-07-23 05:26:16.000000000 +0000 @@ -0,0 +1,14 @@ +%mathpiper,def="DefaultPrint" + +/// The new default pretty-printer: DefaultPrint +Function("DefaultPrint", {x}) +[ + DumpErrors(); + WriteString("Result: "); + Write(x); + WriteString("; +"); +]; +HoldArgument("DefaultPrint", x); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/DumpErrors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/DumpErrors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/DumpErrors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/DumpErrors.mpw 2010-12-16 03:29:28.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="DumpErrors" + +/// print all errors and clear the tableau +DumpErrors() <-- +[ + Local(error'object, error'word); + CheckErrorTableau(); + ForEach(error'object, GetErrorTableau()) + [ // error'object might be e.g. {"critical", {"bad bad", -1000}} + If( + IsList(error'object), + [ + If( // special case: error class "warning" + Length(error'object) > 0 And error'object[1] = "warning", + [ + error'word := "Warning"; + error'object[1] := ""; // don't print the word "warning" again + ], + error'word := "Error: " // important hack: insert ": " here but not after "Warning" + ); + + If( // special case: {"error'class", True} + Length(error'object)=2 And error'object[2]=True, + Echo(error'word, error'object[1]), + [ + Echo(error'word, error'object[1], ": ", + PrintList(Rest(error'object))); + ] + ); + ], + // error'object is not a list: just print it + Echo("Error: ", error'object) + ); + ]; + ClearErrors(); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="DumpErrors",categories="Programmer Functions;Error Reporting",access="private" +*CMD DumpErrors --- simple error handlers +*STD +*CALL + DumpErrors() + +*DESC + +{DumpErrors} is a simple error handler for the global error reporting mechanism. It prints all errors posted using {Assert} and clears the error tableau. + +*SEE Assert, IsError, ClearErrors + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Echo.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Echo.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Echo.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Echo.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,104 @@ +%mathpiper,def="Echo" + +//Retract("EchoInternal",*); + +10 # EchoInternal(string_IsString) <-- +[ + WriteString(string); +]; + +20 # EchoInternal(_item) <-- +[ + Write(item);Space(); +]; + + + + + + +//Retract("Echo",*); + +RulebaseListed("Echo",{firstParameter, parametersList}); + +//Handle no option call. +5 # Echo(_firstParameter) <-- Echo(firstParameter, {}); + + +//Main routine. It will automatically accept 1 or more option calls because the +//options come in a list. +10 # Echo(_firstParameter, parametersList_IsList) <-- +[ + EchoInternal(firstParameter); + ForEach(item,parametersList) EchoInternal(item); + NewLine(); + +]; + + +//Handle a single option call because the option does not come in a list for some reason. +20 # Echo(_firstParameter, _secondParameter) <-- Echo(firstParameter, {secondParameter}); + + +//No argument Echo simply prints a newline. +Echo() := NewLine(); + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Echo",categories="User Functions;Input/Output" +*CMD Echo --- high-level printing routine +*STD +*CALL + Echo(item,item,item,...) + +*PARMS + +{item} -- the items to be printed + + +*DESC + +If passed a single item, {Echo} will evaluate it and print it to the +current output, followed by a newline. If {item} is a string, it is +printed without quotation marks. + +If {Echo} is called with a variable number of arguments, they will all +be printed with spaces inbetween them and finally a newline will be printed. + +If no arguments are passed to {Echo}, it will simply output a newline. + +{Echo} always returns {True}. + +*E.G. +In> Echo(5+3); +Result: True +Side Effects: +8 + + +In> Echo("The square of two is ", 2*2); +Result: True +Side Effects: +The square of two is 4 + + +In> Echo({a,b,c}); +Result: True +Side Effects: +{a,b,c} + +*SEE PrettyForm, Write, WriteString, RulebaseListed +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/GetErrorTableau.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/GetErrorTableau.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/GetErrorTableau.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/GetErrorTableau.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,112 @@ +%mathpiper,def="GetErrorTableau;ClearErrors;GetError" + +/* def file definitions +ClearErrors +GetError +*/ + +////////////////////////////////////////////////// +/// ErrorTableau, Assert, IsError --- global error reporting +////////////////////////////////////////////////// + +LocalSymbols(ErrorTableau) [ + + /// global error tableau. Its entries do not have to be lists. + Bind(ErrorTableau, {}); + + GetErrorTableau() := ErrorTableau; + + ClearErrors() <-- Bind(ErrorTableau, {}); + + /// aux function to check for corrupt tableau + CheckErrorTableau() <-- + If( + Not IsList(ErrorTableau), + Bind(ErrorTableau, {{"general", "corrupted ErrorTableau"}}) + ); + +]; // LocalSymbols(ErrorTableau) + + +/// obtain error object +GetError(error'class_IsString) <-- +[ + Local(error); + error := GetErrorTableau()[error'class]; + If( + error != Empty, + error, + False + ); +]; + + +/// delete error +ClearError(error'class_IsString) <-- AssocDelete(GetErrorTableau(), error'class); + +%/mathpiper + + + + +%mathpiper_docs,name="ClearErrors",categories="Programmer Functions;Error Reporting",access="private" +*CMD ClearErrors --- simple error handlers +*STD +*CALL + ClearErrors() + +*DESC + +{ClearErrors} is a trivial error handler that does nothing except it clears the tableau. + +*SEE Assert, IsError, DumpErrors + +%/mathpiper_docs + + + + +%mathpiper_docs,name="GetError;ClearError;GetErrorTableau",categories="Programmer Functions;Error Reporting",access="private" +*CMD GetError --- custom errors handlers +*CMD ClearError --- custom errors handlers +*CMD GetErrorTableau --- custom errors handlers +*STD +*CALL + GetError("str") + ClearError("str") + GetErrorTableau() + +*PARMS + +{"str"} -- string to classify the error + +*DESC + +These functions can be used to create a custom error handler. + +{GetError} returns the error object if a custom error of class {"str"} has been +reported using {Assert}, or {False} if no errors of this class have been +reported. + +{ClearError("str")} deletes the same error object that is returned by +{GetError("str")}. It deletes at most one error object. It returns {True} if an +object was found and deleted, and {False} otherwise. + +{GetErrorTableau()} returns the entire association list of currently reported errors. + +*E.G. + +In> x:=1 +Result: 1; +In> Assert("bad value", {x,"must be zero"}) x=0 +Result: False; +In> GetError("bad value") +Result: {1, "must be zero"}; +In> ClearError("bad value"); +Result: True; +In> IsError() +Result: False; + +*SEE IsError, Assert, Check, ClearErrors + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/IsError.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/IsError.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/IsError.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/IsError.mpw 2010-12-16 03:29:28.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="IsError" + +/// check for errors +IsError() <-- +[ + CheckErrorTableau(); + Length(GetErrorTableau())>0; +]; + +/// check for errors of a given kind +IsError(error'class_IsString) <-- +[ + CheckErrorTableau(); + GetErrorTableau()[error'class] != Empty; +]; + +%/mathpiper + + + + +%mathpiper_docs,name="IsError",categories="Programmer Functions;Error Reporting;Predicates",access="private" +*CMD IsError --- check for custom error +*STD +*CALL + IsError() + IsError("str") + +*PARMS + +{"str"} -- string to classify the error + +*DESC + +{IsError()} returns {True} if any custom errors have been reported using {Assert}. +The second form takes a parameter {"str"} that designates the class of the +error we are interested in. It returns {True} if any errors of the given class +{"str"} have been reported. + +*SEE GetError, ClearError, Assert, Check + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Print.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Print.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Print.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Print.mpw 2010-01-08 23:36:41.000000000 +0000 @@ -0,0 +1,120 @@ +%mathpiper,def="Print" + + +/* A reference print implementation. Expand at own leisure. + * + * This file implements Print, a scripted expression printer. + */ + + +/* 60000 is the maximum precedence allowed for operators */ +10 # Print(_x) <-- +[ + Print(x,60000); + NewLine(); + DumpErrors(); +]; + +/* Print an argument within an environment of precedence n */ +10 # Print(x_IsAtom,_n) <-- Write(x); +10 # Print(_x,_n)_(IsInfix(Type(x))And ArgumentsCount(x) = 2) <-- +[ + Local(bracket); + bracket:= (PrecedenceGet(Type(x)) > n); + If(bracket,WriteString("(")); + Print(x[1],LeftPrecedenceGet(Type(x))); + Write(x[0]); + Print(x[2],RightPrecedenceGet(Type(x))); + If(bracket,WriteString(")")); +]; + +10 # Print(_x,_n)_(IsPrefix(Type(x)) And ArgumentsCount(x) = 1) <-- +[ + Local(bracket); + bracket:= (PrecedenceGet(Type(x)) > n); + Write(x[0]); + If(bracket,WriteString("(")); + Print(x[1],RightPrecedenceGet(Type(x))); + If(bracket,WriteString(")")); +]; + +10 # Print(_x,_n)_(IsPostfix(Type(x))And ArgumentsCount(x) = 1) <-- +[ + Local(bracket); + bracket:= (PrecedenceGet(Type(x)) > n); + If(bracket,WriteString("(")); + Print(x[1],LeftPrecedenceGet(Type(x))); + Write(x[0]); + If(bracket,WriteString(")")); +]; + +20 # Print(_x,_n)_(Type(x) = "List") <-- +[ + WriteString("{"); + PrintArg(x); + WriteString("}"); +]; + +20 # Print(_x,_n)_(Type(x) = "Prog") <-- +[ + WriteString("["); + PrintArgProg(Rest(FunctionToList(x))); + WriteString("]"); +]; +20 # Print(_x,_n)_(Type(x) = "Nth") <-- +[ + Print(x[1],0); + WriteString("["); + Print(x[2],60000); + WriteString("]"); +]; + +100 # Print(x_IsFunction,_n) <-- + [ + Write(x[0]); + WriteString("("); + PrintArg(Rest(FunctionToList(x))); + WriteString(")"); + ]; + + +/* Print the arguments of an ordinary function */ +10 # PrintArg({}) <-- True; + +20 # PrintArg(_list) <-- +[ + Print(First(list),60000); + PrintArgComma(Rest(list)); +]; +10 # PrintArgComma({}) <-- True; +20 # PrintArgComma(_list) <-- +[ + WriteString(","); + Print(First(list),60000); + PrintArgComma(Rest(list)); +]; + + +18 # Print(Complex(0,1),_n) <-- [WriteString("I");]; +19 # Print(Complex(0,_y),_n) <-- [WriteString("I*");Print(y,4);]; +19 # Print(Complex(_x,1),_n) <-- [Print(x,7);WriteString("+I");]; +20 # Print(Complex(_x,_y),_n) <-- [Print(x,7);WriteString("+I*");Print(y,4);]; + + +/* Tail-recursive printing the body of a compound statement */ +10 # PrintArgProg({}) <-- True; +20 # PrintArgProg(_list) <-- +[ + Print(First(list),60000); + WriteString(";"); + PrintArgProg(Rest(list)); +]; + + + + + + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Show.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Show.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Show.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Show.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,72 @@ +%mathpiper,def="Show" +Macro("Show",{id}) [SysOut("<< ",@id," >>");]; +Macro("Show",{id,x}) [SysOut("<< ",@id," >> ",Hold(@x),": ",Eval(@x));]; +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + +%mathpiper_docs,name="Show",categories="Programmer Functions;Testing" + +*CMD Show --- debug routine using SysOut to print ID and (optional) variable(s) + +*STD +*CALL + Show(ID) + Show(ID,list) + +*PARMS + +{ID} -- an arbitrary identifier for this printout + +{list} -- a list of items to be printed (may be a single item) + +*DESC + +If passed a single item, {Show} will display it using SysOut(). +The dispayed value will be enclosed with << >> (see below). +If ID consists of more than one word, it should be quoted. + +If there are two arguments, the first should be an ID as above, and the second +should be a list of variables which are bound to values at the place where +{Show} is called. Using SysOut(), the list of variable names will be printed +out, along with a list of their currently bound values. + +{Show} can be called with any number of variable names in the list. + +{Show} always returns {True}. + +Because {Show} uses SysOut() to print its output, the output will be visible +both on Standard Output and also on the Shell console (if MathPiper is started +this way), or on the MathPiperIDE Activity Log (if started in MathPiperIDE). +The latter is very useful for debugging programs which hang in a loop or +otherwise, because standard output may not then be visible, but the alternative +output will usually be available. + +*E.G. notest +In> var1:=123 +Result: 123 +In> var2:= "a string" +Result: "a string" +In> var3:=Sin(x)+Exp(x) +Result: Sin(x)+Exp(x) +In> Show(ID1) +Result: True + Side Effects> + << ID1 >> +In> Show(ID2,{var1}) +Result: True + Side Effects> + << ID2 >> {var1}: {123} +In> Show(ID3,{var1,var2}) +Result: True + Side Effects> + << ID3 >> {var1,var2}: {123,a string} +In> Show(ID4,{var1,var2,var3}) +Result: True + Side Effects> + << ID4 >> {var1,var2,var3}: {123,a string,Sin(x)+Exp(x)} + +*SEE Tell +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/TableForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/TableForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/TableForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/TableForm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="TableForm" + +Function("TableForm",{list}) +[ + Local(i); + ForEach(i,list) + [ + Write(i); + NewLine(); + ]; + True; +]; + +%/mathpiper + + + + +%mathpiper_docs,name="TableForm",categories="User Functions;Lists (Operations)" +*CMD TableForm --- print each entry in a list on a line +*STD +*CALL + TableForm(list) + +*PARMS + +{list} -- list to print + +*DESC + +This functions writes out the list {list} in a better readable form, by +printing every element in the list on a separate line. + +*E.G. + +In> TableForm(Table(i!, i, 1, 10, 1)); + + 1 + 2 + 6 + 24 + 120 + 720 + 5040 + 40320 + 362880 + 3628800 +Result: True; + +*SEE PrettyForm, Echo, Table +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Tell.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Tell.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/io/Tell.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/io/Tell.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,70 @@ +%mathpiper,def="Tell" +Macro("Tell",{id}) [Echo(<<,@id,>>);]; +Macro("Tell",{id,x}) [Echo(<<,@id,>>,Hold(@x),": ",Eval(@x));]; +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + +%mathpiper_docs,name="Tell",categories="Programmer Functions;Testing" + +*CMD Tell --- debug routine using Echo to print ID and (optional) variable(s) + +*STD +*CALL + Tell(ID) + Tell(ID,list) + +*PARMS + +{ID} -- an arbitrary identifier for this printout + +{list} -- a list of items to be printed (may be a single item) + +*DESC + +If passed a single item, {Tell} will display it using Echo(). +The dispayed value will be enclosed with << >> (see below). +If ID consists of more than one word, it should be quoted. + +If there are two arguments, the first should be an ID as above, and the second +should be a list of variables which are bound to values at the place where +{Tell} is called. Using Echo(), the list of variable names will be printed +out, along with a list of their currently bound values. + +{Tell} can be called with any number of variable names in the list. + +{Tell} always returns {True}. + +Because {Tell} uses Echo(), it prints to Standard Output. If you are debuging +a program which may hang, you may get no printout. In that case, use {Show} +instead of {Tell} + +*E.G. notest +In> var1:=123 +Result: 123 +In> var2:= "a string" +Result: "a string" +In> var3:=Sin(x)+Exp(x) +Result: Sin(x)+Exp(x) +In> Tell(ID1) +Result: True + Side Effects> + << ID1 >> +In> Tell(ID2,{var1}) +Result: True + Side Effects> + << ID2 >> {var1} : {123} +In> Tell(ID3,{var1,var2}) +Result: True + Side Effects> + << ID3 >> {var1,var2} {123,"a string"} +In> Tell(ID4,{var1,var2,var3}) +Result: True + Side Effects> + << ID4 >> {var1,var2,var3} : {123,"a string",Sin(x)+Exp(x)} + + +*SEE Show +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/limit/Limit.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/limit/Limit.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/limit/Limit.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/limit/Limit.mpw 2011-04-16 10:44:47.000000000 +0000 @@ -0,0 +1,357 @@ +%mathpiper,def="Limit" + +100 # IsIrrationalFunction(Sqrt(_expr), _var)_(IsPolynomial(expr, var) And Degree(expr, var) > 0 Or IsIrrationalFunction(expr,var)) <-- True; +100 # IsIrrationalFunction(_expr^_p, _var)_((IsPolynomial(expr, var) Or IsIrrationalFunction(expr,var)) And IsRationalOrNumber(p) And Not IsZero(p) And Not IsPositiveInteger(p)) <-- True; +100 # IsIrrationalFunction(_e1 + _e2, _var)_(IsIrrationalFunction(e1, var) And IsIrrationalFunction(e2, var) Or IsPolynomial(e1, var) And IsIrrationalFunction(e2, var) Or IsIrrationalFunction(e1, var) And IsPolynomial(e2, var)) <-- True; +100 # IsIrrationalFunction(_e1 - _e2, _var)_(IsIrrationalFunction(e1, var) And IsIrrationalFunction(e2, var) Or IsPolynomial(e1, var) And IsIrrationalFunction(e2, var) Or IsIrrationalFunction(e1, var) And IsPolynomial(e2, var)) <-- True; +100 # IsIrrationalFunction(_e1 * _e2, _var)_(IsIrrationalFunction(e1, var) And IsIrrationalFunction(e2, var) Or IsPolynomial(e1, var) And IsIrrationalFunction(e2, var) Or IsIrrationalFunction(e1, var) And IsPolynomial(e2, var)) <-- True; +100 # IsIrrationalFunction(_e1 / _e2, _var)_(IsIrrationalFunction(e1, var) And IsIrrationalFunction(e2, var) Or IsPolynomial(e1, var) And IsIrrationalFunction(e2, var) Or IsIrrationalFunction(e1, var) And IsPolynomial(e2, var)) <-- True; + +500 # IsIrrationalFunction(_expr, _var) <-- False; + +100 # IrrationalFunctionDegree(Sqrt(_expr), _var)_(IsPolynomial(expr, var)) <-- Degree(expr, var) / 2; +105 # IrrationalFunctionDegree(Sqrt(_expr), _var)_(IsIrrationalFunction(expr, var)) <-- IrrationalFunctionDegree(expr, var) / 2; +110 # IrrationalFunctionDegree(_expr^_p, _var)_(IsPolynomial(expr, var) And IsRationalOrNumber(p) And Not IsZero(p) And Not IsPositiveInteger(p)) <-- Degree(expr, var) * p; +110 # IrrationalFunctionDegree(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var)) <-- Maximum(IrrationalFunctionDegree(e1,var), IrrationalFunctionDegree(e2,var)); +110 # IrrationalFunctionDegree(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var)) <-- Maximum(IrrationalFunctionDegree(e1,var), Degree(e2, var)); +110 # IrrationalFunctionDegree(_e1 - _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var)) <-- Maximum(Degree(e1, var), IrrationalFunctionDegree(e2,var)); +110 # IrrationalFunctionDegree(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var)) <-- Maximum(IrrationalFunctionDegree(e1,var), IrrationalFunctionDegree(e2,var)); +110 # IrrationalFunctionDegree(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var)) <-- Maximum(IrrationalFunctionDegree(e1,var), Degree(e2, var)); +110 # IrrationalFunctionDegree(_e1 + _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var)) <-- Maximum(Degree(e1, var), IrrationalFunctionDegree(e2,var)); +110 # IrrationalFunctionDegree(_e1 * _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var)) <-- IrrationalFunctionDegree(e1,var) + IrrationalFunctionDegree(e2,var); +110 # IrrationalFunctionDegree(_e1 * _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var)) <-- IrrationalFunctionDegree(e1,var) + Degree(e2, var); +110 # IrrationalFunctionDegree(_e1 * _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var)) <-- Degree(e1, var) + IrrationalFunctionDegree(e2,var); + +110 # IrrationalFunctionDegree(_e1 / _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var)) <-- IrrationalFunctionDegree(e1,var) - IrrationalFunctionDegree(e2,var); +110 # IrrationalFunctionDegree(_e1 / _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var)) <-- IrrationalFunctionDegree(e1,var) - Degree(e2, var); +110 # IrrationalFunctionDegree(_e1 / _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var)) <-- Degree(e1, var) - IrrationalFunctionDegree(e2,var); + +100 # IrrationalFunctionLeadingCoef(Sqrt(_expr), _var)_(IsPolynomial(expr, var)) <-- Sqrt(LeadingCoef(expr, var)); +105 # IrrationalFunctionLeadingCoef(Sqrt(_expr), _var)_(IsIrrationalFunction(expr, var)) <-- Sqrt(IrrationalFunctionLeadingCoef(expr, var)); +110 # IrrationalFunctionLeadingCoef(_expr^_p, _var)_(IsPolynomial(expr, var) And IsRationalOrNumber(p) And Not IsZero(p) And Not IsPositiveInteger(p)) <-- LeadingCoef(expr, var)^p; + +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var) And IrrationalFunctionDegree(e1,var) > IrrationalFunctionDegree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var); +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var) And IrrationalFunctionDegree(e1,var) < IrrationalFunctionDegree(e2,var)) <-- IrrationalFunctionLeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var) And IrrationalFunctionDegree(e1,var) = IrrationalFunctionDegree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) + IrrationalFunctionLeadingCoef(e2,var); + +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var) And IrrationalFunctionDegree(e1,var) > Degree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var); +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var) And IrrationalFunctionDegree(e1,var) < Degree(e2,var)) <-- LeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var) And IrrationalFunctionDegree(e1,var) = Degree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) + LeadingCoef(e2,var); + +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var) And Degree(e1,var) > IrrationalFunctionDegree(e2,var)) <-- LeadingCoef(e1,var); +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var) And Degree(e1,var) < IrrationalFunctionDegree(e2,var)) <-- IrrationalFunctionLeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 + _e2, _var)_(IsPolynomiaml(e1,var) And IsIrrationalFunction(e2,var) And Degree(e1,var) = IrrationalFunctionDegree(e2,var)) <-- LeadingCoef(e1,var) + IrrationalFunctionLeadingCoef(e2,var); + +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var) And IrrationalFunctionDegree(e1,var) > IrrationalFunctionDegree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var); +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var) And IrrationalFunctionDegree(e1,var) < IrrationalFunctionDegree(e2,var)) <-- -IrrationalFunctionLeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var) And IrrationalFunctionDegree(e1,var) = IrrationalFunctionDegree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) - IrrationalFunctionLeadingCoef(e2,var); + +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var) And IrrationalFunctionDegree(e1,var) > Degree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var); +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var) And IrrationalFunctionDegree(e1,var) < Degree(e2,var)) <-- -LeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var) And IrrationalFunctionDegree(e1,var) = Degree(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) - LeadingCoef(e2,var); + +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var) And Degree(e1,var) > IrrationalFunctionDegree(e2,var)) <-- LeadingCoef(e1,var); +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var) And Degree(e1,var) < IrrationalFunctionDegree(e2,var)) <-- -IrrationalFunctionLeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 - _e2, _var)_(IsPolynomiaml(e1,var) And IsIrrationalFunction(e2,var) And Degree(e1,var) = IrrationalFunctionDegree(e2,var)) <-- LeadingCoef(e1,var) - IrrationalFunctionLeadingCoef(e2,var); + +110 # IrrationalFunctionLeadingCoef(_e1 * _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) * IrrationalFunctionLeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 * _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) * LeadingCoef(e2, var); +110 # IrrationalFunctionLeadingCoef(_e1 * _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var)) <-- LeadingCoef(e1, var) * IrrationalFunctionLeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 / _e2, _var)_(IsIrrationalFunction(e1,var) And IsIrrationalFunction(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) / IrrationalFunctionLeadingCoef(e2,var); +110 # IrrationalFunctionLeadingCoef(_e1 / _e2, _var)_(IsIrrationalFunction(e1,var) And IsPolynomial(e2,var)) <-- IrrationalFunctionLeadingCoef(e1,var) / LeadingCoef(e2, var); +110 # IrrationalFunctionLeadingCoef(_e1 / _e2, _var)_(IsPolynomial(e1,var) And IsIrrationalFunction(e2,var)) <-- LeadingCoef(e1, var) / IrrationalFunctionLeadingCoef(e2,var); + + + +/* */ +/* Limit operator rule base */ +/* */ + +/* Special case: limits of polynomials as x approaches infinity */ +100 # Lim(_var, _tar, _dir, _p)_(IsPolynomial(p, var) And Degree(p, var) > 0 And IsInfinity(tar)) + <-- LeadingCoef(p,var) * Sign(tar)^Degree(p,var) * Infinity; + +/* Special case: limits of rational function as x approaches infinity */ +110 # Lim(_var, _tar, _dir, _r)_(IsRationalFunction(r, var) And IsInfinity(tar)) <-- +[ + Local(p,q,pd,qd,pc,qc); + + p:=Numerator(r); + q:=Denominator(r); + + pd:=Degree(p,var); + qd:=Degree(q,var); + + pc:=LeadingCoef(p,var); + qc:=LeadingCoef(q,var); + + If(pd>qd, + pc/qc*tar, + If(pd=qd,pc/qc,0) + ); +]; + +/* Special case: limits of irrational function as x approaches infinity */ +110 # Lim(_var, _tar, _dir, _expr)_(IsIrrationalFunction(expr, var) And IsInfinity(tar)) <-- +[ + Local(lc,dg); + + lc:=IrrationalFunctionLeadingCoef(expr, var); + dg:=IrrationalFunctionDegree(expr, var); + + If(lc = 0, + 0, + If(dg > 0, + Sign(tar)^dg * Infinity, + If(dg = 0, lc, 0) + ) + ); +]; + + +/* Special case: make use of the logarithm properties */ +120 # Lim(_var, _tar, _dir, Ln(_a) + Ln(_b)) <-- Lim(var, tar, dir, Ln(a*b)); +120 # Lim(_var, _tar, _dir, Ln(_a) - Ln(_b)) <-- Lim(var, tar, dir, Ln(a/b)); + +/* Exponentiation rules */ + +/* Special limit #1: 0 ^ 0; #2: 1 ^ Infinity; #3: Infinity ^ 0 */ +200 # Lim(_var, _tar, _dir, _x ^ _y)_ +( [ + Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); + ((IsZero(lx) And IsZero(ly)) Or ((lx = 1) And IsInfinity(ly)) Or (IsInfinity(lx) And IsZero(ly))); +] ) +<-- Exp(Lim(var, tar, dir, y * Ln(x))); + +/* Default rule */ +210 # Lim(_var, _tar, _dir, _x ^ _y) +<-- Lim(var, tar, dir, x)^Lim(var, tar, dir, y); + + +/* Division rules */ + +/* Special limit #4: 0 / 0; #5: Infinity / Infinity */ +300 # Lim(_var, _tar, _dir, _x / _y)_ +( [ + Local(lx,ly,infx,infy); + lx := Lim(var, tar, dir, x); + ly := Lim(var, tar, dir, y); + infx := (IsInfinity(lx) Or (IsZero(Re(lx)) And IsInfinity(Im(lx)))); + infy := (IsInfinity(ly) Or (IsZero(Re(ly)) And IsInfinity(Im(ly)))); + ((IsZero(lx) And IsZero(ly)) Or + (infx And infy) + ); +] ) +<-- Lim(var, tar, dir, ApplyFast("Differentiate", {var, x})/ApplyFast("Differentiate", {var, y})); + +/* Special limit #6: null denominator */ +/* Probably there are still some problems. */ + +Dir(Right) <-- 1; +Dir(Left) <-- -1; + +/* To get the sign of the denominator on one side: */ +Sign(_var, _tar, _dir, _exp, _n) +<-- [ + Local(der, coef); der := ApplyFast("Differentiate", {var, exp}); + coef := Eval(ApplyFast("Subst", {var, tar, der})); + If ( coef = 0, + Sign(var, tar, dir, der, n+1), + (Sign(coef)*Dir(dir)) ^ n + ); +]; + +/* To avoid infinite recursion (with 1/Exp(-x) for instance) */ +310 # Lim(_var, _tar, _dir, _x / _y)_ +(IsInfinity(tar) And IsZero(Lim(var, tar, dir, y))) +<-- Sign(Lim(var, tar, dir, x))*Sign(Lim(var, tar, dir, ApplyFast("Differentiate", {var, y})))*tar; + +320 # Lim(_var, _tar, _dir, _x / _y)_IsZero(Lim(var, tar, dir, y)) +<-- Sign(Lim(var, tar, dir, x))*Sign(var, tar, dir, y, 1)*Infinity; + + +/* Default rule */ +330 # Lim(_var, _tar, _dir, _x / _y) <-- [ + Local(u,v,r); + + u := Lim(var, tar, dir, x); + v := Lim(var, tar, dir, y); + + r := u / v; + + If (u = Undefined And IsInfinity(v), [ + li := LimInf(var,tar,dir,x); + ls := LimSup(var,tar,dir,x); + r := (li * ls) / v; + ]); + + r; +]; + + +/* Multiplication rules */ + +/* To avoid some infinite recursions */ +400 # Lim(_var, _tar, _dir, _x * Exp(_y))_ +(IsInfinity(Lim(var, tar, dir, x)) And (Lim(var, tar, dir, y) = -Infinity)) +<-- Lim(var, tar, dir, x/Exp(-y)); +400 # Lim(_var, _tar, _dir, Exp(_x) * _y)_ +((Lim(var, tar, dir, x) = -Infinity) And IsInfinity(Lim(var, tar, dir, y))) +<-- Lim(var, tar, dir, y/Exp(-x)); +400 # Lim(_var, _tar, _dir, Ln(_x) * _y)_ +(IsZero(Lim(var, tar, dir, x)) And IsZero(Lim(var, tar, dir, y))) +<-- Lim(var, tar, dir, y*Ln(x)); + +/* Special limit #7: 0 * Infinity */ +410 # Lim(_var, _tar, _dir, _x * _y)_ +((IsZero(Lim(var, tar, dir, x)) And IsInfinity(Lim(var, tar, dir, y))) + Or (IsInfinity(Lim(var, tar, dir, x)) And IsZero(Lim(var, tar, dir, y)))) +<-- Lim(var, tar, dir, Simplify(ApplyFast("Differentiate", {var, y})/ApplyFast("Differentiate", +{var, 1/x}))); + +/* Default rule */ +420 # Lim(_var, _tar, _dir, _x * _y) <-- [ + Local(u,v,r); + + u := Lim(var, tar, dir, x); + v := Lim(var, tar, dir, y); + + r := u * v; + + If (u = 0 And v = Undefined, [ + li := LimInf(var,tar,dir,y); + ls := LimSup(var,tar,dir,y); + r := u * li * ls; + ], If (u = Undefined And v = 0, [ + li := LimInf(var,tar,dir,x); + ls := LimSup(var,tar,dir,x); + r := v * li * ls; + ])); + + r; +]; + +/* Substraction rules */ + +/* Special limit #8: Infinity - Infinity */ +500 # Lim(_var, _tar, _dir, _x - _y)_ +( [ + Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); + ((lx = Infinity) And (ly = Infinity)) Or ((lx = -Infinity) And (ly = -Infinity)); +] ) +<-- Lim(var, tar, dir, x*(1-y/x)); + +/* Default rule */ +510 # Lim(_var, _tar, _dir, _x - _y) +<-- Lim(var, tar, dir, x)-Lim(var, tar, dir, y); + +/* Unary minus */ +520 # Lim(_var, _tar, _dir, - _x) +<-- - Lim(var, tar, dir, x); + + +/* Addition rules */ + +/* Special limit #9: Infinity + (-Infinity) */ +600 # Lim(_var, _tar, _dir, _x + _y)_ +( [ + Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); + ((lx = Infinity) And (ly = -Infinity)) Or ((lx = -Infinity) And (ly = Infinity)); +] ) +<-- Lim(var, tar, dir, x*(1+y/x)); + +/* Default rule */ +610 # Lim(_var, _tar, _dir, _x + _y) +<-- Lim(var, tar, dir, x)+Lim(var, tar, dir, y); + +/* Global default rule : evaluate expression */ + +700 # Lim(_var, _tar, _dir, exp_IsFunction) +<-- Eval(MapArgs(exp,"LimitArgs")); + +LimitArgs(_arg) <-- Lim(var,tar,dir,arg); +UnFence("LimitArgs",1); /* Allow LimitArgs to have access to the local variables of the caller. */ + +701 # Lim(_var, _tar, _dir, _exp) +<-- Eval(ApplyFast("Subst", {var, tar, exp})); + + +/* Limit without direction */ + +10 # Lim(_var, tar_IsInfinity, _exp) <-- Lim(var, tar, None, exp); + +20 # Lim(_var, _tar, _exp) +<-- [ + Local(l); l := Lim(var, tar, Left, exp); + If ( l = Lim(var, tar, Right, exp), + l, + Undefined + ); +]; + + +100 # LimInf(_var, _tar, _dir, Cos( _exp ))_IsInfinity(Lim(var,tar,dir,exp)) <-- -1; +100 # LimInf(_var, _tar, _dir, Sin( _exp ))_IsInfinity(Lim(var,tar,dir,exp)) <-- -1; + +500 # LimInf(_var, _tar, _dir, _exp) <-- Lim(var,tar,dir,exp); + +100 # LimSup(_var, _tar, _dir, Cos( _exp ))_IsInfinity(Lim(var,tar,dir,exp)) <-- 1; +100 # LimSup(_var, _tar, _dir, Sin( _exp ))_IsInfinity(Lim(var,tar,dir,exp)) <-- 1; + +500 # LimSup(_var, _tar, _dir, _exp) <-- Lim(var,tar,dir,exp); + + +/* User-callable function */ + +(Limit(_var,_lim)(_fie)) <-- Lim(var,lim,fie); +(Limit(_var,_lim,_direction)(_fie)) <-- Lim(var,lim,direction,fie); +UnFence("Limit",3); + + +%/mathpiper + + + +%mathpiper_docs,name="Limit",categories="User Functions;Calculus Related (Symbolic)" +*CMD Limit --- limit of an expression +*STD +*CALL + Limit(var, val) expr + Limit(var, val, dir) expr + +*PARMS + +{var} -- a variable + +{val} -- a number + +{dir} -- a direction ({Left} or {Right}) + +{expr} -- an expression + +*DESC + +This command tries to determine the value that the expression "expr" +converges to when the variable "var" approaches "val". One may use +{Infinity} or {-Infinity} for +"val". The result of {Limit} may be one of the +symbols {Undefined} (meaning that the limit does not +exist), {Infinity}, or {-Infinity}. + +The second calling sequence is used for unidirectional limits. If one +gives "dir" the value {Left}, the limit is taken as +"var" approaches "val" from the positive infinity; and {Right} will take the limit from the negative infinity. + +*E.G. + +In> Limit(x,0) Sin(x)/x +Result: 1; +In> Limit(x,0) (Sin(x)-Tan(x))/(x^3) +Result: -1/2; +In> Limit(x,0) 1/x +Result: Undefined; +In> Limit(x,0,Left) 1/x +Result: -Infinity; +In> Limit(x,0,Right) 1/x +Result: Infinity; +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/limit/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/limit/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/limit/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/limit/om/om.mpw 2010-01-05 19:46:52.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="" + +// From code.mpi.def: +OMDef("Limit", "limit1","limit", + { _0, _2, OMS("limit1", "under"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) + |{ _0, _2, OMS("limit1", "above"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) + |{ _0, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, + { _0, _{3,2,1}, _1, Left, _{3,3}}_(_2=OMS("limit1", "below")) + |{_0, _{3,2,1}, _1, Right, _{3,3}}_(_2=OMS("limit1", "above")) + |{_0, _{3,2,1}, _1, _{3,3}} + ); +// Test [result Limit(x,0,Right)1/x]: PipeFromString(PipeToString()OMForm(Limit(x,0,Right) 1/x))OMRead() + +// As explained in the manual, "limit1:both_sides" and "fns1:lambda" will +// be handled as OMS("limit1", "both_sides") and OMS("fns1", "lambda"), so +// we don't need to define bogus mappings for them: +// OMDef("OMSymbolLimit1BothSides", "limit1", "both_sides"); +// OMDef("OMSymbolLambda", "fns1", "lambda"); +// The same applies to "Left" and "Right", which are undefined symbols +// that are used only inside limit expressions, so they don't need a mapping +// of their own. +// We could define them as follows: +//OMDef("Left", "limit1","below"); +//OMDef("Right", "limit1","above"); +// and then use the following rules instead: +// { _0, _2, Left, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) +// |{ _0, _2, Right, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) +// |{ _0, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, +// { _0, _{3,2,1}, _1, _2, _{3,3}}_(_2=Left Or _2=Right) +// |{_0, _{3,2,1}, _1, _{3,3}} +// The result is exactly the same. The only difference is when producing the +// OMForm of the symbols themselves, outside the limit expression. + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/BaseVector.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/BaseVector.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/BaseVector.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/BaseVector.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="BaseVector" + +Function("BaseVector",{row,n}) +[ + Local(i,result); + result:=ZeroVector(n); + result[row] := 1; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="BaseVector",categories="User Functions;Linear Algebra" +*CMD BaseVector --- base vector +*STD +*CALL + BaseVector(k, n) + +*PARMS + +{k} -- index of the base vector to construct + +{n} -- dimension of the vector + +*DESC + +This command returns the "k"-th base vector of dimension "n". This +is a vector of length "n" with all zeros except for the "k"-th +entry, which contains a 1. + +*E.G. + +In> BaseVector(2,4) +Result: {0,1,0,0}; + +*SEE ZeroVector, Identity +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/CartesianProduct.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/CartesianProduct.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/CartesianProduct.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/CartesianProduct.mpw 2011-01-31 08:17:40.000000000 +0000 @@ -0,0 +1,70 @@ +%mathpiper,def="CartesianProduct" + +//Retract("CartesianProduct",*); + +CartesianProduct(xList_IsList, yList_IsList) <-- +[ + Local(cartesianProduct); + + cartesianProduct := {}; + + ForEach(x, xList) + [ + ForEach(y, yList) + [ + cartesianProduct := DestructiveAppend(cartesianProduct, {x,y}); + + ]; + ]; + + cartesianProduct; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="CartesianProduct",categories="User Functions;Linear Algebra;Lists (Operations)",access="experimental" +*CMD CartesianProduct --- returns the Cartesian product of two lists +*CALL + CartesianProduct(list1, list2) + +*PARMS + +{list1} -- a list + +{list2} -- a list + +*DESC + +This function returns the Cartesian product of two lists. + +*E.G. +In> CartesianProduct({a,b}, {c,d}) +Result: {{a,c},{a,d},{b,c},{b,d}} + +In> CartesianProduct({2,3,4,5,6,7,8,9,10,Jack,Queen,King,Ace}, {Spades, Hearts, Diamonds, Clubs}) +Result: {{2,Spades},{2,Hearts},{2,Diamonds},{2,Clubs}, +{3,Spades},{3,Hearts},{3,Diamonds},{3,Clubs}, +{4,Spades},{4,Hearts},{4,Diamonds},{4,Clubs}, +{5,Spades},{5,Hearts},{5,Diamonds},{5,Clubs}, +{6,Spades},{6,Hearts},{6,Diamonds},{6,Clubs}, +{7,Spades},{7,Hearts},{7,Diamonds},{7,Clubs}, +{8,Spades},{8,Hearts},{8,Diamonds},{8,Clubs}, +{9,Spades},{9,Hearts},{9,Diamonds},{9,Clubs}, +{10,Spades},{10,Hearts},{10,Diamonds},{10,Clubs}, +{Jack,Spades},{Jack,Hearts},{Jack,Diamonds},{Jack,Clubs}, +{Queen,Spades},{Queen,Hearts},{Queen,Diamonds},{Queen,Clubs}, +{King,Spades},{King,Hearts},{King,Diamonds},{King,Clubs}, +{Ace,Spades},{Ace,Hearts},{Ace,Diamonds},{Ace,Clubs}} +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Cholesky.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Cholesky.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Cholesky.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Cholesky.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,79 @@ +%mathpiper,def="Cholesky" + +// Cholesky Decomposition, adapted from: +// Fundamentals Of Matrix Computation (2nd), David S. Watkins, pp38 +// This algorithm performs O(n^3) flops where A is nxn +// Given the positive definite matrix A, a matrix R is returned such that +// A = Transpose(R) * R + +10 # Cholesky(A_IsMatrix) <-- +[ + Local(matrix,n,k,j); + n:=Length(A); + matrix:=ZeroMatrix(n); + + // copy entries of A into matrix + ForEach(i,1 .. n) + ForEach(j,1 .. n) + matrix[i][j] := A[i][j]; + + // in place algorithm for cholesky decomp + ForEach(i,1 .. n)[ + For(k:=1,k<=(i-1),k++) + matrix[i][i] := matrix[i][i] - matrix[k][i]^2; + Check( matrix[i][i] > 0, "Math", "Cholesky: Matrix is not positive definite"); + matrix[i][i] := Sqrt(matrix[i][i]); + //Echo({"matrix[",i,"][",i,"] = ", matrix[i][i] }); + For(j:=i+1,j<=n,j++)[ + For(k:=1,k<=(i-1),k++) + matrix[i][j]:= matrix[i][j] - matrix[k][i]*matrix[k][j]; + matrix[i][j] := matrix[i][j]/matrix[i][i]; + //Echo({"matrix[",i,"][",j,"] = ", matrix[i][j] }); + ]; + ]; + // cholesky factorization is upper triangular + ForEach(i,1 .. n) + ForEach(j,1 .. n) + If(i>j,matrix[i][j] := 0); + matrix; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Cholesky",categories="User Functions;Linear Algebra" +*CMD Cholesky --- find the Cholesky Decomposition +*STD +*CALL + Cholesky(A) + +*PARMS + +{A} -- a square positive definite matrix + +*DESC + +{Cholesky} returns a upper triangular matrix {R} such that {Transpose(R)*R = A}. +The matrix {A} must be positive definite, {Cholesky} will notify the user if the matrix +is not. Some families of positive definite matrices are all symmetric matrices, diagonal +matrices with positive elements and Hilbert matrices. + +*E.G. + +In> A:={{4,-2,4,2},{-2,10,-2,-7},{4,-2,8,4},{2,-7,4,7}} +Result: {{4,-2,4,2},{-2,10,-2,-7},{4,-2,8,4},{2,-7,4,7}}; +In> R:=Cholesky(A); +Result: {{2,-1,2,1},{0,3,0,-2},{0,0,2,1},{0,0,0,1}}; +In> Transpose(R)*R = A +Result: True; +In> Cholesky(4*Identity(5)) +Result: {{2,0,0,0,0},{0,2,0,0,0},{0,0,2,0,0},{0,0,0,2,0},{0,0,0,0,2}}; +In> Cholesky(HilbertMatrix(3)) +Result: {{1,1/2,1/3},{0,Sqrt(1/12),Sqrt(1/12)},{0,0,Sqrt(1/180)}}; +In> Cholesky(ToeplitzMatrix({1,2,3})) + In function "Check" : + CommandLine(1) : "Cholesky: Matrix is not positive definite" + +*SEE IsSymmetric, IsDiagonal, Diagonal +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/CoFactor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/CoFactor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/CoFactor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/CoFactor.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,62 @@ +%mathpiper,def="CoFactor" + +Function("CoFactor",{matrix,ii,jj}) +[ + Local(perms,indices,result); + indices:=Table(i,i,1,Length(matrix),1); + perms:=PermutationsList(indices); + result:=0; + ForEach(item,perms) + If(item[ii] = jj, + result:=result+ + Product(i,1,Length(matrix), + If(ii=i,1,matrix[i][item[i] ]) + )*LeviCivita(item)); + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="CoFactor",categories="User Functions;Linear Algebra" +*CMD CoFactor --- cofactor of a matrix +*STD +*CALL + CoFactor(M,i,j) + +*PARMS + +{M} -- a matrix + +{i}, {j} - positive integers + +*DESC + +{CoFactor} returns the cofactor of a matrix around +the element ($i$, $j$). The cofactor is the minor times +$(-1)^(i+j)$. + +*E.G. + +In> A := {{1,2,3}, {4,5,6}, {7,8,9}}; +Result: {{1,2,3},{4,5,6},{7,8,9}}; +In> PrettyForm(A); + + / \ + | ( 1 ) ( 2 ) ( 3 ) | + | | + | ( 4 ) ( 5 ) ( 6 ) | + | | + | ( 7 ) ( 8 ) ( 9 ) | + \ / +Result: True; +In> CoFactor(A,1,2); +Result: 6; +In> Minor(A,1,2); +Result: -6; +In> Minor(A,1,2) * (-1)^(1+2); +Result: 6; + +*SEE Minor, Determinant, Inverse +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/CrossProduct.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/CrossProduct.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/CrossProduct.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/CrossProduct.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="CrossProduct" + +Function("CrossProduct",{aLeft,aRight}) +[ + Local(length); + length:=Length(aLeft); + Check(length = 3, "Argument", "OutProduct: error, vectors not of dimension 3"); + Check(length = Length(aRight), "Argument", "OutProduct: error, vectors not of the same dimension"); + + Local(perms); + perms := PermutationsList({1,2,3}); + + Local(result); + result:=ZeroVector(3); + + Local(term); + ForEach(term,perms) + [ + result[ term[1] ] := result[ term[1] ] + + LeviCivita(term) * aLeft[ term[2] ] * aRight[ term[3] ] ; + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="CrossProduct",categories="User Functions;Linear Algebra" +*CMD CrossProduct --- outer product of vectors +*STD +*CALL + CrossProduct(a,b) + a X b +Precedence: +*EVAL PrecedenceGet("X") + +*PARMS + +{a}, {b} -- three-dimensional vectors + +*DESC + +The cross product of the vectors "a" +and "b" is returned. The result is perpendicular to both "a" and +"b" and its length is the product of the lengths of the vectors. +Both "a" and "b" have to be three-dimensional. + +*E.G. + +In> {a,b,c} X {d,e,f}; +Result: {b*f-c*e,c*d-a*f,a*e-b*d}; + +*SEE InProduct, X +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Deteminant.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Deteminant.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Deteminant.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Deteminant.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,49 @@ +%mathpiper,def="Determinant" + +10 # Determinant(_matrix)_(IsUpperTriangular(matrix) Or IsLowerTriangular(matrix)) <-- +[ + Local(result); + result:=1; + ForEach(i, Diagonal(matrix) ) + result:=result*i; + result; +]; + +// +// The fast determinant routine that does the determinant numerically, rule 20, +// divides things by the elements on the diagonal of the matrix. So if one of these +// elements happens to be zero, the result is something like Infinity or Undefined. +// Use the symbolic determinant in that case, as it is slower but much more robust. +// +15 # Determinant(_matrix)_(Length(Select(Diagonal(matrix), "IsZero")) > 0) <-- SymbolicDeterminant(matrix); + +// Not numeric entries, so lets treat it symbolically. +16 # Determinant(_matrix)_(VarList(matrix) != {}) <-- SymbolicDeterminant(matrix); + +20 # Determinant(_matrix) <-- GaussianDeterminant(matrix); + +%/mathpiper + + + +%mathpiper_docs,name="Determinant",categories="User Functions;Linear Algebra" +*CMD Determinant --- determinant of a matrix +*STD +*CALL + Determinant(M) + +*PARMS + +{M} -- a matrix + +*DESC + +Returns the determinant of a matrix M. + +*E.G. + +In> A:=DiagonalMatrix(1 .. 4) +Result: {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; +In> Determinant(A) +Result: 24; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/DiagonalMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/DiagonalMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/DiagonalMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/DiagonalMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="DiagonalMatrix" + +Function("DiagonalMatrix",{list}) +[ + Local(result,i,n); + n:=Length(list); + result:=Identity(n); + For(i:=1,i<=n,i++) + [ + result[i][i] := list[i]; + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="DiagonalMatrix",categories="User Functions;Linear Algebra" +*CMD DiagonalMatrix --- construct a diagonal matrix +*STD +*CALL + DiagonalMatrix(d) + +*PARMS + +{d} -- list of values to put on the diagonal + +*DESC + +This command constructs a diagonal matrix, that is a square matrix +whose off-diagonal entries are all zero. The elements of the vector +"d" are put on the diagonal. + +*E.G. + +In> DiagonalMatrix(1 .. 4) +Result: {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; + +*SEE Identity, ZeroMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Diagonal.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Diagonal.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Diagonal.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Diagonal.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="Diagonal" + +// +// Diagonal: return a vector with the diagonal elements of the matrix +// +Function("Diagonal",{A}) +[ + Local(result,i,n); + n:=Length(A); + result:=ZeroVector(n); + For(i:=1,i<=n,i++) + [ + result[i] := A[i][i]; + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Diagonal",categories="User Functions;Linear Algebra" +*CMD Diagonal --- extract the diagonal from a matrix +*STD +*CALL + Diagonal(A) + +*PARMS + +{A} -- matrix + +*DESC + +This command returns a vector of the diagonal components +of the matrix {A}. + + +*E.G. + +In> Diagonal(5*Identity(4)) +Result: {5,5,5,5}; +In> Diagonal(HilbertMatrix(3)) +Result: {1,1/3,1/5}; + +*SEE DiagonalMatrix, IsDiagonal +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Dimensions.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Dimensions.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Dimensions.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Dimensions.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,79 @@ +%mathpiper,def="Dimensions" + +//Retract("Dimensions",*); + +/* Code that returns the list of the dimensions of a tensor or matrix + Code submitted by Dirk Reusch. + */ + +LocalSymbols(x,i,n,m,aux,dim,result) +[ + 1 # Dimensions(x_IsList) <-- + [ + Local(i,n,m,aux,dim,result); + result:=List(Length(x)); + If(Length(x)>0 And Length(Select(x, IsList))=Length(x), + [ + n:=Length(x); + dim:=MapSingle(Dimensions,x); + m:=Minimum(MapSingle(Length,dim)); + For(i:=1,i<=m,i++) + [ + aux:=Table(dim[j][i],j,1,n,1); + If(Minimum(aux)=Maximum(aux), + result:=DestructiveAppend(result,dim[1][i]), + i:=m+1 + ); + ]; + ] + ); + result; + ]; + + 2 # Dimensions(_x) <-- List(); +]; // LocalSymbols + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Dimensions",categories="User Functions;Linear Algebra" +*CMD Dimensions --- dimensions (number of rows and columns etc) of input Matrix +*STD +*CALL + Dimensions(Matrix) + +*PARMS + +{Matrix} -- a matrix + + +*DESC + +This command returns an array of dimensions {nrows,ncols,...} corresponding to the input array. +The input array can be 1-dimensional (i.e., vector), 2-dimensional (i.e., matrix), +or higher dimensioned (tensor). + +If multidimensional, the array must not be "ragged", else this function will give +an incorrect result. + +*E.G. +In> Dimensions({1,2,3,4}) +Result: {4} + +In> Dimensions({{1,2,3,4},{5,6,7,8}}) +Result: {2,4} + +In> Dimensions({{{4,8,1,2},{1,7,-3,-14}},{{2,-3,2,3},{11,12,13,14}},{{21,22,23,24},{31,32,33,34}}}) +Result: {3,2,4} + +In> Dimensions({{1,2,3,4},{5,6,7,8,9}}) +Result: {2} + +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Dot.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Dot.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Dot.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Dot.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,103 @@ +%mathpiper,def="Dot" + +////// +// dot product for vectors and matrices (dr) +////// + +LocalSymbols(Dot0,Dot1) +[ +// vector . vector +Dot(t1_IsVector,t2_IsVector)_(Length(t1)=Length(t2)) <-- + Dot0(t1,t2,Length(t1)); + +// matrix . vector +Dot(t1_IsMatrix,t2_IsVector)_(Length(t1[1])=Length(t2)) <-- +[ + Local(i,n,m,result); + n:=Length(t1); + m:=Length(t2); + result:=List(); + For(i:=1,i<=n,i++) + DestructiveInsert(result,1,Dot0(t1[i],t2,m)); + DestructiveReverse(result); +]; + +// vector . matrix +Dot(t1_IsVector,t2_IsMatrix)_(Length(t1)=Length(t2) + And Length(t2[1])>0) <-- + Dot1(t1,t2,Length(t1),Length(t2[1])); + +// matrix . matrix +Dot(t1_IsMatrix,t2_IsMatrix)_(Length(t1[1])=Length(t2) + And Length(t2[1])>0) <-- +[ + Local(i,n,k,l,result); + n:=Length(t1); + k:=Length(t2); + l:=Length(t2[1]); + result:=List(); + For(i:=1,i<=n,i++) + DestructiveInsert(result,1,Dot1(t1[i],t2,k,l)); + DestructiveReverse(result); +]; + +// vector . vector +Dot0(_t1,_t2,_n) <-- +[ + Local(i,result); + result:=0; + For(i:=1,i<=n,i++) + result:=result+t1[i]*t2[i]; + result; +]; + +// vector . matrix +// m vector length +// n number of matrix cols +Dot1(_t1,_t2,_m,_n) <-- +[ + Local(i,j,result); + result:=ZeroVector(n); + For(i:=1,i<=n,i++) + For(j:=1,j<=m,j++) + result[i]:=result[i]+t1[j]*t2[j][i]; + result; +]; + +]; // LocalSymbols(Dot0,Dot1) + +%/mathpiper + + + +%mathpiper_docs,name="Dot",categories="User Functions;Linear Algebra" +*CMD Dot --- get dot product of tensors +*STD +*CALL + Dot(t1,t2) + +*PARMS + +{t1,t2} -- tensor lists (currently only vectors and matrices are supported) + +*DESC + +{Dot} returns the dot (aka inner) product of two tensors t1 and t2. The last +index of t1 and the first index of t2 are contracted. Currently {Dot} works +only for vectors and matrices. {Dot}-multiplication of two vectors, a matrix +with a vector (and vice versa) or two matrices yields either a scalar, a +vector or a matrix. + +*E.G. + +In> Dot({1,2},{3,4}) +Result: 11; +In> Dot({{1,2},{3,4}},{5,6}) +Result: {17,39}; +In> Dot({5,6},{{1,2},{3,4}}) +Result: {23,34}; +In> Dot({{1,2},{3,4}},{{5,6},{7,8}}) +Result: {{19,22},{43,50}}; + +*SEE Outer, Cross, IsScalar, IsVector, IsMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ExtractSubmatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ExtractSubmatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ExtractSubmatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ExtractSubmatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,title="ExtractSubMatrix" + +//Retract("ExtractSubMatrix",*); + +10 # ExtractSubMatrix( mat_IsMatrix, _row1, _col1, _row2, _col2 )_ + (And(IsPositiveInteger(row1),IsPositiveInteger(col1), + IsPositiveInteger(row2),IsPositiveInteger(col2))) <-- +[ + Local(nrows,ncols,r,row,result); + {nrows,ncols} := Dimensions( mat ); + Check(And(row1>0,col1>0,row1row1,col2>col1,row2<=nrows,col2<=ncols), "Math", "ERROR: LR out of range"); + result := {}; + For(r:=row1,r<=row2,r++) + [ + row := Take( MatrixRow(mat,r), {col1,col2} ); + result := DestructiveAppend( result, row ); + ]; + result; +]; + + +10 # ExtractSubMatrix( mat_IsMatrix, _row1, _col1 )_ + (And(IsPositiveInteger(row1),IsPositiveInteger(col1))) <-- +[ + Local(nrows,ncols); + {nrows,ncols} := Dimensions( mat ); + Check(And(row1>0,col1>0,row1 AM := {{11,12,13,14},{21,22,23,24},{31,32,33,34}} +Result: {{11,12,13,14},{21,22,23,24},{31,32,33,34}} + +In> ExtractSubMatrix(AM,2,2,3,3) +Result: {{22,23},{32,33}} + +In> ExtractSubMatrix(AM,2,2); +Result: {{22,23,24},{32,33,34}} + +In> ExtractSubMatrix(AM,0,2,1,3); +Result: ExtractSubMatrix({{11,12,13,14},{21,22,23,24},{31,32,33,34}},0,2,1,3) + +In> ExtractSubMatrix(AM,1,3,2,5) +Result: +Exception: ERROR: LR out of range + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/FrobeniusNorm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/FrobeniusNorm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/FrobeniusNorm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/FrobeniusNorm.mpw 2010-01-11 03:15:47.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="FrobeniusNorm" + +FrobeniusNorm(matrix_IsMatrix) <-- +[ + Local(i,j,result); + result:=0; + For(i:=1,i<=Length(matrix),i++) + For(j:=1,j<=Length(matrix[1]),j++) + result:=result+Abs(matrix[i][j])^2; + + Sqrt(result); + +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="FrobeniusNorm",categories="User Functions;Linear Algebra" +*CMD FrobeniusNorm --- todo +*CALL + FrobeniusNorm(matrix) + +*PARMS +{matrix} -- a matrix + +*DESC +todo + +*E.G. +todo +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/GaussianDeterminant.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/GaussianDeterminant.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/GaussianDeterminant.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/GaussianDeterminant.mpw 2010-01-11 03:15:47.000000000 +0000 @@ -0,0 +1,65 @@ +%mathpiper,def="GaussianDeterminant" + +GaussianDeterminant(matrix):= +[ + Local(n,s,result); + n:=Length(matrix); + result:=1; + + [ + matrix:=FlatCopy(matrix); + Local(i); + For(i:=1,i<=n,i++) + [ + matrix[i]:=FlatCopy(matrix[i]); + ]; + ]; + + // gaussian elimination + ForEach(i, 1 .. (n-1) ) + [ + ForEach(k, (i+1) .. n ) + [ + s:=matrix[k][i]; + ForEach(j, i .. n ) + [ + matrix[k][j] := matrix[k][j] - (s/matrix[i][i])*matrix[i][j]; + //Echo({"matrix[",k,"][",j,"] =", aug[k][j]," - ", + // matrix[k][i],"/",matrix[i][i],"*",matrix[i][j]," k i =", k,i }); + ]; + ]; + ]; + +//Echo("mat: ",matrix); +//Echo("diagmat: ",Diagonal(matrix)); + // now upper triangular + ForEach(i, Diagonal(matrix) ) + result:=result*i; + result; +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="GaussianDeterminant",categories="User Functions;Linear Algebra" +*CMD GaussianDeterminant --- todo +*CALL + GaussianDeterminant(matrix) + +*PARMS +{matrix} -- a matrix + +*DESC +todo + +*E.G. +todo +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/GenMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/GenMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/GenMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/GenMatrix.mpw 2011-02-05 04:04:44.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="GenMatrix" + +Function("GenMatrix",{func,m,n}) +[ + Local(i,j,result); + result:=ZeroMatrix(m,n); + + For(i:=1,i<=m,i++) + For(j:=1,j<=n,j++) + result[i][j]:=ApplyFast(func,{i,j}); + + result; +]; +HoldArgument("GenMatrix",func); +UnFence("GenMatrix",3); + +%/mathpiper + + + + + +%mathpiper_docs,name="GenMatrix",categories="User Functions;Linear Algebra" +*CMD GenMatrix --- generate a matrix with a function +*CALL + GenMatrix(function,m,n) + +*PARMS +{function} -- a pure function +{m} -- row index +{n} -- column index + +*DESC +Generate a matrix with a pure function. + +*E.G. +In> GenMatrix(Lambda({m,n},m*n),3,3) +Result: {{1,2,3},{2,4,6},{3,6,9}} +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HankelMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HankelMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HankelMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HankelMatrix.mpw 2010-01-11 03:15:47.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="HankelMatrix" + +// The arguments of the following functions should be checked +HankelMatrix(n):=GenMatrix({{i,j}, If(i+j-1>n,0,i+j-1) }, n,n ); +HankelMatrix(m,n):=GenMatrix({{i,j}, If(i+j-1>n,0,i+j-1)}, m,n ); + +%/mathpiper + + + + +%mathpiper_docs,name="HankelMatrix",categories="User Functions;Matrices (Special)" +*CMD HankelMatrix --- todo +*CALL + HankelMatrix(matrix) + +*PARMS +{n} -- todo +{m} -- todo + +*DESC +todo + +*E.G. +todo +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HessianMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HessianMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HessianMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HessianMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="HessianMatrix" + +// The arguments of the following functions should be checked +// this takes 1 func in N vars +HessianMatrix(f,v):=GenMatrix({{i,j}, Deriv(v[i]) Deriv(v[j]) f},Length(v),Length(v)); + +%/mathpiper + + + +%mathpiper_docs,name="HessianMatrix",categories="User Functions;Matrices (Special)" +*CMD HessianMatrix --- create the Hessian matrix +*STD +*CALL + HessianMatrix(function,var) +*PARMS + +{function} -- a function in $n$ variables + +{var} -- an $n$-dimensional vector of variables + +*DESC + +The function {HessianMatrix} calculates the Hessian matrix +of a vector. + +If $f(x)$ is a function of an $n$-dimensional vector $x$, then the ($i$,$j$)-th element of the Hessian matrix of the function $f(x)$ is defined as +$ Deriv(x[i]) Deriv(x[j]) f(x) $. If the third +order mixed partials are continuous, then the Hessian +matrix is symmetric (a standard theorem of calculus). + +The Hessian matrix is used in the second derivative test +to discern if a critical point is a local maximum, a local +minimum or a saddle point. + + +*E.G. + +In> HessianMatrix(3*x^2-2*x*y+y^2-8*y, {x,y} ) +Result: {{6,-2},{-2,2}}; +In> PrettyForm(%) + + / \ + | ( 6 ) ( -2 ) | + | | + | ( -2 ) ( 2 ) | + \ / +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HilbertInverseMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HilbertInverseMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HilbertInverseMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HilbertInverseMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="HilbertInverseMatrix" + +HilbertInverseMatrix(n):=GenMatrix({{i,j}, + (-1)^(i+j)*(i+j-1)*BinomialCoefficient(n+i-1,n-j)*BinomialCoefficient(n+j-1,n-i)*BinomialCoefficient(i+j-2,i-1)^2},n,n); + +%/mathpiper + + + +%mathpiper_docs,name="HilbertInverseMatrix",categories="User Functions;Matrices (Special)" +*CMD HilbertInverseMatrix --- create a Hilbert inverse matrix +*STD +*CALL + HilbertInverseMatrix(n) +*PARMS + +{n} -- positive integer + +*DESC + +The function {HilbertInverseMatrix} returns the {n} by {n} inverse of the +corresponding Hilbert matrix. All Hilbert inverse matrices have integer +entries that grow in magnitude rapidly. + +*E.G. +In> PrettyForm(HilbertInverseMatrix(4)) + + / \ + | ( 16 ) ( -120 ) ( 240 ) ( -140 ) | + | | + | ( -120 ) ( 1200 ) ( -2700 ) ( 1680 ) | + | | + | ( 240 ) ( -2700 ) ( 6480 ) ( -4200 ) | + | | + | ( -140 ) ( 1680 ) ( -4200 ) ( 2800 ) | + \ / + +*SEE HilbertMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HilbertMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HilbertMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/HilbertMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/HilbertMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="HilbertMatrix" + +// The arguments of the following functions should be checked +// notoriously hard to manipulate numerically +HilbertMatrix(n):=GenMatrix({{i,j}, 1/(i+j-1)}, n,n ); +HilbertMatrix(m,n):=GenMatrix({{i,j}, 1/(i+j-1)}, m,n ); + + +%/mathpiper + + + +%mathpiper_docs,name="HilbertMatrix",categories="User Functions;Matrices (Special)" +*CMD HilbertMatrix --- create a Hilbert matrix +*STD +*CALL + HilbertMatrix(n) + HilbertMatrix(n,m) +*PARMS + +{n,m} -- positive integers + +*DESC + +The function {HilbertMatrix} returns the {n} by {m} Hilbert matrix +if given two arguments, and the square {n} by {n} Hilbert matrix +if given only one. The Hilbert matrix is defined as {A(i,j) = 1/(i+j-1)}. +The Hilbert matrix is extremely sensitive to manipulate and invert numerically. + +*E.G. + +In> PrettyForm(HilbertMatrix(4)) + + / \ + | ( 1 ) / 1 \ / 1 \ / 1 \ | + | | - | | - | | - | | + | \ 2 / \ 3 / \ 4 / | + | | + | / 1 \ / 1 \ / 1 \ / 1 \ | + | | - | | - | | - | | - | | + | \ 2 / \ 3 / \ 4 / \ 5 / | + | | + | / 1 \ / 1 \ / 1 \ / 1 \ | + | | - | | - | | - | | - | | + | \ 3 / \ 4 / \ 5 / \ 6 / | + | | + | / 1 \ / 1 \ / 1 \ / 1 \ | + | | - | | - | | - | | - | | + | \ 4 / \ 5 / \ 6 / \ 7 / | + \ / + +*SEE HilbertInverseMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Identity.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Identity.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Identity.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Identity.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="Identity" + +Identity(n_IsNonNegativeInteger) <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=n,i++) + [ + DestructiveAppend(result,BaseVector(i,n)); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Identity",categories="User Functions;Linear Algebra" +*CMD Identity --- make identity matrix +*STD +*CALL + Identity(n) + +*PARMS + +{n} -- size of the matrix + +*DESC + +This commands returns the identity matrix of size "n" by "n". This +matrix has ones on the diagonal while the other entries are zero. + +*E.G. + +In> Identity(3) +Result: {{1,0,0},{0,1,0},{0,0,1}}; + +*SEE BaseVector, ZeroMatrix, DiagonalMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/InfinityNorm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/InfinityNorm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/InfinityNorm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/InfinityNorm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="xnfinityNorm" + +//Retract("InfinityNorm",*); + + +10 # InfinityNorm( M_IsMatrix ) <-- +[ + Local(sumlist,row); + sumlist := {}; + ForEach(row,M) + Push(sumlist,Sum(Abs(row))); + Maximum(sumlist); +]; + +10 # InfinityNorm( M_IsVector ) <-- Maximum(Abs(M)); + +%/mathpiper + + + + + + + +%mathpiper_docs,name="InfinityNorm",categories="User Functions;Linear Algebra" +*CMD InfinityNorm --- Compute the "Infinity Norm" of a Vector or Matrix +*STD +*CALL + InfinityNorm(Matrix) +*PARMS + +{Matrix} -- a Matrix or Vector + + +*DESC + +The function {InfinityNorm} calculates one of the most valuable types +of Norm for Matrices. It can also be applied to Vectors, but is less +often used that way. + +For a Matrix, the so-called "Infinity Norm" is calculated by finding the +sum of the absolute values of all the elements in each row, then returning +the largest of these row sums. + + +*E.G. + +In> InfinityNorm({{3,5,7},{2,-6,4},{0,2,8}}) +Result: 15 + +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/InProduct.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/InProduct.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/InProduct.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/InProduct.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="InProduct" + +Function("InProduct",{aLeft,aRight}) +[ + Local(length); + length:=Length(aLeft); + Check(length = Length(aRight), "Argument", "InProduct: error, vectors not of the same dimension"); + + Local(result); + result:=0; + Local(i); + For(i:=1,i<=length,i++) + [ + result := result + aLeft[i] * aRight[i]; + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="InProduct",categories="User Functions;Linear Algebra" +*CMD InProduct --- inner product of vectors (deprecated) +*STD +*CALL + InProduct(a,b) + +*PARMS + +{a}, {b} -- vectors of equal length + +*DESC + +The inner product of the two vectors "a" and "b" is returned. The +vectors need to have the same size. + +*E.G. + +In> Dot({a,b,c}, {d,e,f}); +Result: a*d+b*e+c*f; + +*SEE Outer, Dot, CrossProduct +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Inverse.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Inverse.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Inverse.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Inverse.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,59 @@ +%mathpiper,def="Inverse" + +Function("Inverse",{matrix}) +[ + Local(perms,indices,inv,det,n); + n:=Length(matrix); + indices:=Table(i,i,1,n,1); + perms:=PermutationsList(indices); + inv:=ZeroMatrix(n,n); + det:=0; + ForEach(item,perms) + [ + Local(i,lc); + lc := LeviCivita(item); + det:=det+Product(i,1,n,matrix[i][item[i] ])* lc; + For(i:=1,i<=n,i++) + [ + inv[item[i] ][i] := inv[item[i] ][i]+ + Product(j,1,n, + If(j=i,1,matrix[j][item[j] ]))*lc; + ]; + ]; + Check(det != 0, "Math", "Zero determinant"); + (1/det)*inv; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Inverse",categories="User Functions;Linear Algebra" +*CMD Inverse --- get inverse of a matrix +*STD +*CALL + Inverse(M) + +*PARMS + +{M} -- a matrix + +*DESC + +Inverse returns the inverse of matrix $M$. The determinant of $M$ should +be non-zero. Because this function uses {Determinant} for calculating +the inverse of a matrix, you can supply matrices with non-numeric (symbolic) +matrix elements. + +*E.G. + +In> A:=DiagonalMatrix({a,b,c}) +Result: {{a,0,0},{0,b,0},{0,0,c}}; +In> B:=Inverse(A) +Result: {{(b*c)/(a*b*c),0,0},{0,(a*c)/(a*b*c),0}, + {0,0,(a*b)/(a*b*c)}}; +In> Simplify(B) +Result: {{1/a,0,0},{0,1/b,0},{0,0,1/c}}; + +*SEE Determinant +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/JacobianMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/JacobianMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/JacobianMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/JacobianMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="JacobianMatrix" + +// The arguments of the following functions should be checked +// this takes N funcs in N vars +JacobianMatrix(f,v):=GenMatrix({{i,j},Deriv(v[j])f[i]},Length(f),Length(f)); + +%/mathpiper + + + +%mathpiper_docs,name="JacobianMatrix",categories="User Functions;Matrices (Special)" +*CMD JacobianMatrix --- calculate the Jacobian matrix of $n$ functions in $n$ variables +*STD +*CALL + JacobianMatrix(functions,variables) + +*PARMS + +{functions} -- an $n$-dimensional vector of functions + +{variables} -- an $n$-dimensional vector of variables + +*DESC + +The function {JacobianMatrix} calculates the Jacobian matrix +of n functions in n variables. + +The ($i$,$j$)-th element of the Jacobian matrix is defined as the derivative +of $i$-th function with respect to the $j$-th variable. + +*E.G. + +In> JacobianMatrix( {Sin(x),Cos(y)}, {x,y} ); +Result: {{Cos(x),0},{0,-Sin(y)}}; +In> PrettyForm(%) + + / \ + | ( Cos( x ) ) ( 0 ) | + | | + | ( 0 ) ( -( Sin( y ) ) ) | + \ / +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/LeviCivita.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/LeviCivita.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/LeviCivita.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/LeviCivita.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,67 @@ +%mathpiper,def="LeviCivita" + +/* Levi-civita symbol */ +Function("LeviCivita",{indices}) +[ + Local(i,j,length,left,right,factor); + length:=Length(indices); + factor:=1; + + For (j:=length,j>1,j--) + [ + For(i:=1,i LeviCivita({1,2,3}) +Result: 1; +In> LeviCivita({2,1,3}) +Result: -1; +In> LeviCivita({2,2,3}) +Result: 0; + +*SEE PermutationsList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/LU.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/LU.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/LU.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/LU.mpw 2010-01-11 03:15:47.000000000 +0000 @@ -0,0 +1,66 @@ +%mathpiper,def="LU" + +// In place LU decomposition +// Pivotting is not implemented +// Adapted from Numerical Methods with Matlab +// Gerald Recktenwald, Sec 8.4 +10 # LU(A_IsSquareMatrix) <-- +[ + Local(n,matrix,L,U); + n:=Length(A); + L:=ZeroMatrix(n,n); + U:=ZeroMatrix(n,n); + matrix:=ZeroMatrix(n,n); + + ForEach(i,1 .. n) + ForEach(j,1 .. n) + matrix[i][j] := A[i][j]; + + // loop over pivot rows + ForEach(i,1 ..(n-1))[ + // loop over column below the pivot + ForEach(k,i+1 .. n)[ + // compute multiplier and store it in L + matrix[k][i] := matrix[k][i] / matrix[i][i]; + // loop over elements in row k + ForEach(j,i+1 .. n)[ + matrix[k][j] := matrix[k][j] - matrix[k][i]*matrix[i][j]; + ]; + ]; + ]; + ForEach(i,1 .. n)[ + ForEach(j,1 .. n)[ + If(i<=j,U[i][j]:=matrix[i][j],L[i][j]:=matrix[i][j]); + ]; + // diagonal of L is always 1's + L[i][i]:=1; + ]; + + {L,U}; +]; + + +%/mathpiper + + + + +%mathpiper_docs,name="LU",categories="User Functions;Linear Algebra" +*CMD LU --- in-place LU decomposition +*CALL + LU(matrix) + +*PARMS +{matrix} -- a matrix + +*DESC +todo + +*E.G. +todo +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixColumn.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixColumn.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixColumn.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixColumn.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,50 @@ +%mathpiper,def="MatrixColumn" + +Function("MatrixColumn",{matrix,col}) +[ + Local(m); + m:=matrix[1]; + + Check(col > 0, "Argument", "MatrixColumn: column index out of range"); + Check(col <= Length(m), "Argument", "MatrixColumn: column index out of range"); + + Local(i,result); + result:={}; + For(i:=1,i<=Length(matrix),i++) + DestructiveAppend(result,matrix[i][col]); + + result; +]; + +%/mathpiper + + + + +%mathpiper_docs,name="MatrixColumn",categories="User Functions;Linear Algebra" +*CMD MatrixColumn --- obtain the column of a matrix +*STD +*CALL + MatrixColumn(matrix,column) + +*PARMS +{matrix} -- a matrix +{column} -- the index of a matrix column + +*DESC +Returns the column of a matrix which is specified by {column}. + +*E.G. +In> A := {{1,2}, {3,4}}; +Result: {{1,2},{3,4}} + +In> MatrixColumn(A,1) +Result: {1,3}} + +*SEE MatrixRow +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixPower.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixPower.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixPower.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixPower.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="MatrixPower" + +////// +// power of a matrix (dr) +////// + +MatrixPower(x_IsSquareMatrix, n_IsNonNegativeInteger) <-- +[ + Local(result); + result:=Identity(Length(x)); + While(n != 0) + [ + If(IsOdd(n), + result:=Dot(result,x)); + x:=Dot(x,x); + n:=n>>1; + ]; + result; +]; + +MatrixPower(x_IsSquareMatrix, n_IsNegativeInteger) <-- + MatrixPower(Inverse(x),-n); + +%/mathpiper + + + +%mathpiper_docs,name="MatrixPower",categories="User Functions;Linear Algebra" +*CMD MatrixPower --- get nth power of a square matrix +*STD +*CALL + MatrixPower(mat,n) + +*PARMS + +{mat} -- a square matrix + +{n} -- an integer + +*DESC + +{MatrixPower(mat,n)} returns the {n}th power of a square matrix {mat}. For +positive {n} it evaluates dot products of {mat} with itself. For negative +{n} the nth power of the inverse of {mat} is returned. For {n}=0 the identity +matrix is returned. + +*E.G. +In> A:={{1,2},{3,4}} +Result: {{1,2},{3,4}}; +In> MatrixPower(A,0) +Result: {{1,0},{0,1}}; +In> MatrixPower(A,1) +Result: {{1,2},{3,4}}; +In> MatrixPower(A,3) +Result: {{37,54},{81,118}}; +In> MatrixPower(A,-3) +Result: {{-59/4,27/4},{81/8,-37/8}}; + +*SEE IsSquareMatrix, Inverse, Dot +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixRowAndColumnOps.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixRowAndColumnOps.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixRowAndColumnOps.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixRowAndColumnOps.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,95 @@ +%mathpiper,def="MatrixRowAndColumnOps" + +//Retract("MatrixRowReplace",*); +//Retract("MatrixRowSwap",*); +//Retract("MatrixRowStack",*); +//Retract("MatrixColumnReplace",*); +//Retract("MatrixColumnSwap",*); +//Retract("MatrixColumnAugment",*); + +MatrixRowReplace( M_IsMatrix, iRow_IsPositiveInteger, v_IsVector )_(Length(v)=Length(M[1])) <-- +[ + If( Not IsBound(iDebug), iDebug := False ); + If( iDebug, Tell(MatrixRowReplace,{M,iRow,v}) ); + Local(mRows,nCols); + {mRows,nCols} := Dimensions(M); + If( iRow <= mRows, DestructiveReplace(M,iRow,v) ); + M; +]; + + +MatrixRowSwap( M_IsMatrix, iRow1_IsPositiveInteger, iRow2_IsPositiveInteger )_ + (And(iRow1<=Dimensions(M)[1],iRow2<=Dimensions(M)[1])) <-- +[ + If( Not IsBound(iDebug), iDebug := False ); + If( iDebug, Tell(MatrixRowSwap,{M,iRow1,iRow2}) ); + Local(row1,row2); + If( iRow1 != iRow2, + [ + row1 := MatrixRow(M,iRow1); row2 := MatrixRow(M,iRow2); + DestructiveReplace(M,iRow1,row2); DestructiveReplace(M,iRow2,row1); + ] + ); + M; +]; + + +MatrixRowStack( M_IsMatrix, v_IsVector )_(Length(v)=Dimensions(M)[1]) <-- +[ + If( Not IsBound(iDebug), iDebug := False ); + If( iDebug, Tell(MatrixRowStack,{M,v}) ); + Local(mRows,nCols,newMat,ir); + {mRows,nCols} := Dimensions(M); + newMat := ZeroMatrix(mRows+1,nCols); + For(ir:=1,ir 0, "Argument", "MatrixRow: row index out of range"); + Check(row <= Length(matrix), "Argument", "MatrixRow: row index out of range"); + + Local(result); + result:=matrix[row]; + + result; +]; + +%/mathpiper + + + + +%mathpiper_docs,name="MatrixRow",categories="User Functions;Linear Algebra" +*CMD MatrixRow --- obtain the row of a matrix +*STD +*CALL + MatrixRow(matrix,row) + +*PARMS +{matrix} -- a matrix +{row} -- the index of a matrix row + +*DESC +Returns the row of a matrix which is specified by {row}. + +*E.G. +In> A := {{1,2}, {3,4}}; +Result: {{1,2},{3,4}} + +In> MatrixRow(A,1) +Result: {1,2} + +*SEE MatrixColumn +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixSolve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixSolve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/MatrixSolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/MatrixSolve.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,157 @@ +%mathpiper,def="MatrixSolve" + +//Retract("MatrixSolve",*); + +10 # MatrixSolve(matrix_IsDiagonal,b_IsVector) <-- +[ + If(InVerboseMode(),Tell(" MatrixSolve_diag",{matrix,b})); + Local(rowsm,rowsb,x); + rowsm:=Length(matrix); + rowsb:=Length(b); + Check(rowsm=rowsb, "Argument", "MatrixSolve: Matrix and vector must have same number of rows"); + x:=ZeroVector(rowsb); + ForEach(i,1 .. rowsb) + x[i]:=b[i]/matrix[i][i]; + x; +]; + +// Backward Substitution +15 # MatrixSolve(matrix_IsUpperTriangular,b_IsVector) <-- +[ + If(InVerboseMode(),Tell(" MatrixSolve_ut",{matrix,b})); + Local(rowsm,rowsb,x,s); + rowsm:=Length(matrix); + rowsb:=Length(b); + Check(rowsm=rowsb, "Argument", "MatrixSolve: Matrix and vector must have same number of rows"); + x:=ZeroVector(rowsb); + + x[rowsb]:=b[rowsb]/matrix[rowsb][rowsb]; + If(InVerboseMode(),Echo({"set x[",rowsb,"] = ",b[rowsb]/matrix[rowsb][rowsb]})); + + ForEach(i,(rowsb-1) .. 1 )[ + s:=b[i]; + ForEach(j,i+1 .. rowsb )[ + s:= s - matrix[i][j]*x[j]; + ]; + x[i]:= s/matrix[i][i]; + If(InVerboseMode(),Echo({"set x[",i,"] = ",s/matrix[i][i]})); + ]; + x; +]; + +// Forward Substitution +15 # MatrixSolve(matrix_IsLowerTriangular,b_IsVector) <-- +[ + If(InVerboseMode(),Tell(" MatrixSolve_lt",{matrix,b})); + Local(rowsm,rowsb,x,s); + rowsm:=Length(matrix); + rowsb:=Length(b); + Check(rowsm=rowsb, "Argument", "MatrixSolve: Matrix and vector must have same number of rows"); + x:=ZeroVector(rowsb); + + x[1]:=b[1]/matrix[1][1]; + If(InVerboseMode(),Echo({"set x[1] = ",b[1]/matrix[1][1]})); + + ForEach(i,2 .. rowsb )[ + s:=b[i]; + ForEach(j,1 .. (i-1) )[ + s:= s - matrix[i][j]*x[j]; + ]; + x[i]:= s/matrix[i][i]; + If(InVerboseMode(),Echo({"set x[",i,"] = ",s/matrix[i][i]})); + ]; + x; +]; +// Gaussian Elimination and Back Substitution +// pivoting not implemented yet +20 # MatrixSolve(matrix_IsMatrix,b_IsVector) <-- +[ + If(InVerboseMode(),Tell(" MatrixSolve",{matrix,b})); + Local(aug,rowsm,rowsb,x,s); + rowsm:=Length(matrix); + rowsb:=Length(b); + Check(rowsm=rowsb, "Argument", "MatrixSolve: Matrix and vector must have same number of rows"); + aug:=ZeroMatrix(rowsb,rowsb+1); + x:=ZeroVector(rowsb); + + // create augmented matrix + ForEach(i, 1 .. rowsb ) + ForEach(j, 1 .. rowsb ) + aug[i][j] := matrix[i][j]; + ForEach(i, 1 .. rowsb ) + aug[i][rowsb+1] := b[i]; + + // gaussian elimination + ForEach(i, 1 .. (rowsb-1) )[ + // If our pivot element is 0 we need to switch + // this row with a row that has a nonzero element + If(aug[i][i] = 0, [ + Local(p,tmp); + p:=i+1; + While( aug[p][p] = 0 )[ p++; ]; + If(InVerboseMode(), Echo({"switching row ",i,"with ",p}) ); + tmp:=aug[i]; + aug[i]:=aug[p]; + aug[p]:=tmp; + ]); + + + ForEach(k, (i+1) .. rowsb )[ + s:=aug[k][i]; + ForEach(j, i .. (rowsb+1) )[ + aug[k][j] := aug[k][j] - (s/aug[i][i])*aug[i][j]; + //Echo({"aug[",k,"][",j,"] =", aug[k][j]," - ", + // aug[k][i],"/",aug[i][i],"*",aug[i][j]," k i =", k,i }); + ]; + ]; + ]; + //PrettyForm(aug); + x[rowsb]:=aug[rowsb][rowsb+1]/aug[rowsb][rowsb]; + If(InVerboseMode(),Echo({"set x[",rowsb,"] = ",x[rowsb] })); + + ForEach(i,(rowsb-1) .. 1 )[ + s:=aug[i][rowsb+1]; + ForEach(j,i+1 .. rowsb)[ + s := s - aug[i][j]*x[j]; + ]; + x[i]:=Simplify(s/aug[i][i]); + If(InVerboseMode(),Echo({"set x[",i,"] = ",x[i] })); + ]; + x; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="MatrixSolve",categories="User Functions;Solvers (Symbolic);Linear Algebra" +*CMD MatrixSolve --- solve a system of equations +*STD +*CALL + MatrixSolve(A,b) + +*PARMS + +{A} -- coefficient matrix + +{b} -- row vector + +*DESC + +{MatrixSolve} solves the matrix equations {A*x = b} using Gaussian Elimination +with Backward substitution. If your matrix is triangular or diagonal, it will +be recognized as such and a faster algorithm will be used. + +*E.G. + +In> A:={{2,4,-2,-2},{1,2,4,-3},{-3,-3,8,-2},{-1,1,6,-3}}; +Result: {{2,4,-2,-2},{1,2,4,-3},{-3,-3,8,-2},{-1,1,6,-3}}; +In> b:={-4,5,7,7}; +Result: {-4,5,7,7}; +In> MatrixSolve(A,b); +Result: {1,2,3,4}; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Minor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Minor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Minor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Minor.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="Minor" + +Minor(matrix,i,j) := CoFactor(matrix,i,j)*(-1)^(i+j); + +%/mathpiper + + + +%mathpiper_docs,name="Minor",categories="User Functions;Linear Algebra" +*CMD Minor --- get principal minor of a matrix +*STD +*CALL + Minor(M,i,j) + +*PARMS + +{M} -- a matrix + +{i}, {j} - positive integers + +*DESC + +Minor returns the minor of a matrix around +the element ($i$, $j$). The minor is the determinant of the matrix obtained from $M$ by +deleting the $i$-th row and the $j$-th column. + +*E.G. + +In> A := {{1,2,3}, {4,5,6}, {7,8,9}}; +Result: {{1,2,3},{4,5,6},{7,8,9}}; +In> PrettyForm(A); + + / \ + | ( 1 ) ( 2 ) ( 3 ) | + | | + | ( 4 ) ( 5 ) ( 6 ) | + | | + | ( 7 ) ( 8 ) ( 9 ) | + \ / +Result: True; +In> Minor(A,1,2); +Result: -6; +In> Determinant({{2,3}, {8,9}}); +Result: -6; + +*SEE CoFactor, Determinant, Inverse +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Normalize.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Normalize.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Normalize.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Normalize.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="Normalize" + +Function("Normalize",{vector}) +[ + Local(norm); + norm:=0; + ForEach(item,vector) + [ + norm:=norm+item*item; + ]; + (1/(norm^(1/2)))*vector; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Normalize",categories="User Functions;Linear Algebra" +*CMD Normalize --- normalize a vector +*STD +*CALL + Normalize(v) + +*PARMS + +{v} -- a vector + +*DESC + +Return the normalized (unit) vector parallel to {v}: a vector having the same +direction but with length 1. + +*E.G. + +In> v:=Normalize({3,4}) +Result: {3/5,4/5}; +In> Dot(v, v) +Result: 1; + +*SEE InProduct, CrossProduct +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Norm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Norm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Norm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Norm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,29 @@ +%mathpiper,def="Norm" + +10 # Norm(_v) <-- PNorm(v,2); + +%/mathpiper + + + +%mathpiper_docs,name="Norm",categories="User Functions;Linear Algebra" +*CMD Norm --- the norm (magnitude or length) of a vector +*STD +*CALL + Norm(v) + +*PARMS + +{v} -- a vector + +*DESC + +Return the norm (i.e., the magnitude, or length) of vector {v} + +*E.G. + +In> Norm({3,4}) + Result: 5 + +*SEE InProduct, CrossProduct, Normalize +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/o_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/o_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/o_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/o_operator.mpw 2010-01-11 03:15:47.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="o" + +_x o _y <-- Outer(x,y); + +%/mathpiper + + + +%mathpiper_docs,name="o",categories="Operators" +*CMD o --- get outer tensor product +*STD +*CALL + t1 o t2 + +*PARMS + +{t1,t2} -- tensor lists (currently only vectors are supported) + +*DESC + +See the {Outer} function for more information. + +*SEE Outer +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/OrthogonalBasis.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/OrthogonalBasis.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/OrthogonalBasis.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/OrthogonalBasis.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,49 @@ +%mathpiper,def="OrthogonalBasis" + +// This is the standard textbook definition of the Gram-Schmidt +// Orthogonalization process, from: +// Friedberg,Insel,Spence "Linear Algebra" (1997) +// TODO: This function does not check if the input vectors are LI, it +// only checks for zero vectors +Function("OrthogonalBasis",{W})[ + Local(V,j,k); + + V:=ZeroMatrix(Length(W),Length(W[1]) ); + + V[1]:=W[1]; + For(k:=2,k<=Length(W),k++)[ + Check(Not IsZero(Norm(W[k])), "Argument", "OrthogonalBasis: Input vectors must be linearly independent"); + V[k]:=W[k]-Sum(j,1,k-1,InProduct(W[k],V[j])*V[j]/Norm(V[j])^2); + ]; + V; +]; + +%/mathpiper + + + +%mathpiper_docs,name="OrthogonalBasis",categories="User Functions;Linear Algebra" +*CMD OrthogonalBasis --- create an orthogonal basis +*STD +*CALL + OrthogonalBasis(W) + +*PARMS + +{W} - A linearly independent set of row vectors (aka a matrix) + +*DESC + +Given a linearly independent set {W} (constructed of rows vectors), +this command returns an orthogonal basis {V} for {W}, which means +that span(V) = span(W) and {InProduct(V[i],V[j]) = 0} when {i != j}. +This function uses the Gram-Schmidt orthogonalization process. + +*E.G. + +In> OrthogonalBasis({{1,1,0},{2,0,1},{2,2,1}}) +Result: {{1,1,0},{1,-1,1},{-1/3,1/3,2/3}}; + + +*SEE OrthonormalBasis, InProduct +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/OrthonormalBasis.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/OrthonormalBasis.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/OrthonormalBasis.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/OrthonormalBasis.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="OrthonormalBasis" + +// Like orthogonalization, only normalize all vectors +Function("OrthonormalBasis",{W})[ + Local(i); + W:=OrthogonalBasis(W); + For(i:=1,i<=Length(W),i++)[ + W[i]:=W[i]/Norm(W[i]); + ]; + W; +]; + +%/mathpiper + + + +%mathpiper_docs,name="OrthonormalBasis",categories="User Functions;Linear Algebra" +*CMD OrthonormalBasis --- create an orthonormal basis +*STD +*CALL + OrthonormalBasis(W) + +*PARMS + +{W} - A linearly independent set of row vectors (aka a matrix) + +*DESC + +Given a linearly independent set {W} (constructed of rows vectors), +this command returns an orthonormal basis {V} for {W}. This is done +by first using {OrthogonalBasis(W)}, then dividing each vector by its +magnitude, so as the give them unit length. + +*E.G. + +In> OrthonormalBasis({{1,1,0},{2,0,1},{2,2,1}}) +Result: {{Sqrt(1/2),Sqrt(1/2),0},{Sqrt(1/3),-Sqrt(1/3),Sqrt(1/3)}, + {-Sqrt(1/6),Sqrt(1/6),Sqrt(2/3)}}; + +*SEE OrthogonalBasis, InProduct, Normalize +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Outer.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Outer.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Outer.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Outer.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="Outer" + +// outer product of vectors +Outer(t1_IsVector, t2_IsVector) <-- +[ + Local(i,j,n,m,result); + n:=Length(t1); + m:=Length(t2); + result:=ZeroMatrix(n,m); + For(i:=1,i<=n,i++) + For(j:=1,j<=m,j++) + result[i][j]:=t1[i]*t2[j]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Outer",categories="User Functions;Linear Algebra" +*CMD Outer, o --- get outer tensor product +*STD +*CALL + Outer(t1,t2) + t1 o t2 +Precedence: +*EVAL PrecedenceGet("o") + +*PARMS + +{t1,t2} -- tensor lists (currently only vectors are supported) + +*DESC + +{Outer} returns the outer product of two tensors t1 and t2. Currently +{Outer} work works only for vectors, i.e. tensors of rank 1. The outer +product of two vectors yields a matrix. + +*E.G. + +In> Outer({1,2},{3,4,5}) +Result: {{3,4,5},{6,8,10}}; +In> Outer({a,b},{c,d}) +Result: {{a*c,a*d},{b*c,b*d}}; + + Or, using the "o"-Operator: + +In> {1,2} o {3,4,5} +Result: {{3,4,5},{6,8,10}}; +In> {a,b} o {c,d} +Result: {{a*c,a*d},{b*c,b*d}}; + + +*SEE InProduct, Dot, Cross +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/period_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/period_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/period_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/period_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="" + +////// +// dot product for vectors and matrices (dr) +////// + +//_x . _y <-- Dot(x,y); + +%/mathpiper + + + + +mathpiper_docs,name=".",categories="Operators" +*CMD . --- get dot product of tensors +*STD +*CALL + t1 . t2 +Precedence: +*EVAL PrecedenceGet(".") + +*PARMS + +{t1,t2} -- tensor lists (currently only vectors and matrices are supported) + +*DESC + +See the {Dot} function for more information. + +*SEE Dot +/mathpiper_docs + + + Or, using the "."-Operator: + +In> {1,2} . {3,4} +Result: 11; +In> {{1,2},{3,4}} . {5,6} +Result: {17,39}; +In> {5,6} . {{1,2},{3,4}} +Result: {23,34}; +In> {{1,2},{3,4}} . {{5,6},{7,8}} +Result: {{19,22},{43,50}}; \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/PNorm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/PNorm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/PNorm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/PNorm.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="PNorm" + +// p-norm, reduces to euclidean norm when p = 2 +Function("PNorm",{v,p}) +[ + Local(result,i); + Check(p>=1, "Argument", "PNorm: p must be >= 1"); + + result:=0; + For(i:=1,i<=Length(v),i++)[ + result:=result+Abs(v[i])^p; + ]; + + // make it look nicer when p = 2 + If(p=2,Sqrt(result),(result)^(1/p) ); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="PNorm",categories="User Functions;Linear Algebra" +*CMD PNorm --- todo:? +*CALL + PNorm(v,p) + +*PARMS +{v} -- ? +{p} -- ? + +*DESC +? + +*E.G. +todo +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/RecursiveDeterminant.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/RecursiveDeterminant.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/RecursiveDeterminant.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/RecursiveDeterminant.mpw 2010-01-11 03:15:47.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="RecursiveDeterminant" + +/* Recursive calculation of determinant, provided by Sebastian Ferraro + */ +20 # RecursiveDeterminant(_matrix) <-- +[ + /* + + */ + Local(result); + If(IsEqual(Length(matrix),1),matrix[1][1],[ + result:=0; + ForEach(i,1 .. Length(matrix)) + //Consider only non-zero entries + If(Not(IsEqual(matrix[1][i],0)), + //Transpose and Drop eliminate row 1, column i + result:=result+matrix[1][i]*(-1)^(i+1)* RecursiveDeterminant(Transpose(Drop(Transpose(Drop(matrix,{1,1})),{i,i})))); + result; + ]); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="RecursiveDeterminant",categories="User Functions;Linear Algebra" +*CMD RecursiveDeterminant --- computes a determinant recursively +*STD +*CALL + RecursiveDeterminant(matrix) + +*PARMS +{matrix} -- a matrix +*DESC +Computes a determinant recursively by summing the product of each (nonzero) element +on the first row of the matrix by +/- the determinant of the submatrix with the +corresponding row and column deleted. + +*E.G. +todo +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ReducedRowEchelonForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ReducedRowEchelonForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ReducedRowEchelonForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ReducedRowEchelonForm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,211 @@ +%mathpiper,def="ReducedRowEchelonForm" + +//Retract("ReducedRowEchelonForm",*); + +10 # ReducedRowEchelonForm( am_IsMatrix ) <-- +[ + If(InVerboseMode(),Tell("Reduced Row Echelon Form",am)); + Local(r,c,eps,ii,jj,e,pivot,scalar,singular); + singular := False; + {r,c} := Dimensions(am); + LHS := ExtractSubMatrix(am,1,1,r,r); + eps := N(Abs(InfinityNorm(LHS))*10^(-BuiltinPrecisionGet())); // somewhat arbitrary! + If(InVerboseMode(), + [ + Tell(" ",{r,c}); + Tell(" ",Determinant(LHS)); + Tell(" ",InfinityNorm(LHS)); + Tell(" ",eps); + ] + ); + + // L O W E R T R I A N G L E + If(InVerboseMode(), + [ + NewLine(); + Tell("LOWER TRIANGLE"); + Tell(" range_r",1 ..r); + Tell(" range_c",1 ..c); + NewLine(); + ] + ); + ForEach(ii,1 .. r) + [ + If(InVerboseMode(),Echo(" Row ",ii," is ",am[ii])); + ForEach(jj,1 .. c) + [ + e := am[ii][jj]; + If(ii=jj And e!=1, + [ + pivot := e; + If( Abs(pivot)jj And Abs(e)>eps, + [ + scalar := e; + If(InVerboseMode(), + [ + Echo(" Row ",jj," is ",am[jj]); + Echo(" Subtracting ",scalar," times Row ",jj," from Row ",ii); + ] + ); + am[ii] := am[ii] - scalar * am[jj]; + If(InVerboseMode(), + [ + Echo(" Row ",ii," goes to ",am[ii]); + NewLine(); + ] + ); + ] + ); + ] + ); + ]; + ]; + //TableForm(am); + + If( Not singular, + [ + // U P P E R T R I A N G L E + If(InVerboseMode(), + [ + NewLine(); + Tell("UPPER TRIANGLE"); + Tell(" range_r",Reverse(1 ..r)); + Tell(" range_c",Reverse(1 ..c)); + NewLine(); + ] + ); + ForEach(ii,Reverse(1 .. r)) + [ + If(InVerboseMode(),Echo(" Row ",ii," is ",am[ii])); + ForEach(jj,Reverse(1 .. c)) + [ + e := am[ii][jj]; + If(iieps, + [ + scalar := e; + If(InVerboseMode(), + [ + Echo(" Row ",jj," is ",am[jj]); + Echo(" Subtracting ",scalar," times Row ",jj," from Row ",ii); + ] + ); + am[ii] := am[ii] - scalar * am[jj]; + If(InVerboseMode(), + [ + Echo(" Row ",ii," goes to ",am[ii]); + NewLine(); + ] + ); + ] + ); + ]; + ]; + //TableForm(am); + ] + ); + am; +]; + +%/mathpiper + + + + + + +%mathpiper_docs,name="ReducedRowEchelonForm",categories="User Functions;Linear Algebra" +*CMD ReducedRowEchelonForm --- convert a system of equations to reduced row echelon form +*STD +*CALL + ReducedRowEchelonForm(AugmentedMatrix) + +*PARMS + +{AugmentedMatrix} -- Augmented matrix describing the system of equations + + +*DESC + +{ReducedRowEchelonForm} solves a system of linear equations by using the Gauss-Jordan +elimination method with partial pivoting, to convert the augmented matrix to the +(unique) reduced row echelon form. +The original matrix is modified in place. + +If the system of equations has a unique solution, this function returns a matrix in +a form like +[ 1 0 0 a] +[ 0 1 0 b] +[ 0 0 1 c] +where the diagonal form of the left submatrix indicates that the solution is unique +and has been found, and the right-hand column is the vector of solutions. + +If the system of equations has {no} solution, this function returns a matrix in +a form like +[ 1 0 0 a] +[ 0 1 0 b] +[ 0 0 0 c] +where the presence of a row like {0 0 0 c} at the bottom indicates that the system is +inconsistent and has no solution (0==c). + +If the system of equations is {dependent} and has a family of valid solutions, this +function returns a matrix in a form like +[ 1 0 q a] +[ 0 1 0 b] +[ 0 0 0 0] +where the presence of a row (or several rows) of all zeros at the bottom indicates +that the corresponding variables appear as parameters describing a family of solutions +for the remaining variables. + + +*E.G. + +In> AM := {{2,-3,2,3},{4,8,1,2},{1,7,-3,-14}}; +Result: {{2,-3,2,3},{4,8,1,2},{1,7,-3,-14}} + +In> ReducedRowEchelonForm(AM) +Result: {{1,0,0,-3},{0,1,0,1},{0,0,1,6}} + +NOTE: This is fully solved. The solution is + {{x==-3},{y==1},{z==6}} + +In> AM := {{2,-1,3},{6,-3,9}}; +Result: {{2,-1,3},{6,-3,9}} + +In> ReducedRowEchelonForm(AM) +Result: {{1,(-1)/2,3/2},{0,0,0}} + +NOTE: This is a "dependent" set of equations. + The presence of a row of zeros at the bottom of the result + shows that the solution is + {{x==x},{y==2*x-3}} for any real x. + +In> AM := {{2,-4,6,5},{-1,3,-2,-1},{1,-2,3,1}}; +Result: {{2,-4,6,5},{-1,3,-2,-1},{1,-2,3,1}} + +In> ReducedRowEchelonForm(AM) +Result: {{1,-2,3,5/2},{0,1,1,3/2},{0,0,0,(-3)/2}} + +NOTE: This is an "inconsistent" set of equations. + The last row, which states that 0==-3/2, shows + that there is no solution. +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/RREF.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/RREF.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/RREF.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/RREF.mpw 2011-03-11 03:22:18.000000000 +0000 @@ -0,0 +1,199 @@ +%mathpiper,title="RREF" + +//Retract("RREF",*); + +/*------------------------------------------------------------------------ + * RREF + * Takes an Augmented Matrix AM and convert it to Reduced Row Echelon + * Form (Row Canonical Form). + * + * Algorithm based on Anton & Rorres, Elementary Linear Algebra, p 10ff + * + *------------------------------------------------------------------------*/ + +10 # RREF( AM_IsMatrix ) <-- +[ + If( Not IsBound(iDebug), iDebug := False ); + If(iDebug,Tell("RREF",AM)); + Local(mRows,nCols,nVars,varVec,ir,jc,col,am,e,ii,pivot); + {mRows,nCols} := Dimensions(AM); + am := FlatCopy(AM); // so as not to mess with original matrix! + + Local(cc,cr,col,cnz); // cc = current column, cr = current row + cc := 1; // initialize cc and cr to 1, to start with + cr := 1; + + While( cr <= mRows ) // iterating over successively lower submatrices + [ + // STEP 1: Locate first (sub)column that is NOT all zeros + If(iDebug, Tell(" STEP 1")); + cnz := 0; // column number of first non-zero column in submatrix + For(ic:=1,ic<=nCols,ic++) + [ + col := MatrixColumn(am,ic); + If( cr > 1, col := Drop( col, {1,cr-1} ) ); + //Tell(" ",{ic,col}); + If(Not IsZeroVector(col), [cnz := ic; Break();]); + ]; + cc := cnz; + If( iDebug, Tell(" first non-zero column is ",cc)); + + // STEP 2:: Now, find the first row which does not have a zero in column cc, + // and bring it to the top if necessary + If(iDebug, Tell(" STEP 2")); + For( ir:=cr, ir<=mRows,ir++ ) + [ + If( am[ir][cc] != 0 And ir != 1, + [ + {am[ir],am[cr]} := {am[cr],am[ir]}; + If(iDebug, Tell(" swapping rows ",{cr,ir})); + Break(); + ] + ); + ]; + If(iDebug,[Tell("working matrix");TableForm(am);]); + + // STEP 3: If the entry am[cr][cc] = a, then multiply row cr by 1/a + // in order to introduce a leading 1. + If(iDebug, Tell(" STEP 3")); + am[cr] := am[cr]/am[cr][cc]; + If(iDebug,TableForm(am)); + + // STEP 4: Add suitable multiples of the top row to the rows below, + // so that all entries below the leading 1 become zeros. + If(iDebug, Tell(" STEP 4")); + For(ir:=cr+1,ir<=mRows,ir++) + [ + If( am[ir][cc] != 0, + [ + am[ir] := am[ir] - am[ir][cc]*am[cr]; + ] + ); + ]; + If(iDebug,TableForm(am)); + + // STEP 5: Now cover the top row and begin again with STEP 1, + // applied to the submatrix that remains. Continue until the + // entire matrix is in row-echelon form + If(iDebug, Tell(" STEP 5")); + cr := cr + 1; + If(iDebug And cr <= mRows, [NewLine();Tell(" ",cr);]); + //Tell(" ",cr); + //Tell(" ",am[cr]); + If( cr=mRows And IsZeroVector(am[cr]), Break() ); + ]; // end while cr <= mRows + + // STEP 6: convert to unique reduced row-echelon form + // Beginning with the last non-zero row, and working upward, + // add suitable multiples of each row to the rows above to + // introduce zeros above the leading 1's. + If(iDebug, Tell(" STEP 6")); + Local(pc,jr); + For(ir:=mRows,ir>1,ir--) + [ + + If(iDebug,Tell("",{ir,am[ir]})); + If(IsZeroVector(am[ir]), + [If(iDebug,Tell(" trailing row of zeros: row ",ir)); ir:=ir-1;Continue();], + [ + pc := Find(am[ir],1); // find leading 1 in row + If(pc > 0, + [ + For(jr:=ir-1,jr>=1,jr--) + [ + If(am[jr][pc]!=0, am[jr]:=am[jr]-am[jr][pc]*am[ir]); + If(iDebug,[NewLine();TableForm(am);]); + ]; + ] + ); + ] + ); + ]; + am; +]; +%/mathpiper + + + + +%mathpiper_docs,name="RREF",categories="User Functions;Linear Algebra" +*CMD RREF --- convert a system of equations to reduced row echelon form +*STD +*CALL + RREF(AugmentedMatrix) + +*PARMS + +{AugmentedMatrix} -- Augmented matrix describing the system of equations + + +*DESC + +{RREF} solves a system of linear equations by using the Gauss-Jordan +elimination method with partial pivoting, to convert the augmented matrix to the +(unique) reduced row echelon form. +The original matrix is not modified. + +If the system of equations has a unique solution, this function returns a matrix in +a form like +[ 1 0 0 a] +[ 0 1 0 b] +[ 0 0 1 c] +where the diagonal form of the left submatrix indicates that the solution is unique +and has been found, and the right-hand column is the vector of solutions. + +If the system of equations has {no} solution, this function returns a matrix in +a form like +[ 1 0 0 a] +[ 0 1 0 b] +[ 0 0 0 c] +where the presence of a row like {0 0 0 c} at the bottom indicates that the system is +inconsistent and has no solution (0==c). + +If the system of equations is {dependent} and has a family of valid solutions, this +function returns a matrix in a form like +[ 1 0 q a] +[ 0 1 0 b] +[ 0 0 0 0] +where the presence of a row (or several rows) of all zeros at the bottom indicates +that the corresponding variables appear as parameters describing a family of solutions +for the remaining variables. + + +*E.G. + +In> AM := {{2,-3,2,3},{4,8,1,2},{1,7,-3,-14}}; +Result: {{2,-3,2,3},{4,8,1,2},{1,7,-3,-14}} + +In> RREF(AM) +Result: {{1,0,0,-3},{0,1,0,1},{0,0,1,6}} + +NOTE: This is fully solved. The solution is + {{x==-3},{y==1},{z==6}} + +In> AM := {{2,-1,3},{6,-3,9}}; +Result: {{2,-1,3},{6,-3,9}} + +In> RREF(AM) +Result: {{1,(-1)/2,3/2},{0,0,0}} + +NOTE: This is a "dependent" set of equations. + The presence of a row of zeros at the bottom of the result + shows that the solution is + {{x==x},{y==2*x-3}} for any real x. + +In> AM := {{2,-4,6,5},{-1,3,-2,-1},{1,-2,3,1}}; +Result: {{2,-4,6,5},{-1,3,-2,-1},{1,-2,3,1}} + +In> RREF(AM) +Result: {{1,0,5,0},{0,1,1,0},{0,0,0,1}} +NOTE: This is an "inconsistent" set of equations. + The last row, which states that 0==1, shows + that there is no solution. +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Sparsity.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Sparsity.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Sparsity.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Sparsity.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper,def="Sparsity" + +Function("Sparsity",{matrix}) +[ + Local(rows,cols,nonzero); + nonzero:=0; + rows:=Length(matrix); + cols:=Length(matrix[1]); + ForEach(i, 1 .. rows ) + ForEach(j, 1 .. cols ) + If(matrix[i][j] != 0, nonzero:=nonzero+1 ); + + N(1 - nonzero/(rows*cols)); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Sparsity",categories="User Functions;Linear Algebra" +*CMD Sparsity --- get the sparsity of a matrix +*STD +*CALL + Sparsity(matrix) +*PARMS + +{matrix} -- a matrix + +*DESC + +The function {Sparsity} returns a number between {0} and {1} which +represents the percentage of zero entries in the matrix. Although +there is no definite critical value, a sparsity of {0.75} or more +is almost universally considered a "sparse" matrix. These type of +matrices can be handled in a different manner than "full" matrices +which speedup many calculations by orders of magnitude. + +*E.G. + +In> Sparsity(Identity(2)) +Result: 0.5; +In> Sparsity(Identity(10)) +Result: 0.9; +In> Sparsity(HankelMatrix(10)) +Result: 0.45; +In> Sparsity(HankelMatrix(100)) +Result: 0.495; +In> Sparsity(HilbertMatrix(10)) +Result: 0; +In> Sparsity(ZeroMatrix(10,10)) +Result: 1; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/SylvesterMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/SylvesterMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/SylvesterMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/SylvesterMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,89 @@ +%mathpiper,def="SylvesterMatrix" + +/* SylvesterMatrix */ + +Function("SylvesterMatrix",{poly1, poly2, var}) +[ + Local(i,m,p,q,y,z,result); + y:=Degree(poly1,var); + z:=Degree(poly2,var); + m:=y+z; + p:={}; + q:={}; + result:=ZeroMatrix(m,m); + + For(i:=y,i>=0,i--) + DestructiveAppend(p,Coef(poly1,var,i)); + For(i:=z,i>=0,i--) + DestructiveAppend(q,Coef(poly2,var,i)); + + For(i:=1,i<=z,i++) + [ + Local(j,k); + k:=1; + For(j:=i,k<=Length(p),j++) + [ + result[i][j]:=p[k]; + k++; + ]; + ]; + + For(i:=1,i<=y,i++) + [ + Local(j,k); + k:=1; + For(j:=i,k<=Length(q),j++) + [ + result[i+z][j]:=q[k]; + k++; + ]; + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="SylvesterMatrix",categories="User Functions;Matrices (Special)" +*CMD SylvesterMatrix --- calculate the Sylvester matrix of two polynomials +*STD +*CALL + SylvesterMatrix(poly1,poly2,variable) + +*PARMS + +{poly1} -- polynomial + +{poly2} -- polynomial + +{variable} -- variable to express the matrix for + +*DESC + +The function {SylvesterMatrix} calculates the Sylvester matrix +for a pair of polynomials. + +The Sylvester matrix is closely related to the resultant, which +is defined as the determinant of the Sylvester matrix. Two polynomials +share common roots only if the resultant is zero. + +*E.G. + +In> ex1:= x^2+2*x-a +Result: x^2+2*x-a; +In> ex2:= x^2+a*x-4 +Result: x^2+a*x-4; +In> A:=SylvesterMatrix(ex1,ex2,x) +Result: {{1,2,-a,0},{0,1,2,-a}, + {1,a,-4,0},{0,1,a,-4}}; +In> B:=Determinant(A) +Result: 16-a^2*a- -8*a-4*a+a^2- -2*a^2-16-4*a; +In> Simplify(B) +Result: 3*a^2-a^3; + +The above example shows that the two polynomials have common +zeros if $ a = 3 $. + +*SEE Determinant, Simplify, Solve, PSolve +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/SymbolicDeterminant.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/SymbolicDeterminant.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/SymbolicDeterminant.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/SymbolicDeterminant.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="SymbolicDeterminant" + +20 # SymbolicDeterminant(_matrix) <-- +[ + Local(perms,indices,result); + Check((IsMatrix(matrix)), "Argument", "Determinant: Argument must be a matrix"); + indices:=Table(i,i,1,Length(matrix),1); + perms:=PermutationsList(indices); + result:=0; + ForEach(item,perms) + result:=result+Product(i,1,Length(matrix),matrix[i][item[i] ])* + LeviCivita(item); + result; +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="SymbolicDeterminant",categories="User Functions;Linear Algebra" +*CMD SymbolicDeterminant --- todo +*CALL + SymbolicDeterminant(matrix) + +*PARMS +{matrix} -- a matrix + +*DESC +todo + +*E.G. +todo +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ToeplitzMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ToeplitzMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ToeplitzMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ToeplitzMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="ToeplitzMatrix" + +// The arguments of the following functions should be checked +ToeplitzMatrix(N):=GenMatrix({{i,j},N[Abs(i-j)+1]}, Length(N), Length(N) ); + +%/mathpiper + + + +%mathpiper_docs,name="ToeplitzMatrix",categories="User Functions;Matrices (Special)" +*CMD ToeplitzMatrix --- create a Toeplitz matrix +*STD +*CALL + ToeplitzMatrix(N) +*PARMS + +{N} -- an $n$-dimensional row vector + +*DESC + +The function {ToeplitzMatrix} calculates the Toeplitz matrix given +an $n$-dimensional row vector. This matrix has the same entries in +all diagonal columns, from upper left to lower right. + +*E.G. + +In> PrettyForm(ToeplitzMatrix({1,2,3,4,5})) + + / \ + | ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) | + | | + | ( 2 ) ( 1 ) ( 2 ) ( 3 ) ( 4 ) | + | | + | ( 3 ) ( 2 ) ( 1 ) ( 2 ) ( 3 ) | + | | + | ( 4 ) ( 3 ) ( 2 ) ( 1 ) ( 2 ) | + | | + | ( 5 ) ( 4 ) ( 3 ) ( 2 ) ( 1 ) | + \ / +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Trace.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Trace.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Trace.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Trace.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="Trace" + +//Retract("Trace",*); + +Trace(matrix_IsList) <-- +[ + Local(i,j,n,d,r,aux,result); + + d:=Dimensions(matrix); + + r:=Length(d); // tensor rank. + + n:=Minimum(d); // minimal dim. + + result:=0; + + For(i:=1,i<=n,i++) + [ + aux:=matrix[i]; + For(j:=2,j<=r,j++) + aux:=aux[i]; + result:=result+aux; + ]; + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Trace",categories="User Functions;Linear Algebra" +*CMD Trace --- trace of a matrix +*STD +*CALL + Trace(M) + +*PARMS + +{M} -- a matrix + +*DESC + +{Trace} returns the trace of a matrix $M$ (defined as the sum of the +elements on the diagonal of the matrix). + +*E.G. + +In> A:=DiagonalMatrix(1 .. 4) +Result: {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; +In> Trace(A) +Result: 10; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Transpose.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Transpose.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/Transpose.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/Transpose.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="Transpose" + +Transpose(matrix_IsList)_(Length(Dimensions(matrix))>1) <-- +[ + Local(i,j,result); + result:=ZeroMatrix(Length(matrix[1]),Length(matrix)); + For(i:=1,i<=Length(matrix),i++) + For(j:=1,j<=Length(matrix[1]),j++) + result[j][i]:=matrix[i][j]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Transpose",categories="User Functions;Linear Algebra" +*CMD Transpose --- get transpose of a matrix +*STD +*CALL + Transpose(M) + +*PARMS + +{M} -- a matrix + +*DESC + +{Transpose} returns the transpose of a matrix $M$. Because matrices are +just lists of lists, this is a useful operation too for lists. + +*E.G. + +In> Transpose({{a,b}}) +Result: {{a},{b}}; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/VandermondeMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/VandermondeMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/VandermondeMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/VandermondeMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="VandermondeMatrix" + +Function("VandermondeMatrix",{vector})[ + Local(len,i,j,item,matrix); + len:=Length(vector); + matrix:=ZeroMatrix(len,len); + + For(i:=1,i<=Length(matrix),i++)[ + For(j:=1,j<=Length(matrix[1]),j++)[ + matrix[j][i]:=vector[i]^(j-1); + ]; + ]; + + matrix; +]; + +%/mathpiper + + + +%mathpiper_docs,name="VandermondeMatrix",categories="User Functions;Matrices (Special)" +*CMD VandermondeMatrix --- create the Vandermonde matrix +*STD +*CALL + VandermondeMatrix(vector) +*PARMS + +{vector} -- an $n$-dimensional vector + +*DESC + +The function {VandermondeMatrix} calculates the Vandermonde matrix +of a vector. + +The ($i$,$j$)-th element of the Vandermonde matrix is defined as $i^(j-1)$. + +*E.G. +In> VandermondeMatrix({1,2,3,4}) +Result: {{1,1,1,1},{1,2,3,4},{1,4,9,16},{1,8,27,64}}; +In>PrettyForm(%) + + / \ + | ( 1 ) ( 1 ) ( 1 ) ( 1 ) | + | | + | ( 1 ) ( 2 ) ( 3 ) ( 4 ) | + | | + | ( 1 ) ( 4 ) ( 9 ) ( 16 ) | + | | + | ( 1 ) ( 8 ) ( 27 ) ( 64 ) | + \ / +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/WilkinsonMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/WilkinsonMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/WilkinsonMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/WilkinsonMatrix.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,13 @@ +%mathpiper,def="WilkinsonMatrix" + +// Used to test numerical eigenvalue algorithms, because it +// has eigenvalues extremely close to each other. +// WilkinsonMatrix(21) has 2 eigenvalues near 10.7 that agree +// to 14 decimal places +// Leto: I am not going to document this until we actually have +// numerical eigenvalue algorithms +WilkinsonMatrix(N):=GenMatrix({{i,j}, + If( Abs(i-j)=1,1, + [ If(i=j,Abs( (N-1)/2 - i+1 ),0 ); ] )}, N,N ); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/WronskianMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/WronskianMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/WronskianMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/WronskianMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="WronskianMatrix" + +// The arguments of the following functions should be checked +// this takes N funcs in 1 var +WronskianMatrix(f,v):=GenMatrix({{i,j}, Deriv(v,i-1) f[j]}, Length(f), Length(f) ); + +%/mathpiper + + + +%mathpiper_docs,name="WronskianMatrix",categories="User Functions;Matrices (Special)" +*CMD WronskianMatrix --- create the Wronskian matrix +*STD +*CALL + WronskianMatrix(func,var) +*PARMS + +{func} -- an $n$-dimensional vector of functions + +{var} -- a variable to differentiate with respect to + +*DESC + +The function {WronskianMatrix} calculates the Wronskian matrix +of $n$ functions. + +The Wronskian matrix is created by putting each function as the +first element of each column, and filling in the rest of each +column by the ($i-1$)-th derivative, where $i$ is the current row. + +The Wronskian matrix is used to verify that the $n$ functions are linearly +independent, usually solutions to a differential equation. +If the determinant of the Wronskian matrix is zero, then the functions +are dependent, otherwise they are independent. + +*E.G. +In> WronskianMatrix({Sin(x),Cos(x),x^4},x); +Result: {{Sin(x),Cos(x),x^4},{Cos(x),-Sin(x),4*x^3}, + {-Sin(x),-Cos(x),12*x^2}}; +In> PrettyForm(%) + + / \ + | ( Sin( x ) ) ( Cos( x ) ) / 4 \ | + | \ x / | + | | + | ( Cos( x ) ) ( -( Sin( x ) ) ) / 3 \ | + | \ 4 * x / | + | | + | ( -( Sin( x ) ) ) ( -( Cos( x ) ) ) / 2 \ | + | \ 12 * x / | + \ / +The last element is a linear combination of the first two, so the determinant is zero: +In> A:=Determinant( WronskianMatrix( {x^4,x^3,2*x^4 + + 3*x^3},x ) ) +Result: x^4*3*x^2*(24*x^2+18*x)-x^4*(8*x^3+9*x^2)*6*x + +(2*x^4+3*x^3)*4*x^3*6*x-4*x^6*(24*x^2+18*x)+x^3 + *(8*x^3+9*x^2)*12*x^2-(2*x^4+3*x^3)*3*x^2*12*x^2; +In> Simplify(A) +Result: 0; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/X_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/X_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/X_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/X_operator.mpw 2010-01-11 03:15:47.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="X" + +x X y := CrossProduct(x,y); + +%/mathpiper + + + + + +%mathpiper_docs,name="X",categories="Operators" +*CMD X --- todo +*CALL + x X y + +*PARMS +todo + +*DESC +todo + +*E.G. +todo + +*SEE CrossProduct +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ZeroMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ZeroMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ZeroMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ZeroMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="ZeroMatrix" + +5 # ZeroMatrix(n_IsNonNegativeInteger) <-- ZeroMatrix(n,n); + +10 # ZeroMatrix(n_IsNonNegativeInteger,m_IsNonNegativeInteger) <-- +[ + Local(i,result); + result:={}; + For(i:=1,i<=n,i++) + DestructiveInsert(result,i,ZeroVector(m)); + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="ZeroMatrix",categories="User Functions;Linear Algebra" +*CMD ZeroMatrix --- make a zero matrix +*STD +*CALL + ZeroMatrix(n) + ZeroMatrix(n, m) + +*PARMS + +{n} -- number of rows + +{m} -- number of columns + +*DESC + +This command returns a matrix with {n} rows and {m} columns, +completely filled with zeroes. If only given one parameter, +it returns the square {n} by {n} zero matrix. + +*E.G. + +In> ZeroMatrix(3,4) +Result: {{0,0,0,0},{0,0,0,0},{0,0,0,0}}; +In> ZeroMatrix(3) +Result: {{0,0,0},{0,0,0},{0,0,0}}; + + +*SEE ZeroVector, Identity +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ZeroVector.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ZeroVector.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/linalg/ZeroVector.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/linalg/ZeroVector.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="ZeroVector" + +Function("ZeroVector",{n}) +[ + Local(i,result); + result:={}; + For(i:=1,i<=n,i++) + [ + DestructiveInsert(result,1,0); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="ZeroVector",categories="User Functions;Linear Algebra" +*CMD ZeroVector --- create a vector with all zeroes +*STD +*CALL + ZeroVector(n) + +*PARMS + +{n} -- length of the vector to return + +*DESC + +This command returns a vector of length "n", filled with zeroes. + +*E.G. + +In> ZeroVector(4) +Result: {0,0,0,0}; + +*SEE BaseVector, ZeroMatrix, IsZeroVector +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Append.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Append.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Append.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Append.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="Append" + +Function("Append",{list,element}) +[ + Check(IsList(list), "Argument", "The first argument must be a list."); + + Insert(list,Length(list)+1,element); +]; + + +%/mathpiper + + + +%mathpiper_docs,name="Append",categories="User Functions;Lists (Operations)" +*CMD Append --- append an entry at the end of a list +*STD +*CALL + Append(list, expr) + +*PARMS + +{list} -- list to append "expr" to + +{expr} -- expression to append to the list + +*DESC + +The expression "expr" is appended at the end of "list" and the +resulting list is returned. + +Note that due to the underlying data structure, the time it takes to +append an entry at the end of a list grows linearly with the length of +the list, while the time for prepending an entry at the beginning is +constant. + +*E.G. + +In> Append({a,b,c,d}, 1); +Result: {a,b,c,d,1}; + +*SEE Concat, :, DestructiveAppend +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/BSearch.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/BSearch.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/BSearch.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/BSearch.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,15 @@ +%mathpiper,def="BSearch" + +LocalSymbols(max,f,result) +[ + BSearch(max,f) := + [ + Local(result); + Bind(result, FindIsq(max,f)); + If(Apply(f,{result})!=0,Bind(result,-1)); + result; + ]; +]; +UnFence("BSearch",2); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/BubbleSort.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/BubbleSort.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/BubbleSort.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/BubbleSort.mpw 2010-02-28 01:39:52.000000000 +0000 @@ -0,0 +1,65 @@ +%mathpiper,def="BubbleSort" + +Function("BubbleSort",{list,compare}) +[ + Local(i,j,length,left,right); + + list:=FlatCopy(list); + length:=Length(list); + + For (j:=length,j>1,j--) + [ + For(i:=1,i BubbleSort({4,7,23,53,-2,1}, ">") +Result: {53,23,7,4,1,-2} + +In> BubbleSort({3,5,2},Lambda({x,y},x Contains({a,b,c,d}, b); +Result: True; +In> Contains({a,b,c,d}, x); +Result: False; +In> Contains({a,{1,2,3},z}, 1); +Result: False; +In> Contains(a*b, b); +Result: True; + +*SEE Find, Count +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Count.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Count.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Count.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Count.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="Count" + +Function("Count",{list,element}) +[ + Local(result); + Bind(result,0); + ForEach(item,list) If(IsEqual(item, element), Bind(result,AddN(result,1))); + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Count",categories="User Functions;Lists (Operations)" +*CMD Count --- count the number of occurrences of an expression +*STD +*CALL + Count(list, expr) + +*PARMS + +{list} -- the list to examine + +{expr} -- expression to look for in "list" + +*DESC + +This command counts the number of times that the expression "expr" +occurs in "list" and returns this number. + +*E.G. + +In> lst := {a,b,c,b,a}; +Result: {a,b,c,b,a}; +In> Count(lst, a); +Result: 2; +In> Count(lst, c); +Result: 1; +In> Count(lst, x); +Result: 0; + +*SEE Length, Select, Contains +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/DestructiveAppendList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/DestructiveAppendList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/DestructiveAppendList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/DestructiveAppendList.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,14 @@ +%mathpiper,def="DestructiveAppendList" + +Function("DestructiveAppendList",{list,toadd}) +[ + Local(i,nr); + nr:=Length(toadd); + For(i:=1,i<=nr,i++) + [ + DestructiveAppend(list,toadd[i]); + ]; + True; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/DestructiveAppend.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/DestructiveAppend.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/DestructiveAppend.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/DestructiveAppend.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,49 @@ +%mathpiper,def="DestructiveAppend" + +Function("DestructiveAppend",{list,element}) +[ + DestructiveInsert(list,Length(list)+1,element); +]; + +%/mathpiper + + + +%mathpiper_docs,name="DestructiveAppend",categories="User Functions;Lists (Operations)" +*CMD DestructiveAppend --- destructively append an entry to a list +*STD +*CALL + DestructiveAppend(list, expr) + +*PARMS + +{list} -- list to append "expr" to + +{expr} -- expression to append to the list + +*DESC + +This is the destructive counterpart of {Append}. This +command yields the same result as the corresponding call to +{Append}, but the original list is modified. So if a +variable is bound to "list", it will now be bound to the list with +the expression "expr" inserted. + +Destructive commands run faster than their nondestructive counterparts +because the latter copy the list before they alter it. + +*E.G. + +In> lst := {a,b,c,d}; +Result: {a,b,c,d}; +In> Append(lst, 1); +Result: {a,b,c,d,1}; +In> lst +Result: {a,b,c,d}; +In> DestructiveAppend(lst, 1); +Result: {a,b,c,d,1}; +In> lst; +Result: {a,b,c,d,1}; + +*SEE Concat, :, Append +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Difference.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Difference.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Difference.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Difference.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,54 @@ +%mathpiper,def="Difference" + +Function("Difference",{list1,list2}) +[ + Local(l2,index,result); + l2:=FlatCopy(list2); + result:=FlatCopy(list1); + ForEach(item,list1) + [ + Bind(index,Find(l2,item)); + If(index>0, + [ + DestructiveDelete(l2,index); + DestructiveDelete(result,Find(result,item)); + ] + ); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Difference",categories="User Functions;Lists (Operations)" +*CMD Difference --- return the difference of two lists +*STD +*CALL + Difference(l1, l2) + +*PARMS + +{l1}, {l2} -- two lists + +*DESC + +The difference of the lists "l1" and "l2" is determined and +returned. The difference contains all elements that occur in "l1" +but not in "l2". The order of elements in "l1" is preserved. If a +certain expression occurs "n1" times in the first list and "n2" +times in the second list, it will occur "n1-n2" times in the result +if "n1" is greater than "n2" and not at all otherwise. + +*E.G. + +In> Difference({a,b,c}, {b,c,d}); +Result: {a}; +In> Difference({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); +Result: {a,i}; +In> Difference({1,2,2,3,3,3}, {2,2,3,4,4}); +Result: {1,3,3}; + +*SEE Intersection, Union +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Drop.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Drop.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Drop.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Drop.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,64 @@ +%mathpiper,def="Drop" + +/* ���� Drop ���� */ + +/* Needs to check the parameters */ + +/* + * Drop( list, n ) gives 'list' with its first n elements dropped + * Drop( list, -n ) gives 'list' with its last n elements dropped + * Drop( list, {m,n} ) gives 'list' with elements m through n dropped + */ + +Rulebase("Drop", {lst, range}); + +Rule("Drop", 2, 1, IsList(range)) + Concat(Take(lst,range[1]-1), Drop(lst, range[2])); + +Rule("Drop", 2, 2, range >= 0) + If( range = 0 Or lst = {}, lst, Drop( Rest(lst), range-1 )); + +Rule("Drop", 2, 2, range < 0) + Take( lst, Length(lst) + range ); + +%/mathpiper + + + +%mathpiper_docs,name="Drop",categories="User Functions;Lists (Operations)" +*CMD Drop --- drop a range of elements from a list + +*STD + +*CALL + Drop(list, n) + Drop(list, -n) + Drop(list, {m,n}) + +*PARMS + +{list} -- list to act on + +{n}, {m} -- positive integers describing the entries to drop + +*DESC + +This command removes a sublist of "list" and returns a list +containing the remaining entries. The first calling sequence drops the +first "n" entries in "list". The second form drops the last "n" +entries. The last invocation drops the elements with indices "m" +through "n". + +*E.G. + +In> lst := {a,b,c,d,e,f,g}; +Result: {a,b,c,d,e,f,g}; +In> Drop(lst, 2); +Result: {c,d,e,f,g}; +In> Drop(lst, -3); +Result: {a,b,c,d}; +In> Drop(lst, {2,4}); +Result: {a,e,f,g}; + +*SEE Take, Select, Remove +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FillList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FillList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FillList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FillList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="FillList" + +Function("FillList", {aItem, aLength}) +[ + Local(i, aResult); + aResult:={}; + For(i:=0, i FillList(x, 5); +Result: {x,x,x,x,x}; + +*SEE MakeVector, ZeroVector, RandomIntegerList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FindIsq.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FindIsq.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FindIsq.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FindIsq.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,29 @@ +%mathpiper,def="FindIsq" + +LocalSymbols(max,f,low,high,mid,current) +[ +FindIsq(max,f) := +[ + Local(low,high,mid,current); + low:=1; + high:=max+1; + Bind(mid,((high+low)>>1)); + While(high>low And mid>1) + [ + Bind(mid,((high+low)>>1)); + Bind(current,Apply(f,{mid})); +//Echo({low,high,current}); + If(current = 0, + high:=low-1, + If(current > 0, + Bind(high,mid), + Bind(low,mid+1) + ) + ); + ]; + mid; +]; +]; +UnFence("FindIsq",2); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Find.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Find.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Find.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Find.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper,def="Find" + +Function("Find",{list,element}) +[ + Local(result,count); + Bind(result, -1); + Bind(count, 1); + While(And(result<0, Not(IsEqual(list, {})))) + [ + If(IsEqual(First(list), element), + Bind(result, count) + ); + Bind(list,Rest(list)); + Bind(count,AddN(count,1)); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Find",categories="User Functions;Lists (Operations)" +*CMD Find --- get the index at which a certain element occurs +*STD +*CALL + Find(list, expr) + +*PARMS + +{list} -- the list to examine + +{expr} -- expression to look for in "list" + +*DESC + +This commands returns the index at which the expression "expr" +occurs in "list". If "expr" occurs more than once, the lowest +index is returned. If "expr" does not occur at all, +{-1} is returned. + +*E.G. + +In> Find({a,b,c,d,e,f}, d); +Result: 4; +In> Find({1,2,3,2,1}, 2); +Result: 2; +In> Find({1,2,3,2,1}, 4); +Result: -1; + +*SEE Contains +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FindPredicate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FindPredicate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FindPredicate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FindPredicate.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,20 @@ +%mathpiper,def="FindPredicate" + +// Find the first thingy that matches a predicate +Function("FindPredicate",{list,predicate}) +[ + Local(result,count); + Bind(result, -1); + Bind(count, 1); + While(And(result<0, Not(IsEqual(list, {})))) + [ + If(Apply(predicate,{First(list)}), + Bind(result, count) + ); + Bind(list,Rest(list)); + Bind(count,AddN(count,1)); + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FuncListArith.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FuncListArith.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FuncListArith.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FuncListArith.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="FuncListArith" + +/* FuncListArith() is defined to only look at arithmetic operations +, -, *, /. */ + +FuncListArith(expr) := FuncList(expr, {ToAtom("+"), ToAtom("-"), *, /}); + +HoldArgumentNumber("FuncListArith", 1, 1); + +%/mathpiper + + + +%mathpiper_docs,name="FuncListArith",categories="User Functions;Lists (Operations)" +*CMD FuncList --- list of functions used in an expression +*CMD FuncListArith --- list of functions used in an expression +*CMD FuncListSome --- list of functions used in an expression +*STD +*CALL + FuncList(expr) + FuncListArith(expr) + FuncListSome(expr, list) + +*PARMS + +{expr} -- an expression + +{list} -- list of function atoms to be considered "transparent" + +*DESC + +The command {FuncList(expr)} returns a list of all function atoms that appear +in the expression {expr}. The expression is recursively traversed. + +The command {FuncListSome(expr, list)} does the same, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain any other functions). +For example, {FuncListSome(a + Sin(b-c))} will see that the expression has a "{-}" operation and return {{+,Sin,-}}, but {FuncListSome(a + Sin(b-c), {+})} will not look at arguments of {Sin()} and will return {{+,Sin}}. + +{FuncListArith} is defined through {FuncListSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. notest + +In> FuncList(x+y*Cos(Ln(x)/x)) +Result: {+,*,Cos,/,Ln}; +In> FuncListArith(x+y*Cos(Ln(x)/x)) +Result: {+,*,Cos}; +In> FuncListSome({a+b*2,c/d},{List}) +Result: {List,+,/}; + +*SEE VarList, HasExpr, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FuncList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FuncList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FuncList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FuncList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,86 @@ +%mathpiper,def="FuncList" + +////////////////////////////////////////////////// +/// FuncList --- list all function atoms used in an expression +////////////////////////////////////////////////// +/// like VarList except collects functions + +10 # FuncList(expr_IsAtom) <-- {}; +20 # FuncList(expr_IsFunction) <-- +RemoveDuplicates( + Concat( + {First(FunctionToList(expr))}, + Apply("Concat", + MapSingle("FuncList", Rest(FunctionToList(expr))) + ) + ) +); + +/* +This is like FuncList except only looks at arguments of a given list of functions. All other functions become "opaque". + +*/ +10 # FuncList(expr_IsAtom, look'list_IsList) <-- {}; +// a function not in the looking list - return its type +20 # FuncList(expr_IsFunction, look'list_IsList)_(Not Contains(look'list, ToAtom(Type(expr)))) <-- {ToAtom(Type(expr))}; +// a function in the looking list - traverse its arguments +30 # FuncList(expr_IsFunction, look'list_IsList) <-- +RemoveDuplicates( + Concat( + {First(FunctionToList(expr))}, + [ // gave up trying to do it using Map and MapSingle... so writing a loop now. + // obtain a list of functions, considering only functions in look'list + Local(item, result); + result := {}; + ForEach(item, expr) result := Concat(result, FuncList(item, look'list)); + result; + ] + ) +); + +HoldArgumentNumber("FuncList", 1, 1); +HoldArgumentNumber("FuncList", 2, 1); + +%/mathpiper + + + +%mathpiper_docs,name="FuncList",categories="User Functions;Lists (Operations)" +*CMD FuncList --- list of functions used in an expression +*CMD FuncListArith --- list of functions used in an expression +*CMD FuncListSome --- list of functions used in an expression +*STD +*CALL + FuncList(expr) + FuncListArith(expr) + FuncListSome(expr, list) + +*PARMS + +{expr} -- an expression + +{list} -- list of function atoms to be considered "transparent" + +*DESC + +The command {FuncList(expr)} returns a list of all function atoms that appear +in the expression {expr}. The expression is recursively traversed. + +The command {FuncListSome(expr, list)} does the same, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain any other functions). +For example, {FuncListSome(a + Sin(b-c))} will see that the expression has a "{-}" operation and return {{+,Sin,-}}, but {FuncListSome(a + Sin(b-c), {+})} will not look at arguments of {Sin()} and will return {{+,Sin}}. + +{FuncListArith} is defined through {FuncListSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. notest + +In> FuncList(x+y*Cos(Ln(x)/x)) +Result: {+,*,Cos,/,Ln}; +In> FuncListArith(x+y*Cos(Ln(x)/x)) +Result: {+,*,Cos}; +In> FuncListSome({a+b*2,c/d},{List}) +Result: {List,+,/}; + +*SEE VarList, HasExpr, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FuncListSome.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FuncListSome.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/FuncListSome.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/FuncListSome.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="" + +//todo:tk:not defined in the scripts. + +%/mathpiper + + + +%mathpiper_docs,name="FuncListSome",categories="User Functions;Lists (Operations)" +*CMD FuncList --- list of functions used in an expression +*CMD FuncListArith --- list of functions used in an expression +*CMD FuncListSome --- list of functions used in an expression +*STD +*CALL + FuncList(expr) + FuncListArith(expr) + FuncListSome(expr, list) + +*PARMS + +{expr} -- an expression + +{list} -- list of function atoms to be considered "transparent" + +*DESC + +The command {FuncList(expr)} returns a list of all function atoms that appear +in the expression {expr}. The expression is recursively traversed. + +The command {FuncListSome(expr, list)} does the same, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain any other functions). +For example, {FuncListSome(a + Sin(b-c))} will see that the expression has a "{-}" operation and return {{+,Sin,-}}, but {FuncListSome(a + Sin(b-c), {+})} will not look at arguments of {Sin()} and will return {{+,Sin}}. + +{FuncListArith} is defined through {FuncListSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. notest + +In> FuncList(x+y*Cos(Ln(x)/x)) +Result: {+,*,Cos,/,Ln}; +In> FuncListArith(x+y*Cos(Ln(x)/x)) +Result: {+,*,Cos}; +In> FuncListSome({a+b*2,c/d},{List}) +Result: {List,+,/}; + +*SEE VarList, HasExpr, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/global_stack.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/global_stack.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/global_stack.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/global_stack.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,76 @@ +%mathpiper,def="GlobalPush;GlobalPop" + +////////////////////////////////////////////////// +/// Global stack operations on variables +////////////////////////////////////////////////// + + +LocalSymbols(GlobalStack, x) +[ + GlobalStack := {}; + + GlobalPop(x_IsAtom) <-- + [ + Check(Length(GlobalStack)>0, "Invariant", "GlobalPop: Error: empty GlobalStack"); + MacroBind(x, PopFront(GlobalStack)); + Eval(x); + ]; + + HoldArgumentNumber("GlobalPop", 1, 1); + + GlobalPop() <-- + [ + Check(Length(GlobalStack)>0, "Invariant", "GlobalPop: Error: empty GlobalStack"); + PopFront(GlobalStack); + ]; + + GlobalPush(_x) <-- + [ + Push(GlobalStack, x); + x; + ]; +]; + +%/mathpiper + + + +%mathpiper_docs,name="GlobalPop;GlobalPush",categories="User Functions;Lists (Operations)" +*CMD GlobalPop --- restore variables using a global stack +*CMD GlobalPush --- save variables using a global stack +*STD +*CALL + GlobalPop(var) + GlobalPop() + GlobalPush(expr) + +*PARMS + +{var} -- atom, name of variable to restore from the stack + +{expr} -- expression, value to save on the stack + +*DESC + +These functions operate with a global stack, currently implemented as a list that is not accessible externally (it is protected +through {LocalSymbols}). + +{GlobalPush} stores a value on the stack. {GlobalPop} removes the last pushed value from the stack. If a variable name is given, the variable is assigned, otherwise the popped value is returned. + +If the global stack is empty, an error message is printed. + +*E.G. + +In> GlobalPush(3) +Result: 3; +In> GlobalPush(Sin(x)) +Result: Sin(x); +In> GlobalPop(x) +Result: Sin(x); +In> GlobalPop(x) +Result: 3; +In> x +Result: 3; + +*SEE Push, PopFront +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/HeapSort.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/HeapSort.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/HeapSort.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/HeapSort.mpw 2010-02-28 01:39:52.000000000 +0000 @@ -0,0 +1,79 @@ +%mathpiper,def="HeapSort" + +HeapSort(list, compare) := HeapSort(list, ArrayCreate(Length(list), 0), 1, Length(list), compare); + +// this will sort "list" and mangle "tmplist" +1 # HeapSort(_list, _tmplist, _first, _last, _compare) _ (last - first <= 2) <-- SmallSort(list, first, last, compare); +2 # HeapSort(_list, _tmplist, _first, _last, _compare) <-- +[ // See: J. W. J. Williams, Algorithm 232 (Heapsort), Com. of ACM, vol. 7, no. 6, p. 347 (1964) + // sort two halves recursively, then merge two halves + // cannot merge in-place efficiently, so need a second list + Local(mid, ileft, iright, pleft); + mid := first+((last-first)>>1); + HeapSort(list, tmplist, first, mid, compare); + HeapSort(list, tmplist, mid+1, last, compare); + // copy the lower part to temporary array + For(ileft := first, ileft <= mid, ileft++) + tmplist[ileft] := list[ileft]; + For( + [ileft := first; pleft := first; iright := mid+1;], + ileft <= mid, // if the left half is finished, we don't have to do any more work + pleft++ // one element is stored at each iteration + ) // merge two halves + // elements before pleft have been stored + // the smallest element of the right half is at iright + // the smallest element of the left half is at ileft, access through tmplist + If( // we copy an element from ileft either if it is smaller or if the right half is finished; it is unnecessary to copy the remainder of the right half since the right half stays in the "list" + iright>last Or Apply(compare,{tmplist[ileft],list[iright]}), + [ // take element from ileft + list[pleft] := tmplist[ileft]; + ileft++; + ], + [ // take element from iright + list[pleft] := list[iright]; + iright++; + ] + ); + + list; +]; + +%/mathpiper + + + +%mathpiper_docs,name="HeapSort",categories="User Functions;Lists (Operations)" +*CMD HeapSort --- sort a list +*STD +*CALL + HeapSort(list, compare) + +*PARMS + +{list} -- list to sort + +{compare} -- function used to compare elements of {list} + +*DESC + +This command returns {list} after it is sorted using {compare} to +compare elements. The function {compare} should accept two arguments, +which will be elements of {list}, and compare them. It should return +{True} if in the sorted list the second argument +should come after the first one, and {False} +otherwise. The function {compare} can either be a string which +contains the name of a function or a pure function. + +The function {HeapSort} uses a recursive algorithm "heapsort" and is much +faster for large lists. The sorting time is proportional to $n*Ln(n)$ where $n$ +is the length of the list. + +*E.G. +In> HeapSort({4,7,23,53,-2,1}, ">") +Result: {53,23,7,4,1,-2} + +In> HeapSort({3,5,2},Lambda({x,y},x",LI)); + L0 := FlatCopy(LI); + ]; + //If(InVerboseMode(),Tell(" result ",L0)); + result := L0; + ] + ); + result; +]; + + +11 # Intersection(list1_IsList,list2_IsList) <-- +[ + //If(InVerboseMode(),Tell("Intersection_pairOfLists",{list1,list2})); + Local(l2,index,result); + l2:=FlatCopy(list2); + result:={}; + ForEach(item,list1) + [ + Bind(index, Find(l2,item)); + If(index>0, + [ + DestructiveDelete(l2,index); + DestructiveInsert(result,1,item); + ] + ); + ]; + DestructiveReverse(result); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="Intersection",categories="User Functions;Lists (Operations)" +*CMD Intersection --- return the Intersection of two or more lists +*STD +*CALL + Intersection(L1, L2) +or + Intersection( ListOfLists ) + +*PARMS + +{L1}, {L2} -- two lists +or +{ListOfLists} -- a List of two or more lists + +*DESC + +The Intersection of all the lists is determined and +returned. The Intersection contains all elements that occur in all +lists. The entries in the result are listed in the same order as in +the first list. If an expression occurs multiple times in all the +lists, then it will occur the same number of times in the result. + +*E.G. + +In> Intersection({a,b,c}, {b,c,d}) +Result: {b,c} + +In> Intersection({a,e,i,o,u}, {f,o,u,r,t,e,e,n}) +Result: {e,o,u} + +In> Intersection({1,2,2,3,3,3}, {1,1,2,2,3,3}) +Result: {1,2,2,3,3} + +In> Intersection({{1,2,2,3,3,3,a,c,e},{1,1,2,2,3,3,a,c,e},{3,a,b,c,d,e,f,1,3,5}}) +Result: {1,3,3,a,c,e} + +*SEE Union, Difference + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MacroMapArgs.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MacroMapArgs.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MacroMapArgs.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MacroMapArgs.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,19 @@ +%mathpiper,def="MacroMapArgs" + +/* Another Macro... hack for /: to work. */ +Macro("MacroMapArgs",{expr,oper}) +[ + Local(ex,tl,op); + Bind(op,@oper); + Bind(ex,FunctionToList(@expr)); + Bind(tl,Rest(ex)); + + ListToFunction(Concat({ex[1]}, + `MacroMapSingle(@op,Hold(@tl))) + ); +]; + +UnFence("MacroMapArgs",2); +HoldArgument("MacroMapArgs",oper); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MacroMapSingle.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MacroMapSingle.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MacroMapSingle.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MacroMapSingle.mpw 2011-02-05 04:04:44.000000000 +0000 @@ -0,0 +1,20 @@ +%mathpiper,def="MacroMapSingle" + +/* Another Macro... hack for /: to work. */ +TemplateFunction("MacroMapSingle",{func,list}) +[ + Local(mapsingleresult); + mapsingleresult:={}; + + ForEach(mapsingleitem,list) + [ + DestructiveInsert(mapsingleresult,1, + `ApplyFast(func,{Hold(Hold(@mapsingleitem))})); + ]; + DestructiveReverse(mapsingleresult); +]; +UnFence("MacroMapSingle",2); +HoldArgument("MacroMapSingle",func); +HoldArgument("MacroMapSingle",list); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MapArgs.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MapArgs.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MapArgs.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MapArgs.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="MapArgs" + +TemplateFunction("MapArgs",{expr,oper}) +[ + Bind(expr,FunctionToList(expr)); + ListToFunction(Concat({expr[1]}, + Apply("MapSingle",{oper,Rest(expr)}) + ) ); +]; +UnFence("MapArgs",2); +HoldArgument("MapArgs",oper); + +%/mathpiper + + + +%mathpiper_docs,name="MapArgs",categories="User Functions;Control Flow" +*CMD MapArgs --- apply a function to all top-level arguments +*STD +*CALL + MapArgs(expr, fn) + +*PARMS + +{expr} -- an expression to work on + +{fn} -- an operation to perform on each argument + +*DESC + +Every top-level argument in "expr" is substituted by the result of +applying "fn" to this argument. Here "fn" can be either the name +of a function or a pure function (see Apply for more information on +pure functions). + +*E.G. + +In> MapArgs(f(x,y,z),"Sin"); +Result: f(Sin(x),Sin(y),Sin(z)); +In> MapArgs({3,4,5,6}, {{x},x^2}); +Result: {9,16,25,36}; + +*SEE MapSingle, Map, Apply +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Map.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Map.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Map.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Map.mpw 2010-07-27 05:50:28.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="Map" + +LocalSymbols(func,lists,mapsingleresult,mapsingleitem) +[ + TemplateFunction("Map",{func,lists}) + [ + Local(mapsingleresult,mapsingleitem); + mapsingleresult:={}; + lists:=Transpose(lists); + ForEach(mapsingleitem,lists) + [ + DestructiveInsert(mapsingleresult,1,Apply(func,mapsingleitem)); + ]; + DestructiveReverse(mapsingleresult); + ]; + UnFence("Map",2); + HoldArgument("Map",func); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Map",categories="User Functions;Lists (Operations)" +*CMD Map --- apply an $n$-ary function to all entries in a list +*STD +*CALL + Map(fn, list) + +*PARMS + +{fn} -- function to apply + +{list} -- list of lists of arguments + +*DESC + +This function applies "fn" to every list of arguments to be found in +"list". So the first entry of "list" should be a list containing +the first, second, third, ... argument to "fn", and the same goes +for the other entries of "list". The function can either be given as +a string or as a pure function (see Apply for more information on +pure functions). + +*E.G. +In> MapSingle("Sin",{a,b,c}); +Result> {Sin(a),Sin(b),Sin(c)}; + +In> Map("+",{{a,b},{c,d}}); +Result> {a+c,b+d}; + +In> Map("List",{{1,2,3},{4,5,6}}); +Result: {{1,4},{2,5},{3,6}} + +*SEE MapSingle, MapArgs, Apply +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MapSingle.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MapSingle.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/MapSingle.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/MapSingle.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper,def="MapSingle" + +TemplateFunction("MapSingle",{func,list}) +[ + Local(mapsingleresult); + mapsingleresult:={}; + + ForEach(mapsingleitem,list) + [ + DestructiveInsert(mapsingleresult,1, + Apply(func,{mapsingleitem})); + ]; + DestructiveReverse(mapsingleresult); +]; +UnFence("MapSingle",2); +HoldArgument("MapSingle",func); + +%/mathpiper + + + +%mathpiper_docs,name="MapSingle",categories="User Functions;Lists (Operations)" +*CMD MapSingle --- apply a unary function to all entries in a list +*STD +*CALL + MapSingle(fn, list) + +*PARMS + +{fn} -- function to apply + +{list} -- list of arguments + +*DESC + +The function "fn" is successively applied to all entries in +"list", and a list containing the respective results is +returned. The function can be given either as a string or as a pure +function (see Apply for more information on pure functions). + +The {/@} operator provides a shorthand for +{MapSingle}. + +*E.G. + +In> MapSingle("Sin",{a,b,c}); +Result: {Sin(a),Sin(b),Sin(c)}; +In> MapSingle({{x},x^2}, {a,2,c}); +Result: {a^2,4,c^2}; + +*SEE Map, MapArgs, /@, Apply +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Partition.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Partition.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Partition.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Partition.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="Partition" + +/* ���� Partition ���� */ + +/* Partition( list, n ) partitions 'list' into non-overlapping sublists of length n */ + +Partition(lst, len):= + If( Length(lst) < len Or len = 0, {}, + Concat( {Take(lst,len)}, Partition(Drop(lst,len), len) )); + +%/mathpiper + + + +%mathpiper_docs,name="Partition",categories="User Functions;Lists (Operations)" +*CMD Partition --- partition a list in sublists of equal length +*STD +*CALL + Partition(list, n) + +*PARMS + +{list} -- list to partition + +{n} -- length of partitions + +*DESC + +This command partitions "list" into non-overlapping sublists of +length "n" and returns a list of these sublists. The first "n" +entries in "list" form the first partition, the entries from +position "n+1" up to "2n" form the second partition, and so on. If +"n" does not divide the length of "list", the remaining entries +will be thrown away. If "n" equals zero, an empty list is +returned. + +*E.G. + +In> Partition({a,b,c,d,e,f,}, 2); +Result: {{a,b},{c,d},{e,f}}; +In> Partition(1 .. 11, 3); +Result: {{1,2,3},{4,5,6},{7,8,9}}; + +*SEE Take, PermutationsList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/PopBack.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/PopBack.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/PopBack.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/PopBack.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="PopBack" + +Function("PopBack",{stack}) Pop(stack,Length(stack)); + +%/mathpiper + + + +%mathpiper_docs,name="PopBack",categories="User Functions;Lists (Operations)" +*CMD PopBack --- remove an element from the bottom of a stack +*STD +*CALL + PopBack(stack) + +*PARMS + +{stack} -- a list (which serves as the stack container) + +*DESC + +This is part of a simple implementation of a stack, internally +represented as a list. This command removes the element at the bottom +of the stack and returns this element. Of course, the stack should not +be empty. + +*E.G. + +In> stack := {}; +Result: {}; +In> Push(stack, x); +Result: {x}; +In> Push(stack, x2); +Result: {x2,x}; +In> Push(stack, x3); +Result: {x3,x2,x}; +In> PopBack(stack); +Result: x; +In> stack; +Result: {x3,x2}; + +*SEE Push, Pop, PopFront +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/PopFront.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/PopFront.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/PopFront.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/PopFront.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="PopFront" + +Function("PopFront",{stack}) Pop(stack,1); + +%/mathpiper + + + +%mathpiper_docs,name="PopFront",categories="User Functions;Lists (Operations)" +*CMD PopFront --- remove an element from the top of a stack +*STD +*CALL + PopFront(stack) + +*PARMS + +{stack} -- a list (which serves as the stack container) + +*DESC + +This is part of a simple implementation of a stack, internally +represented as a list. This command removes the element on the top of +the stack and returns it. This is the last element that is pushed onto +the stack. + +*E.G. + +In> stack := {}; +Result: {}; +In> Push(stack, x); +Result: {x}; +In> Push(stack, x2); +Result: {x2,x}; +In> Push(stack, x3); +Result: {x3,x2,x}; +In> PopFront(stack); +Result: x3; +In> stack; +Result: {x2,x}; + +*SEE Push, Pop, PopBack +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Pop.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Pop.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Pop.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Pop.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="Pop" + +Function("Pop",{stack,index}) +[ + Local(result); + result:=stack[index]; + DestructiveDelete(stack,index); + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Pop",categories="User Functions;Lists (Operations)" +*CMD Pop --- remove an element from a stack +*STD +*CALL + Pop(stack, n) + +*PARMS + +{stack} -- a list (which serves as the stack container) + +{n} -- index of the element to remove + +*DESC + +This is part of a simple implementation of a stack, internally +represented as a list. This command removes the element with index +"n" from the stack and returns this element. The top of the stack is +represented by the index 1. Invalid indices, for example indices +greater than the number of element on the stack, lead to an error. + +*E.G. + +In> stack := {}; +Result: {}; +In> Push(stack, x); +Result: {x}; +In> Push(stack, x2); +Result: {x2,x}; +In> Push(stack, x3); +Result: {x3,x2,x}; +In> Pop(stack, 2); +Result: x2; +In> stack; +Result: {x3,x}; + +*SEE Push, PopFront, PopBack +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/PrintList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/PrintList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/PrintList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/PrintList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="PrintList" + +////////////////////////////////////////////////// +/// Print a list using a padding string +////////////////////////////////////////////////// + +10 # PrintList(list_IsList) <-- PrintList(list, ", "); +10 # PrintList({}, padding_IsString) <-- ""; +20 # PrintList(list_IsList, padding_IsString) <-- PipeToString() [ + Local(i); + ForEach(i, list) [ + If(Not(IsEqual(i, First(list))), WriteString(padding)); + If (IsString(i), WriteString(i), If(IsList(i), WriteString("{" : PrintList(i, padding) : "}"), Write(i))); + ]; +]; + +%/mathpiper + + + +%mathpiper_docs,name="PrintList",categories="User Functions;Lists (Operations)" +*CMD PrintList --- print list with padding +*STD +*CALL + PrintList(list) + PrintList(list, padding); + +*PARMS + +{list} -- a list to be printed + +{padding} -- (optional) a string + +*DESC + +Prints {list} and inserts the {padding} string between each pair of items of the list. Items of the list which are strings are printed without quotes, unlike {Write()}. Items of the list which are themselves lists are printed inside braces {{}}. If padding is not specified, a standard one is used (comma, space). + +*E.G. + +In> PrintList({a,b,{c, d}}, " .. ") +Result: " a .. b .. { c .. d}"; + +*SEE Write, WriteString +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Push.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Push.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Push.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Push.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="Push" + +Function("Push",{stack,element}) +[ + DestructiveInsert(stack,1,element); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Push",categories="User Functions;Lists (Operations)" +*CMD Push --- add an element on top of a stack +*STD +*CALL + Push(stack, expr) + +*PARMS + +{stack} -- a list (which serves as the stack container) + +{expr} -- expression to push on "stack" + +*DESC + +This is part of a simple implementation of a stack, internally +represented as a list. This command pushes the expression "expr" on +top of the stack, and returns the stack afterwards. + +*E.G. + +In> stack := {}; +Result: {}; +In> Push(stack, x); +Result: {x}; +In> Push(stack, x2); +Result: {x2,x}; +In> PopFront(stack); +Result: x2; + +*SEE Pop, PopFront, PopBack +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/RemoveDuplicates.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/RemoveDuplicates.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/RemoveDuplicates.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/RemoveDuplicates.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="RemoveDuplicates" + +Function("RemoveDuplicates",{list}) +[ + Local(result); + Bind(result,{}); + ForEach(item,list) + If(Not(Contains(result,item)),DestructiveAppend(result,item)); + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="RemoveDuplicates",categories="User Functions;Lists (Operations)" +*CMD RemoveDuplicates --- remove any duplicates from a list +*STD +*CALL + RemoveDuplicates(list) + +*PARMS + +{list} -- list to act on + +*DESC + +This command removes all duplicate elements from a given list and returns the resulting list. +To be +precise, the second occurrence of any entry is deleted, as are the +third, the fourth, etc. + +*E.G. + +In> RemoveDuplicates({1,2,3,2,1}); +Result: {1,2,3}; +In> RemoveDuplicates({a,1,b,1,c,1}); +Result: {a,1,b,c}; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Remove.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Remove.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Remove.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Remove.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="Remove" + +Remove(list, expression) := +[ + Local(result); + Bind(result,{}); + ForEach(item,list) + If(item != expression, DestructiveAppend(result,item)); + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Remove",categories="User Functions;Lists (Operations)" +*CMD Remove --- remove all occurrences of an expression from a list +*STD +*CALL + Remove(list, expr) + +*PARMS + +{list} -- list to act on + +{expr} -- expression to look for in "list" + +*DESC + +This command removes all elements that match a given expression from a given list and returns the resulting list. + +*E.G. +In> Remove({a,b,a,b,c,a,c},a) +Result> {b,b,c,c} + +*SEE RemoveDuplicates + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Reverse.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Reverse.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Reverse.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Reverse.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="Reverse" + +// Non-destructive Reverse operation +Reverse(list):=DestructiveReverse(FlatCopy(list)); + +%/mathpiper + + + +%mathpiper_docs,name="Reverse",categories="User Functions;Lists (Operations)" +*CMD Reverse --- return the reversed list (without touching the original) +*STD +*CALL + Reverse(list) + +*PARMS + +{list} -- list to reverse + +*DESC + +This function returns a list reversed, without changing the +original list. It is similar to {DestructiveReverse}, but safer +and slower. + + +*E.G. + +In> lst:={a,b,c,13,19} +Result: {a,b,c,13,19}; +In> revlst:=Reverse(lst) +Result: {19,13,c,b,a}; +In> lst +Result: {a,b,c,13,19}; + +*SEE FlatCopy, DestructiveReverse +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/scopestack/scopestack.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/scopestack/scopestack.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/scopestack/scopestack.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/scopestack/scopestack.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,78 @@ +%mathpiper,def="NewStack;PushStackFrame;PopStackFrame;StackDepth;AddToStack;IsOnStack;FindOnStack" + +/* def file list +NewStack +PushStackFrame +PopStackFrame +StackDepth +AddToStack +IsOnStack +FindOnStack + +*/ + + +/* + Stack simulator. Api: + + NewStack() - creates a stack simulation + PushStackFrame(stack,unfenced) - push frame on stack, (un)fenced + PushStackFrame(stack,fenced) + PopStackFrame(stack) - pop stack frame + StackDepth(_stack) - return stack depth + AddToStack(stack,element) - add element to top stack frame + + IsOnStack(stack,element) - returns True if element is accessible + on current stack, False otherwise + FindOnStack(stack,element) - return assoc list for element. + Check first with IsOnStack that it is available! + +*/ + +NewStack() := {{},{}}; + +10 # PushStackFrame(_stack,unfenced) + <-- + [ + DestructiveInsert(stack[1],1,{}); + DestructiveInsert(stack[2],1,True); + ]; +10 # PushStackFrame(_stack,fenced) + <-- + [ + DestructiveInsert(stack[1],1,{}); + DestructiveInsert(stack[2],1,False); + ]; +PopStackFrame(stack):= +[ + DestructiveDelete(stack[1],1); + DestructiveDelete(stack[2],1); +]; +StackDepth(_stack) <-- Length(stack[1]); + +AddToStack(stack,element) := +[ + DestructiveInsert(stack[1][1],1,{element,{}}); +]; + +DropOneFrame(_stack) <-- {Rest(stack[1]),Rest(stack[2])}; + +10 # IsOnStack({{},{}},_element) <-- False; +11 # IsOnStack(_stack,_element)_(stack[1][1][element] != Empty) <-- True; +20 # IsOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) + <-- IsOnStack(DropOneFrame(stack),element); +30 # IsOnStack(_stack,_element) <-- +[ +//Echo("stack depth = ",StackDepth(stack)); +//Echo(stack[2][1]); +False; +]; +10 # FindOnStack(_stack,_element)_(stack[1][1][element] != Empty) + <-- stack[1][1][element]; +20 # FindOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) + <-- FindOnStack(DropOneFrame(stack),element); +30 # FindOnStack(_stack,_element) <-- Check(False, "Argument", "Illegal stack access! Use IsOnStack."); + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Select.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Select.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Select.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Select.mpw 2010-07-23 05:26:16.000000000 +0000 @@ -0,0 +1,63 @@ +%mathpiper,def="Select" + +LocalSymbols(predicate,list,result,item) +[ + Function("Select",{list,predicate}) + [ + Local(result); + result:={}; + ForEach(item,list) + [ + If(Apply(predicate,{item}),DestructiveAppend(result,item)); + ]; + result; + ]; + HoldArgument("Select",predicate); + UnFence("Select",2); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Select",categories="User Functions;Lists (Operations)" +*CMD Select --- select entries satisfying some predicate +*STD +*CALL + Select(list, pred) + +*PARMS + +{pred} -- a predicate + +{list} -- a list of elements to select from + +*DESC + +{Select} returns a sublist of "list" which contains all +the entries for which the predicate "pred" returns +{True} when applied to this entry. + +The {Lambda} function can be used in place of a predicate function +if desired. + +*E.G. + +In> Select({a,b,2,c,3,d,4,e,f}, "IsInteger") +Result: {2,3,4}; + + +/%mathpiper + +list := {1,-3,2,-6,-4,3}; + +Select(list, Lambda({i}, i > 0 )); + +/%/mathpiper + + /%output,preserve="false" + Result: {1,2,3} +. /%/output + +*SEE Length, Find, Count, Lambda +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/SmallSort.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/SmallSort.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/SmallSort.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/SmallSort.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper,def="SmallSort" + +/// fast in-place sorting of a list (or array!) +/// SmallSort sorts up to 3 elements, HeapSort sorts 4 and more elements +SmallSort(_list, _first, _last, _compare) _ (last=first) <-- list; +SmallSort(_list, _first, _last, _compare) _ (last=first+1) <-- +[ + Local(temp); + temp := list[first]; + If( + Apply(compare,{temp,list[last]}), + list, + [ + list[first] := list[last]; + list[last] := temp; + ] //Swap(list, first, last) + ); + list; +]; +SmallSort(_list, _first, _last, _compare) _ (last=first+2) <-- +[ + Local(temp); + temp := list[first]; + If( + Apply(compare,{list[first+1],temp}), + [ + list[first] := list[first+1]; + list[first+1] := temp; + ] //Swap(list, first, first+1) // x>y, z + ); + // xx 1, 2, 3 + list[last] := list[first+1]; + list[first+1] := list[first]; + list[first] := temp; + ] + ); + list; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Swap.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Swap.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Swap.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Swap.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="Swap" + +Function("Swap",{list,index1,index2}) +[ + Local(item1,item2); + item1:=list[index1]; + item2:=list[index2]; + list[index1] := item2; + list[index2] := item1; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Swap",categories="User Functions;Lists (Operations)" +*CMD Swap --- swap two elements in a list +*STD +*CALL + Swap(list, i1, i2) + +*PARMS + +{list} -- the list in which a pair of entries should be swapped + +{i1, i2} -- indices of the entries in "list" to swap + +*DESC + +This command swaps the pair of entries with entries "i1" and "i2" +in "list". So the element at index "i1" ends up at index "i2" +and the entry at "i2" is put at index "i1". Both indices should be +valid to address elements in the list. Then the updated list is +returned. + +{Swap()} works also on generic arrays. + +*E.G. + +In> lst := {a,b,c,d,e,f}; +Result: {a,b,c,d,e,f}; +In> Swap(lst, 2, 4); +Result: {a,d,c,b,e,f}; + +*SEE Replace, DestructiveReplace, Array'Create +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Table.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Table.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Table.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Table.mpw 2010-03-24 05:15:50.000000000 +0000 @@ -0,0 +1,78 @@ +%mathpiper,def="Table" + +/* Juan: TemplateFunction (as defined in the file "deffunc") + * also makes the arguments to the function local symbols. + * Use HoldArgumentNumber to specify the index of a variable to hold + * (since they are defined as local symbols). + */ + +TemplateFunction("Table",{body,var,count'from,count'to,step}) + [ + MacroLocal(var); + Local(result,nr,ii); + result:={}; + nr := (count'to - count'from) / step; + ii := 0; + While( ii <= nr ) + [ + MacroBind( var, count'from + ii * step ); + DestructiveInsert( result,1,Eval(body) ); + Bind(ii,AddN(ii,1)); + ]; + DestructiveReverse(result); + ]; +HoldArgumentNumber("Table",5,1); /* body */ +HoldArgumentNumber("Table",5,2); /* var */ +UnFence("Table",5); + +%/mathpiper + + + +%mathpiper_docs,name="Table",categories="User Functions;Lists (Operations)" +*CMD Table --- evaluate while some variable ranges over interval +*STD +*CALL + Table(body, var, from, to, step) + +*PARMS + +{body} -- expression to evaluate multiple times + +{var} -- variable to use as loop variable + +{from} -- initial value for "var" + +{to} -- final value for "var" + +{step} -- step size with which "var" is incremented + +*DESC + +This command generates a list of values from "body", by assigning +variable "var" values from "from" up to "to", incrementing +"step" each time. So, the variable "var" first gets the value +"from", and the expression "body" is evaluated. Then the value +"from"+"step" is assigned to "var" and the expression "body" +is again evaluated. This continues, incrementing "var" with "step" +on every iteration, until "var" exceeds "to". At that moment, all +the results are assembled in a list and this list is returned. + +*E.G. +In> Table(i!, i, 1, 9, 1); +Result: {1,2,6,24,120,720,5040,40320,362880} + +In> Table(i, i, 3, 16, 4); +Result: {3,7,11,15} + +In> Table(i^2, i, 10, 1, -1); +Result: {100,81,64,49,36,25,16,9,4,1} + +In> Table(a+b, b, 0, 2, 1) +Result: {a,a+1,a+2} + +In> Table(Table(a+b, b, 0, 2, 1), a, 0, 2, 1) +Result: {{0,1,2},{1,2,3},{2,3,4}} + +*SEE For, MapSingle, .., TableForm +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Take.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Take.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Take.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Take.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,63 @@ +%mathpiper,def="Take" + +/* ���� Take ���� */ + +/* Needs to check the parameters */ + +/* + * Take( list, n ) gives the first n elements of 'list' + * Take( list, -n ) gives the last n elements of 'list' + * Take( list, {m,n} ) elements m through n of 'list' + */ + +Rulebase("Take", {lst, range}); + +Rule("Take", 2, 1, IsList(range)) + Take( Drop(lst, range[1] -1), range[2] - range[1] + 1); + +Rule("Take", 2, 2, range >= 0) + If( Length(lst)=0 Or range=0, {}, + Concat({First(lst)}, Take(Rest(lst), range-1))); + +Rule("Take", 2, 2, range < 0) + Drop( lst, Length(lst) + range ); + +%/mathpiper + + + +%mathpiper_docs,name="Take",categories="User Functions;Lists (Operations)" +*CMD Take --- take a sublist from a list (dropping the rest) +*STD +*CALL + Take(list, n) + Take(list, -n) + Take(list, {m,n}) + +*PARMS + +{list} -- list to act on + +{n}, {m} -- positive integers describing the entries to take + +*DESC + +This command takes a sublist of "list", drops the rest, and returns +the selected sublist. The first calling sequence selects the first +"n" entries in "list". The second form takes the last "n" +entries. The last invocation selects the sublist beginning with entry +number "m" and ending with the "n"-th entry. + +*E.G. + +In> lst := {a,b,c,d,e,f,g}; +Result: {a,b,c,d,e,f,g}; +In> Take(lst, 2); +Result: {a,b}; +In> Take(lst, -3); +Result: {e,f,g}; +In> Take(lst, {2,4}); +Result: {b,c,d}; + +*SEE Drop, Select, Remove +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Union.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Union.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/Union.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/Union.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="Union" + +Function("Union",{list1,list2}) +[ + RemoveDuplicates(Concat(list1,list2)); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Union",categories="User Functions;Lists (Operations)" +*CMD Union --- return the union of two lists +*STD +*CALL + Union(l1, l2) + +*PARMS + +{l1}, {l2} -- two lists + +*DESC + +The union of the lists "l1" and "l2" is determined and +returned. The union contains all elements that occur in one or both of +the lists. In the resulting list, any element will occur only once. + +*E.G. + +In> Union({a,b,c}, {b,c,d}); +Result: {a,b,c,d}; +In> Union({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); +Result: {a,e,i,o,u,f,r,t,n}; +In> Union({1,2,2,3,3,3}, {2,2,3,3,4,4}); +Result: {1,2,3,4}; + +*SEE Intersection, Difference +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarListAll.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarListAll.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarListAll.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarListAll.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,28 @@ +%mathpiper,def="VarListAll" + +/* + * Rulebase for VarListAll: recursively traverse an expression looking + * up all variables the expression depends on. + */ +/* Accept any variable. */ + +VarListAll(_expr) <-- VarListAll(expr,"IsVariable"); + +10 # VarListAll(_expr,_filter)_(Apply(filter,{expr}) = True) <-- + {expr}; + +/* Otherwise check all leafs of a function. */ +20 # VarListAll(expr_IsFunction,_filter) <-- +[ + Local(item,result, flatlist); + Bind(flatlist,Rest(FunctionToList(expr))); + Bind(result,{}); + ForEach(item,flatlist) + Bind(result,Concat(result,VarListAll(item,filter))); + result; +]; + +/* Else it doesn't depend on any variable. */ +30 # VarListAll(_expr,_filter) <-- {}; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarListArith.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarListArith.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarListArith.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarListArith.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,57 @@ +%mathpiper,def="VarListArith" + +/// VarListArith --- obtain arithmetic variables +// currently the VarList(x,y) semantic is convoluted so let's introduce a new name; but in principle this needs to be cleaned up +VarListArith(expr) := VarListSome(expr, {ToAtom("+"), ToAtom("-"), *, /}); + +%/mathpiper + + + +%mathpiper_docs,name="VarListArith",categories="User Functions;Lists (Operations)" +*CMD VarList --- list of variables appearing in an expression +*CMD VarListArith --- list of variables appearing in an expression +*CMD VarListSome --- list of variables appearing in an expression +*STD +*CALL + VarList(expr) + VarListArith(expr) + VarListSome(expr, list) + +*PARMS + +{expr} -- an expression + +{list} -- a list of function atoms + +*DESC + +The command {VarList(expr)} returns a list of all variables that appear in the +expression {expr}. The expression is traversed recursively. + +The command {VarListSome} looks only at arguments of functions in the {list}. All other functions are considered "opaque" (as if they do not contain any variables) and their arguments are not checked. +For example, {VarListSome(a + Sin(b-c))} will return {{a, b, c}}, but {VarListSome(a*Sin(b-c), {*})} will not look at arguments of {Sin()} and will return {{a,Sin(b-c)}}. Here {Sin(b-c)} is considered a "variable" because the function {Sin} does not belong to {list}. + + +The command {VarListArith} returns a list of all variables that appear +arithmetically in the expression {expr}. This is implemented through +{VarListSome} by restricting to the arithmetic functions {+}, {-}, {*}, {/}. +Arguments of other functions are not checked. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> VarList(Sin(x)) +Result: {x}; +In> VarList(x+a*y) +Result: {x,a,y}; +In> VarListSome(x+a*y, {ToAtom("+")}) +Result: {x,a*y}; +In> VarListArith(x+y*Cos(Ln(x)/x)) +Result: {x,y,Cos(Ln(x)/x)} +In> VarListArith(x+a*y^2-1) +Result: {x,a,y^2}; + +*SEE IsFreeOf, IsVariable, FuncList, HasExpr, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,61 @@ +%mathpiper,def="VarList" + +/* VarList: return the variables this expression depends on. */ +VarList(_expr) <-- VarList(expr,"IsVariable"); + +Function("VarList",{expr,filter}) +[ + RemoveDuplicates(VarListAll(expr,filter)); +]; + +%/mathpiper + + + +%mathpiper_docs,name="VarList",categories="User Functions;Lists (Operations)" +*CMD VarList --- list of variables appearing in an expression +*CMD VarListArith --- list of variables appearing in an expression +*CMD VarListSome --- list of variables appearing in an expression +*STD +*CALL + VarList(expr) + VarListArith(expr) + VarListSome(expr, list) + +*PARMS + +{expr} -- an expression + +{list} -- a list of function atoms + +*DESC + +The command {VarList(expr)} returns a list of all variables that appear in the +expression {expr}. The expression is traversed recursively. + +The command {VarListSome} looks only at arguments of functions in the {list}. All other functions are considered "opaque" (as if they do not contain any variables) and their arguments are not checked. +For example, {VarListSome(a + Sin(b-c))} will return {{a, b, c}}, but {VarListSome(a*Sin(b-c), {*})} will not look at arguments of {Sin()} and will return {{a,Sin(b-c)}}. Here {Sin(b-c)} is considered a "variable" because the function {Sin} does not belong to {list}. + + +The command {VarListArith} returns a list of all variables that appear +arithmetically in the expression {expr}. This is implemented through +{VarListSome} by restricting to the arithmetic functions {+}, {-}, {*}, {/}. +Arguments of other functions are not checked. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> VarList(Sin(x)) +Result: {x}; +In> VarList(x+a*y) +Result: {x,a,y}; +In> VarListSome(x+a*y, {ToAtom("+")}) +Result: {x,a*y}; +In> VarListArith(x+y*Cos(Ln(x)/x)) +Result: {x,y,Cos(Ln(x)/x)} +In> VarListArith(x+a*y^2-1) +Result: {x,a,y^2}; + +*SEE IsFreeOf, IsVariable, FuncList, HasExpr, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarListSome.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarListSome.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/lists/VarListSome.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/lists/VarListSome.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,72 @@ +%mathpiper,def="VarListSome" + +/// VarListSome is just like FuncList(x,y) + +10 # VarListSome({}, _look'list) <-- {}; +// an atom should be a variable to qualify +10 # VarListSome(expr_IsVariable, _look'list) <-- {expr}; +15 # VarListSome(expr_IsAtom, _look'list) <-- {}; +// a function not in the looking list - return it whole +20 # VarListSome(expr_IsFunction, look'list_IsList)_(Not Contains(look'list, ToAtom(Type(expr)))) <-- {expr}; +// a function in the looking list - traverse its arguments +30 # VarListSome(expr_IsFunction, look'list_IsList) <-- +RemoveDuplicates( + [ // obtain a list of functions, considering only functions in look'list + Local(item, result); + result := {}; + ForEach(item, expr) result := Concat(result, VarListSome(item, look'list)); + result; + ] +); + +%/mathpiper + + + +%mathpiper_docs,name="VarListSome",categories="User Functions;Lists (Operations)" +*CMD VarList --- list of variables appearing in an expression +*CMD VarListArith --- list of variables appearing in an expression +*CMD VarListSome --- list of variables appearing in an expression +*STD +*CALL + VarList(expr) + VarListArith(expr) + VarListSome(expr, list) + +*PARMS + +{expr} -- an expression + +{list} -- a list of function atoms + +*DESC + +The command {VarList(expr)} returns a list of all variables that appear in the +expression {expr}. The expression is traversed recursively. + +The command {VarListSome} looks only at arguments of functions in the {list}. All other functions are considered "opaque" (as if they do not contain any variables) and their arguments are not checked. +For example, {VarListSome(a + Sin(b-c))} will return {{a, b, c}}, but {VarListSome(a*Sin(b-c), {*})} will not look at arguments of {Sin()} and will return {{a,Sin(b-c)}}. Here {Sin(b-c)} is considered a "variable" because the function {Sin} does not belong to {list}. + + +The command {VarListArith} returns a list of all variables that appear +arithmetically in the expression {expr}. This is implemented through +{VarListSome} by restricting to the arithmetic functions {+}, {-}, {*}, {/}. +Arguments of other functions are not checked. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> VarList(Sin(x)) +Result: {x}; +In> VarList(x+a*y) +Result: {x,a,y}; +In> VarListSome(x+a*y, {ToAtom("+")}) +Result: {x,a*y}; +In> VarListArith(x+y*Cos(Ln(x)/x)) +Result: {x,y,Cos(Ln(x)/x)} +In> VarListArith(x+a*y^2-1) +Result: {x,a,y^2}; + +*SEE IsFreeOf, IsVariable, FuncList, HasExpr, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/AddTo.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/AddTo.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/AddTo.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/AddTo.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="AddTo" + +// (a or b) and (c or d) -> (a and c) or (a and d) or (b and c) or (b and d) +20 # (list_IsList AddTo _rest) <-- +[ + Local(res); + res:={}; + ForEach(item,list) + [ + res := Concat(res,item AddTo rest); + ]; + res; +]; +30 # (_a'item AddTo list_IsList) <-- +[ + MapSingle({{orig},a'item And orig},list); +]; +40 # (_a'item AddTo _b) <-- a'item And b; + +%/mathpiper + + + +%mathpiper_docs,name="AddTo",categories="User Functions;Solvers (Symbolic)" +*CMD AddTo --- add an equation to a set of equations or set of set of equations +*STD +*CALL + eq1 AddTo eq2 + +*PARMS + +{eq} - (set of) set of equations + +*DESC + +Given two (sets of) sets of equations, the command AddTo combines +multiple sets of equations into one. + +A list {a,b} means that a is a solution, OR b is a solution. +AddTo then acts as a AND operation: + + (a or b) and (c or d) => + (a or b) Addto (c or d) => + (a and c) or (a and d) or (b and c) + or (b and d) + +This function is useful for adding an identity to an already +existing set of equations. Suppose a solve command returned +{a>=0 And x==a,a<0 And x== -a} from an expression x==Abs(a), +then a new identity a==2 could be added as follows: + +In> a==2 AddTo {a>=0 And x==a,a<0 And x== -a} +Result: {a==2 And a>=0 And x==a,a==2 And a<0 And x== -a}; + +Passing this set of set of identities back to solve, solve +should recognize that the second one is not a possibility +any more, since a==2 And a<0 can never be true at the same time. + +This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. + +*E.G. + +In> {A==2,c==d} AddTo {b==3 And d==2} +Result: {A==2 And b==3 And d==2,c==d And b==3 And d==2}; +In> {A==2,c==d} AddTo {b==3, d==2} +Result: {A==2 And b==3,A==2 And d==2,c==d And b==3,c==d And d==2}; + +*SEE Where, Solve +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/CompilePatterns.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/CompilePatterns.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/CompilePatterns.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/CompilePatterns.mpw 2010-07-13 20:51:29.000000000 +0000 @@ -0,0 +1,94 @@ +%mathpiper,def="CompilePatterns" + +LocalSymbols(LocResult) [ + + Bind(LocResult,True); + 10 # LocPredicate(exp_IsAtom) <-- + [ + Local(tr,result); + tr:=patterns; + result:=False; + While (tr != {}) + [ + If (First(First(tr)) = exp, + [ + Bind(LocResult,Eval(First(Rest(First(tr))))); + result := True; + tr:={}; + ], + [ + tr := Rest(tr); + ]); + ]; + result; + ]; + + 10 # LocPredicate(exp_IsFunction) <-- + [ + Local(tr,result,head); + tr:=patterns; + result:=False; + While (tr != {}) + [ + Bind(head, First(First(tr))); + If (Not(IsAtom(head)) And exp[0]=head[1] And PatternMatches(head[2], exp), + [ + Bind(LocResult,Eval(First(Rest(First(tr))))); + Bind(result, True); + Bind(tr,{}); + ], + [ + Bind(tr, Rest(tr)); + ]); + ]; + result; + ]; + 20 # LocPredicate(_exp) <-- False; + + LocChange(_exp) <-- LocResult; +]; // LocalSymbols(LocResult) + +UnFence("LocPredicate",1); +UnFence("LocChange",1); + +10 # LocProcessSingle({_pat,_post,_exp}) <-- { {pat[0],PatternCreate(pat,post)},exp }; + +20 # LocProcessSingle({pat_IsFunction,_exp}) <-- { {pat[0],PatternCreate(pat,True)},exp }; + +30 # LocProcessSingle({pat_IsAtom,_exp}) <-- { pat,exp }; + +/* + 40 # LocProcessSingle(pat_IsFunction <- _exp) <-- { {pat[0],PatternCreate(pat,True)},exp }; + todo:tk:this rule was not handling post predicates so I replaced it with a new version that does. + I suspect that the other rules for this Rulebase have problems too. +*/ +40 # LocProcessSingle(pat_IsFunction <- _exp) <-- +[ + Local(justPattern, postPredicate); + + If(Type(pat) = "_", + [ + //A post predicate was submitted. + justPattern := pat[1]; + postPredicate := pat[2]; + ], + [ + //No post predicate was submitted. + justPattern := pat; + postPredicate := True; + ] + ); + + { {justPattern[0],PatternCreate(justPattern,postPredicate)},exp }; +]; + +50 # LocProcessSingle(pat_IsAtom <- _exp) <-- { pat,exp }; + +LocProcess(patterns) := +[ + MapSingle("LocProcessSingle",patterns); +]; + +CompilePatterns(patterns) := LocPatterns(LocProcess(patterns)); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/lessthan_minus_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/lessthan_minus_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/lessthan_minus_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/lessthan_minus_operator.mpw 2010-01-09 00:07:57.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="<-" + +Rulebase("<-",{left,right}); +HoldArgument("<-",left); +HoldArgument("<-",right); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/slash_colon_colon_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/slash_colon_colon_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/slash_colon_colon_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/slash_colon_colon_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,91 @@ +%mathpiper,def="/::" + +5 # (_expression /:: LocPatterns(_patterns)) <-- +[ + MacroSubstitute(expression,"LocPredicate","LocChange"); +]; +10 # (_expression /:: _patterns) <-- +[ + Local(old); + Bind(patterns, LocProcess(patterns)); + Bind(old, expression); + Bind(expression, MacroSubstitute(expression,"LocPredicate","LocChange")); + While (expression != old) + [ + Bind(old, expression); + Bind(expression, MacroSubstitute(expression,"LocPredicate","LocChange")); + ]; + expression; +]; + + +%/mathpiper + + + +%mathpiper_docs,name="/::",categories="Operators" +*CMD /: --- local simplification rules +*CMD /:: --- local simplification rules +*STD +*CALL + expression /: patterns + expressions /:: patterns +Precedence: +*EVAL PrecedenceGet("/:") + + +*PARMS + +{expression} -- an expression + +{patterns} -- a list of patterns + +*DESC + +Sometimes you have an expression, and you want to use specific +simplification rules on it that are not done by default. This +can be done with the {/:} and the {/::} operators. Suppose we have the +expression containing things such as {Ln(a*b)}, and we want +to change these into {Ln(a)+Ln(b)}, the easiest way +to do this is using the {/:} operator, as follows: + +In> Sin(x)*Ln(a*b) +Result: Sin(x)*Ln(a*b); +In> % /: { Ln(_x*_y) <- Ln(x)+Ln(y) } +Result: Sin(x)*(Ln(a)+Ln(b)); + +A whole list of simplification rules can be built up in the list, +and they will be applied to the expression on the left hand side +of {/:} . + +The forms the patterns can have are one of: + + pattern <- replacement + {pattern,replacement} + {pattern,postpredicate,replacement} + +Note that for these local rules, {<-} should be used instead of +{<--} which would be used in a global rule. + +The {/:} operator traverses an expression much as {Subst} does, that is, top +down, trying to apply the rules from the beginning of the list of +rules to the end of the list of rules. If the rules cannot be applied +to an expression, it will try subexpressions of that +expression and so on. + +It might be necessary sometimes to use the {/::} operator, which +repeatedly applies the {/:} operator until the result doesn't change +any more. Caution is required, since rules can contradict each other, +which could result in an infinite loop. To detect this situation, +just use /: repeatedly on the expression. The repetitive nature +should become apparent. + +*E.G. + +In> Sin(u)*Ln(a*b) /: {Ln(_x*_y) <- Ln(x)+Ln(y)} +Result: Sin(u)*(Ln(a)+Ln(b)); +In> Sin(u)*Ln(a*b) /:: { a <- 2, b <- 3 } +Result: Sin(u)*Ln(6); + +*SEE Subst +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/slash_colon_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/slash_colon_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/slash_colon_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/slash_colon_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,101 @@ +%mathpiper,def="/:" + +5 # (_expression /: LocPatterns(_patterns)) <-- +[ + MacroSubstitute(expression,"LocPredicate","LocChange"); +]; + + +10 # (_expression /: _patterns) <-- +[ + Bind(patterns, LocProcess(patterns)); + MacroSubstitute(expression,"LocPredicate","LocChange"); +]; + +%/mathpiper + + + +%mathpiper_docs,name="/:",categories="Operators" +*CMD /: --- local simplification rules +*CMD /:: --- local simplification rules +*STD +*CALL + expression /: patterns + expressions /:: patterns +Precedence: +*EVAL PrecedenceGet("/:") + + +*PARMS + +{expression} -- an expression + +{patterns} -- a list of patterns + +*DESC + +Sometimes you have an expression, and you want to use specific +simplification rules on it that are not done by default. This +can be done with the {/:} and the {/::} operators. Suppose we have the +expression containing things such as {Ln(a*b)}, and we want +to change these into {Ln(a)+Ln(b)}, the easiest way +to do this is using the {/:} operator, as follows: + +In> Sin(x)*Ln(a*b) +Result: Sin(x)*Ln(a*b); +In> % /: { Ln(_x*_y) <- Ln(x)+Ln(y) } +Result: Sin(x)*(Ln(a)+Ln(b)); + +A whole list of simplification rules can be built up in the list, +and they will be applied to the expression on the left hand side +of {/:} . + +The forms the patterns can have are one of: + + pattern <- replacement + {pattern,replacement} + {pattern,postpredicate,replacement} + +Note that for these local rules, {<-} should be used instead of +{<--} which would be used in a global rule. + +The {/:} operator traverses an expression much as {Subst} does, that is, top +down, trying to apply the rules from the beginning of the list of +rules to the end of the list of rules. If the rules cannot be applied +to an expression, it will try subexpressions of that +expression and so on. + +It might be necessary sometimes to use the {/::} operator, which +repeatedly applies the {/:} operator until the result doesn't change +any more. Caution is required, since rules can contradict each other, +which could result in an infinite loop. To detect this situation, +just use /: repeatedly on the expression. The repetitive nature +should become apparent. + +*E.G. + +In> Sin(u)*Ln(a*b) /: {Ln(_x*_y) <- Ln(x)+Ln(y)} +Result: Sin(u)*(Ln(a)+Ln(b)); +In> Sin(u)*Ln(a*b) /:: { a <- 2, b <- 3 } +Result: Sin(u)*Ln(6); + +*SEE Subst +%/mathpiper_docs + + +/* +Examples to add to docs in the future. + +Hold((a + b) * (1 + 2) * (2 + 1) * (1/2 + c) * (3/4 + d) ) /: + { + (x_IsOdd + y_IsEven) <- m1, + (x_IsEven + y_IsOdd) <- m2, + (x_IsRational + y_IsAtom)_(Denominator(x) = 2) <- m3, + }; + + %output,preserve="false" + Result: (a+b)*m1*m2*m3*(3/4+d) +. %/output + +*/ \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/Where.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/Where.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/localrules/Where.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/localrules/Where.mpw 2011-02-03 08:38:42.000000000 +0000 @@ -0,0 +1,91 @@ +%mathpiper,def="Where" + +Rulebase("Where",{left,right}); +//HoldArgument("Where",left); +//HoldArgument("Where",right); +UnFence("Where",2); +10 # (_body Where var_IsAtom == _value) + <-- `[Local(@var);@var := @value;@body;]; +20 # (_body Where (_a And _b)) + <-- +[ + Bind(body,`(@body Where @a)); + `(@body Where @b); +]; + +30 # (_body Where {}) <-- {}; +40 # (_body Where list_IsList)_IsList(list[1]) + <-- + [ + Local(head,rest); + head:=First(list); + rest:=Rest(list); + rest:= `(@body Where @rest); + `(@body Where @head) : rest; + ]; + +50 # (_body Where list_IsList) + <-- + [ + Local(head,rest); + While (list != {}) + [ + head:=First(list); + body := `(@body Where @head); + list:=Rest(list); + ]; + body; + ]; + + +60 # (_body Where _var == _value) <-- Subst(var,value)body; + +%/mathpiper + + + +%mathpiper_docs,name="Where",categories="User Functions;Solvers (Symbolic)" +*CMD Where --- substitute result into expression +*STD +*CALL + expr Where x==v + expr Where x1==v1 And x2==v2 And ... + expr Where {x1==v1 And x2==v2,x1==v3 + And x2==v4,...} + +*PARMS + +{expr} - expression to evaluate + +{x} - variable to set + +{v} - value to substitute for variable + +*DESC + +The operator {Where} fills in values for variables, in its simplest form. +It accepts sets of variable/value pairs defined as + + var1==val1 And var2==val2 And ... + +and fills in the corresponding values. Lists of value pairs are +also possible, as: + + {var1==val1 And var2==val2, var1==val3 And var2==val4} + +These values might be obtained through {Solve}. + +This operator can help the user to program in the style of functional programming languages such as Miranda or Haskell. + +*E.G. +In> x^2+y^2 Where x==2 +Result: y^2+4; +In> x^2+y^2 Where x==2 And y==3 +Result: 13; +In> x^2+y^2 Where {x==2 And y==3} +Result: {13}; +In> x^2+y^2 Where {x==2 And y==3,x==4 And y==5} +Result: {13,41}; + +*SEE Solve, AddTo +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/CanProve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/CanProve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/CanProve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/CanProve.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,118 @@ +%mathpiper,def="CanProve" + +/* Small theorem prover for propositional logic, based on the + * resolution principle. + * Written by Ayal Pinkus, based on the simple theorem prover from "Prolog, Ivan Bratko, chapter 20" + * Version 0.1 initial implementation. + * + * + * Examples: +CanProve(( (a=>b) And (b=>c)=>(a=>c) )) <-- True +CanProve(a Or Not a) <-- True +CanProve(True Or a) <-- True +CanProve(False Or a) <-- a +CanProve(a And Not a) <-- False +CanProve(a Or b Or (a And b)) <-- a Or b + */ + + // <==> LogicSimplify(expr, 3) + +/* CanProve tries to prove that the negation of the negation of + the proposition is true. Negating twice is just a trick to + allow all the simplification rules a la De Morgan to operate + */ +/*CanProve(_proposition) <-- CanProveAux( Not CanProveAux( Not proposition));*/ + +CanProveAux(_proposition) <-- LogicSimplify(proposition, 3); + +CanProve(_proposition) <-- CanProveAux( proposition ); + +%/mathpiper + + + +%mathpiper_docs,name="CanProve",categories="User Functions;Propositional Logic" +*CMD CanProve --- try to prove statement +*STD +*CALL + CanProve(proposition) + +*PARMS + +{proposition} -- an expression with logical operations + +*DESC + +MathPiper has a small built-in propositional logic theorem prover. +It can be invoked with a call to {CanProve}. + +An example of a proposition is: "if a implies b and b implies c then +a implies c". MathPiper supports the following logical operations: + +{Not} : negation, read as "not" + +{And} : conjunction, read as "and" + +{Or} : disjunction, read as "or" + +{=>} : implication, read as "implies" + +The abovementioned proposition would be represented by the following expression, + + ( (a=>b) And (b=>c) ) => (a=>c) + +MathPiper can prove that is correct by applying {CanProve} +to it: + +In> CanProve(( (a=>b) And (b=>c) ) => (a=>c)) +Result: True; + +It does this in the following way: in order to prove a proposition $p$, it +suffices to prove that $Not p$ is false. It continues to simplify $Not p$ +using the rules: + + Not ( Not x) --> x +(eliminate double negation), + x=>y --> Not x Or y +(eliminate implication), + Not (x And y) --> Not x Or Not y +(De Morgan's law), + Not (x Or y) --> Not x And Not y +(De Morgan's law), + (x And y) Or z --> (x Or z) And (y Or z) +(distribution), + x Or (y And z) --> (x Or y) And (x Or z) +(distribution), +and the obvious other rules, such as, + True Or x --> True +etc. +The above rules will translate a proposition into a form + + (p1 Or p2 Or ...) And (q1 Or q2 + Or ...) And ... +If any of the clauses is false, the entire expression will be false. +In the next step, clauses are scanned for situations of the form: + + (p Or Y) And ( Not p Or Z) --> (Y Or Z) +If this combination {(Y Or Z)} is empty, it is false, and +thus the entire proposition is false. + +As a last step, the algorithm negates the result again. This has the +added advantage of simplifying the expression further. + +*E.G. + +In> CanProve(a Or Not a) +Result: True; +In> CanProve(True Or a) +Result: True; +In> CanProve(False Or a) +Result: a; +In> CanProve(a And Not a) +Result: False; +In> CanProve(a Or b Or (a And b)) +Result: a Or b; + + +*SEE True, False, And, Or, Not +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/CNF.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/CNF.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/CNF.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/CNF.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,99 @@ +%mathpiper,def="CNF" + + + // former LogicSimplify + +/* + Simplify a boolean expression. CNF is responsible + for converting an expression to the following form: + (p1 Or p2 Or ...) And (q1 Or q2 Or ...) And ... + That is, a conjunction of disjunctions. +*/ + + +// Trivial simplifications +10 # CNF( Not True) <-- False; +11 # CNF( Not False) <-- True; +12 # CNF(True And (_x)) <-- CNF(x); +13 # CNF(False And (_x)) <-- False; +14 # CNF(_x And True) <-- CNF(x); +15 # CNF(_x And False) <-- False; +16 # CNF(True Or (_x)) <-- True; +17 # CNF(False Or (_x)) <-- CNF(x); +18 # CNF((_x) Or True ) <-- True; +19 # CNF((_x) Or False) <-- CNF(x); + +// A bit more complext +21 # CNF(_x Or _x) <-- CNF(x); +22 # CNF(_x And _x) <-- CNF(x); +23 # CNF(_x Or Not (_x)) <-- True; +14 # CNF(Not (_x) Or _x) <-- True; +25 # CNF(_x And Not (_x)) <-- False; +26 # CNF(Not (_x) And _x) <-- False; + +// Simplifications that deal with (in)equalities +25 # CNF(((_x) == (_y)) Or ((_x) !== (_y))) <-- True; +25 # CNF(((_x) !== (_y)) Or ((_x) == (_y))) <-- True; +26 # CNF(((_x) == (_y)) And ((_x) !== (_y))) <-- False; +26 # CNF(((_x) !== (_y)) And ((_x) == (_y))) <-- False; + +27 # CNF(((_x) >= (_y)) And ((_x) < (_y))) <-- False; +27 # CNF(((_x) < (_y)) And ((_x) >= (_y))) <-- False; +28 # CNF(((_x) >= (_y)) Or ((_x) < (_y))) <-- True; +28 # CNF(((_x) < (_y)) Or ((_x) >= (_y))) <-- True; + + +// some things that are more complex +120 # CNF((_x) Or (_y)) <-- LogOr(x, y, CNF(x), CNF(y)); +10 # LogOr(_x,_y,_x,_y) <-- x Or y; +20 # LogOr(_x,_y,_u,_v) <-- CNF(u Or v); + +130 # CNF( Not (_x)) <-- LogNot(x, CNF(x)); +10 # LogNot(_x, _x) <-- Not (x); +20 # LogNot(_x, _y) <-- CNF(Not (y)); + +40 # CNF( Not ( Not (_x))) <-- CNF(x); // eliminate double negation +45 # CNF((_x)=>(_y)) <-- CNF((Not (x)) Or (y)); // eliminate implication + +50 # CNF( Not ((_x) And (_y))) <-- CNF((Not x) Or (Not y)); // De Morgan's law +60 # CNF( Not ((_x) Or (_y))) <-- CNF(Not (x)) And CNF(Not (y)); // De Morgan's law + +/* +70 # CNF((_x) And ((_y) Or (_z))) <-- CNF(x And y) Or CNF(x And z); +70 # CNF(((_x) Or (_y)) And (_z)) <-- CNF(x And z) Or CNF(y And z); + +80 # CNF((_x) Or ((_y) And (_z))) <-- CNF(x Or y) And CNF(x Or z); +80 # CNF(((_x) And (_y)) Or (_z)) <-- CNF(x Or z) And CNF(y Or z); +*/ + +70 # CNF(((_x) And (_y)) Or (_z)) <-- CNF(x Or z) And CNF(y Or z); // Distributing Or over And +80 # CNF((_x) Or ((_y) And (_z))) <-- CNF(x Or y) And CNF(x Or z); + +90 # CNF((_x) And (_y)) <-- CNF(x) And CNF(y); // Transform subexpression + +101 # CNF( (_x) < (_y) ) <-- Not CNFInEq(x >= y); +102 # CNF( (_x) > (_y) ) <-- CNFInEq(x > y); +103 # CNF( (_x) >= (_y) ) <-- CNFInEq(x >= y); +104 # CNF( (_x) <= (_y) ) <-- Not CNFInEq(x > y); +105 # CNF( (_x) == (_y) ) <-- CNFInEq(x == y); +106 # CNF( (_x) !== (_y) ) <-- Not CNFInEq(x == y); + +111 # CNF( Not((_x) < (_y)) ) <-- CNFInEq( x >= y ); +113 # CNF( Not((_x) <= (_y)) ) <-- CNFInEq( x > y ); +116 # CNF( Not((_x) !== (_y)) ) <-- CNFInEq( x == y ); + +/* Accept as fully simplified, fallthrough case */ +200 # CNF(_x) <-- x; + +20 # CNFInEq((_xex) == (_yex)) <-- (CNFInEqSimplify(xex-yex) == 0); +20 # CNFInEq((_xex) > (_yex)) <-- (CNFInEqSimplify(xex-yex) > 0); +20 # CNFInEq((_xex) >= (_yex)) <-- (CNFInEqSimplify(xex-yex) >= 0); +30 # CNFInEq(_exp) <-- (CNFInEqSimplify(exp)); + +10 # CNFInEqSimplify((_x) - (_x)) <-- 0; // strictly speaking, this is not always valid, i.e. 1/0 - 1/0 != 0... +100# CNFInEqSimplify(_x) <-- [/*Echo({"Hit the bottom of CNFInEqSimplify with ", x, Nl()});*/ x;]; + // former "Simplify"; + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/Contradict.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/Contradict.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/Contradict.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/Contradict.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="Contradict" + +10 # Contradict((_x) - (_y) == 0, (_x) - (_z) == 0)_(y != z) <-- True; +12 # Contradict((_x) == (_y), (_x) == (_z))_(y != z) <-- True; +13 # Contradict((_x) - (_y) == 0, (_x) - (_z) >= 0)_(z > y) <-- True; +14 # Contradict((_x) - (_y) == 0, (_x) - (_z) > 0)_(z > y) <-- True; +14 # Contradict(Not (_x) - (_y) >= 0, (_x) - (_z) > 0)_(z > y) <-- True; +15 # Contradict(_a, _b) <-- IsEqual(SimpleNegate(a), b); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/DoUnitSubsumptionAndResolution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/DoUnitSubsumptionAndResolution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/DoUnitSubsumptionAndResolution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/DoUnitSubsumptionAndResolution.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,63 @@ +%mathpiper,def="DoUnitSubsumptionAndResolution" + +// perform unit subsumption and resolutiuon for a unit clause # i +// a boolean indicated whether there was a change is returned +DoUnitSubsumptionAndResolution(_list) <-- +[ + Local(i, j, k, isFalse, isTrue, changed); + Bind(isFalse, False); + Bind(isTrue, False); + Bind(changed, True); + + //Echo({"In DoUnitSubsumptionAndResolution", Nl()}); + + While(changed) [ + Bind(changed, False); + + For(i:=1, (Not isFalse And Not isTrue) And i <= Length(list), i++) + [ + If(Length(list[i]) = 1, [ + Local(x); Bind(x, list[i][1]); //n := SimpleNegate(x); + //Echo({"Unit clause ", x, Nl()}); + + // found a unit clause, {x}, not use it to modify other clauses + For(j:=1, (Not isFalse And Not isTrue) And j <= Length(list), j++) + [ + If(i !=j, [ + Local(deletedClause); Bind(deletedClause, False); + For(k:=1, (Not isFalse And Not isTrue And Not deletedClause) And k <= Length(list[j]), k++) + [ + // In both of these, if a clause becomes empty, the whole thing is False + + //Echo({" ", x, " subsumes ", list[j][k], i,j, Subsumes(x, list[j][k]), Nl()}); + + // unit subsumption -- this kills clause j + If(Subsumes(x, list[j][k]), [ + // delete this clause + DestructiveDelete(list, j); + j--; + If(i>j, i--); // i also needs to be decremented + Bind(deletedClause, True); + Bind(changed, True); + If(Length(list) = 0, [Bind(isTrue, True);]); + ], + // else, try unit resolution + If(Contradict(x, list[j][k]), [ + //Echo({x, " contradicts", list[j][k], Nl()}); + DestructiveDelete(list[j], k); + k--; + Bind(changed, True); + If(Length(list[j]) = 0, [Bind(isFalse, True);]); + ]) + ); + ]; + ]); + ]; + ]); + ]; + ]; + + list; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/equals_greaterthan_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/equals_greaterthan_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/equals_greaterthan_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/equals_greaterthan_operator.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="=>" + +Rulebase("=>",{a,b}); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicCombine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicCombine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicCombine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicCombine.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="LogicCombine" + +/* LogicCombine is responsible for scanning a list of lists, which represent + a form (p1 Or p2 Or ...) And (q1 Or q2 Or ...) And ... by scanning the lists + for combinations x Or Y And Not x Or Z <-- Y Or Z . If Y Or Z is empty then this clause + is false, and thus the entire proposition is false. +*/ +LogicCombine(_list) <-- +[ + Local(i, j); + For(Bind(i,1), i<=Length(list), Bind(i,AddN(i,1))) + [ + //Echo({"list[", i, "/", Length(list), "]: ", list[i], Nl()}); + + For(j := 1, (j<=Length(list[i])), j++) + [ + Local(tocombine, n, k); + Bind(n, list[i][j]); + + {tocombine, k} := LogicFindWith(list, i, n);// search forward for n, tocombine is the list we + // will combine the current one with + If(tocombine != -1, + [ + Local(combination); + Check(k != -1, "Math", "k is -1"); + + Bind(combination, LogicRemoveTautologies(Concat(list[i], list[tocombine]))); + If(combination = {}, // the combined clause is false, so the whole thing is false + [Bind(list, {{}}); Bind(i, Length(list)+1);], [/*Bind(i, 0);*/]); + ]); + ]; + ]; + list; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicFindWith.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicFindWith.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicFindWith.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicFindWith.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,23 @@ +%mathpiper,def="LogicFindWith" + +/* find the number of the list that contains n in it, a pointer to a list of lists in passed */ +LogicFindWith(_list, _i, _n) <-- +[ + Local(result, index, j); + Bind(result, -1); Bind(index, -1); + + For(j := i+1, (result<0) And (j <= Length(list)), j++) + [ + Local(k, len); Bind(len, Length(list[j])); + For(k := 1, (result<0) And (k<=len), k++) + [ + Local(el); Bind(el, list[j][k]); + + If(Contradict(n, el), + [Bind(result, j); Bind(index, k);]); + ]; + ]; + {result, index}; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicRemoveTautologies.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicRemoveTautologies.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicRemoveTautologies.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicRemoveTautologies.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,66 @@ +%mathpiper,def="LogicRemoveTautologies" + + // not clear is this will stay, but it is eq. to LogicSimplify(expr, 2) + +1 # SimpleNegate(Not (_x)) <-- x; +2 # SimpleNegate(_x) <-- Not(x); + +/* LogicRemoveTautologies scans a list representing e1 Or e2 Or ... to find + if there are elements p and Not p in the list. This signifies p Or Not p, + which is always True. These pairs are removed. Another function that is used + is RemoveDuplicates, which converts p Or p into p. +*/ + +/* this can be optimized to walk through the lists a bit more efficiently and also take +care of duplicates in one pass */ +LocalCmp(_e1, _e2) <-- IsLessThan(PipeToString() Write(e1), PipeToString() Write(e2)); + +// we may want to add other expression simplifers for new expression types +100 # SimplifyExpression(_x) <-- x; + +// Return values: +// {True} means True +// {} means False +LogicRemoveTautologies(_e) <-- +[ + Local(i, len, negationfound); Bind(len, Length(e)); + Bind(negationfound, False); + + //Echo(e); + e := BubbleSort(e, "LocalCmp"); + + For(Bind(i, 1), (i <= len) And (Not negationfound), i++) + [ + Local(x, n, j); + // we can register other simplification rules for expressions + //e[i] := MathNth(e,i) /:: {gamma(_y) <- SimplifyExpression(gamma(y))}; + Bind(x, MathNth(e,i)); + Bind(n, SimpleNegate(x)); /* this is all we have to do because of + the kind of expressions we can have coming in */ + + For(Bind(j, i+1), (j <= len) And (Not negationfound), j++) [ + Local(y); + Bind(y, MathNth(e,j)); + + If(IsEqual(y, n), + [ + //Echo({"Deleting from ", e, " i=", i, ", j=", j, Nl()}); + + Bind(negationfound, True); + //Echo({"Removing clause ", i, Nl()}); + ], + If(IsEqual(y, x), + [ + //Echo({"Deleting from ", e, " j=", j, Nl()}); + DestructiveDelete(e, j); + Bind(len,SubtractN(len,1)); + ]) + ); + ]; + Check(len = Length(e), "Math", "The length computation is incorrect"); + ]; + + If(negationfound, {True}, e); /* note that a list is returned */ +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicSimplify.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicSimplify.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/LogicSimplify.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/LogicSimplify.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="LogicSimplify" + + // (expression, level=1..3 + +// Some shortcuts to match prev interface + +10 # LogicSimplify(_proposition, _level)_(level<2) <-- CNF(proposition); + +20 # LogicSimplify(_proposition, _level) <-- +[ + Local(cnf, list, clauses); + Check(level > 1, "Argument", "Wrong level"); + // First get the CNF version of the proposition + Bind(cnf, CNF(proposition)); + + If(level <= 1, cnf, [ + Bind(list, Flatten(cnf, "And")); + Bind(clauses, {}); + ForEach(clause, list) + [ + Local(newclause); + //newclause := BubbleSort(LogicRemoveTautologies(Flatten(clause, "Or")), LessThan); + Bind(newclause, LogicRemoveTautologies(Flatten(clause, "Or"))); + If(newclause != {True}, DestructiveAppend(clauses, newclause)); + ]; + + /* + Note that we sort each of the clauses so that they look the same, + i.e. if we have (A And B) And ( B And A), only the first one will + persist. + */ + Bind(clauses, RemoveDuplicates(clauses)); + + If(IsEqual(level, 3) And (Length(clauses) != 0), [ + Bind(clauses, DoUnitSubsumptionAndResolution(clauses)); + Bind(clauses, LogicCombine(clauses)); + ]); + + Bind(clauses, RemoveDuplicates(clauses)); + + If(IsEqual(Length(clauses), 0), True, [ + /* assemble the result back into a boolean expression */ + Local(result); + Bind(result, True); + ForEach(item,clauses) + [ + Bind(result, result And UnFlatten(item, "Or", False)); + ]; + + result; + ]); + ]); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/om/om.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,16 @@ +%mathpiper,def="" + +// From code.mpi.def: +OMDef( "=>" , "logic1","implies" ); +OMDef( "CNF" , mathpiper,"cnf" ); +OMDef( "LogicSimplify", mathpiper,"logic_simplify" ); +OMDef( "CanProve" , mathpiper,"can_prove" ); +OMDef( "LogicRemoveTautologies", mathpiper,"logic_remove_tautologies" ); +OMDef( "Subsumes" , mathpiper,"subsumes" ); +// The following appear in the def file, but commented out: +// "~", mathpiper, "Not" +// "|", mathpiper, "Or" +// "&", mathpiper, "And" + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/Subsumes.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/Subsumes.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/logic/Subsumes.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/logic/Subsumes.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,15 @@ +%mathpiper,def="Subsumes" + +10 # Subsumes((_x) - (_y) == 0, Not ((_x) - (_z)==0))_(y!=z) <-- True; +// suif_tmp0_127_1-72==0 And 78-suif_tmp0_127_1>=0 +20 # Subsumes((_x) - (_y) == 0, (_z) - (_x) >= 0)_(z>=y) <-- True; +20 # Subsumes((_x) - (_y) == 0, (_z) - (_x) > 0)_(z>y) <-- True; +// suif_tmp0_127_1-72==0 And suif_tmp0_127_1-63>=0 +30 # Subsumes((_x) - (_y) == 0, (_x) - (_z) >= 0)_(y>=z) <-- True; +30 # Subsumes((_x) - (_y) == 0, (_x) - (_z) > 0)_(y>z) <-- True; + +90 # Subsumes((_x), (_x)) <-- True; + +100# Subsumes((_x), (_y)) <-- False; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/DisassembleExpression.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/DisassembleExpression.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/DisassembleExpression.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/DisassembleExpression.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,124 @@ +%mathpiper,def="DisassembleExpression" + +//Retract("DisassembleExpression",*); + +10 # DisassembleExpression( _expr ) <-- +[ + Local(vars); + vars := MultiExpressionList( expr ); + DisassembleExpression( expr, vars ); +]; + +10 # DisassembleExpression( _expr, vars_IsList ) <-- +[ + Local(mexpr,func,termList,result,powers,coeffs); + mexpr := MakeMultiNomial(expr,vars); + func := Lambda({x,y},If(y!=0,DestructiveAppend(termList,{x,y}))); + termList := {}; + ScanMultiNomial(func,mexpr); + result := Concat({vars},Transpose(termList)); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="DisassembleExpression",categories="User Functions;Polynomials (Operations)" + +*CMD DisassembleExpression --- returns a list describing composition of an expression + +*STD +*CALL + DisassembleExpression(expr) + DisassembleExpression(expr,vars) + +*PARMS + +{expr} -- an expression + +{vars} -- a list of variable names + +*DESC + +This function is primarily used to succinctly describe the components of a +polynomial, but it can also be used with some non-polynomial expressions. + +The command {DisassembleExpression(expr)} returns a list composed of three elements: + + 1. a list of the variable names in the expression + + 2. a list of the powers of each variable in each term + + 3. a list of the coefficients of these powers in each term + +This list-of-lists comprises in essence a sparse database containing a +complete representation of the expression. Any function which needs to +examine and process the terms of an expression, in sequence, can use +{DisassembleExpression} as a starting point. + +If the first form, {DisassembleExpression(expr)}, is used, MathPiper will +employ the function "MultiExpressionList" to try to extract the names of all the +"variables" in the expression -- which may or may not result in +the list you would prefer to get. In particular, if {expr} contains +"parameters" in addition to "variables", MathPiper cannot distinguish them, +and considers them all to be "variables". +This is where the user should employ the second form, in which a preferred set +of variables is explicitly given. See the examples below. + +The pair of functions, {DisassembleExpression} and {ReassembleListTerms}, +together constitute a foundation for the analysis of polynomials and -- more +generally -- any expressions which can be regarded as sum or difference of terms. + +*E.G. +In> uu:=ExpandBrackets((x+1)^4) +Result: x^4+4*x^3+6*x^2+4*x+1 + +In> DisassembleExpression(uu) +Result: {{x},{{4},{3},{2},{1},{0}},{1,4,6,4,1}} + clear signature of binomial expansion in coefficients list + +In> vv:=ExpandBrackets((x+y)^4) +Result: x^4+4*x^3*y+6*x^2*y^2+4*x*y^3+y^4 + +In> DisassembleExpression(vv) +Result: {{x,y},{{4,0},{3,1},{2,2},{1,3},{0,4}},{1,4,6,4,1}} + same signature + +In> vv:=ExpandBrackets((a*x+b*y)^4) +Result: a^4*x^4+4*a^3*x^3*b*y+6*a^2*x^2*b^2*y^2+4*a*x*b^3*y^3+b^4*y^4 + +In> DisassembleExpression(vv) +Result: {{a,x,b,y},{{4,4,0,0},{3,3,1,1},{2,2,2,2},{1,1,3,3},{0,0,4,4}},{1,4,6,4,1}} + parameters {a,b} mistaken for variables, but binomial signature still visible + +In> DisassembleExpression(vv,{x,y}) +Result: {{x,y},{{4,0},{3,1},{2,2},{1,3},{0,4}},{a^4,4*b*a^3,6*b^2*a^2,4*b^3*a,b^4}} + user guidance helps distinguish parameters from variables, + but binomial signature still visible + +In> ww:=x+2*Sqrt(x)+1 +Result: x+2*Sqrt(x)+1 + +In> DisassembleExpression(ww) +Result: {{x,Sqrt(x)},{{1,0},{0,1},{0,0}},{1,2,1}} + {MultiExpressionList} identified as "variables" both {x} and + {Sqrt(x)} -- we call the latter a {quasi-variable}. See documentation for + {ReassembleListTerms} for an example of how this can be used to perform + automatic substitution of variables. + +*SEE MultiExpressionList, ReassembleListTerms,MM +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/Groebner.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/Groebner.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/Groebner.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/Groebner.mpw 2010-07-23 05:26:16.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="Groebner" + +/* + Groebner : Calculate the Groebner basis of a set of polynomials. + Nice example of its power is + +In> TableForm(Groebner({x*(y-1),y*(x-1)})) + x*y-x + x*y-y + y-x + y^2-y +In> Factor(y^2-y) +Result: y*(y-1); + +From which you can see that x = y, and x^2 = x so x is 0 or 1. + +*/ + +Groebner(f_IsList) <-- +[ + Local(vars,i,j,S,nr,r); + nr:=Length(f); + vars:=VarList(f); + For(i:=1,i<=nr,i++) + [ + f[i] := MakeMultiNomial(f[i],vars); + ]; + S:={}; + For(i:=1,i ListTerms(Sin(Sqrt(x))-Sqrt(x+1)-Exp(-2*x)) +Result: {Sin(Sqrt(x)),-Sqrt(x+1),-Exp(-2*x)} + +In> ListTerms((a+b*x)/(x-d*x)-(e-f*x^2)/(g+h*x)) +Result: {(a+b*x)/(x-d*x),(f*x^2-e)/(g+h*x)} + +In> ListTerms((3*x+5*y)^5) +Result: {(3*x+5*y)^5} + +In> ListTerms(ExpandBrackets((3*x+5*y)^5)) +Result: {243*x^5,2025*x^4*y,6750*x^3*y^2,11250*x^2*y^3,9375*x*y^4,3125*y^5} + + +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/makemulti/MakeMultiNomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/makemulti/MakeMultiNomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/makemulti/MakeMultiNomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/makemulti/MakeMultiNomial.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,183 @@ +%mathpiper,def="MakeMultiNomial" + + +/* code pertaining to creating the internal format for multivariate + polynomials (the inverse of NormalForm + +- MultiExpressionList(x) + extract all variable-like sub-expressions from the main expression, + including functions, which can then get treated as if they were + a variable. +- IsMultiExpression(x) + determing whether 'x' can be a 'variable' for a multiNomial +- IsMulti(x) + returns True if 'x' is a multivariate expression in internal format. + Useful for transformation rules. + */ + +MultiExpressionList(_expr) <-- VarList(expr,"IsMultiExpression"); +10 # IsMultiExpression(_x + _y) <-- False; +10 # IsMultiExpression(_x - _y) <-- False; +10 # IsMultiExpression( - _y) <-- False; +10 # IsMultiExpression(_x * _y) <-- False; +10 # IsMultiExpression(_x / _y) <-- False; +10 # IsMultiExpression(_x ^ y_IsPositiveInteger) <-- False; +11 # IsMultiExpression(_x ^ _y)_(IsPositiveInteger(Simplify(y))) <-- False; +//10 # IsMultiExpression(x_IsConstant) <-- False; +10 # IsMultiExpression(x_IsMultiConstant) <-- False; + +//TODO: shouldn't this be more global? The problem right now is +// that IsConstant/IsVariable take Pi to be a constant... +IsMultiConstant(_n) <-- (VarList(n,"IsVr")={}); +10 # IsVr(n_IsNumber) <-- False; +10 # IsVr(n_IsFunction) <-- False; +10 # IsVr(n_IsString) <-- False; +20 # IsVr(_n) <-- True; +100 # IsMultiExpression(_x) <-- True; + +10 # IsMulti(MultiNomial(vars_IsList,_terms)) <-- True; +20 # IsMulti(_anything) <-- False; + + + +LocalSymbols(a,vars,pow) [ + 20 # MultiSingleFactor(_vars,_a,_pow) <-- + [ + Local(term); + term:={FillList(0,Length(vars)),1}; + term[1][Find(vars,a)] := pow; + CreateTerm(vars,term); + ]; +]; +LocalSymbols(x,y,vars) [ +10 # MakeMultiNomial(x_IsMultiConstant,vars_IsList) <-- + CreateTerm(vars,{FillList(0,Length(vars)),x}); +20 # MakeMultiNomial(_x,vars_IsList)_(Contains(vars,x)) <-- MultiSingleFactor(vars,x,1); +30 # MakeMultiNomial(_x + _y,vars_IsList) <-- + MakeMultiNomial(x,vars) + MakeMultiNomial(y,vars); +30 # MakeMultiNomial(_x * _y,vars_IsList) <-- + MakeMultiNomial(x,vars) * MakeMultiNomial(y,vars); +30 # MakeMultiNomial(- _x,vars_IsList) <-- -MakeMultiNomial(x,vars); +30 # MakeMultiNomial(_x - _y,vars_IsList) <-- + MakeMultiNomial(x,vars) - MakeMultiNomial(y,vars); +30 # MakeMultiNomial(MultiNomial(_vars,_terms),vars_IsList) + <-- MultiNomial(vars,terms); + +// This rule would accept almost all terms, assuming them to be const. +100 # MakeMultiNomial(_x,vars_IsList) <-- + [ + CreateTerm(vars,{FillList(0,Length(vars)),x}); + ]; + +]; + +LocalSymbols(x,y,z,vars,gcd,a,a) [ + 20 # MakeMultiNomial(_x / (_y / _z),vars_IsList) + <-- MakeMultiNomial((x*z) / y,vars_IsList); + 20 # MakeMultiNomial((_x / _y) / _z,vars_IsList) + <-- MakeMultiNomial((x*z) / y,vars_IsList); + 25 # MakeMultiNomial(_x / y_IsConstant,vars_IsList) + <-- MakeMultiNomial(1/y,vars)*MakeMultiNomial(x,vars); + 30 # MakeMultiNomial(_x / _y,vars_IsList) <-- + [ + Local(result); +//Echo("1...",x); +//Echo("2...",y); + Bind(result,MultiRemoveGcd(MakeMultiNomial(x,vars)/MakeMultiNomial(y,vars))); +//Echo("3...",result); + result; + ]; + ]; + + +MultiNomial(_vars,_x) + MultiNomial(_vars,_y) <-- + MultiNomialAdd(MultiNomial(vars,x), MultiNomial(vars,y)); +MultiNomial(_vars,_x) * MultiNomial(_vars,_y) <-- + MultiNomialMultiply(MultiNomial(vars,x), MultiNomial(vars,y)); +MultiNomial(_vars,_x) - MultiNomial(_vars,_y) <-- + MultiNomialAdd(MultiNomial(vars,x), MultiNomialNegate(MultiNomial(vars,y))); + - MultiNomial(_vars,_y) <-- + MultiNomialNegate(MultiNomial(vars,y)); + + +LocalSymbols(x,n,vars) [ +30 # MakeMultiNomial(_x ^ n_IsInteger,vars_IsList)_(Contains(vars,x)) <-- + MultiSingleFactor(vars,x,n); +40 # MakeMultiNomial(_x ^ n_IsPositiveInteger,vars_IsList) <-- + [ + Local(mult,result); + Bind(mult,MakeMultiNomial(x,vars)); + Bind(result,MakeMultiNomial(1,vars)); + While(n>0) + [ + If(n&1 != 0, Bind(result, MultiNomialMultiply(result,mult))); + Bind(n,n>>1); + If(n!=0,Bind(mult,MultiNomialMultiply(mult,mult))); + ]; + result; + ]; + + 15 # MakeMultiNomial(_x ^ _n,vars_IsList)_(Not(IsInteger(n)) And IsInteger(Simplify(n))) <-- + MakeMultiNomial( x ^ Simplify(n),vars); + + 50 # MakeMultiNomial(_x ^ (_n),vars_IsList)_(Contains(vars,x)) <-- + [ + Bind(n,Simplify(n)); + If(IsInteger(n), + MultiSingleFactor(vars,x,n), + MultiSingleFactor(vars,x^n,1) + ); + ]; +]; + + +x_IsMulti + (y_IsMulti/z_IsMulti) <-- ((x*z+y)/z); +(y_IsMulti/z_IsMulti) + x_IsMulti <-- ((x*z+y)/z); +(y_IsMulti/z_IsMulti) + (x_IsMulti/w_IsMulti) <-- ((y*w+x*z)/(z*w)); +(y_IsMulti/z_IsMulti) - (x_IsMulti/w_IsMulti) <-- ((y*w-x*z)/(z*w)); +(y_IsMulti/z_IsMulti) * (x_IsMulti/w_IsMulti) <-- ((y*x)/(z*w)); +(y_IsMulti/z_IsMulti) / (x_IsMulti/w_IsMulti) <-- ((y*w)/(z*x)); +x_IsMulti - (y_IsMulti/z_IsMulti) <-- ((x*z-y)/z); +(y_IsMulti/z_IsMulti) - x_IsMulti <-- ((y-x*z)/z); +(a_IsMulti/(c_IsMulti/b_IsMulti)) <-- ((a*b)/c); +((a_IsMulti/c_IsMulti)/b_IsMulti) <-- (a/(b*c)); +((a_IsMulti/b_IsMulti) * c_IsMulti) <-- ((a*c)/b); +(a_IsMulti * (c_IsMulti/b_IsMulti)) <-- ((a*c)/b); +- ((a_IsMulti)/(b_IsMulti)) <-- (-a)/b; + + +MultiNomialMultiply( + MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2), + MultiNomial(_vars,_terms3)/MultiNomial(_vars,_terms4)) <-- +[ + MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ + MultiNomialMultiply(MultiNomial(vars,terms2),MultiNomial(vars,terms4)); +]; +MultiNomialMultiply( + MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2), + MultiNomial(_vars,_terms3)) <-- +[ + MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ + MultiNomial(vars,terms2); +]; +MultiNomialMultiply( + MultiNomial(_vars,_terms3), + MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2)) <-- +[ + MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ + MultiNomial(vars,terms2); +]; + +10 # MultiNomialMultiply(_a,_b) <-- +[ + Echo({"ERROR!",a,b}); + Echo({"ERROR!",Type(a),Type(b)}); +]; + + + + + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MM.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MM.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MM.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MM.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,6 @@ +%mathpiper,def="MM" + +MM(_expr) <-- MM(expr,MultiExpressionList(expr)); +MM(_expr,_vars) <-- MakeMultiNomial(expr,vars); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiDivide.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiDivide.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiDivide.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiDivide.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,def="MultiDivide" + +/************************************************************* + MultiDivide : + input + f - a multivariate polynomial + g[1 .. n] - a list of polynomials to divide by + output + {q[1 .. n],r} such that f = q[1]*g[1] + ... + q[n]*g[n] + r + + Basically quotient and remainder after division by a group of + polynomials. +**************************************************************/ +20 # MultiDivide(_f,g_IsList) <-- +[ + Local(i,v,q,r,nr); + v:=MultiExpressionList(f+Sum(g)); + f:=MakeMultiNomial(f,v); + nr := Length(g); + For(i:=1,i<=nr,i++) + [ + g[i] := MakeMultiNomial(g[i],v); + ]; + {q,r}:=MultiDivide(f,g); + q:=MapSingle("NormalForm",q); + r:=NormalForm(r); + {q,r}; +]; + +10 # MultiDivide(f_IsMulti,g_IsList) <-- +[ + Local(i,nr,q,r,p,v,finished); + Bind(nr, Length(g)); + Bind(v, MultiVars(f)); + Bind(q, FillList(0,nr)); + Bind(r, 0); + Bind(p, f); + Bind(finished,MultiZero(p)); + Local(plt,glt); + While (Not finished) + [ + Bind(plt, MultiLT(p)); + For(i:=1,i<=nr,i++) + [ + Bind(glt, MultiLT(g[i])); + + if (MultiLM(glt) = MultiLM(plt) Or MultiTermLess({MultiLM(glt),1}, {MultiLM(plt),1})) + if (Select(MultiLM(plt)-MultiLM(glt)) = {}, {{n},n<0}) + [ + Local(ff); + Bind(ff, CreateTerm(v,{MultiLM(plt)-MultiLM(glt),MultiLC(plt)/MultiLC(glt)})); + q[i] := q[i] + ff; + Local(ltbefore,ltafter); + Bind(ltbefore,MultiLeadingTerm(p)); +// Echo(ltbefore,MultiLeadingTerm(p)); + Bind(p, p - ff*g[i]); + Bind(ltafter,MultiLeadingTerm(p)); +// Echo(ltbefore,MultiLeadingTerm(p)); + if (ltbefore[1] = ltafter[1]) + [ + Bind(ltafter,MultiLT(p)); + Bind(p,p-ltafter); + ]; +// Echo(ltbefore,MultiLeadingTerm(p)); + Bind(i,nr+2); + ]; + ]; + + If (i = nr+1, + [ + Bind(r, r + LocalSymbols(a,b)(Subst(a,b)plt)); + Bind(p, p - LocalSymbols(a,b)(Subst(a,b)plt)); + ]); +//Echo(p); + Bind(finished,MultiZero(p)); + ]; + {q,r}; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiDivTerm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiDivTerm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiDivTerm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiDivTerm.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,25 @@ +%mathpiper,def="MultiDivTerm" + +MultiDivTerm(MultiNomial(_vars,_term1),MultiNomial(_vars,_term2)) <-- +[ + Local(lm1,lm2); + Bind(lm1,MultiLeadingTerm(MultiNomial(vars,term1)) ); + Bind(lm2,MultiLeadingTerm(MultiNomial(vars,term2)) ); + CreateTerm(vars,{lm1[1]-lm2[1],lm1[2] / lm2[2]}); +]; +MultiS(_g,_h,MultiNomial(_vars,_terms)) <-- +[ + Local(gamma); + + gamma :=Maximum(MultiDegree(g),MultiDegree(h)); + Local(result,topterm); + topterm := MM(Product(vars^gamma)); + + result := + MultiDivTerm(topterm,MultiLT(g))*g - + MultiDivTerm(topterm,MultiLT(h))*h; + + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiGcd.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiGcd.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiGcd.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiGcd.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="MultiGcd" + +//TODO optimize this! keeps on converting to and from internal format! + +10 # MultiGcd( 0,_g) <-- g; +10 # MultiGcd(_f, 0) <-- f; + +20 # MultiGcd(_f,_g) <-- +[ + Local(v); + v:=MultiExpressionList(f+g); //hier + NormalForm(MultiGcd(MakeMultiNomial(f,v),MakeMultiNomial(g,v))); +]; + + +5 # MultiGcd(f_IsMulti,g_IsMulti)_(MultiTermLess({MultiLM(f),1},{MultiLM(g),1})) <-- +[ +//Echo("lesser"); + MultiGcd(g,f); +]; + +5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(MultiLM(MultiNomial(vars,terms)) = MultiLM(g)) + <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); + +5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_( Select(MultiLM(MultiNomial(vars,terms))-MultiLM(g), {{n},n<0} ) != {}) + <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); + +5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(NormalForm(g) = 0) + <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); +10 # MultiGcd(f_IsMulti,g_IsMulti) <-- +[ + LocalSymbols(a) + [ + Bind(f,Subst(a,a)f); + Bind(g,Subst(a,a)g); + ]; + Local(new); + While(g != 0) + [ +//Echo("before f",f,NormalForm(f)); +//Echo("before g",g,NormalForm(g)); + Bind(new, MultiDivide(f,{g})); +//Echo("new g",NormalForm(new[1][1]),NormalForm(new[2])); +If(new[1][1]=0, +[ + g:=MakeMultiNomial(1,MultiVars(f)); +//Echo("PRIM ",MultiPrimitivePart(g)); + new[2]:=0; +]); + Bind(new, new[2]); + Bind(f,g); + Bind(g,new); + +//Echo("after f",f,NormalForm(f)); +//Echo("after g",g,NormalForm(g)); + ]; + MultiPrimitivePart(f); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiNomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiNomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiNomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiNomial.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="MultiNomial" + +// The basic container for multivariates +Rulebase("MultiNomial",{vars,terms}); + +// using the sparse tree driver for multivariate polynomials +//LoadScriptOnce("multivar.rep/sparsenomial.mpi"); +//LoadScriptOnce("multivar.rep/partialdensenomial.mpi"); + +If(IsBound(MultiNomialDriver), + `LoadScriptOnce(@MultiNomialDriver), + LoadScriptOnce("multivar.rep/sparsenomial.mpi")); + +// Code that can build the internal representation of a multivariate polynomial +LoadScriptOnce("multivar.rep/makemulti.mpi"); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiSimp.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiSimp.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/MultiSimp.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/MultiSimp.mpw 2011-02-06 16:56:54.000000000 +0000 @@ -0,0 +1,114 @@ +%mathpiper,def="MultiSimp" + +MultiSimp(_expr) <-- +[ + Local(vars); + vars:=MultiExpressionList(expr); +//Echo({"step1 ",MM(expr,vars)}); + MultiSimp2(MM(expr,vars)); +]; + +10 # MultiSimp2(_a / _b) <-- +[ + Local(c1,c2,gcd,cmn,vars); + + + c1 := MultiContentTerm(a); + c2 := MultiContentTerm(b); + gcd:=Gcd(c1[2],c2[2]); + c1[2] := c1[2]/gcd; + c2[2] := c2[2]/gcd; + + cmn:=Minimum(c1[1],c2[1]); + c1[1] := c1[1] - cmn; + c2[1] := c2[1] - cmn; + + vars:=MultiVars(a); + Check(vars = MultiVars(a), "Argument", "incompatible Multivars to simplify"); + + (NormalForm(CreateTerm(vars,c1))/NormalForm(CreateTerm(vars,c2))) + *(NormalForm(MultiPrimitivePart(a))/NormalForm(MultiPrimitivePart(b))); +]; + +20 # MultiSimp2(expr_IsMulti) <-- +[ + NormalForm(MultiContent(expr))*NormalForm(MultiPrimitivePart(expr)); +]; +30 # MultiSimp2(_expr) <-- expr; + +MultiContent(multi_IsMulti) +<-- +[ + Local(least,gcd); + Bind(least, MultiDegree(multi)); + Bind(gcd,MultiLeadingCoef(multi)); + ScanMultiNomial("MultiContentScan",multi); + CreateTerm(MultiVars(multi),MultiContentTerm(multi)); +]; + +MultiContentTerm(multi_IsMulti) +<-- +[ + Local(least,gcd); + Bind(least, MultiDegree(multi)); + Bind(gcd,MultiLeadingCoef(multi)); + ScanMultiNomial("MultiContentScan",multi); + {least,gcd}; +]; + +MultiContentScan(_coefs,_fact) <-- +[ + Bind(least,Minimum({least,coefs})); + Bind(gcd,Gcd(gcd,fact)); +]; +UnFence("MultiContentScan",2); + +MultiPrimitivePart(MultiNomial(vars_IsList,_terms)) +<-- +[ + Local(cont); + Bind(cont,MultiContentTerm(MultiNomial(vars,terms))); + Bind(cont,CreateTerm(vars,{-cont[1],1/Rationalize(cont[2])})); + MultiNomialMultiply(MultiNomial(vars,terms), cont); +]; + +10 # MultiRemoveGcd(x_IsMulti/y_IsMulti) <-- +[ + Local(gcd); + Bind(gcd,MultiGcd(x,y)); + Bind(x,MultiDivide(x,{gcd})[1][1]); + Bind(y,MultiDivide(y,{gcd})[1][1]); + x/y; +]; +20 # MultiRemoveGcd(_x) <-- x; + + + +5 # MultiDegree(MultiNomial(_vars,_term))_(Not(IsList(term))) <-- {}; +10 # MultiDegree(MultiNomial(_vars,{})) <-- FillList(-Infinity,Length(vars)); +20 # MultiDegree(MultiNomial(_vars,_terms)) + <-- (MultiLeadingTerm(MultiNomial(vars,terms))[1]); + + +10 # MultiLeadingCoef(MultiNomial(_vars,_terms)) + <-- (MultiLeadingTerm(MultiNomial(vars,terms))[2]); + +10 # MultiLeadingMono(MultiNomial(_vars,{})) <-- 0; +20 # MultiLeadingMono(MultiNomial(_vars,_terms)) + <-- Product(vars^(MultiDegree(MultiNomial(vars,terms)))); + +20 # MultiLeadingTerm(_m) <-- MultiLeadingCoef(m) * MultiLeadingMono(m); + +MultiVars(MultiNomial(_vars,_terms)) <-- vars; + +20 # MultiLT(multi_IsMulti) + <-- CreateTerm(MultiVars(multi),MultiLeadingTerm(multi)); + +10 # MultiLM(multi_IsMulti) <-- MultiDegree(multi); + +10 # MultiLC(MultiNomial(_vars,{})) <-- 0; +20 # MultiLC(multi_IsMulti) <-- MultiLeadingCoef(multi); + +DropZeroLC(multi_IsMulti) <-- MultiDropLeadingZeroes(multi); + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/ReassembleListTerms.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/ReassembleListTerms.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/ReassembleListTerms.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/ReassembleListTerms.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,94 @@ +%mathpiper,def="ReassembleListTerms" + +//Retract("ReassembleListTerms",*); + +10 # ReassembleListTerms( disassembly_IsList ) <-- +[ + Local(vars,lst,powers,coeffs,ii,pows,coef,term); + vars := disassembly[1]; + powers := disassembly[2]; + coeffs := disassembly[3]; + lst := {}; + For(ii:=1,ii<=Length(powers),ii++) + [ + pows := powers[ii]; + coef := coeffs[ii]; + //Tell(" ",{pows,coef}); + term := coef*Product(vars^pows); + //Tell(" ",term); + DestructiveAppend(lst,term); + ]; + lst; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="ReassembleListTerms",categories="User Functions;Polynomials (Operations)" + +*CMD ResassembleListTerms --- returns a list of the terms in an expression + +*STD +*CALL + ResassembleListTerms(disassembly) + +*PARMS + +{disassembly} -- a disassembly list generated by {DisassembleExpression} + +*DESC + +After an expression (usually, but not always, a polynomial) has been disassembled +by the function {DisassembleExpression}, the function +{ReassembleListTerms} converts this into a list of the individual terms +in the expression. + +This is useful in itself, because a list of terms can be processed term-by-term +in any desired manner. + +But also, the items in the disassembly may be transformed in various ways before +being reassembled. This can facilitate automatic transformations of +polynomials or expressions into forms more convenient for further processing. + +See the examples below. + +The pair of functions, {DisassembleExpression} and {ReassembleListTerms}, +together constitute a foundation for the analysis of polynomials and -- more +generally -- any expressions which can be regarded as sum or difference of terms. + +*E.G. + +In> ww:=x+2*Sqrt(x)+1 +Result: x+2*Sqrt(x)+1 + This expression is really a disguised quadratic + +In> ex:=DisassembleExpression(ww) +Result: {{x,Sqrt(x)},{{1,0},{0,1},{0,0}},{1,2,1}} + The disassembly has recognized Sqrt(x) as a quasi-variable + +In> exx:=Subst({x,Sqrt(x)},{t^2,t})ex +Result: {{t^2,t},{{1,0},{0,1},{0,0}},{1,2,1}} + An algorithm could observe the list {x,Sqrt(x)} and automatically + perform the substitution to make a change-of-variables + +In> Sum(ReassembleListTerms(exx)) +Result: t^2+2*t+1 + The expression has now been transformed into an obvious quadratic, + which can now be solved. + + +*SEE MultiExpressionList, DisassembleExpression,MM +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/sparsenomial/sparsenomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/sparsenomial/sparsenomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/sparsenomial/sparsenomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/sparsenomial/sparsenomial.mpw 2011-04-16 16:45:46.000000000 +0000 @@ -0,0 +1,152 @@ +%mathpiper,def="" + + +/* Implementation of MultiNomials based on sparse representation + in the sparsetree.mpi code. This is the real driver, using + the sparse trees just for representation. + */ +LoadScriptOnce("multivar.rep/sparsetree.mpi"); + +LocalSymbols(NormalMultiNomial) [ + +CreateTerm(_vars,{_coefs,_fact}) + <-- MultiNomial(vars,CreateSparseTree(coefs,fact)); + +/************************************************************ + +Adding and multiplying multivariate polynomials + +************************************************************/ +MultiNomialAdd(MultiNomial(_vars,_x), MultiNomial(_vars,_y)) + <-- MultiNomial(vars,AddSparseTrees(Length(vars),x,y)); +MultiNomialMultiplyAdd(MultiNomial(_vars,_x), MultiNomial(_vars,_y),_coefs,_fact) + <-- MultiNomial(vars,MultiplyAddSparseTrees(Length(vars),x,y,coefs,fact)); +MultiNomialNegate(MultiNomial(_vars,_terms)) + <-- + [ + SparseTreeMap(Hold({{coefs,list},-list}),Length(vars),terms); + MultiNomial(vars,terms); + ]; +MultiNomialMultiply(MultiNomial(_vars,_x),_multi2) + <-- + [ + Local(result); + Bind(result,MakeMultiNomial(0,vars)); + SparseTreeScan("muadm",Length(vars),x); + result; + ]; +muadm(_coefs,_fact) <-- +[ + Bind(result,MultiNomialMultiplyAdd(result, multi2,coefs,fact)); +]; +UnFence("muadm",2); + + +/* NormalForm: done as an explicit loop in stead of using SparseTreeScan + for speed. This routine is a lot faster! + */ +10 # NormalForm(x_IsMulti/y_IsMulti) <-- NormalForm(x)/NormalForm(y); +20 # NormalForm(MultiNomial(_vars,_list) ) + <-- NormalMultiNomial(vars,list,1); +10 # NormalMultiNomial({},_term,_prefact) <-- prefact*term; +20 # NormalMultiNomial(_vars,_list,_prefact) + <-- + [ + Local(first,rest,result); + Bind(first,First(vars)); + Bind(rest,Rest(vars)); + Bind(result,0); + ForEach(item,list) + [ + Bind(result,result+NormalMultiNomial(rest,item[2],prefact*first^(item[1]))); + ]; + result; + ]; + +]; // LocalSymbols + +MultiLeadingTerm(MultiNomial(_vars,_terms)) + <-- + [ + Local(coefs,fact); + Bind(coefs,MultiDegreeScanHead(terms,Length(vars))); + {coefs,fact}; + ]; +10 # MultiDegreeScanHead(_tree,0) + <-- + [ + Bind(fact,tree); + {}; + ]; +10 # MultiDegreeScanHead(_tree,1) + <-- + [ + Bind(fact,tree[1][2]); + {tree[1][1]}; + ]; +20 # MultiDegreeScanHead(_tree,_depth) + <-- + [ + (tree[1][1]):MultiDegreeScanHead(tree[1][2],depth-1); + ]; +UnFence("MultiDegreeScanHead",2); + +ScanMultiNomial(_op,MultiNomial(vars_IsList,_terms)) + <-- SparseTreeScan(op,Length(vars),terms); +UnFence("ScanMultiNomial",2); + + +MultiDropLeadingZeroes(MultiNomial(_vars,_terms)) + <-- + [ + MultiDropScan(terms,Length(vars)); + MultiNomial(vars,terms); + ]; +10 # MultiDropScan(0,0) <-- True; +10 # MultiDropScan({_n,0},0) <-- True; +20 # MultiDropScan(_n,0) + <-- + [ + False; + ]; +30 # MultiDropScan(_tree,_depth) + <-- + [ + Local(i); + For(i:=1,i<=Length(tree),i++) + [ + if (MultiDropScan(tree[i][2],depth-1)) + [ + DestructiveDelete(tree,i); + i--; + ] + else + [ + i:=Length(tree); + ]; + ]; + (tree = {}); + ]; +UnFence("MultiDropScan",2); + + +MultiTermLess({_deg1,_fact1},{_deg2,_fact2}) <-- + [ + Local(deg); + Bind(deg, deg1-deg2); + While(deg != {} And First(deg) = 0) [ Bind(deg, Rest(deg));]; + + ((deg = {}) And (fact1-fact2 < 0)) Or + ((deg != {}) And (deg[1] < 0)); + ]; + +20 # MultiZero(multi_IsMulti) <-- +[ + CheckMultiZero(DropZeroLC(multi)); +]; +10 # CheckMultiZero(MultiNomial(_vars,{})) <-- True; +20 # CheckMultiZero(MultiNomial(_vars,_terms)) <-- False; + + + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/sparsetree/sparsetree.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/sparsetree/sparsetree.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/multivar/sparsetree/sparsetree.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/multivar/sparsetree/sparsetree.mpw 2011-02-05 04:04:44.000000000 +0000 @@ -0,0 +1,220 @@ +%mathpiper,def="CreateSparseTree;SparseTreeMap;SparseTreeScan;AddSparseTrees;MultiplyAddSparseTrees;SparseTreeGet" + +/* def file definitions +CreateSparseTree +SparseTreeMap +SparseTreeScan +AddSparseTrees +MultiplyAddSparseTrees +SparseTreeGet +*/ + +/* Implementation of a sparse tree of Multidimensional matrix elements. +*/ + +10 # SparseTreeGet({},_tree) <-- tree; +20 # SparseTreeGet(_key,_tree) <-- +[ + SparseTreeGet2(Rest(key),Assoc(First(key),tree)); +]; +10 # SparseTreeGet2(_key,Empty) <-- 0; +20 # SparseTreeGet2(_key,_item) <-- SparseTreeGet(key,First(Rest(item))); + +10 # SparseTreeSet({_i},_tree,_newvalue) + <-- +[ + Local(Current,assoc,result); + Bind(assoc,Assoc(i,tree)); + if(assoc=Empty) + [ + Bind(Current,0); + Bind(result,Eval(newvalue)); + AddSparseTrees(1,tree,CreateSparseTree({i},result)); + ] + else + [ + Bind(Current,assoc[2]); + Bind(result,Eval(newvalue)); + assoc[2] := result; + ]; + result; +]; +20 # SparseTreeSet(_key,_tree,_newvalue) <-- +[ + SparseTreeSet2(Rest(key),Assoc(First(key),tree)); +]; +10 # SparseTreeSet2(_key,Empty) <-- 0; +20 # SparseTreeSet2(_key,_item) + <-- SparseTreeSet(key,First(Rest(item)),newvalue); +UnFence("SparseTreeSet",3); +UnFence("SparseTreeSet2",2); + + +LocalSymbols(SparseTreeMap2,SparseTreeScan2,Muaddterm,MuMuaddterm, + meradd,meraddmap) [ + +10 # CreateSparseTree({},_fact) <-- fact; + +20 # CreateSparseTree(_coefs,_fact) + <-- CreateSparseTree(First(coefs),Rest(coefs),fact); +10 # CreateSparseTree(_first,{},_fact) <-- {{first,fact}}; +20 # CreateSparseTree(_first,_coefs,_fact) + <-- {{first,CreateSparseTree(First(coefs),Rest(coefs),fact)}}; + +10 # SparseTreeMap(_op,_depth,_list) <-- SparseTreeMap2(list,depth,{}); +10 # SparseTreeMap2(_list,1,_coefs) + <-- + ForEach(item,list) + [ + item[2] := ApplyFast(op,{Concat(coefs,{item[1]}),item[2]}); + ]; +20 # SparseTreeMap2(_list,_depth,_coefs) + <-- + ForEach(item,list) + [ + SparseTreeMap2(item[2],AddN(depth,-1),Concat(coefs,{item[1]})); + ]; +UnFence("SparseTreeMap", 3); +[Local(fn);fn:=ToString(SparseTreeMap2);`UnFence(@fn,3);]; + +10 # SparseTreeScan(_op,_depth,_list) <-- SparseTreeScan2(list,depth,{}); +10 # SparseTreeScan2(_list,0,_coefs) <-- ApplyFast(op,{coefs,list}); +20 # SparseTreeScan2(_list,_depth,_coefs) + <-- + ForEach(item,list) + [ + SparseTreeScan2(item[2],AddN(depth,-1),Concat(coefs,{item[1]})); + ]; +UnFence("SparseTreeScan", 3); +[Local(fn);fn:=ToString(SparseTreeScan2);`UnFence(@fn,3);]; + + + +5 # AddSparseTrees(0,_x,_y) <-- x+y; +10 # AddSparseTrees(_depth,_x,_y) <-- +[ + Local(i,t1,t2,inspt); + Bind(t1,x); + Bind(i,1); + Bind(t2,y); + Bind(inspt,{}); + While(t1 != {} And t2 != {}) + [ + Muaddterm(First(t1),First(t2)); + ]; + While(t2 != {}) + [ + Bind(x,DestructiveAppend(x,First(t2))); + Bind(t2,Rest(t2)); + ]; + While(inspt != {}) + [ + Bind(i,First(inspt)); + Bind(x,DestructiveInsert(x,i[2],i[1])); + Bind(inspt,Rest(inspt)); + ]; + x; +]; + +10 # Muaddterm({_pow,_list1},{_pow,_list2}) <-- +[ + if(depth=1) + [ t1[1][2] := list1+list2; ] + else + [ t1[1][2] := AddSparseTrees(AddN(depth,-1),list1,list2);]; + Bind(t2,Rest(t2)); +]; +20 # Muaddterm(_h1,_h2)_(h1[1] Abs(N(Eval(eps*r)) ) ) ) + [ + r2 := r1; + n++; + r1 := ContFracEval(Take(cflist,n)); + ]; + // now r1 and r2 are some rational numbers. + // decide whether the search was successful. + If( + n=Length(cflist), + {}, // return empty list if not enough precision + If(N(Eval(r-r1))>0, + {r1, r2}, // successive approximations are always bracketing, we only need to decide their order + {r2, r1} + ) + ); +]; + +%/mathpiper + + + +%mathpiper_docs,name="BracketRational",categories="User Functions;Numbers (Operations)" +*CMD BracketRational --- find optimal rational approximations +*STD +*CALL + BracketRational(x, eps) + +*PARMS + +{x} -- a number to be approximated (must be already evaluated to floating-point) + +{eps} -- desired precision + +*DESC + +The function {BracketRational(x,eps)} can be used to find approximations with a given relative precision from above and from below. +This function returns a list of two rational numbers {{r1,r2}} such that $r1 BracketRational(N(Ln(10)), 10^(-8)) +Result: {12381/5377,41062/17833}; + + +*SEE GuessRational, NearRational, ContFrac, ContFracList, Rationalize +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/CharacteristicEquation.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/CharacteristicEquation.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/CharacteristicEquation.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/CharacteristicEquation.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="CharacteristicEquation" + +Function("CharacteristicEquation",{matrix,var}) + SymbolicDeterminant(matrix-var*Identity(Length(matrix))); +HoldArgument("CharacteristicEquation",var); + +%/mathpiper + + + +%mathpiper_docs,name="CharacteristicEquation",categories="User Functions;Linear Algebra" +*CMD CharacteristicEquation --- get characteristic polynomial of a matrix +*STD +*CALL + CharacteristicEquation(matrix,var) + +*PARMS + +{matrix} -- a matrix + +{var} -- a free variable + +*DESC + +CharacteristicEquation +returns the characteristic equation of "matrix", using +"var". The zeros of this equation are the eigenvalues +of the matrix, Det(matrix-I*var); + +*E.G. + +In> A:=DiagonalMatrix({a,b,c}) +Result: {{a,0,0},{0,b,0},{0,0,c}}; +In> B:=CharacteristicEquation(A,x) +Result: (a-x)*(b-x)*(c-x); +In> Expand(B,x) +Result: (b+a+c)*x^2-x^3-((b+a)*c+a*b)*x+a*b*c; + +*SEE EigenValues, EigenVectors +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ContFracEval.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ContFracEval.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ContFracEval.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ContFracEval.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,63 @@ +%mathpiper,def="ContFracEval" + +////////////////////////////////////////////////// +/// ContFracEval: evaluate continued fraction from the list of coefficients +////////////////////////////////////////////////// +/// Each coefficient is either a single expression or a list of 2 expressions, giving the term and the numerator of the current level in the fraction. +/// ContFracEval({{a0, b0}, {a1, b1}, ...}) = a0+b0/(a1+b1/(...)) +/// ContFracEval({a0, a1, ...}) = a0+1/(a1+1/(...)) + +10 # ContFracEval({}, _rest) <-- rest; +// finish recursion here +10 # ContFracEval({{_n, _m}}, _rest) <-- n+m+rest; +15 # ContFracEval({_n}, _rest) <-- n+rest; +/// Continued fractions with nontrivial numerators +20 # ContFracEval(list_IsList, _rest)_(IsList(First(list))) <-- First(First(list)) + Rest(First(list)) / ContFracEval(Rest(list), rest); +/// Continued fractions with unit numerators +30 # ContFracEval(list_IsList, _rest) <-- First(list) + 1 / ContFracEval(Rest(list), rest); + +/// evaluate continued fraction: main interface +ContFracEval(list_IsList) <-- ContFracEval(list, 0); + +%/mathpiper + + + +%mathpiper_docs,name="ContFracEval",categories="User Functions;Numbers (Operations)" +*CMD ContFracList --- manipulate continued fractions +*CMD ContFracEval --- manipulate continued fractions +*STD +*CALL + ContFracList(frac) + ContFracList(frac, depth) + ContFracEval(list) + ContFracEval(list, rest) + +*PARMS + +{frac} -- a number to be expanded + +{depth} -- desired number of terms + +{list} -- a list of coefficients + +{rest} -- expression to put at the end of the continued fraction + +*DESC + +The function {ContFracList} computes terms of the continued fraction +representation of a rational number {frac}. It returns a list of terms of length {depth}. If {depth} is not specified, it returns all terms. + +The function {ContFracEval} converts a list of coefficients into a continued fraction expression. The optional parameter {rest} specifies the symbol to put at the end of the expansion. If it is not given, the result is the same as if {rest=0}. + +*E.G. + +In> A:=ContFracList(33/7 + 0.000001) +Result: {4,1,2,1,1,20409,2,1,13,2,1,4,1,1,3,3,2}; +In> ContFracEval(Take(A, 5)) +Result: 33/7; +In> ContFracEval(Take(A,3), remainder) +Result: 1/(1/(remainder+2)+1)+4; + +*SEE ContFrac, GuessRational +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ContFracList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ContFracList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ContFracList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ContFracList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,64 @@ +%mathpiper,def="ContFracList" + +///////////////////////////////////////////////// +/// Continued fractions stuff +///////////////////////////////////////////////// + +/// compute the list of continued fraction coefficients for a given number +/// if order is not given, computes to the end +10 # ContFracList(_n) <-- ContFracList(n, Infinity); +/// compute list of given length +10 # ContFracList(_n, _depth)_(depth <= 0) <-- {}; +20 # ContFracList(n_IsInteger, _depth) <-- {n}; +// prevent infinite loop when in numeric mode +30 # ContFracList(n_IsNumber, _depth) _InNumericMode() <-- NonN(ContFracList(Rationalize(n), depth)); + +40 # ContFracList(n_IsNumber, _depth) <-- ContFracList(Rationalize(n), depth); + +/* n/m = Quotient(n,m) + 1/( m/Modulo(n,m) ) */ +35 # ContFracList((n_IsNegativeInteger) / (m_IsInteger), _depth) <-- Push( ContFracList(m/Modulo(n,m), depth-1) , Quotient(n,m)-1); + +40 # ContFracList((n_IsInteger) / (m_IsInteger), _depth) <-- Push( ContFracList(m/Modulo(n,m), depth-1) , Quotient(n,m)); + +%/mathpiper + + + +%mathpiper_docs,name="ContFracList",categories="User Functions;Numbers (Operations)" +*CMD ContFracList --- manipulate continued fractions +*CMD ContFracEval --- manipulate continued fractions +*STD +*CALL + ContFracList(frac) + ContFracList(frac, depth) + ContFracEval(list) + ContFracEval(list, rest) + +*PARMS + +{frac} -- a number to be expanded + +{depth} -- desired number of terms + +{list} -- a list of coefficients + +{rest} -- expression to put at the end of the continued fraction + +*DESC + +The function {ContFracList} computes terms of the continued fraction +representation of a rational number {frac}. It returns a list of terms of length {depth}. If {depth} is not specified, it returns all terms. + +The function {ContFracEval} converts a list of coefficients into a continued fraction expression. The optional parameter {rest} specifies the symbol to put at the end of the expansion. If it is not given, the result is the same as if {rest=0}. + +*E.G. + +In> A:=ContFracList(33/7 + 0.000001) +Result: {4,1,2,1,1,20409,2,1,13,2,1,4,1,1,3,3,2}; +In> ContFracEval(Take(A, 5)) +Result: 33/7; +In> ContFracEval(Take(A,3), remainder) +Result: 1/(1/(remainder+2)+1)+4; + +*SEE ContFrac, GuessRational +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ContFrac.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ContFrac.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ContFrac.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ContFrac.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,88 @@ +%mathpiper,def="ContFrac" + +////////////////////////////////////////////////// +/// continued fractions for polynomials +////////////////////////////////////////////////// + +/// main interface +10 # ContFrac(_n) <-- ContFrac(n, 6); +50 # ContFrac(_n,_depth) <-- ContFracEval(ContFracList(n, depth), rest); + +40 # ContFrac(n_CanBeUni,_depth)_(Length(VarList(n)) = 1) <-- +[ + ContFracDoPoly(n,depth,VarList(n)[1]); +]; + +5 # ContFracDoPoly(_exp,0,_var) <-- rest; +5 # ContFracDoPoly(0,0,_var) <-- rest; +10 # ContFracDoPoly(_exp,_depth,_var) <-- +[ + Local(content,exp2,first,second); + first:=Coef(exp,var,0); + exp:=exp-first; + content:=Content(exp); + exp2:=DivPoly(1,PrimitivePart(exp),var,5+3*depth)-1; + second:=Coef(exp2,0); + exp2 := exp2 - second; + first+content/((1+second)+ContFracDoPoly(exp2,depth-1,var)); +]; + +%/mathpiper + + + +%mathpiper_docs,name="ContFrac",categories="User Functions;Numbers (Operations)" +*CMD ContFrac --- continued fraction expansion +*STD +*CALL + ContFrac(x) + ContFrac(x, depth) + +*PARMS + +{x} -- number or polynomial to expand in continued fractions + +{depth} -- integer, maximum required depth of result + +*DESC + +This command returns the continued fraction expansion of {x}, which +should be either a floating point number or a polynomial. If +{depth} is not specified, it defaults to 6. The remainder is +denoted by {rest}. + +This is especially useful for polynomials, since series expansions +that converge slowly will typically converge a lot faster if +calculated using a continued fraction expansion. + +*E.G. + +In> PrettyForm(ContFrac(N(Pi))) + + 1 + --------------------------- + 3 + 1 + ----------------------- + 7 + 1 + ------------------ + 15 + 1 + -------------- + 1 + 1 + -------- + 292 + rest + 1 + +Result: True; +In> PrettyForm(ContFrac(x^2+x+1, 3)) + + x + ---------------- + 1 + x + 1 - ------------ + x + -------- + 1 + rest + 1 + +Result: True; + +*SEE PAdicExpand, N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Decimal.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Decimal.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Decimal.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Decimal.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,99 @@ +%mathpiper,def="Decimal" + +10 # Decimal( n_IsInteger ) <-- {n,{0}}; +10 # Decimal( (n_IsPositiveInteger) / (d_IsPositiveInteger) ) <-- +[ + Local(result,rev,first,period,repeat,static); + result:={Quotient(n,d)}; + Decimal(result,Modulo(n,d),d,350); + rev:=DecimalFindPeriod(result); + first:=rev[1]; + period:=rev[2]; + repeat:=result[first .. (first+period-1)]; + static:=result[1 .. (first-1)]; + DestructiveAppend(static,repeat); +]; +20 # Decimal(_n/_m)_((n/m)<0) <-- "-":Decimal(-n/m); + +10 # Decimal(_result , _n , _d,_count ) <-- +[ + While(count>0) + [ + DestructiveAppend(result,Quotient(10*n,d)); + n:=Modulo(10*n,d); + count--; + ]; +]; + +DecimalFindPeriod(_list) <-- +[ + Local(period,nr,reversed,first,i); + reversed:=Rest(DestructiveReverse(FlatCopy(Rest(list)))); + nr:=Length(reversed)>>1; + period:=1; + first:=reversed[1]; + + For(i:=1,i1 And list[first] = list[first+period]) first--; + first++; + + {first,period}; +]; + +DecimalMatches(_reversed,_period) <-- +[ + Local(nr,matches,first); + nr:=0; + matches:=True; + first:=1; + While((nr<100) And matches) + [ + matches := (matches And + (reversed[first .. (first+period-1)] = reversed[(first+period) .. (first+2*period-1)])); + first:=first+period; + nr:=nr+period; + ]; + matches; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Decimal",categories="User Functions;Numbers (Operations)" +*CMD Decimal --- decimal representation of a rational +*STD +*CALL + Decimal(frac) + +*PARMS + +{frac} -- a rational number + +*DESC + +This function returns the infinite decimal representation of a +rational number {frac}. It returns a list, with the first element +being the number before the decimal point and the last element the +sequence of digits that will repeat forever. All the intermediate list +elements are the initial digits before the period sets in. + +*E.G. + +In> Decimal(1/22) +Result: {0,0,{4,5}}; +In> N(1/22,30) +Result: 0.045454545454545454545454545454; + +*SEE N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/EigenValues.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/EigenValues.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/EigenValues.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/EigenValues.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="EigenValues" + +// diagonal matrices will be caught by IsUpperTriangular +10 # EigenValues(matrix_IsUpperTriangular) <-- Diagonal(matrix); +10 # EigenValues(matrix_IsLowerTriangular) <-- Diagonal(matrix); + +20 # EigenValues(matrix_IsMatrix) <-- Roots(CharacteristicEquation(matrix,xx)); + +%/mathpiper + + + +%mathpiper_docs,name="EigenValues",categories="User Functions;Linear Algebra" +*CMD EigenValues --- get eigenvalues of a matrix +*STD +*CALL + EigenValues(matrix) + +*PARMS + +{matrix} -- a square matrix + +*DESC + +EigenValues returns the eigenvalues of a matrix. +The eigenvalues x of a matrix M are the numbers such that +$M*v=x*v$ for some vector. + +It first determines the characteristic equation, and then factorizes this +equation, returning the roots of the characteristic equation +Det(matrix-x*identity). + +*E.G. + +In> M:={{1,2},{2,1}} +Result: {{1,2},{2,1}}; +In> EigenValues(M) +Result: {3,-1}; + +*SEE EigenVectors, CharacteristicEquation +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/EigenVectors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/EigenVectors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/EigenVectors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/EigenVectors.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,58 @@ +%mathpiper,def="EigenVectors" + +EigenVectors(_matrix,_eigenvalues) <-- +[ + Local(result,n); +/* eigenvalues:=N(Eval(eigenvalues)); */ + n:=Length(eigenvalues); + result:={}; + ForEach(e,eigenvalues) + [ + Local(possible); +/* Echo({"1...",result}); */ + possible:=OldSolve(matrix*MakeVector(k,n)==e*MakeVector(k,n),MakeVector(k,n))[1]; +/* Echo({"2..."}); */ +/* Echo({"2..."}); */ + + If(Not(IsZeroVector(possible)), + DestructiveAppend(result,possible) + ); +/* Echo({"3..."}); */ + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="EigenVectors",categories="User Functions;Linear Algebra" +*CMD EigenVectors --- get eigenvectors of a matrix +*STD +*CALL + EigenVectors(A,eigenvalues) + +*PARMS + +{matrix} -- a square matrix + +{eigenvalues} -- list of eigenvalues as returned by {EigenValues} + +*DESC + +{EigenVectors} returns a list of the eigenvectors of a matrix. +It uses the eigenvalues and the matrix to set up n equations with +n unknowns for each eigenvalue, and then calls {Solve} to determine +the values of each vector. + +*E.G. + +In> M:={{1,2},{2,1}} +Result: {{1,2},{2,1}}; +In> e:=EigenValues(M) +Result: {3,-1}; +In> EigenVectors(M,e) +Result: {{-ki2/ -1,ki2},{-ki2,ki2}}; + +*SEE EigenValues, CharacteristicEquation +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/GuessRational.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/GuessRational.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/GuessRational.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/GuessRational.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,92 @@ +%mathpiper,def="GuessRational" + +/// guess the rational number behind an imprecise number +/// prec parameter is the max number of digits you can have in the denominator +GuessRational(_x) <-- GuessRational(x, Floor(1/2*BuiltinPrecisionGet())); +GuessRational(x_IsRationalOrNumber, prec_IsInteger) <-- [ + Local(denom'estimate, cf, i); + denom'estimate := 1; + cf := ContFracList(x); + For(i:=2, i<=Length(cf) And denom'estimate < 10^prec, i++) + [ // estimate the denominator + denom'estimate := denom'estimate * If( + cf[i] = 1, + If( + i+2<=Length(cf), // have at least two more terms, do a full estimate + RoundTo(N(Eval(cf[i]+1/(cf[i+1]+1/cf[i+2]))), 3), + // have only one more term + RoundTo(N(Eval(cf[i]+1/cf[i+1])), 3) + ), + // term is not 1, use the simple estimate + cf[i] + ); + ]; + If (denom'estimate < 10^prec, + //If(InVerboseMode(), Echo({"GuessRational: all ", i, "terms are within limits"})), + i-- // do not use the last term + ); + i--; // loop returns one more number + //If(InVerboseMode(), Echo({"GuessRational: using ", i, "terms of the continued fraction"})); + ContFracEval(Take(cf, i)); +]; + +%/mathpiper + + + +%mathpiper_docs,name="GuessRational",categories="User Functions;Numbers (Operations)" +*CMD GuessRational --- find optimal rational approximations +*STD +*CALL + GuessRational(x) + GuessRational(x, digits) + +*PARMS + +{x} -- a number to be approximated (must be already evaluated to floating-point) + +{digits} -- desired number of decimal digits (integer) + +*DESC + +The functions {GuessRational(x)} and {NearRational(x)} attempt to find "optimal" +rational approximations to a given value {x}. The approximations are "optimal" +in the sense of having smallest numerators and denominators among all rational +numbers close to {x}. This is done by computing a continued fraction +representation of {x} and truncating it at a suitably chosen term. Both +functions return a rational number which is an approximation of {x}. + +Unlike the function {Rationalize()} which converts floating-point numbers to +rationals without loss of precision, the functions {GuessRational()} and +{NearRational()} are intended to find the best rational that is approximately +equal to a given value. + +The function {GuessRational()} is useful if you have obtained a +floating-point representation of a rational number and you know +approximately how many digits its exact representation should contain. +This function takes an optional second parameter {digits} which limits +the number of decimal digits in the denominator of the resulting +rational number. If this parameter is not given, it defaults to half +the current precision. This function truncates the continuous fraction +expansion when it encounters an unusually large value (see example). +This procedure does not always give the "correct" rational number; a +rule of thumb is that the floating-point number should have at least as +many digits as the combined number of digits in the numerator and the +denominator of the correct rational number. + +*E.G. + +Start with a rational number and obtain a floating-point approximation: +In> x:=N(956/1013) +Result: 0.9437314906 +In> Rationalize(x) +Result: 4718657453/5000000000; +In> V(GuessRational(x)) + + GuessRational: using 10 terms of the continued fraction +Result: 956/1013; +In> ContFracList(x) +Result: {0,1,16,1,3,2,1,1,1,1,508848,3,1,2,1,2,2}; + +*SEE BracketRational, NearRational, ContFrac, ContFracList, Rationalize +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/InverseTaylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/InverseTaylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/InverseTaylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/InverseTaylor.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,66 @@ +%mathpiper,def="InverseTaylor" + +/* InverseTaylor : given a function y=f(x), determine the Taylor series + * expansion of the inverse f^-1(y)=x this function around y0=f(x0). + * + */ +Function("InverseTaylor",{var,val,degree,func}) +[ + Local(l1); + l1:=UniTaylor(func,var,val,degree); + val+ReversePoly(l1,var,var,var,degree+1); +]; + +%/mathpiper + + + +%mathpiper_docs,name="InverseTaylor",categories="User Functions;Series" +*CMD InverseTaylor --- Taylor expansion of inverse +*STD +*CALL + InverseTaylor(var, at, order) expr + +*PARMS + +{var} -- variable + +{at} -- point to get inverse Taylor series around + +{order} -- order of approximation + +{expr} -- expression to get inverse Taylor series for + +*DESC + +This function builds the Taylor series expansion of the inverse of the +expression "expr" with respect to the variable "var" around "at" +up to order "order". It uses the function {ReversePoly} to perform the task. + +*E.G. + +In> PrettyPrinterSet("PrettyForm") + + True + +In> exp1 := Taylor(x,0,7) Sin(x) + + 3 5 7 + x x x + x - -- + --- - ---- + 6 120 5040 + +In> exp2 := InverseTaylor(x,0,7) ArcSin(x) + + 5 7 3 + x x x + --- - ---- - -- + x + 120 5040 6 + +In> Simplify(exp1-exp2) + + 0 + + +*SEE ReversePoly, Taylor, BigOh +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/IsFreeOf.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/IsFreeOf.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/IsFreeOf.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/IsFreeOf.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,59 @@ +%mathpiper,def="IsFreeOf" + +1 # IsFreeOf({},_expr) <-- True; +2 # IsFreeOf(var_IsList, _expr) <-- And(IsFreeOf(First(var),expr), IsFreeOf(Rest(var),expr)); + +4 # IsFreeOf(_var,{}) <-- True; +5 # IsFreeOf(_var,expr_IsList) <-- And(IsFreeOf(var,First(expr)), IsFreeOf(var,Rest(expr))); + +/* Accept any variable. */ +10 # IsFreeOf(_expr,_expr) <-- False; + +/* Otherwise check all leafs of a function. */ +11 # IsFreeOf(_var,expr_IsFunction) <-- IsFreeOf(var,Rest(FunctionToList(expr))); + +/* Else it doesn't depend on any variable. */ +12 # IsFreeOf(_var,_expr) <-- True; + +%/mathpiper + + + +%mathpiper_docs,name="IsFreeOf",categories="User Functions;Predicates" +*CMD IsFreeOf --- test whether expression depends on variable +*STD +*CALL + IsFreeOf(var, expr) + IsFreeOf({var, ...}, expr) + +*PARMS + +{expr} -- expression to test + +{var} -- variable to look for in "expr" + +*DESC + +This function checks whether the expression "expr" (after being +evaluated) depends on the variable "var". It returns {False} if this is the case and {True} +otherwise. + +The second form test whether the expression depends on any of +the variables named in the list. The result is {True} if none of the variables appear in the expression and {False} otherwise. + +*E.G. + +In> IsFreeOf(x, Sin(x)); +Result: False; +In> IsFreeOf(y, Sin(x)); +Result: True; +In> IsFreeOf(x, Differentiate(x) a*x+b); +Result: True; +In> IsFreeOf({x,y}, Sin(x)); +Result: False; + +The third command returns {True} because the +expression {Differentiate(x) a*x+b} evaluates to {a}, which does not depend on {x}. + +*SEE Contains +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/IsZeroVector.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/IsZeroVector.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/IsZeroVector.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/IsZeroVector.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsZeroVector" + +Function("IsZeroVector",{aList}) aList = ZeroVector(Length(aList)); + +%/mathpiper + + + +%mathpiper_docs,name="IsZeroVector",categories="User Functions;Predicates" +*CMD IsZeroVector --- test whether list contains only zeroes +*STD +*CALL + IsZeroVector(list) + +*PARMS + +{list} -- list to compare against the zero vector + +*DESC + +The only argument given to {IsZeroVector} should be +a list. The result is {True} if the list contains +only zeroes and {False} otherwise. + +*E.G. + +In> IsZeroVector({0, x, 0}); +Result: False; +In> IsZeroVector({x-x, 1 - Differentiate(x) x}); +Result: True; + +*SEE IsList, ZeroVector +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/LagrangeInterpolant.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/LagrangeInterpolant.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/LagrangeInterpolant.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/LagrangeInterpolant.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,89 @@ +%mathpiper,def="LagrangeInterpolant" + +LagrangeInt(_var,_list) <-- +[ + Local(nr); + nr:=Length(list); + Product(FillList(var,nr)-list); +]; + +LagrangeInterpolant(list_IsList,_values,_var) <-- +[ + Local(i,nr,sublist); + nr:=Length(list); + result:=0; + For(i:=1,i<=nr,i++) + [ + sublist:=FlatCopy(list); + DestructiveDelete(sublist,i); + result:=result + values[i]*LagrangeInt(var,sublist)/LagrangeInt(list[i],sublist); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="LagrangeInterpolant",categories="User Functions;Series" +*CMD LagrangeInterpolant --- polynomial interpolation +*STD +*CALL + LagrangeInterpolant(xlist, ylist, var) + +*PARMS + +{xlist} -- list of argument values + +{ylist} -- list of function values + +{var} -- free variable for resulting polynomial + +*DESC + +This function returns a polynomial in the variable "var" which +interpolates the points "(xlist, ylist)". Specifically, the value of +the resulting polynomial at "xlist[1]" is "ylist[1]", the value at +"xlist[2]" is "ylist[2]", etc. The degree of the polynomial is not +greater than the length of "xlist". + +The lists "xlist" and "ylist" should be of equal +length. Furthermore, the entries of "xlist" should be all distinct +to ensure that there is one and only one solution. + +This routine uses the Lagrange interpolant formula to build up the +polynomial. + +*E.G. + +In> f := LagrangeInterpolant({0,1,2}, \ + {0,1,1}, x); +Result: (x*(x-1))/2-x*(x-2); +In> Eval(Subst(x,0) f); +Result: 0; +In> Eval(Subst(x,1) f); +Result: 1; +In> Eval(Subst(x,2) f); +Result: 1; + +In> PrettyPrinterSet("PrettyForm"); + + True + +In> LagrangeInterpolant({x1,x2,x3}, {y1,y2,y3}, x) + + y1 * ( x - x2 ) * ( x - x3 ) + ---------------------------- + ( x1 - x2 ) * ( x1 - x3 ) + + y2 * ( x - x1 ) * ( x - x3 ) + + ---------------------------- + ( x2 - x1 ) * ( x2 - x3 ) + + y3 * ( x - x1 ) * ( x - x2 ) + + ---------------------------- + ( x3 - x1 ) * ( x3 - x2 ) + + +*SEE Subst +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/NearRational.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/NearRational.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/NearRational.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/NearRational.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,138 @@ +%mathpiper,def="NearRational" + +//Retract("NearRational",*); + +////////////////////////////////////////////////// +/// NearRational, GuessRational +////////////////////////////////////////////////// + +/// find rational number with smallest num./denom. near a given number x +/// See: HAKMEM, MIT AI Memo 239, 02/29/1972, Item 101C + +10 # NearRational(_x) <-- NearRational(x, Floor(1/2*BuiltinPrecisionGet())); + +15 # NearRational(x_IsRationalOrNumber, prec_IsInteger) <-- +[ + Local(x1, x2, i, old'prec); + old'prec := BuiltinPrecisionGet(); + BuiltinPrecisionSet(prec + 8); // 8 guard digits (?) + x1 := ContFracList(N(Eval(x+10^(-prec)))); + x2 := ContFracList(N(Eval(x-10^(-prec)))); + + /* + If(InVerboseMode(), + [ + Echo("NearRational: x = ", N(Eval(x )))); + Echo("NearRational: xplus = ", N(Eval(x+10^(-prec))))); + Echo("NearRational: xmin = ", N(Eval(x-10^(-prec))))); + Echo("NearRational: Length(x1) = ", Length(x1)," ",x1)); + Echo("NearRational: Length(x2) = ", Length(x2)," ",x1)); + ] + ); + */ + + // find where the continued fractions for "x1" and "x2" differ + // prepare result in "x1" and length of result in "i" + For (i:=1, i<=Length(x1) And i<=Length(x2) And x1[i]=x2[i], i++ ) True; + If( + i>Length(x1), + // "x1" ended but matched, so use "x2" as "x1" + x1:=x2, + If( + i>Length(x2), + // "x2" ended but matched, so use "x1" + True, + // neither "x1" nor "x2" ended and there is a mismatch at "i" + // apply recipe: select the smalest of the differing terms + x1[i]:=Minimum(x1[i],x2[i]) + ) + ); + // recipe: x1dd 1 to the lx1st term unless it's the lx1st in the originx1l sequence + //Ayal added this line, i could become bigger than Length(x1)! + //If(InVerboseMode(), Echo({"NearRational: using ", i, "terms of the continued fraction"})); + If(i>Length(x1),i:=Length(x1)); + x1[i] := x1[i] + If(i=Length(x1), 0, 1); + BuiltinPrecisionSet(old'prec); + ContFracEval(Take(x1, i)); +]; + + +20 # NearRational(_z, prec_IsInteger)_ + (And(Im(z)!=0,IsRationalOrNumber(Im(z)),IsRationalOrNumber(Re(z)))) <-- +[ + Local(rr,ii); + rr := Re(z); + ii := Im(z); + Complex( NearRational(rr,prec), NearRational(ii,prec) ); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="NearRational",categories="User Functions;Numbers (Operations)" +*CMD NearRational --- find optimal rational approximations +*STD +*CALL + NearRational(x) + NearRational(x, digits) + NearRational(z) + NearRational(z, digits) + +*PARMS + +{x} -- a number to be approximated (must be already evaluated to floating-point) +{z} -- a complex number to be approximated (Re and Im as above) + +{digits} -- desired number of decimal digits (integer) + +*DESC + +The functions {GuessRational(x)} and {NearRational(x)} attempt to find "optimal" +rational approximations to a given value {x}. The approximations are "optimal" +in the sense of having smallest numerators and denominators among all rational +numbers close to {x}. This is done by computing a continued fraction +representation of {x} and truncating it at a suitably chosen term. Both +functions return a rational number which is an approximation of {x}. + +Unlike the function {Rationalize()} which converts floating-point numbers to +rationals without loss of precision, the functions {GuessRational()} and +{NearRational()} are intended to find the best rational that is approximately +equal to a given value. + +The function {NearRational(x)} is useful if one needs to +approximate a given value, i.e. to find an "optimal" rational number +that lies in a certain small interval around a certain value {x}. This +function takes an optional second parameter {digits} which has slightly +different meaning: it specifies the number of digits of precision of +the approximation; in other words, the difference between {x} and the +resulting rational number should be at most one digit of that +precision. The parameter {digits} also defaults to half of the current +precision. + +*E.G. + +Start with a rational number and obtain a floating-point approximation: +In> x:=N(956/1013) +Result: 0.9437314906 +In> Rationalize(x) +Result: 4718657453/5000000000; +The first 10 terms of this continued fraction correspond to the correct continued fraction for the original rational number. +In> NearRational(x) +Result: 218/231; +This function found a different rational number closeby because the precision was not high enough. +In> NearRational(x, 10) +Result: 956/1013; + +*SEE BracketRational, GuessRational, ContFrac, ContFracList, Rationalize +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/NewLine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/NewLine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/NewLine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/NewLine.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="NewLine" + +//Retract("NewLine",*); + +10 # NewLine() <-- WriteN(Nl(),1); +20 # NewLine(n_IsPositiveInteger) <-- WriteN(Nl(),n); +30 # NewLine(_n) <-- Check(False, "Argument", "The argument must be a positive integer "); + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="NewLine",categories="User Functions;Input/Output" +*CMD NewLine --- print one or more newline characters +*STD +*CALL + NewLine() + NewLine(nr) + +*PARMS + +{nr} -- the number of newline characters to print + +*DESC + +The command {NewLine()} prints one newline character +on the current output. The second form prints "nr" newlines on the +current output. The result is always True. + +*E.G. notest + +In> NewLine(); + +Result: True; + +*SEE Echo, Write, Space +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Nl.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Nl.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Nl.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Nl.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="Nl" + +Nl():= +" +"; + +%/mathpiper + + + +%mathpiper_docs,name="Nl",categories="User Functions;Input/Output" +*CMD Nl --- the newline character +*STD +*CALL + Nl() + +*DESC + +This function returns a string with one element in it, namely a newline +character. This may be useful for building strings to send to some +output in the end. + +Note that the second letter in the name of this command is a lower +case {L} (from "line"). + +*E.G. notest + +In> WriteString("First line" : Nl() : "Second line" : Nl()); + First line + Second line +Result: True; + +*SEE NewLine +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ReversePoly.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ReversePoly.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/ReversePoly.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/ReversePoly.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,100 @@ +%mathpiper,def="ReversePoly" + +/* Lagrangian power series reversion. Copied + from Knuth seminumerical algorithms */ + +ReversePoly(_f,_g,_var,_newvar,_degree) <-- +[ + Local(orig,origg,G,V,W,U,n,initval,firstder,j,k,newsum); + orig:=MakeUni(f,var); + origg:=MakeUni(g,var); + initval:=Coef(orig,0); + firstder:=Coef(orig,1); + V:=Coef(orig,1 .. Degree(orig)); + V:=Concat(V,FillList(0,degree)); + G:=Coef(origg,1 .. Degree(origg)); + G:=Concat(G,FillList(0,degree)); + W:=FillList(0,Length(V)+2); + W[1]:=G[1]/firstder; + U:=FillList(0,Length(V)+2); + U[1]:=1/firstder; + n:=1; + While(n f(x):=Eval(Expand((1+x)^4)) +Result: True; +In> g(x) := x^2 +Result: True; +In> h(y):=Eval(ReversePoly(f(x),g(x),x,y,8)) +Result: True; +In> BigOh(h(f(x)),x,8) +Result: x^2; +In> h(x) +Result: (-2695*(x-1)^7)/131072+(791*(x-1)^6) + /32768 +(-119*(x-1)^5)/4096+(37*(x-1)^4) + /1024+(-3*(x-1)^3)/64+(x-1)^2/16; + +*SEE InverseTaylor, Taylor, BigOh +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Series.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Series.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Series.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Series.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//todo:tk:not implemented. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Space.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Space.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/Space.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/Space.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="Space" + +Space() := WriteN(" ",1); +Space(n):= WriteN(" ",n); + +%/mathpiper + + + +%mathpiper_docs,name="Space",categories="User Functions;Input/Output" +*CMD Space --- print one or more spaces +*STD +*CALL + Space() + Space(nr) + +*PARMS + +{nr} -- the number of spaces to print + +*DESC + +The command {Space()} prints one space on the +current output. The second form prints {nr} spaces on the current +output. The result is always True. + +*E.G. notest + +In> Space(5); + Result: True; + +*SEE Echo, Write, NewLine +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/TRun.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/TRun.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/TRun.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/TRun.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="" + +//todo:tk:this function is completely commented out. + +/* +TRun(_f,_g,_degree)<-- +[ + Local(l2,l3,l4); + l2:=ReversePoly(f,g,t,z,degree); + l3:=Subst(z,f)l2; + l4:=BigOh(l3,t,degree); + Echo({g," == ",l4}); + NewLine(); +]; + +TRun(t+t^2,t,10); +TRun(t/2-t^2,t,10); +TRun(t/2-t^2,3+t+t^2/2,10); +TRun(2+t/2-t^2,t,10); +*/ + +/* +TRun(_f,_degree)<-- +[ + Local(l2,l3,l4); + l2:=InverseTaylor(t,0,degree)f; + l3:=Subst(t,Taylor(t,0,degree)f)l2; + l4:=BigOh(l3,t,degree); + + Echo({t," == ",Simplify(l4)}); + NewLine(); +]; +TRun(Sin(a*t),3); +TRun(a^t,3); +TRun(a^t,3); +TRun(t+t^2,10); +TRun(t/2-t^2,10); +TRun(t/2-t^2,10); +TRun(2+t/2-t^2,10); +*/ + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/UniqueConstant.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/UniqueConstant.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/UniqueConstant.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/UniqueConstant.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="UniqueConstant" + +UniqueConstant() <-- +[ + Local(result); + result := ToString(LocalSymbols(C)(C)); + ToAtom(StringMidGet(2,Length(result)-1,result)); +]; + +%/mathpiper + + + +%mathpiper_docs,name="UniqueConstant",categories="User Functions;Variables" +*CMD UniqueConstant --- create a unique identifier +*STD +*CALL + UniqueConstant() + +*DESC + +This function returns a unique constant atom each time you call +it. The atom starts with a C character, and a unique number is +appended to it. + +*E.G. + +In> UniqueConstant() +Result: C9 +In> UniqueConstant() +Result: C10 + +*SEE LocalSymbols +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/WithValue.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/WithValue.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/WithValue.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/WithValue.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="WithValue" + +TemplateFunction("WithValue",{var,val,expr}) +[ + If(IsList(var), + ApplyFast("MacroLocal",var), + MacroLocal(var) + ); + ApplyFast(":=",{var,val}); + Eval(expr); +]; + +%/mathpiper + + + +%mathpiper_docs,name="WithValue",categories="User Functions;Control Flow" +*CMD WithValue --- temporary assignment during an evaluation +*STD +*CALL + WithValue(var, val, expr) + WithValue({var,...}, {val,...}, expr) + +*PARMS + +{var} -- variable to assign to + +{val} -- value to be assigned to "var" + +{expr} -- expression to evaluate with "var" equal to "val" + +*DESC + +First, the expression "val" is assigned to the variable +"var". Then, the expression "expr" is evaluated and +returned. Finally, the assignment is reversed so that the variable +"var" has the same value as it had before {WithValue} was evaluated. + +The second calling sequence assigns the first element in the list of +values to the first element in the list of variables, the second value +to the second variable, etc. + +*E.G. + +In> WithValue(x, 3, x^2+y^2+1); +Result: y^2+10; +In> WithValue({x,y}, {3,2}, x^2+y^2+1); +Result: 14; + +*SEE Subst, /: +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/WriteN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/WriteN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/newly/WriteN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/newly/WriteN.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="WriteN" + +WriteN(string,n) := +[ + Local(i); + For(i:=1,i<=n,i++) WriteString(string); + True; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/BellNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/BellNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/BellNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/BellNumber.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="BellNumber" + +10 # BellNumber(n_IsInteger) <-- Sum(k,1,n,StirlingNumber2(n,k)); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/CatalanNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/CatalanNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/CatalanNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/CatalanNumber.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="CatalanNumber" + +CatalanNumber(_n) <-- +[ + Check( IsPositiveInteger(n), "Argument", "CatalanNumber: Error: argument must be positive" ); + BinomialCoefficient(2*n,n)/(n+1); +]; + +%/mathpiper + + + +%mathpiper_docs,name="CatalanNumber",categories="User Functions;Number Theory" +*CMD CatalanNumber --- return the {n}th Catalan Number +*STD +*CALL + CatalanNumber(n) +*PARMS + +{n} -- positive integer + +*DESC + +This function returns the {n}-th Catalan number, defined as $BinomialCoefficient(2*n,n)/(n+1)$. + +*E.G. + +In> CatalanNumber(10) +Result: 16796; +In> CatalanNumber(5) +Result: 42; + +*SEE BinomialCoefficient +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/CheckIntPower.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/CheckIntPower.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/CheckIntPower.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/CheckIntPower.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="CheckIntPower" + +/// Check whether n is a power of some integer, assuming that it has no prime factors <= limit. +/// This routine uses only integer arithmetic. +/// Returns {p, s} where s is the smallest prime integer such that n=p^s. (p is not necessarily a prime!) +/// If no powers found, returns {n, 1}. Primality testing of n is not done. +CheckIntPower(n, limit) := +[ + Local(s0, s, root); + If(limit<=1, limit:=2); // guard against too low value of limit + // compute the bound on power s + s0 := IntLog(n, limit); + // loop: check whether n^(1/s) is integer for all prime s up to s0 + root := 0; + s := 0; + While(root = 0 And NextPseudoPrime(s)<=s0) // root=0 while no root is found + [ + s := NextPseudoPrime(s); + root := IntNthRoot(n, s); + If( + root^s = n, // found root + True, + root := 0 + ); + ]; + // return result + If( + root=0, + {n, 1}, + {root, s} + ); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/DigitalRoot.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/DigitalRoot.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/DigitalRoot.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/DigitalRoot.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,6 @@ +%mathpiper,def="DigitalRoot" + +// Digital root of n (repeatedly add digits until reach a single digit). +10 # DigitalRoot(n_IsPositiveInteger) <-- If(n%9=0,9,n%9); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Divisors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Divisors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Divisors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Divisors.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="Divisors" + +// Algorithm adapted from: +// Elementary Number Theory, David M. Burton +// Theorem 6.2 p112 +5 # Divisors(0) <-- 0; +5 # Divisors(1) <-- 1; +// Unsure about if there should also be a function that returns +// n's divisors, may have to change name in future +10 # Divisors(_n) <-- +[ + Check(IsPositiveInteger(n), "Argument", "Divisors: argument must be positive integer"); + Local(len,sum,factors,i); + sum:=1; + factors:=Factors(n); + len:=Length(factors); + For(i:=1,i<=len,i++)[ + sum:=sum*(factors[i][2]+1); + ]; + sum; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Divisors",categories="User Functions;Number Theory" +*CMD Divisors --- number of divisors +*STD +*CALL + Divisors(n) +*PARMS + +{n} -- positive integer + +*DESC + +{Divisors} returns the number of positive divisors of a number. +A number is prime if and only if it has two divisors, 1 and itself. + +*E.G. +In> Divisors(180) +Result: 18; +In> Divisors(37) +Result: 2; + +*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/DivisorsSum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/DivisorsSum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/DivisorsSum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/DivisorsSum.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="DivisorsSum" + +// Algorithm adapted from: +// Elementary Number Theory, David M. Burton +// Theorem 6.2 p112 +5 # DivisorsSum(0) <-- 0; +5 # DivisorsSum(1) <-- 1; +10 # DivisorsSum(_n) <-- +[ + Check(IsPositiveInteger(n), "Argument", "DivisorsSum: argument must be positive integer"); + Local(factors,i,sum,len,p,k); + p:=0;k:=0; + factors:={}; + factors:=Factors(n); + len:=Length(factors); + sum:=1; + For(i:=1,i<=len,i++)[ + p:=factors[i][1]; + k:=factors[i][2]; + sum:=sum*(p^(k+1)-1)/(p-1); + ]; + sum; +]; + +%/mathpiper + + + +%mathpiper_docs,name="DivisorsSum",categories="User Functions;Number Theory" +*CMD DivisorsSum --- the sum of divisors +*STD +*CALL + DivisorsSum(n) +*PARMS + +{n} -- positive integer + +*DESC + +{DivisorsSum} returns the sum all numbers that divide it. A number +{n} is prime if and only if the sum of its divisors are {n+1}. + +*E.G. + +In> DivisorsSum(180) +Result: 546; +In> DivisorsSum(37) +Result: 38; + +*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/EulerArray.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/EulerArray.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/EulerArray.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/EulerArray.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,20 @@ +%mathpiper,def="EulerArray" + +/** Compute an array of Euler numbers using recurrence relations. +*/ +10 # EulerArray(n_IsInteger) <-- +[ + Local(E,i,sum,r); + E:=ZeroVector(n+1); + E[1]:=1; + For(i:=1,2*i<=n,i++)[ + sum:=0; + For(r:=0,r<=i-1,r++)[ + sum:=sum+BinomialCoefficient(2*i,2*r)*E[2*r+1]; + ]; + E[2*i+1] := -sum; + ]; + E; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Eulerian.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Eulerian.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Eulerian.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Eulerian.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="Eulerian" + +Eulerian(n_IsInteger,k_IsInteger) <-- Sum(j,0,k+1,(-1)^j*BinomialCoefficient(n+1,j)*(k-j+1)^n); + +%/mathpiper + + + +%mathpiper_docs,name="Eulerian",categories="User Functions;Combinatorics" +*CMD Eulerian --- Eulerian numbers +*STD +*CALL + Eulerian(n,m) + +*PARMS + +{n}, {m} --- integers + +*DESC + +The Eulerian numbers can be viewed as a generalization of the binomial coefficients, +and are given explicitly by $$ Sum(j,0,k+1,(-1)^j*BinomialCoefficient(n+1,j)*(k-j+1)^n) $$ . + +*E.G. + +In> Eulerian(6,2) +Result: 302; +In> Eulerian(10,9) +Result: 1; + +*SEE BinomialCoefficient +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Euler.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Euler.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Euler.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Euler.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="Euler" + +5 # Euler(0) <-- 1; +10 # Euler(n_IsOdd) <-- 0; +10 # Euler(n_IsEven) <-- - Sum(r,0,n/2-1,BinomialCoefficient(n,2*r)*Euler(2*r)); +10 # Euler(n_IsNonNegativeInteger,_x) <-- Sum(i,0,Round(n/2),BinomialCoefficient(n,2*i)*Euler(2*i)*(x-1/2)^(n-2*i)/2^(2*i)); + +%/mathpiper + + + +%mathpiper_docs,name="Euler",categories="User Functions;Special Functions" +*CMD Euler --- Euler numbers and polynomials +*STD +*CALL + Euler(index) + Euler(index,x) + +*PARMS + +{x} -- expression that will be the variable in the polynomial + +{index} -- expression that can be evaluated to an integer + +*DESC + +{Euler(n)} evaluates the $n$-th Euler number. {Euler(n,x)} returns the $n$-th Euler polynomial in the variable $x$. + +*E.G. + +In> Euler(6) +Result: -61; +In> A:=Euler(5,x) +Result: (x-1/2)^5+(-10*(x-1/2)^3)/4+(25*(x-1/2))/16; +In> Simplify(A) +Result: (2*x^5-5*x^4+5*x^2-1)/2; + +*SEE BinomialCoefficient +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/FermatNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/FermatNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/FermatNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/FermatNumber.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="FermatNumber" + +Function("FermatNumber",{n})[ + Check(IsPositiveInteger(n), "Argument", "FermatNumber: argument must be a positive integer"); + 2^(2^n)+1; +]; + +%/mathpiper + + + +%mathpiper_docs,name="FermatNumber",categories="User Functions;Number Theory" +*CMD FermatNumber --- return the {n}th Fermat Number +*STD +*CALL + FermatNumber(n) +*PARMS + +{n} -- positive integer + +*DESC + +This function returns the {n}-th Fermat number, which is defined as +$2^(2^n) + 1$. + +*E.G. + +In> FermatNumber(7) +Result: 340282366920938463463374607431768211457; + +*SEE Factor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/FactorGaussianInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/FactorGaussianInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/FactorGaussianInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/FactorGaussianInteger.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="FactorGaussianInteger" + +// Algorithm adapted from: Number Theory: A Programmer's Guide +// Mark Herkommer +// Program 8.7.1c, p 264 +// This function needs to be modified to return the factors in +// data structure instead of printing them out + +// THIS FUNCTION IS DEPRECATED NOW! +// Use GaussianFactors instead (Pablo) +// I've leave this here so that you can compare the eficiency of one +// function against the other + +Function("FactorGaussianInteger",{x}) [ + Check( IsGaussianInteger(x), "Argument", "FactorGaussianInteger: argument must be a Gaussian integer"); + Local(re,im,norm,a,b,d,i,j); + + re:=Re(x);im:=Im(x); + + If(re<0, re:=(-re) ); + If(im<0, im:=(-im) ); + norm:=re^2+im^2; + + if( IsComposite(norm) )[ + For(i:=0, i^2 <= norm, i++ )[ // real part + For(j:=0, i^2 + j^2 <= norm, j++)[ // complex part + if( Not( (i = re And j = im) Or + (i = im And j = re) ) )[ // no associates + d:=i^2+j^2; + if( d > 1 )[ + a := re * i + im * j; + b := im * i - re * j; + While( (Modulo(a,d) = 0) And (Modulo(b,d) = 0) ) [ + FactorGaussianInteger(Complex(i,j)); + re:= a/d; + im:= b/d; + a := re * i + im * j; + b := im * i - re * j; + norm := re^2 + im^2; + ]; + ]; + ]; + ]; + ]; + If( re != 1 Or im != 0, Echo(Complex(re,im)) ); + ] else [ + Echo(Complex(re,im)); + ]; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactorPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactorPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactorPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactorPrime.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,21 @@ +%mathpiper,def="GaussianFactorPrime" + +/* GaussianFactorPrime(p): auxiliary function for Gaussian factors. +If p is a rational prime of the form 4n+1, we find a factor of p in the +Gaussian Integers. We compute + a = (2n)! +By Wilson's theorem a^2 is -1 (mod p), it follows that + + p| (a+I)(a-I) + +in the Gaussian integers. The desired factor is then the Gaussian GCD of a+i +and p. Note: If the result is Complex(a,b), then p=a^2+b^2 */ + +GaussianFactorPrime(p_IsInteger) <-- [ + Local(a,i); + a := 1; + For (i:=2,i<=(p-1)/2,i++) a := Modulo(a*i,p); + GaussianGcd(a+I,p); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianFactors.mpw 2011-02-03 08:00:50.000000000 +0000 @@ -0,0 +1,114 @@ +%mathpiper,def="GaussianFactors" + +//Retract("GaussianFactors",*); + + +/* AddGaussianFactor: auxiliary function for Gaussian Factors. +L is a lists of factors of the Gaussian integer z and p is a Gaussian prime +that we want to add to the list. We first find the exponent e of p in the +decomposition of z (into Gaussian primes). If it is not zero, we add {p,e} +to the list */ + +AddGaussianFactor(L_IsList,z_IsGaussianInteger,p_IsGaussianInteger) <-- +[ + Local(e); + e :=0; + While (IsGaussianInteger(z:= z/p)) e++; + If (e != 0, DestructiveAppend(L,{p,e})); +]; + + + + +/* +GaussianFactors(n) : returns a list of factors of n, in a similar way to Factors(n). +If n is a rational integer, we factor n in the Gaussian integers, by first +factoring it in the rational integers, and after that factoring each of +its integer prime factors. +*/ + +10 # GaussianFactors(n_IsInteger) <-- +[ + // Chosing to factor this integer as a Gaussian Integer + Local(ifactors,gfactors,p,alpha); + ifactors := FactorizeInt(n); // since we know it is an integer + gfactors := {}; + ForEach(p,ifactors) + [ + If (p[1]=2, [ DestructiveAppend(gfactors,{1+I,p[2]}); + DestructiveAppend(gfactors,{1-I,p[2]}); ]); + If (Modulo(p[1],4)=3, DestructiveAppend(gfactors,p)); + If (Modulo(p[1],4)=1, [ alpha := GaussianFactorPrime(p[1]); + DestructiveAppend(gfactors,{alpha,p[2]}); + DestructiveAppend(gfactors,{Conjugate(alpha),p[2]}); + ]); + ]; +gfactors; +]; + +/* +If z is is a Gaussian integer, we find its possible Gassian prime factors, +by factoring its norm +*/ + +20 # GaussianFactors(z_IsGaussianInteger) <-- +[ + Local(n,nfactors,gfactors,p); + gfactors :={}; + n := GaussianNorm(z); + nfactors := Factors(n); + ForEach(p,nfactors) + [ + If (p[1]=2, [ AddGaussianFactor(gfactors,z,1+I);]); + If (Modulo(p[1],4)=3, AddGaussianFactor(gfactors,z,p[1])); + If (Modulo(p[1],4)=1, [ Local(alpha); + alpha := GaussianFactorPrime(p[1]); + AddGaussianFactor(gfactors,z,alpha); + AddGaussianFactor(gfactors,z,Conjugate(alpha)); + ]); + ]; + gfactors; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="GaussianFactors",categories="User Functions;Number Theory" +*CMD GaussianFactors --- factorization in Gaussian integers +*STD +*CALL + GaussianFactors(z) + +*PARMS + +{z} -- Gaussian integer + +*DESC + +This function decomposes a Gaussian integer number {z} into a product of +Gaussian prime factors. +A Gaussian integer is a complex number with integer real and imaginary parts. +A Gaussian integer $z$ can be decomposed into Gaussian primes essentially in a +unique way (up to Gaussian units and associated prime factors), i.e. one +can write $z$ as +$$z = u*p[1]^n[1] * ... * p[s]^n[s]$$, +where $u$ is a Gaussian unit and $p[1]$, $p[2]$, ..., $p[s]$ are Gaussian primes. + +The factorization is returned as a list of pairs. The first member of +each pair is the factor (a Gaussian integer) and the second member denotes the power to +which this factor should be raised. So the factorization is returned as +a list, e.g. {{{p1,n1}, {p2,n2}, ...}}. + +*E.G. +In> GaussianFactors(5) +Result: {{Complex(2,1),1},{Complex(2,-1),1}}; +In> GaussianFactors(3+I) +Result: {{Complex(1,1),1},{Complex(2,-1),1}}; + +*SEE Factors, IsGaussianPrime, IsGaussianUnit +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianGcd.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianGcd.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianGcd.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianGcd.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="GaussianGcd" + +10 # GaussianGcd(n_IsGaussianInteger,m_IsGaussianInteger) <-- +[ + If(N(Abs(m))=0,n, GaussianGcd(m,n - m*Round(n/m) ) ); +]; + +%/mathpiper + + + +%mathpiper_docs,name="GaussianGcd",categories="User Functions;Number Theory" +*CMD GaussianGcd --- greatest common divisor in Gaussian integers +*STD +*CALL + GaussianGcd(z,w) + +*PARMS + +{z}, {w} -- Gaussian integers + +*DESC + +This function returns the greatest common divisor, in the ring of Gaussian +integers, computed using Euclid's algorithm. Note that in the Gaussian +integers, the greatest common divisor is only defined up to a Gaussian unit factor. + +*E.G. + +In> GaussianGcd(2+I,5) +Result: Complex(2,1); +The GCD of two mutually prime Gaussian integers might come out to be equal to some Gaussian unit instead of $1$: +In> GaussianGcd(2+I,3+I) +Result: -1; + +*SEE Gcd, Lcm, IsGaussianUnit +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianMod.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianMod.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianMod.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianMod.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="GaussianMod" + +GaussianMod(z_IsGaussianInteger,w_IsGaussianInteger) <-- z - w * Round(z/w); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianNorm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianNorm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianNorm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/GaussianNorm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,30 @@ +%mathpiper,def="GaussianNorm" + +GaussianNorm(z_IsGaussianInteger) <-- Re(z)^2+Im(z)^2; + +%/mathpiper + + + +%mathpiper_docs,name="GaussianNorm",categories="User Functions;Number Theory" +*CMD GaussianNorm --- norm of a Gaussian integer +*STD +*CALL + GaussianNorm(z) + +*PARMS + +{z} -- Gaussian integer + +*DESC + +This function returns the norm of a Gaussian integer $z=a+b*I$, defined as +$a^2+b^2$. + +*E.G. + +In> GaussianNorm(2+I) +Result: 5; + +*SEE IsGaussianInteger +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianInteger.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="IsGaussianInteger" + +5 # IsGaussianInteger(x_IsList) <-- False; + +// ?????? why is the following rule needed? +// 5 # IsGaussianInteger(ProductPrimesTo257) <-- False; + +10 # IsGaussianInteger(x_IsComplex) <-- (IsInteger(Re(x)) And IsInteger(Im(x))); +// to catch IsGaussianInteger(x+2) from Apart +15 # IsGaussianInteger(_x) <-- False; + +%/mathpiper + + + +%mathpiper_docs,name="IsGaussianInteger",categories="User Functions;Predicates" +*CMD IsGaussianInteger --- test for a Gaussian integer +*STD +*CALL + IsGaussianInteger(z) +*PARMS + +{z} -- a complex or real number + +*DESC + +This function returns {True} if the argument is a Gaussian integer and {False} otherwise. +A Gaussian integer is a generalization +of integers into the complex plane. A complex number $a+b*I$ is a Gaussian +integer if and only if $a$ and $b$ are integers. + +*E.G. +In> IsGaussianInteger(5) +Result: True; +In> IsGaussianInteger(5+6*I) +Result: True; +In> IsGaussianInteger(1+2.5*I) +Result: False; + +*SEE IsGaussianUnit, IsGaussianPrime +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianPrime.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="IsGaussianPrime" + +Function("IsGaussianPrime",{x}) +[ + if( IsGaussianInteger(x) )[ + if( IsZero(Re(x)) )[ + ( Abs(Im(x)) % 4 = 3 And IsPrime(Abs(Im(x))) ); + ] else if ( IsZero(Im(x)) ) [ + ( Abs(Re(x)) % 4 = 3 And IsPrime(Abs(Re(x))) ); + ] else [ + IsPrime(Re(x)^2 + Im(x)^2); + ]; + ] else [ + False; + ]; + +]; + + +/* +10 # IsGaussianPrime(p_IsInteger) <-- IsPrime(p) And Modulo(p,3)=1; +20 # IsGaussianPrime(p_IsGaussianInteger) <-- IsPrime(GaussianNorm(p)); +*/ + +%/mathpiper + + + +%mathpiper_docs,name="IsGaussianPrime",categories="User Functions;Number Theory;Predicates" +*CMD IsGaussianPrime --- test for a Gaussian prime +*STD +*CALL + IsGaussianPrime(z) +*PARMS + +{z} -- a complex or real number + +*DESC + +This function returns {True} if the argument +is a Gaussian prime and {False} otherwise. + +A prime element $x$ of a ring is divisible only by the units of +the ring and by associates of $x$. +("Associates" of $x$ are elements of the form $x*u$ where $u$ is +a unit of the ring). + +Gaussian primes are Gaussian integers $z=a+b*I$ that satisfy one of the +following properties: + +* If $Re(z)$ and $Im(z)$ are nonzero then $z$ is a Gaussian prime if and only +if $Re(z)^2 + Im(z)^2$ is an ordinary prime. +* If $Re(z)==0$ then $z$ is a Gaussian prime if and only if $Im(z)$ is an +ordinary prime and $Im(z):=Modulo(3,4)$. +* If $Im(z)==0$ then $z$ is a Gaussian prime +if and only if $Re(z)$ is an ordinary prime and $Re(z):=Modulo(3,4)$. + +*E.G. +In> IsGaussianPrime(13) +Result: False; +In> IsGaussianPrime(2+2*I) +Result: False; +In> IsGaussianPrime(2+3*I) +Result: True; +In> IsGaussianPrime(3) +Result: True; + +*SEE IsGaussianInteger, GaussianFactors +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianUnit.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianUnit.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianUnit.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/gaussianintegers/IsGaussianUnit.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,34 @@ +%mathpiper,def="IsGaussianUnit" + +IsGaussianUnit(z_IsGaussianInteger) <-- GaussianNorm(z)=1; + +%/mathpiper + + + +%mathpiper_docs,name="IsGaussianUnit",categories="User Functions;Number Theory;Predicates" +*CMD IsGaussianUnit --- test for a Gaussian unit +*STD +*CALL + IsGaussianUnit(z) +*PARMS + +{z} -- a Gaussian integer + +*DESC + +This function returns {True} if the argument is a unit in the Gaussian +integers and {False} otherwise. A unit in a ring is an element that divides +any other element. + +There are four "units" in the ring of Gaussian integers, which are +$1$, $-1$, $I$, and $-I$. + +*E.G. +In> IsGaussianInteger(I) +Result: True; +In> IsGaussianUnit(5+6*I) +Result: False; + +*SEE IsGaussianInteger, IsGaussianPrime, GaussianNorm +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/GetPrimePower.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/GetPrimePower.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/GetPrimePower.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/GetPrimePower.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="GetPrimePower" + +/// Check whether n is a power of some prime integer and return that integer and the power. +/// This routine uses only integer arithmetic. +/// Returns {p, s} where p is a prime and n=p^s. +/// If no powers found, returns {n, 1}. Primality testing of n is not done. +20 # GetPrimePower(n_IsPositiveInteger) <-- +[ + Local(s, factors, new'factors); + // first, separate any small prime factors + factors := TrialFactorize(n, 257); // "factors" = {n1, {p1,s1},{p2,s2},...} or just {n} if no factors found + If( + Length(factors) > 1, // factorized into something + // now we return {n, 1} either if we haven't completely factorized, or if we factorized into more than one prime factor; otherwise we return the information about prime factors + If( + factors[1] = 1 And Length(factors) = 2, // factors = {1, {p, s}}, so we have a prime power n=p^s + factors[2], + {n, 1} + ), + // not factorizable into small prime factors -- use main algorithm + [ + factors := CheckIntPower(n, 257); // now factors = {p, s} with n=p^s + If( + factors[2] > 1, // factorized into something + // now need to check whether p is a prime or a prime power and recalculate "s" + If( + IsPrime(factors[1]), + factors, // ok, prime power, return information + [ // not prime, need to check if it's a prime power + new'factors := GetPrimePower(factors[1]); // recursive call; now new'factors = {p1, s1} where n = (p1^s1)^s; we need to check that s1>1 + If( + new'factors[2] > 1, + {new'factors[1], new'factors[2]*factors[2]}, // recalculate and return prime power information + {n, 1} // not a prime power + ); + ] + ), + // not factorizable -- return {n, 1} + {n, 1} + ); + ] + ); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/HarmonicNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/HarmonicNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/HarmonicNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/HarmonicNumber.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="HarmonicNumber" + +10 # HarmonicNumber(n_IsInteger) <-- HarmonicNumber(n,1); +HarmonicNumber(n_IsInteger,r_IsPositiveInteger) <-- +[ + // small speed up + if( r=1 )[ + Sum(k,1,n,1/k); + ] else [ + Sum(k,1,n,1/k^r); + ]; +]; + +%/mathpiper + + + +%mathpiper_docs,name="HarmonicNumber",categories="User Functions;Number Theory" +*CMD HarmonicNumber --- return the {n}th Harmonic Number +*STD +*CALL + HarmonicNumber(n) + HarmonicNumber(n,r) +*PARMS + +{n}, {r} -- positive integers + +*DESC + +This function returns the {n}-th Harmonic number, which is defined +as $Sum(k,1,n,1/k)$. If given a second argument, the Harmonic number +of order $r$ is returned, which is defined as $Sum(k,1,n,k^(-r))$. + +*E.G. + +In> HarmonicNumber(10) +Result: 7381/2520; +In> HarmonicNumber(15) +Result: 1195757/360360; +In> HarmonicNumber(1) +Result: 1; +In> HarmonicNumber(4,3) +Result: 2035/1728; + + + +*SEE Sum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IntLog.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IntLog.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IntLog.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IntLog.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,75 @@ +%mathpiper,def="IntLog" + +/// Return integer part of the logarithm of x in given base. Use only integer arithmetic. +10 # IntLog(_x, _base) _ (base<=1) <-- Undefined; +/// Use variable steps to speed up operation for large numbers x +20 # IntLog(_x, _base) <-- +[ + Local(result, step, old'step, factor, old'factor); + result := 0; + old'step := step := 1; + old'factor := factor := base; + // first loop: increase step + While (x >= factor) + [ + old'factor := factor; + factor := factor*factor; + old'step := step; + step := step*2; + ]; + If(x >= base, + [ + step := old'step; + result := step; + x := Quotient(x, old'factor); + ], + step := 0 + ); + // second loop: decrease step + While (step > 0 And x != 1) + [ + step := Quotient(step,2); // for each step size down to 1, divide by factor if x is up to it + factor := base^step; + If( + x >= factor, + [ + x:=Quotient(x, factor); + result := result + step; + ] + ); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="IntLog",categories="User Functions;Numbers (Operations)" +*CMD IntLog --- integer part of logarithm +*STD +*CALL + IntLog(n, base) + +*PARMS + +{n}, {base} -- positive integers + +*DESC + +{IntLog} calculates the integer part of the logarithm of {n} in base {base}. The algorithm uses only integer +math and may be faster than computing $$Ln(n)/Ln(base)$$ with multiple precision floating-point math and rounding off to get the integer part. + +This function can also be used to quickly count the digits in a given number. + +*E.G. +Count the number of bits: +In> IntLog(257^8, 2) +Result: 64; + +Count the number of decimal digits: +In> IntLog(321^321, 10) +Result: 804; + +*SEE IntNthRoot, Quotient, Modulo, Ln +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IntNthRoot.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IntNthRoot.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IntNthRoot.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IntNthRoot.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,105 @@ +%mathpiper,def="IntNthRoot" + +/// Compute integer part of s-th root of (positive) integer n. +// algorithm using floating-point math +10 # IntNthRoot(_n, 2) <-- Floor(SqrtN(n)); +20 # IntNthRoot(_n, s_IsInteger) <-- +[ + Local(result, k); + GlobalPush(BuiltinPrecisionGet()); + // find integer k such that 2^k <= n^(1/s) < 2^(k+1) + k := Quotient(IntLog(n, 2), s); + // therefore we need k*Ln(2)/Ln(10) digits for the floating-point calculation + BuiltinPrecisionSet(2+Quotient(k*3361, 11165)); // 643/2136 < Ln(2)/Ln(10) < 3361/11165 + result := Round(ExpN(DivideN(Internal'LnNum(DivideN(n, 2^(k*s))), s))*2^k); + BuiltinPrecisionSet(GlobalPop()); + // result is rounded and so it may overshoot (we do not use Floor above because numerical calculations may undershoot) + If(result^s>n, result-1, result); +]; + +/* algorithm using only integer arithmetic. +(this is slower than the floating-point algorithm for large numbers because all calculations are with long integers) +IntNthRoot1(_n, s_IsInteger) <-- +[ + Local(x1, x2, x'new, y1); + // initial guess should always undershoot + // x1:= 2 ^ Quotient(IntLog(n, 2), s); // this is worse than we can make it + x1 := IntLog(n,2); + // select initial interval using (the number of bits in n) mod s + // note that if the answer is 1, the initial guess must also be 1 (not 0) + x2 := Quotient(x1, s); // save these values for the next If() + x1 := Modulo(x1, s)/s; // this is kept as a fraction + // now assign the initial interval, x1 <= root <= x2 + {x1, x2} := If( + x1 >= 263/290, // > Ln(15/8)/Ln(2) + Quotient({15,16}*2^x2, 8), + If( + x1 >= 373/462, // > Ln(7/4)/Ln(2) + Quotient({7,8}*2^x2, 4), + If( + x1 >= 179/306, // > Ln(3/2)/Ln(2) + Quotient({6,7}*2^x2, 4), + If( + x1 >= 113/351, // > Ln(5/4)/Ln(2) + Quotient({5,6}*2^x2, 4), + Quotient({4,5}*2^x2, 4) // between x1 and (5/4)*x1 + )))); + // check whether x2 is the root + y1 := x2^s; + If( + y1=n, + x1 := x2, + // x2 is not a root, so continue as before with x1 + y1 := x1^s // henceforth, y1 is always x1^s + ); + // Newton iteration combined with bisection + While(y1 < n) + [ +// Echo({x1, x2}); + x'new := Quotient(x1*((s-1)*y1+(s+1)*n), (s+1)*y1+(s-1)*n) + 1; // add 1 because the floating-point value undershoots + If( + x'new < Quotient(x1+x2, 2), + // x'new did not reach the midpoint, need to check progress + If( + Quotient(x1+x2, 2)^s <= n, + // Newton's iteration is not making good progress, so leave x2 in place and update x1 by bisection + x'new := Quotient(x1+x2, 2), + // Newton's iteration knows what it is doing. Update x2 by bisection + x2 := Quotient(x1+x2, 2) + ) + // else, x'new reached the midpoint, good progress, continue + ); + x1 := x'new; + y1 := x1^s; + ]; + If(y1=n, x1, x1-1); // subtract 1 if we overshot +]; +*/ + +%/mathpiper + + + +%mathpiper_docs,name="IntNthRoot",categories="User Functions;Numbers (Operations)" +*CMD IntNthRoot --- integer part of $n$-th root +*STD +*CALL + IntNthRoot(x, n) + +*PARMS + +{x}, {n} -- positive integers + +*DESC + +{IntNthRoot} calculates the integer part of the $n$-th root of $x$. The algorithm uses only +integer math and may be faster than computing $x^(1/n)$ with floating-point and rounding. + +This function is used to test numbers for prime powers. + +*E.G. +In> IntNthRoot(65537^111, 37) +Result: 281487861809153; + +*SEE IntLog, PowerN, IsPrimePower +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsAmicablePair.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsAmicablePair.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsAmicablePair.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsAmicablePair.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsAmicablePair" + +IsAmicablePair(m_IsPositiveInteger,n_IsPositiveInteger) <-- ( ProperDivisorsSum(m)=n And ProperDivisorsSum(n)=m ); + +%/mathpiper + + + +%mathpiper_docs,name="IsAmicablePair",categories="User Functions;Number Theory;Predicates" +*CMD IsAmicablePair --- test for a pair of amicable numbers +*STD +*CALL + IsAmicablePair(m,n) + +*PARMS + +{m}, {n} -- positive integers + +*DESC + +This function tests if a pair of numbers are amicable. A pair of +numbers $m$, $n$ has this property if the sum of the proper divisors of $m$ is +$n$ and the sum of the proper divisors of $n$ is $m$. + +*E.G. + +In> IsAmicablePair(200958394875, 209194708485 ) +Result: True; +In> IsAmicablePair(220, 284) +Result: True; + +*SEE ProperDivisorsSum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsCarmichaelNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsCarmichaelNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsCarmichaelNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsCarmichaelNumber.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="IsCarmichaelNumber" + +// Carmichael numbers are odd,squarefree and have at least 3 prime factors +5 # IsCarmichaelNumber(n_IsEven) <-- False; +5 # IsCarmichaelNumber(_n)_(n<561) <-- False; +10 # IsCarmichaelNumber(n_IsPositiveInteger) <-- +[ + Local(i,factors,length,carmichael); + + factors:=Factors(n); + carmichael:=True; + length:=Length(factors); + if( length < 3)[ + carmichael:=False; + ] else [ + For(i:=1,i<=length And carmichael,i++)[ + //Echo( n-1,"%",factors[i][1]-1,"=", Modulo(n-1,factors[i][1]-1) ); + If( Modulo(n-1,factors[i][1]-1) != 0, carmichael:=False ); + If(factors[i][2]>1,carmichael:=False); // squarefree + ]; + ]; + carmichael; +]; + +IsCarmichaelNumber(n_IsList) <-- MapSingle("IsCarmichaelNumber",n); + +%/mathpiper + + + +%mathpiper_docs,name="IsCarmichaelNumber",categories="User Functions;Number Theory;Predicates" +*CMD IsCarmichaelNumber --- test for a Carmichael number +*STD +*CALL + IsCarmichaelNumber(n) + +*PARMS + +{n} -- positive integer + +*DESC + +This function returns {True} if {n} is a Carmichael number, also called an absolute pseudoprime. +They have the property that $ b^(n-1) % n == 1 $ for all $b$ satisfying $Gcd(b,n)==1$. These numbers +cannot be proved composite by Fermat's little theorem. Because the previous property is extremely +slow to test, the following equivalent property is tested by MathPiper: for all prime factors $p[i]$ of $n$, +$(n-1) % (p[i] - 1) == 0$ and $n$ must be square free. Also, Carmichael numbers must be odd and have +at least three prime factors. Although these numbers are rare (there are only 43 such numbers between $1$ and $10^6$), +it has recently been proven that there are infinitely many of them. + +*E.G. notest + +In> IsCarmichaelNumber(561) +Result: True; +In> EchoTime() Select(1 .. 10000, IsCarmichaelNumber) + 504.19 seconds taken +Result: {561,1105,1729,2465,2821,6601,8911}; + +*SEE IsSquareFree, IsComposite +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsComposite.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsComposite.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsComposite.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsComposite.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="IsComposite" + +5 # IsComposite(1) <-- False; +10 # IsComposite(n_IsPositiveInteger) <-- (Not IsPrime(n)); + +%/mathpiper + + + +%mathpiper_docs,name="IsComposite",categories="User Functions;Number Theory;Predicates" +*CMD IsComposite --- test for a composite number +*STD +*CALL + IsComposite(n) + +*PARMS + +{n} -- positive integer + +*DESC + +This function is the logical negation of {IsPrime}, except for the number 1, which is +neither prime nor composite. + +*E.G. + +In> IsComposite(1) +Result: False; +In> IsComposite(7) +Result: False; +In> IsComposite(8) +Result: True; +In> Select(1 .. 20, IsComposite) +Result: {4,6,8,9,10,12,14,15,16,18,20}; + +*SEE IsPrime +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsCoprime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsCoprime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsCoprime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsCoprime.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="IsCoprime" + +5 # IsCoprime(list_IsList) <-- (Lcm(list) = Product(list)); +10 # IsCoprime(n_IsInteger,m_IsInteger) <-- (Gcd(n,m) = 1); + +%/mathpiper + + + +%mathpiper_docs,name="IsCoprime",categories="User Functions;Number Theory;Predicates" +*CMD IsCoprime --- test if integers are coprime +*STD +*CALL + IsCoprime(m,n) + IsCoprime(list) +*PARMS + +{m},{n} -- positive integers + +{list} -- list of positive integers + +*DESC + +This function returns {True} if the given pair or list of integers are coprime, +also called relatively prime. A pair or list of numbers are coprime if they +share no common factors. + +*E.G. + +In> IsCoprime({3,4,5,8}) +Result: False; +In> IsCoprime(15,17) +Result: True; + +*SEE Prime +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsIrregularPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsIrregularPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsIrregularPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsIrregularPrime.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="IsIrregularPrime" + +5 # IsIrregularPrime(p_IsComposite) <-- False; +// First irregular prime is 37 +5 # IsIrregularPrime(_p)_(p<37) <-- False; + +// an odd prime p is irregular iff p divides the numerator of a Bernoulli number B(2*n) with +// 2*n+1

    IsIrregularPrime(5) +Result: False; +In> Select(1 .. 100, IsIrregularPrime) +Result: {37,59,67}; + +*SEE IsPrime +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsPerfect.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsPerfect.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsPerfect.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsPerfect.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="IsPerfect" + +IsPerfect(n_IsPositiveInteger) <-- ProperDivisorsSum(n)=n; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsPrime.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,63 @@ +%mathpiper,def="IsPrime",categories="User Functions;Number Theory" + +2 # IsPrime(_n)_(Not IsInteger(n) Or n<=1) <-- False; +3 # IsPrime(n_IsInteger)_(n<=FastIsPrime(0)) <-- IsSmallPrime(n); + +/* Fast pseudoprime testing: if n is a prime, then 24 divides (n^2-1) */ +5 # IsPrime(n_IsPositiveInteger)_(n > 4 And Modulo(n^2-1,24)!=0) <-- False; + +/* Determine if a number is prime, using Rabin-Miller primality + testing. Code submitted by Christian Obrecht + */ +10 # IsPrime(n_IsPositiveInteger) <-- RabinMiller(n); + +%/mathpiper + + + +%mathpiper_docs,name="IsPrime",categories="User Functions;Number Theory;Predicates" +*CMD IsPrime --- test for a prime number +*CMD IsSmallPrime --- test for a (small) prime number +*STD +*CALL + IsPrime(n) + IsSmallPrime(n) + +*PARMS + +{n} -- integer to test + +*DESC + +The commands checks whether $n$, which should be a positive integer, +is a prime number. A number $n$ is a prime number if it is only divisible +by 1 and itself. As a special case, 1 is not considered a prime number. +The first prime numbers are 2, 3, 5, ... + +The function {IsShortPrime} only works for numbers $n<=65537$ but it is very fast. + +The function {IsPrime} operates on all numbers and uses different algorithms depending on the magnitude of the number $n$. +For small numbers $n<=65537$, a constant-time table lookup is performed. +(The function {IsShortPrime} is used for that.) +For numbers $n$ between $65537$ and $34155071728321$, the function uses the Rabin-Miller test together with table lookups to guarantee correct results. + +For even larger numbers a version of the probabilistic Rabin-Miller test is executed. +The test can sometimes mistakenly mark a number as prime while it is in fact composite, but a prime number will never be mistakenly declared composite. +The parameters of the test are such that the probability for a false result is less than $10^(-24)$. + +*E.G. + +In> IsPrime(1) +Result: False; +In> IsPrime(2) +Result: True; +In> IsPrime(10) +Result: False; +In> IsPrime(23) +Result: True; +In> Select(1 .. 100, "IsPrime") +Result: {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47, + 53,59,61,67,71,73,79,83,89,97}; + +*SEE IsPrimePower, Factors +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsPrimePower.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsPrimePower.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsPrimePower.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsPrimePower.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="IsPrimePower" + +/* Returns whether n is a prime^m. */ +10 # IsPrimePower(n_IsPrime) <-- True; +10 # IsPrimePower(0) <-- False; +10 # IsPrimePower(1) <-- False; +20 # IsPrimePower(n_IsPositiveInteger) <-- (GetPrimePower(n)[2] > 1); + +%/mathpiper + + + +%mathpiper_docs,name="IsPrimePower",categories="User Functions;Number Theory;Predicates" +*CMD IsPrimePower --- test for a power of a prime number +*STD +*CALL + IsPrimePower(n) + +*PARMS + +{n} -- integer to test + +*DESC + +This command tests whether "n", which should be a positive integer, +is a prime power, that is whether it is of the form $p^m$, with +"p" prime and "m" an integer. + +This function does not try to decompose the number $n$ into factors. +Instead we check for all prime numbers $r=2$, $3$, ... that the $r$-th root of $n$ is an integer, and we find such $r$ and $m$ that $n=m^r$, we check that $m$ is a prime. If it is not a prime, we execute the same function call on $m$. + +*E.G. + +In> IsPrimePower(9) +Result: True; +In> IsPrimePower(10) +Result: False; +In> Select(1 .. 50, "IsPrimePower") +Result: {2,3,4,5,7,8,9,11,13,16,17,19,23,25,27, + 29,31,32,37,41,43,47,49}; + +*SEE IsPrime, Factors +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsQuadraticResidue.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsQuadraticResidue.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsQuadraticResidue.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsQuadraticResidue.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="IsQuadraticResidue" + +// Algorithm adapted from: +// Elementary Number Theory, David M. Burton +// Theorem 9.1 p187 +10 # IsQuadraticResidue(_a,_p) <-- +[ + Check( IsInteger(a) And IsInteger(p) And p>2 And IsCoprime(a,p) And IsPrime(p), + "Argument", "IsQuadraticResidue: Invalid arguments"); + If(a^((p-1)/2) % p = 1, True, False); +]; + +%/mathpiper + + + +%mathpiper_docs,name="IsQuadraticResidue",categories="User Functions;Number Theory;Predicates" +*CMD IsQuadraticResidue --- functions related to finite groups +*STD +*CALL + IsQuadraticResidue(m,n) + +*PARMS +{m}, {n} -- integers, $n$ must be odd and positive + +*DESC + +A number $m$ is a "quadratic residue modulo $n$" if there exists a number $k$ such that $k^2:=Modulo(m,n)$. + +*E.G. + +In> IsQuadraticResidue(9,13) +Result: True; + +*SEE Gcd, JacobiSymbol, LegendreSymbol +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsSmallPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsSmallPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsSmallPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsSmallPrime.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,58 @@ +%mathpiper,def="IsSmallPrime" + +/* Returns whether n is a small by a lookup table, very fast. +The largest prime number in the table is returned by FastIsPrime(0). */ + +2 # IsSmallPrime(0) <-- False; +3 # IsSmallPrime(n_IsInteger) <-- (FastIsPrime(n)>0); + +%/mathpiper + + + +%mathpiper_docs,name="IsSmallPrime",categories="User Functions;Number Theory;Predicates" +*CMD IsPrime --- test for a prime number +*CMD IsSmallPrime --- test for a (small) prime number +*STD +*CALL + IsPrime(n) + IsSmallPrime(n) + +*PARMS + +{n} -- integer to test + +*DESC + +The commands checks whether $n$, which should be a positive integer, +is a prime number. A number $n$ is a prime number if it is only divisible +by 1 and itself. As a special case, 1 is not considered a prime number. +The first prime numbers are 2, 3, 5, ... + +The function {IsShortPrime} only works for numbers $n<=65537$ but it is very fast. + +The function {IsPrime} operates on all numbers and uses different algorithms depending on the magnitude of the number $n$. +For small numbers $n<=65537$, a constant-time table lookup is performed. +(The function {IsShortPrime} is used for that.) +For numbers $n$ between $65537$ and $34155071728321$, the function uses the Rabin-Miller test together with table lookups to guarantee correct results. + +For even larger numbers a version of the probabilistic Rabin-Miller test is executed. +The test can sometimes mistakenly mark a number as prime while it is in fact composite, but a prime number will never be mistakenly declared composite. +The parameters of the test are such that the probability for a false result is less than $10^(-24)$. + +*E.G. + +In> IsPrime(1) +Result: False; +In> IsPrime(2) +Result: True; +In> IsPrime(10) +Result: False; +In> IsPrime(23) +Result: True; +In> Select(1 .. 100, "IsPrime") +Result: {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47, + 53,59,61,67,71,73,79,83,89,97}; + +*SEE IsPrimePower, Factors +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsSquareFree.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsSquareFree.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsSquareFree.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsSquareFree.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="IsSquareFree" + +IsSquareFree(n_IsInteger) <-- ( Moebius(n) != 0 ); + +%/mathpiper + + + +%mathpiper_docs,name="IsSquareFree",categories="User Functions;Number Theory;Predicates" +*CMD IsSquareFree --- test for a square-free number +*STD +*CALL + IsSquareFree(n) + +*PARMS + +{n} -- positive integer + +*DESC + +This function uses the {Moebius} function to tell if the given number is square-free, which +means it has distinct prime factors. If $Moebius(n)!=0$, then {n} is square free. All prime +numbers are trivially square-free. + +*E.G. + +In> IsSquareFree(37) +Result: True; +In> IsSquareFree(4) +Result: False; +In> IsSquareFree(16) +Result: False; +In> IsSquareFree(18) +Result: False; + +*SEE Moebius, SquareFreeDivisorsList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsTwinPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsTwinPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/IsTwinPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/IsTwinPrime.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="IsTwinPrime" + +IsTwinPrime(n_IsPositiveInteger) <-- (IsPrime(n) And IsPrime(n+2)); + +%/mathpiper + + + +%mathpiper_docs,name="IsTwinPrime",categories="User Functions;Number Theory;Predicates" +*CMD IsTwinPrime --- test for a twin prime +*STD +*CALL + IsTwinPrime(n) +*PARMS + +{n} -- positive integer + +*DESC + +This function returns {True} if {n} is a twin prime. By definition, a twin +prime is a prime number $n$ such that $n+2$ is also a prime number. + +*E.G. +In> IsTwinPrime(101) +Result: True; +In> IsTwinPrime(7) +Result: False; +In> Select(1 .. 100, IsTwinPrime) +Result: {3,5,11,17,29,41,59,71}; + +*SEE IsPrime +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/LegendreSymbol.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/LegendreSymbol.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/LegendreSymbol.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/LegendreSymbol.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="LegendreSymbol" + +// Algorithm adapted from: +// Elementary Number Theory, David M. Burton +// Definition 9.2 p191 + +10 # LegendreSymbol(_a,_p) <-- +[ + Check( IsInteger(a) And IsInteger(p) And p>2 And IsCoprime(a,p) And IsPrime(p), + "Argument", "LegendreSymbol: Invalid arguments"); + If(IsQuadraticResidue(a,p), 1, -1 ); +]; + +%/mathpiper + + + +%mathpiper_docs,name="LegendreSymbol",categories="User Functions;Number Theory" +*CMD LegendreSymbol --- functions related to finite groups +*STD +*CALL + LegendreSymbol(m,n) + +*PARMS +{m}, {n} -- integers, $n$ must be odd and positive + +*DESC + +The Legendre symbol ($m$/$n$) is defined as $+1$ if $m$ is a quadratic residue modulo $n$ and $-1$ if it is a non-residue. +The Legendre symbol is equal to $0$ if $m/n$ is an integer. + +*E.G. + +In> IsQuadraticResidue(9,13) +Result: True; +In> LegendreSymbol(15,23) +Result: -1; +In> JacobiSymbol(7,15) +Result: -1; + +*SEE Gcd, JacobiSymbol, IsQuadraticResidue +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Moebius.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Moebius.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Moebius.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Moebius.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="Moebius" + +// Algorithm adapted from: +// Elementary Number Theory, David M. Burton +// Definition 6.3 p120 + +5 # Moebius(1) <-- 1; + +10 # Moebius(_n) <-- +[ + Check(IsPositiveInteger(n), "Argument", "Moebius: argument must be positive integer"); + Local(factors,i,repeat); + repeat:=0; + factors:=Factors(n); + len:=Length(factors); + For(i:=1,i<=len,i++)[ + If(factors[i][2]>1,repeat:=1); + ]; + If(repeat=0,(-1)^len,0); + +]; + +%/mathpiper + + + +%mathpiper_docs,name="Moebius",categories="User Functions;Number Theory" +*CMD Moebius --- the Moebius function +*STD +*CALL + Moebius(n) +*PARMS + +{n} -- positive integer + +*DESC + +The Moebius function is 0 when a prime factor is repeated (which means it +is not square-free) and is $(-1)^r$ if $n$ has $r$ distinct factors. Also, +$Moebius(1)==1$. + +*E.G. +In> Moebius(10) +Result: 1; +In> Moebius(11) +Result: -1; +In> Moebius(12) +Result: 0; +In> Moebius(13) +Result: -1; + +*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, MoebiusDivisorsList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NextPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NextPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NextPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NextPrime.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="NextPrime" + +/// obtain the real next prime number -- use primality testing +1# NextPrime(_i) <-- +[ + Until(IsPrime(i)) i := NextPseudoPrime(i); + i; +]; + +%/mathpiper + + + +%mathpiper_docs,name="NextPrime",categories="User Functions;Number Theory" +*CMD NextPrime --- generate a prime following a number +*STD +*CALL + NextPrime(i) + +*PARMS + +{i} -- integer value + +*DESC + +The function finds the smallest prime number that is greater than the given +integer value. + +The routine generates "candidate numbers" using the formula $n+2*Modulo(-n,3)$ +where $n$ is an odd number (this generates the sequence 5, 7, 11, 13, 17, +19, ...) and {IsPrime()} to test whether the next candidate number is in +fact prime. + +*E.G. +In> NextPrime(5) +Result: 7; + +*SEE IsPrime +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NextPseudoPrime.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NextPseudoPrime.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NextPseudoPrime.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NextPseudoPrime.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,30 @@ +%mathpiper,def="NextPseudoPrime" + +/// obtain next number that has good chances of being prime (not divisible by 2,3) +1# NextPseudoPrime(i_IsInteger)_(i<=1) <-- 2; +2# NextPseudoPrime(2) <-- 3; +//2# NextPseudoPrime(3) <-- 5; +3# NextPseudoPrime(i_IsOdd) <-- +[ + // this sequence generates numbers not divisible by 2 or 3 + i := i+2; + If(Modulo(i,3)=0, i:=i+2, i); +/* commented out because it slows things down without a real advantage +// this works only for odd i>=5 + i := If( + Modulo(-i,3)=0, + i + 2, + i + 2*Modulo(-i, 3) + ); + // now check if divisible by 5 + If( + Modulo(i,5)=0, + NextPseudoPrime(i), + i + ); +*/ +]; +// this works only for even i>=4 +4# NextPseudoPrime(i_IsEven) <-- NextPseudoPrime(i-1); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NthRoot.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NthRoot.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NthRoot.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NthRoot.mpw 2011-02-02 08:31:10.000000000 +0000 @@ -0,0 +1,179 @@ +%mathpiper,def="NthRoot" + +/* def file definitions +NthRoot +NthRoot'Calc +NthRoot'List +NthRoot'Save +NthRoot'Restore +NthRoot'Clear + +*/ + +////// +// $Id: nthroot.mpi,v 1.5 2007/05/17 11:56:45 ayalpinkus Exp $ +// calculation/simplifaction of nth roots of nonnegative integers +// NthRoot - interface function +// NthRoot'Calc - actually calculate/simplifies +// NthRoot'List - list table entries for a given n +// NthRoot'Restore - get a root from lookup table +// NthRoot'Save - save a root in lookup table +// NthRoot'Clear - clear lookup table +////// + +// LocalSymbols(m,n,r, +// NthRoot'Table, +// NthRoot'Calc, +// NthRoot'List, +// NthRoot'Restore, +// NthRoot'Save, +// NthRoot'Clear) +LocalSymbols(m,n,r, + NthRoot'Table) +[ + +// interface function for nth root of m +// m>=0, n>1, integers +// m^(1/n) --> f*(r^(1/n)) +NthRoot(m_IsNonNegativeInteger,n_IsInteger)_(n>1) <-- +[ + Local(r); + r:=NthRoot'Restore(m,n); + If(Length(r)=0, + [ + r:=NthRoot'Calc(m,n); + NthRoot'Save(m,n,r); + ]); + r; +]; + +// internal functions +Function("NthRoot'Calc",{m,n}) +[ + Local(i,j,f,r,in); + Bind(i,2); + Bind(j,Ceil(FastPower(m,N(1.0/n))+1)); + Bind(f,1); + Bind(r,m); + // for large j (approx >4000) + // using Factors instead of the + // following. would this be + // faster in general? +//Echo("i j ",i," ",j); + While(IsLessThan(i,j)) + [ + Bind(in,PowerN(i,n)); +//Echo("r in mod ",r, " ",in," ",ModuloN(r,in)); + While(IsEqual(ModuloN(r,in),0)) + [ + Bind(f,MultiplyN(f,i)); + Bind(r,QuotientN(r,in)); + ]; + While(IsEqual(ModuloN(r,i),0)) // + Bind(r,QuotientN(r,i)); // + //Bind(i,NextPrime(i)); + Bind(i,NextPseudoPrime(i)); + Bind(j,Ceil(FastPower(r,N(1.0/n))+1)); + ]; + //List(f,r); + List(f,QuotientN(m,PowerN(f,n))); // +]; + +// lookup table utilities +Function("NthRoot'List",{n}) +[ + If(Length(NthRoot'Table)>0, + [ + Local(p,xx); + p:=Select(NthRoot'Table, {{xx},First(xx)=n}); + If(Length(p)=1,Rest(p[1]),List()); + ], + List()); +]; + +Function("NthRoot'Restore",{m,n}) +[ + Local(p); + p:=NthRoot'List(n); + If(Length(p)>0, + [ + Local(r,xx); + r:=Select(p, {{xx},First(xx)=m}); + If(Length(r)=1,First(Rest(r[1])),List()); + ], + List()); +]; + +Function("NthRoot'Save",{m,n,r}) +[ + Local(p); + p:=NthRoot'List(n); + If(Length(p)=0, + // create power list and save root + DestructiveInsert(NthRoot'Table,1,List(n,List(m,r))), + [ + Local(rr,xx); + rr:=Select(p, {{xx},First(xx)=m}); + If(Length(rr)=0, + [ + // save root only + DestructiveAppend(p,List(m,r)); + ], + // already saved + False); + ]); +]; + +//TODO why is NthRoot'Table both lazy global and protected with LocalSymbols? +Function("NthRoot'Clear",{}) SetGlobalLazyVariable(NthRoot'Table,List()); + +// create empty table +NthRoot'Clear(); + +]; // LocalSymbols(m,n,r,NthRoot'Table); + +////// +////// + + +%/mathpiper + + + +%mathpiper_docs,name="NthRoot",categories="User Functions;Numbers (Operations)" +*CMD NthRoot --- calculate/simplify nth root of an integer +*STD +*CALL + NthRoot(m,n) + +*PARMS + +{m} -- a non-negative integer ($m>0$) + +{n} -- a positive integer greater than 1 ($n>1$) + +*DESC + +{NthRoot(m,n)} calculates the integer part of the $n$-th root $m^(1/n)$ and +returns a list {{f,r}}. {f} and {r} are both positive integers +that satisfy $f^n*r$=$m$. +In other words, $f$ is the largest integer such that $m$ divides $f^n$ and $r$ is the remaining factor. + +For large {m} and small {n} +{NthRoot} may work quite slowly. Every result {{f,r}} for given +{m}, {n} is saved in a lookup table, thus subsequent calls to +{NthRoot} with the same values {m}, {n} will be executed quite +fast. + +*E.G. +In> NthRoot(12,2) +Result: {2,3}; +In> NthRoot(81,3) +Result: {3,3}; +In> NthRoot(3255552,2) +Result: {144,157}; +In> NthRoot(3255552,3) +Result: {12,1884}; + +*SEE IntNthRoot, Factors, PowerN +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/DivisorsList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/DivisorsList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/DivisorsList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/DivisorsList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,49 @@ +%mathpiper,def="DivisorsList" + +/* Implementation of some number theoretical functions for MathPiper */ +/* (C) 2002 Pablo De Napoli under GNU GPL */ + +/* DivisorsList(n) = the list of divisors of n */ + +DivisorsList(n_IsPositiveInteger) <-- +[ + Local(nFactors,f,result,oldresult,x); + nFactors:= Factors(n); + result := {1}; + ForEach (f,nFactors) + [ + oldresult := result; + For (k:=1,k<=f[2],k++) + ForEach (x,oldresult) + result:=Append(result,x*f[1]^k); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="DivisorsList",categories="User Functions;Number Theory" +*CMD DivisorsList --- the list of divisors +*STD +*CALL + DivisorsList(n) +*PARMS + +{n} -- positive integer + +*DESC + +{DivisorsList} creates a list of the divisors of $n$. +This is useful for loops like + + ForEach(d,DivisorsList(n)) + +*E.G. + +In> DivisorsList(18) +Result: {1,2,3,6,9,18}; + +*SEE DivisorsSum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/JacobiSymbol.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/JacobiSymbol.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/JacobiSymbol.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/JacobiSymbol.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,57 @@ +%mathpiper,def="JacobiSymbol" + +/* Implementation of some number theoretical functions for MathPiper */ +/* (C) 2002 Pablo De Napoli under GNU GPL */ + +/** Compute the Jacobi symbol JS(m/n) - n must be odd, both positive. +See the Algo book for documentation. + +*/ + +10 # JacobiSymbol(_a, 1) <-- 1; +15 # JacobiSymbol(0, _b) <-- 0; +18 # JacobiSymbol(_a, _b) _ (Gcd(a,b)>1) <-- 0; + +20 # JacobiSymbol(_a, b_IsOdd)_(a>=Abs(b) Or a<0) <-- JacobiSymbol(Modulo(a,Abs(b)),Abs(b)); + +30 # JacobiSymbol(a_IsEven, b_IsOdd) <-- +[ + Local(c, s); + // compute c,s where a=c*2^s and c is odd + {c,s}:=FindPrimeFactorSimple(a, 2); // use the "Simple" function because we don't expect a worst case here + If(Modulo(s,2)=1 And Abs(Modulo(b,8)-4)=1, -1, 1) * JacobiSymbol(c,b); +]; + +40 # JacobiSymbol(a_IsOdd, b_IsOdd) <-- If(Modulo(a,4)=3 And Modulo(b,4)=3, -1, 1) * JacobiSymbol(b,a); + +%/mathpiper + + + +%mathpiper_docs,name="JacobiSymbol",categories="User Functions;Number Theory" +*CMD JacobiSymbol --- functions related to finite groups +*STD +*CALL + JacobiSymbol(m,n) + +*PARMS +{m}, {n} -- integers, $n$ must be odd and positive + +*DESC + +The Jacobi symbol $[m/n;]$ is defined as the product of the Legendre symbols of the prime factors $f[i]$ of $n=f[1]^p[1]*...*f[s]^p[s]$, +$$ [m/n;] := [m/f[1];]^p[1]*...*[m/f[s];]^p[s] $$. +(Here we used the same notation $[a/b;]$ for the Legendre and the Jacobi symbols; this is confusing but seems to be the current practice.) +The Jacobi symbol is equal to $0$ if $m$, $n$ are not mutually prime (have a common factor). +The Jacobi symbol and the Legendre symbol have values $+1$, $-1$ or $0$. +If $n$ is prime, then the Jacobi symbol is the same as the Legendre symbol. + +The Jacobi symbol can be efficiently computed without knowing the full factorization of the number $n$. + +*E.G. + +In> JacobiSymbol(7,15) +Result: -1; + +*SEE Gcd, LegendreSymbol, IsQuadraticResidue +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/MoebiusDivisorsList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/MoebiusDivisorsList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/MoebiusDivisorsList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/MoebiusDivisorsList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="MoebiusDivisorsList" + +/* Implementation of some number theoretical functions for MathPiper */ +/* (C) 2002 Pablo De Napoli under GNU GPL */ + +/* Returns a list of pairs {d,m} + where d runs through the square free divisors of n + and m=Moebius(m) + This is much more efficient than making a list of all + square-free divisors of n, and then compute Moebius on each of them. + It is useful for computing the Cyclotomic polinomials. + It can be useful in other computations based on + Moebius inversion formula. */ + +MoebiusDivisorsList(n_IsPositiveInteger) <-- +[ + Local(nFactors,f,result,oldresult,x); + nFactors:= Factors(n); + result := {{1,1}}; + ForEach (f,nFactors) + [ + oldresult := result; + ForEach (x,oldresult) + result:=Append(result,{x[1]*f[1],-x[2]}); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="MoebiusDivisorsList",categories="User Functions;Number Theory" +*CMD MoebiusDivisorsList --- the list of divisors and Moebius values +*STD +*CALL + MoebiusDivisorsList(n) +*PARMS + +{n} -- positive integer + +*DESC + +Returns a list of pairs of the form {{d,m}}, where {d} runs through the squarefree divisors of $n$ and $m=Moebius(d)$. +This is more efficient than making a list of all +square-free divisors of $n$ and then computing {Moebius} on each of them. +It is useful for computing the cyclotomic polynomials. +It can be useful in other computations based on the Moebius inversion formula. + +*E.G. + +In> MoebiusDivisorsList(18) +Result: {{1,1},{2,-1},{3,-1},{6,1}}; + +*SEE DivisorsList, Moebius +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/RamanujanSum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/RamanujanSum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/RamanujanSum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/RamanujanSum.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="RamanujanSum" + +/* Implementation of some number theoretical functions for MathPiper */ +/* (C) 2002 Pablo De Napoli under GNU GPL */ + +/* RamanujanSum(k,n) = the sum of the n-th powers of the +k-th primitive roots of the identity */ + +10 # RamanujanSum(k_IsPositiveInteger,0) <-- Totient(k); + +20 # RamanujanSum(k_IsPositiveInteger,n_IsPositiveInteger) <-- +[ + Local(s,gcd,d); + s:= 0; + gcd := Gcd(n,k); + ForEach (d,DivisorsList(gcd)) + s:=s+d*Moebius(k/d); + s; +]; + +%/mathpiper + + + +%mathpiper_docs,name="RamanujanSum",categories="User Functions;Number Theory" +*CMD RamanujanSum --- compute the "Ramanujan sum" +*STD +*CALL + RamanujanSum(k,n) + +*PARMS + +{k}, {n} -- positive integers + +*DESC +This function computes the Ramanujan sum, i.e. the sum of the $n$-th powers of +the $k$-th primitive roots of the unit: + +$$ Sum(l,1,k, Exp(2*Pi*I*(l*n)/k)) $$ + +where $l$ runs thought the integers between $1$ and $k-1$ that are coprime to $l$. + +The computation is done by using the formula in T. M. Apostol, +Introduction to Analytic Theory (Springer-Verlag), Theorem 8.6. +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/SquareFreeDivisorsList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/SquareFreeDivisorsList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/SquareFreeDivisorsList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/SquareFreeDivisorsList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="SquareFreeDivisorsList" + +/* Implementation of some number theoretical functions for MathPiper */ +/* (C) 2002 Pablo De Napoli under GNU GPL */ + +/* Returns a list of the square-free divisors of n */ +SquareFreeDivisorsList(n_IsPositiveInteger) <-- +[ + Local(nFactors,f,result,oldresult,x); + nFactors:= Factors(n); + result := {1}; + ForEach (f,nFactors) + [ + oldresult := result; + ForEach (x,oldresult) + result:=Append(result,x*f[1]); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="SquareFreeDivisorsList",categories="User Functions;Number Theory" +*CMD SquareFreeDivisorsList --- the list of square-free divisors +*STD +*CALL + SquareFreeDivisorsList(n) +*PARMS + +{n} -- positive integer + +*DESC + +{SquareFreeDivisorsList} creates a list of the square-free divisors of $n$. +Square-free numbers are numbers that have only simple prime factors (no prime powers). +For example, $18=2*3*3$ is not square-free because it contains a square of $3$ as a factor. + +*E.G. + +In> SquareFreeDivisorsList(18) +Result: {1,2,3,6}; + +*SEE DivisorsList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/SumForDivisors.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/SumForDivisors.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/numbertheory/SumForDivisors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/numbertheory/SumForDivisors.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="SumForDivisors" + +/* Implementation of some number theoretical functions for MathPiper */ +/* (C) 2002 Pablo De Napoli under GNU GPL */ + +/* This function performs a sum where sumvar runs through + the divisors of n + For example SumForDivisors(d,10,d^2) + sums d^2 with d walking through the divisors of 10 + LocalSymbols is needed since we use Eval() inside + Look at Programming in MathPiper: Evaluating Variables in the Wrong + Scope */ + +Function ("SumForDivisors",{sumvar,n,sumbody}) LocalSymbols(s,d) +[ + Local(s,d); + s:=0; + ForEach (d,DivisorsList(n)) + [ + MacroLocal(sumvar); + MacroBind(sumvar,d); + s:=s+Eval(sumbody); + ]; + s; +]; +UnFence("SumForDivisors",3); +HoldArgument("SumForDivisors",sumvar); +HoldArgument("SumForDivisors",sumbody); + +%/mathpiper + + + +%mathpiper_docs,name="SumForDivisors",categories="User Functions;Number Theory" +*CMD SumForDivisors --- loop over divisors +*STD +*CALL + SumForDivisors(var,n,expr) +*PARMS + +{var} -- atom, variable name + +{n} -- positive integer + +{expr} -- expression depending on {var} + +*DESC + +This function performs the sum of the values of the expression {expr} while the variable {var} runs through +the divisors of {n}. +For example, {SumForDivisors(d, 10, d^2)} sums $d^2$ where $d$ runs +through the divisors of $10$. +This kind of computation is frequently used in number theory. + +*SEE DivisorsList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NumberToRep.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NumberToRep.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/NumberToRep.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/NumberToRep.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,139 @@ +%mathpiper,def="NumberToRep" + +//Retract("NumberToRep",*); + + +10 # NumberToRep( N_IsNumber ) <-- +[ + //If(InVerboseMode(),Tell(NumberToRep,N)); + Local(oldPrec,sgn,assoc,typ,val,prec,rep); + oldPrec := BuiltinPrecisionGet(); + BuiltinPrecisionSet(300); + /* NOTE: the above arbitrary 'magic number' is used because it is + * currently necessary to set BuiltinPrecision to a value large + * enough to handle any forseeable input. Of course, even 300 + * might not be enough! I am looking for a way to base the + * setting directly on the input number itself. */ + + sgn := Sign(N); + assoc := DumpNumber(Abs(N)); + //If(InVerboseMode(),[ Tell(" ",assoc); Tell(" ",sgn); ]); + typ := Assoc("type",assoc)[2]; + //If(InVerboseMode(),Tell(" ",typ)); + If( typ = "BigDecimal", + [ + rep := { sgn*Assoc("unscaledValue",assoc)[2], + Assoc("precision", assoc)[2], + Assoc("scale", assoc)[2] + }; + ], + [ + Local(val,prec); + val := Assoc("value",assoc)[2]; + prec := Length(ExpressionToString(val)); + rep := { sgn*val, prec }; + ] + ); + //If(InVerboseMode(),Tell(" ",rep)); + BuiltinPrecisionSet(oldPrec); + rep; +]; + + + +12 # NumberToRep( N_IsComplex ) <-- +[ + If(IsZero(Re(N)), + {NumberToRep(0.0),NumberToRep(Im(N))}, + {NumberToRep(Re(N)),NumberToRep(Im(N))} + ); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="NumberToRep",categories="Programmer Functions;Numerical (Arbitrary Precision)" +*CMD NumberToRep --- returns a List showing MathPiper's internal representation of a number +*STD +*CALL + NumberToRep(number) + +*PARMS + +{number} -- an Integer, Decimal, or Complex number + + +*DESC + +Internally, MathPiper represents {arbitrary precision} numbers as Java BigIntegers or +BigDecimals. Java code handles calculations using such numbers. + +All the information needed to correctly understand the precision attached to a number, +and the rounding and comparison thereof, is contained in the Java structure. + +For a Decimal number (essentially anything with a decimal point), the representation +consists of an arbitrary-precision integer containing {all} the significant digits of +the number, and a {scale factor} telling where the implied decimal point is supposed to +be placed with respect to the end of the integer. The {precision} of the number is +just the number of digits in the integer. + +The three components of the List returned for a decimal number are, respectively, +{{BigInteger (unscaled), Precision, ScaleFactor}}. +Note that the second of these is redundent: only the BigInteger and the ScaleFactor +are needed to completely define the number. + +For an Integer number, the integer is its own representation, and again, the number of +its digits gives its precision. + +For a Complex number, this function returns a List containing the representations of +the Real and Imaginary parts of the number. + +The best way to {consistently} deal with precision and rounding issues is by making use +of the information given by this function. + +*E.G. + +In> NumberToRep(123.45678) +Result: {12345678,8,5} + +In> NumberToRep(34700) +Result: {34700,5} + +In> NumberToRep(1.5+6.75*I) +Result: {{150,3,2},{675,3,2}} + +In> NumberToRep(123.45678E-10) +Result: {12345678,8,15} + +In> NumberToRep(123.45678E+10) +Result: {12345678,8,-5} + +NOTICE that the first, fourth, and fifth of these have the same +BigInteger representation, and hence the same precision, namely 8. +The ScaleFactor tells how many places the decimal point must be +moved {leftward} from the {end} of the integer. A negative +ScaleFactor says to move the decimal point to the right -- +i.e., effectively, add terminal zeros. However, if the number had +originally been written as 1234567800000., it would actually have +a different representation, namely {1234567800000,13,0}. That is +because, if we write those terminal zeros explicitly, they are assumed +to be "significant", and so the number is shown with precision 13. +Exponential notation must be used if the precision really is 8. + +*SEE RepToNumber, DumpNumber +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/om/om.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,71 @@ +%mathpiper,def="" + +// From code.mpi.def: +OMDef( "BellNumber", mathpiper,"BellNumber" ); +OMDef( "CatalanNumber", mathpiper,"CatalanNumber" ); +OMDef( "DigitalRoot", mathpiper,"DigitalRoot" ); +OMDef( "Divisors", mathpiper,"Divisors" ); +OMDef( "DivisorsSum", mathpiper,"DivisorsSum" ); +OMDef( "Euler", mathpiper,"Euler" ); +OMDef( "EulerArray", mathpiper,"EulerArray" ); +OMDef( "Eulerian", mathpiper,"Eulerian" ); +OMDef( "FermatNumber", mathpiper,"FermatNumber" ); +OMDef( "GetPrimePower", mathpiper,"GetPrimePower" ); +OMDef( "HarmonicNumber", mathpiper,"HarmonicNumber" ); +OMDef( "IntLog", mathpiper,"IntLog" ); +OMDef( "IntNthRoot", mathpiper,"IntNthRoot" ); +OMDef( "IsAmicablePair", mathpiper,"IsAmicablePair" ); +OMDef( "IsCarmichaelNumber", mathpiper,"IsCarmichaelNumber" ); +OMDef( "IsComposite", mathpiper,"IsComposite" ); +OMDef( "IsCoprime", mathpiper,"IsCoprime" ); +OMDef( "IsIrregularPrime", mathpiper,"IsIrregularPrime" ); +OMDef( "IsPerfect", mathpiper,"IsPerfect" ); +OMDef( "IsPrime", mathpiper,"IsPrime" ); +OMDef( "IsPrimePower", mathpiper,"IsPrimePower" ); +OMDef( "IsQuadraticResidue", mathpiper,"IsQuadraticResidue" ); +OMDef( "IsSmallPrime", mathpiper,"IsSmallPrime" ); +OMDef( "IsSquareFree", mathpiper,"IsSquareFree" ); +OMDef( "IsTwinPrime", mathpiper,"IsTwinPrime" ); +OMDef( "LegendreSymbol", mathpiper,"LegendreSymbol" ); +OMDef( "Moebius", mathpiper,"Moebius" ); +OMDef( "NextPrime", mathpiper,"NextPrime" ); +OMDef( "NextPseudoPrime", mathpiper,"NextPseudoPrime" ); +OMDef( "PartitionsP", mathpiper,"PartitionsP" ); +OMDef( "ProductPrimesTo257", mathpiper,"ProductPrimesTo257" ); +OMDef( "ProperDivisors", mathpiper,"ProperDivisors" ); +OMDef( "ProperDivisorsSum", mathpiper,"ProperDivisorsSum" ); +OMDef( "Repunit", mathpiper,"Repunit" ); +OMDef( "StirlingNumber1", mathpiper,"StirlingNumber1" ); +OMDef( "StirlingNumber2", mathpiper,"StirlingNumber2" ); +OMDef( "Totient", mathpiper,"Totient" ); + +// From GaussianIntegers.mpi.def +OMDef( "IsGaussianUnit", mathpiper,"IsGaussianUnit" ); +OMDef( "IsGaussianInteger", mathpiper,"IsGaussianInteger" ); +OMDef( "IsGaussianPrime", mathpiper,"IsGaussianPrime" ); +OMDef( "GaussianFactorPrime", mathpiper,"GaussianFactorPrime" ); +OMDef( "GaussianNorm", mathpiper,"GaussianNorm" ); +OMDef( "GaussianMod", mathpiper,"GaussianMod" ); +OMDef( "GaussianFactors", mathpiper,"GaussianFactors" ); +OMDef( "AddGaussianFactor", mathpiper,"AddGaussianFactor" ); +OMDef( "FactorGaussianInteger", mathpiper,"FactorGaussianInteger" ); +OMDef( "GaussianGcd", mathpiper,"GaussianGcd" ); + +// From nthroot.mpi.def +OMDef( "NthRoot", mathpiper,"NthRoot" ); +OMDef( "NthRoot'Calc", mathpiper,"NthRoot'Calc" ); +OMDef( "NthRoot'List", mathpiper,"NthRoot'List" ); +OMDef( "NthRoot'Save", mathpiper,"NthRoot'Save" ); +OMDef( "NthRoot'Restore", mathpiper,"NthRoot'Restore" ); +OMDef( "NthRoot'Clear", mathpiper,"NthRoot'Clear" ); + +// From NumberTheory.mpi.def +OMDef( "DivisorsList", mathpiper,"DivisorsList" ); +OMDef( "SquareFreeDivisorsList", mathpiper,"SquareFreeDivisorsList" ); +OMDef( "MoebiusDivisorsList", mathpiper,"MoebiusDivisorsList" ); +OMDef( "SumForDivisors", mathpiper,"SumForDivisors" ); +OMDef( "RamanujanSum", mathpiper,"RamanujanSum" ); +OMDef( "JacobiSymbol", mathpiper,"JacobiSymbol" ); + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/PartitionsP.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/PartitionsP.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/PartitionsP.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/PartitionsP.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,151 @@ +%mathpiper,def="PartitionsP" + +/// the restricted partition function +/// partitions of length k + +5 # PartitionsP(n_IsInteger,0) <-- 0; +5 # PartitionsP(n_IsInteger,n_IsInteger) <-- 1; +5 # PartitionsP(n_IsInteger,1) <-- 1; +5 # PartitionsP(n_IsInteger,2) <-- Floor(n/2); +5 # PartitionsP(n_IsInteger,3) <-- Round(n^2/12); +6 # PartitionsP(n_IsInteger,k_IsInteger)_(k>n) <-- 0; +10 # PartitionsP(n_IsInteger,k_IsInteger) <-- PartitionsP(n-1,k-1)+PartitionsP(n-k,k); + +/// the number of additive partitions of an integer +5 # PartitionsP(0) <-- 1; +5 # PartitionsP(1) <-- 1; +// decide which algorithm to use +10 # PartitionsP(n_IsInteger)_(n<250) <-- PartitionsP'recur(n); +20 # PartitionsP(n_IsInteger) <-- PartitionsP'HR(n); + +/// Calculation using the Hardy-Ramanujan series. +10 # PartitionsP'HR(n_IsPositiveInteger) <-- +[ + Local(P0, A, lambda, mu, mu'k, result, term, j, k, l, prec, epsilon); + result:=0; + term:=1; // initial value must be nonzero + GlobalPush(BuiltinPrecisionGet()); + // precision must be at least Pi/Ln(10)*Sqrt(2*n/3)-Ln(4*n*Sqrt(3))/Ln(10) + // here Pi/Ln(10) < 161/118, and Ln(4*Sqrt(3))/Ln(10) <1 so it is disregarded. Add 2 guard digits and compensate for round-off errors by not subtracting Ln(n)/Ln(10) now + prec := 2+Quotient(IntNthRoot(Quotient(2*n+2,3),2)*161+117,118); + BuiltinPrecisionSet(prec); // compensate for round-off errors + epsilon := PowerN(10,-prec)*n*10; // stop when term < epsilon + + // get the leading term approximation P0 - compute once at high precision + lambda := N(Sqrt(n - 1/24)); + mu := N(Pi*lambda*Sqrt(2/3)); + // the hoops with DivideN are needed to avoid roundoff error at large n due to fixed precision: + // Exp(mu)/(n) must be computed by dividing by n, not by multiplying by 1/n + P0 := N(1-1/mu)*DivideN(ExpN(mu),(n-DivideN(1,24))*4*SqrtN(3)); + /* + the series is now equal to + P0*Sum(k,1,Infinity, + ( + Exp(mu*(1/k-1))*(1/k-1/mu) + Exp(-mu*(1/k+1))*(1/k+1/mu) + ) * A(k,n) * Sqrt(k) + ) + */ + + A := 0; // this is also used as a flag + // this is a heuristic, because the next term error is expensive + // to calculate and the theoretic bounds have arbitrary constants + // use at most 5+Sqrt(n)/2 terms, stop when the term is nonzero and result stops to change at precision prec + For(k:=1, k<=5+Quotient(IntNthRoot(n,2),2) And (A=0 Or Abs(term)>epsilon), k++) + [ + // compute A(k,n) + A:=0; + For(l:=1,l<=k,l++) + [ + If( + Gcd(l,k)=1, + A := A + Cos(Pi* + ( // replace Exp(I*Pi*...) by Cos(Pi*...) since the imaginary part always cancels + Sum(j,1,k-1, j*(Modulo(l*j,k)/k-1/2)) - 2*l*n + // replace (x/y - Floor(x/y)) by Modulo(x,y)/y for integer x,y + )/k) + ); + A:=N(A); // avoid accumulating symbolic Cos() expressions + ]; + + term := If( + A=0, // avoid long calculations if the term is 0 + 0, + N( A*Sqrt(k)*( + [ + mu'k := mu/k; // save time, compute mu/k once + Exp(mu'k-mu)*(mu'k-1) + Exp(-mu'k-mu)*(mu'k+1); + ] + )/(mu-1) ) + ); +// Echo("k=", k, "term=", term); + result := result + term; +// Echo("result", new'result* P0); + ]; + result := result * P0; + BuiltinPrecisionSet(GlobalPop()); + Round(result); +]; + +// old code for comparison + +10 # PartitionsP1(n_IsPositiveInteger) <-- + [ + Local(C,A,lambda,m,pa,k,h,term); + GlobalPush(BuiltinPrecisionGet()); + // this is an overshoot, but seems to work up to at least n=4096 + BuiltinPrecisionSet(10 + Floor(N(Sqrt(n))) ); + pa:=0; + C:=Pi*Sqrt(2/3)/k; + lambda:=Sqrt(m - 1/24); + term:=1; + // this is a heuristic, because the next term error is expensive + // to calculate and the theoretic bounds have arbitrary constants + For(k:=1,k<=5+Floor(SqrtN(n)*0.5) And ( term=0 Or Abs(term)>0.1) ,k++)[ + A:=0; + For(h:=1,h<=k,h++)[ + if( Gcd(h,k)=1 )[ + A:=A+Exp(I*Pi*Sum(j,1,k-1,(j/k)*((h*j)/k - Floor((h*j)/k) -1/2)) +- 2*Pi*I*h*n/k ); + ]; + ]; + If(A!=0, term:= N(A*Sqrt(k)*(Deriv(m) Sinh(C*lambda)/lambda) Where m==n ),term:=0 ); +// Echo("Term ",k,"is ",N(term/(Pi*Sqrt(2)))); + pa:=pa+term; +// Echo("result", N(pa/(Pi*Sqrt(2)))); + ]; + pa:=N(pa/(Pi*Sqrt(2))); + BuiltinPrecisionSet(GlobalPop()); + Round(pa); + ]; + +/// integer partitions by recurrence relation P(n) = Sum(k,1,n, (-1)^(k+1)*( P(n-k*(3*k-1)/2)+P(n-k*(3*k+1)/2) ) ) = P(n-1)+P(n-2)-P(n-5)-P(n-7)+... +/// where 1, 2, 5, 7, ... is the "generalized pentagonal sequence" +/// this method is faster with internal math for number<300 or so. +PartitionsP'recur(number_IsPositiveInteger) <-- +[ + // need storage of n values PartitionsP(k) for k=1,...,n + Local(sign, cache, n, k, pentagonal, P); + cache:=ArrayCreate(number+1,1); // cache[n] = PartitionsP(n-1) + n := 1; + While(n ProperDivisors(180) +Result: 17; +In> ProperDivisors(37) +Result: 1; + +*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/ProperDivisorsSum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/ProperDivisorsSum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/ProperDivisorsSum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/ProperDivisorsSum.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="ProperDivisorsSum" + +10 # ProperDivisorsSum(_n) <-- +[ + Check(IsPositiveInteger(n), "Argument", "ProperDivisorsSum: argument must be positive integer"); + DivisorsSum(n)-n; +]; + +%/mathpiper + + + +%mathpiper_docs,name="ProperDivisorsSum",categories="User Functions;Number Theory" +*CMD ProperDivisorsSum --- the sum of proper divisors +*STD +*CALL + ProperDivisorsSum(n) +*PARMS + +{n} -- positive integer + +*DESC + +{ProperDivisorsSum} returns the sum of proper divisors, i.e. {ProperDivisors(n)-n}, +since {n} is not counted. +{n} is prime if and only if {ProperDivisorsSum(n)==1}. + +*E.G. +In> ProperDivisorsSum(180) +Result: 366; +In> ProperDivisorsSum(37) +Result: 1; + + +*SEE DivisorsSum, ProperDivisors, ProperDivisorsSum, Moebius +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Rationalize.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Rationalize.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Rationalize.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Rationalize.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,71 @@ +%mathpiper,def="Rationalize" + +//Retract("Rationalize",*); + +10 # Rationalize(aNumber_IsList) <-- Rationalize /@ aNumber; + +20 # Rationalize( _aNumber ) <-- +[ + Local(result,n,d); + result:=Substitute(aNumber,{{x},IsNumber(x) And Not(IsInteger(x))},"RationalizeNumber"); + If(InVerboseMode(),Tell("",result)); + If(Length(VarList(aNumber))=0, + [ + n:=Numerator(result); + If(Type(n)="Numerator",n:=result); + d:=Denominator(result); + If(Type(d)="Denominator",d:=1); + result := n*(1/d); + ] + ); + result; +]; +%/mathpiper + + + + + + +%mathpiper_docs,name="Rationalize",categories="User Functions;Numbers (Operations)" +*CMD Rationalize --- convert floating point numbers to fractions +*STD +*CALL + Rationalize(expr) + +*PARMS + +{expr} -- an expression containing real numbers + +*DESC + +This command converts every real number in the expression "expr" +into a rational number. This is useful when a calculation needs to be +done on floating point numbers and the algorithm is unstable. +Converting the floating point numbers to rational numbers will force +calculations to be done with infinite precision (by using rational +numbers as representations). + +It does this by finding the smallest integer $n$ such that multiplying +the number with $10^n$ is an integer. Then it divides by $10^n$ again, +depending on the internal gcd calculation to reduce the resulting +division of integers. + +*E.G. + +In> Rationalize(-1.2) +Result: (-6)/5 +In> Rationalize(1.3+7.43*x) +Result: 743/100*x+13/10 +In> {1.2,3.123,4.5} +Result: {1.2,3.123,4.5}; +In> Rationalize(%) +Result: {6/5,3123/1000,9/2}; + +*SEE IsRational + +%/mathpiper_docs + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RationalizeNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RationalizeNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RationalizeNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RationalizeNumber.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,22 @@ +%mathpiper,def="RationalizeNumber" + +Function("RationalizeNumber",{x}) +[ + Check(IsNumber(x), "Argument", "RationalizeNumber: Error: " : (PipeToString()Write(x)) :" is not a number"); + Local(n,i,bip,m); + n := 1; + i := 0; + bip := BuiltinPrecisionGet(); + // We can not take for granted that the internal representation is rounded properly... + While(i<=bip And Not(FloatIsInt(x))) + [ + n := n*10; + x := x*10; + i := i+1; + ]; + m := Floor(x+0.5); + (m/n); +]; + +%/mathpiper + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RepToNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RepToNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RepToNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RepToNumber.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,140 @@ +%mathpiper,def="RepToNumber" + +//Retract("RepToNumber",*); + + +10 # RepToNumber( rep_IsListOfLists ) <-- +[ + //If(InVerboseMode(),[Tell(RepToNumberZ,rep); Tell(" complex");]); + RepToNumber(rep[1])+I*RepToNumber(rep[2]); +]; + + +12 # RepToNumber( rep_IsList ) <-- +[ + //If(InVerboseMode(),Tell(RepToNumber,rep)); + Local(bigInt,precision,scale,strBI,sgn,index,ans); + Local(first,secnd,third,LS,numStr); + precision := rep[2]; + scale := 0; + bigInt := rep[1]; + precision := rep[2]; + sgn := Sign(bigInt); + If( Length(rep) > 2, scale := rep[3] ); + strBI := ExpressionToString(Abs(bigInt)); + LS := Length(strBI); + //If(InVerboseMode(),[Tell(" ",{bigInt,precision,scale,sgn});Tell(" ",strBI);]); + If( Length(rep)=2, + [ numStr := strBI; ], + [ + index := precision-scale; + first := strBI[1]; + secnd := StringMidGet(2,LS-1,strBI); + third := ExpressionToString(index-1); + //If(InVerboseMode(),Tell(" ",{index,first,secnd,third})); + if ( index > 0 ) + [ + if ( index < precision ) + [ + //If(InVerboseMode(),Tell(" index < precision ")); + numStr := ConcatStrings(first,".",secnd,"E",third); + ] + else if ( index >= precision ) + [ + //If(InVerboseMode(),Tell(" index >= precision ")); + numStr := ConcatStrings(first,".",secnd,"E+",third); + ]; + ] + else if ( index < 0 ) + [ + //If(InVerboseMode(),Tell(" index < 0 ")); + numStr := ConcatStrings(first,".",secnd,"E",third); + ] + else + [ + //If(InVerboseMode(),Tell(" index = 0 ")); + first := "0." ; + secnd := strBI; + numStr := ConcatStrings(first,secnd); + ]; + ] + ); + ans := sgn * ToAtom(numStr); + //If(InVerboseMode(),Tell(" ",ans)); + ans; +]; + +%/mathpiper + + + + + + +%mathpiper_docs,name="RepToNumber",categories="Programmer Functions;Numerical (Arbitrary Precision)" +*CMD RepToNumber --- Given a List representing a number as MathPiper stores it, returns the number +*STD +*CALL + RepToNumber(rep) + +*PARMS + +{rep} -- A list representing MathPiper's internal structure for a number + + +*DESC + +This function returns a Decimal, Integer, or Complex number, when given a data +structure containing MathPiper's internal representation of the number. + +Internally, MathPiper represents {arbitrary precision} numbers as Java BigIntegers or +BigDecimals. Java code handles calculations using such numbers. + +All the information needed to correctly understand the precision attached to a number, +and the rounding and comparison thereof, is contained in the Java structure. + +For a Decimal number (essentially anything with a decimal point), the representation +consists of an arbitrary-precision integer containing {all} the significant digits of +the number, and a {scale factor} telling where the implied decimal point is supposed to +be placed with respect to the end of the integer. The {precision} of the number is +just the number of digits in the integer. + +The three components of the List representing a decimal number are, respectively, +{{BigInteger (unscaled), Precision, ScaleFactor}}. +Note that the second of these is redundent: only the BigInteger and the ScaleFactor +are needed to completely define the number. + +For an Integer number, the integer is its own representation, and again, the number of +its digits gives its precision, but the representation is still a list, with the number +as first component and its precision as second. + +For a Complex number, the representation is a List of Lists, +containing the representations of the Real and Imaginary parts of the number. + +The best way to {consistently} deal with precision and rounding issues is by making use +of the information given by the representation (or "rep" for short).. + +*E.G. +In> RepToNumber({12345678,8,5}) +Result: 123.45678 + +In> RepToNumber({34700,5}) +Result: 34700 + +In> RepToNumber({{150,3,2},{675,3,2}}) +Result: Complex(1.50,6.75) + +In> RepToNumber({12345678,8,15}) +Result: 0.000000012345678 : BETTER WOULD BE 123.45678E-10 + +In> RepToNumber({12345678,8,-5}) +Result: 1234567800000 : BETTER WOULD BE 123.45678E+10 + +*SEE NumberToRep, DumpNumber +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Repunit.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Repunit.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Repunit.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Repunit.mpw 2009-12-29 03:31:25.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="Repunit" + +10 # Repunit(0) <-- 0; +// Number consisting of n 1's +Repunit(n_IsPositiveInteger) <-- +[ + (10^n-1)/9; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RoundToPlace.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RoundToPlace.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RoundToPlace.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RoundToPlace.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,149 @@ +%mathpiper,def="RoundToPlace" + +//Retract("RoundToPlace",*); + +10 # RoundToPlace( N_IsDecimal, place_IsInteger ) <-- +[ + //If(InVerboseMode(),Tell("RoundToPlace_D",{N,place})); + Local(rep,sgn,oldInt,oldPrec,oldScale,oldPlaces,strOInt,LS); + Local(newInt,newScale,newRep,ans); + sgn := Sign(N); + rep := NumberToRep( Abs(N) ); + oldInt := rep[1]; + oldPrec := rep[2]; + oldScale := rep[3]; + oldPlaces:= oldPrec - oldScale; + strOInt := ExpressionToString(oldInt); + LS := Length(strOInt); + //If(InVerboseMode(), + // [ + // Tell(" ",rep); + // Tell(" ",oldInt); + // Tell(" ",strOInt); + // Tell(" ",LS); + // Tell(" ",{place,oldPrec}); + // Tell(" ",oldPlaces); + // ] + //); + If(oldPlaces+place>0, + ans := RoundToPrecision(N,oldPlaces+place), + ans := 0. + ); + ans; +]; + + +15 # RoundToPlace( N_IsInteger, place_IsInteger )_(place <= 0) <-- +[ + //If(InVerboseMode(),Tell("RoundToPlace_I",{N,place})); + Local(oldRep,oldPrec,decN,newDecN,ans); + oldRep := NumberToRep(N); + oldPrec := oldRep[2]; + decN := N*1.0; + newDecN := RoundToPlace( decN, place ); + //If(InVerboseMode(),Tell(" ",oldRep)); + //If(InVerboseMode(),Tell(" ",oldPrec)); + //If(InVerboseMode(),Tell(" ",place)); + //If(InVerboseMode(),Tell(" ",newDecN)); + If( place <= oldPrec, + ans := Round(newDecN), + ans := Round(newDecN*10^(place-oldPrec)) + ); + ans; +]; + + + +20 # RoundToPlace( N_IsComplex, place_IsInteger )_(Not IsInteger(N)) <-- +[ + //If(InVerboseMode(),Tell("RoundToPlace_C",{N,place})); + Local(rr,ii); + rr := Re(N); + ii := Im(N); + Complex(RoundToPlace(rr,place),RoundToPlace(ii,place)); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="RoundToPlace",categories="Programmer Functions;Numerical (Arbitrary Precision)" +*CMD RoundToPlace --- Rounds or Sets a number to the specified "decimal place" +*STD +*CALL + RoundToPlace(number,place) +*PARMS +{number} -- a number (Decimal, Integer, or Complex) whose precision is to be changed +{place} -- the decimal place to which to round + + +*DESC +This function rounds an {arbitrary-precision number} (A.P.N.) to the given +decimal place. The variable {place} is an integer counting from the current +position of the decimal point in {number}. If {place} is positive, the +number will be rounded to the position that many places to the right of +the current decimal point. If {place} is negative, the number will be rounded +to the position that many places to the left of the current decimal point. + +The examples shown below will hopefully clarify the above description. + +See the documentation for the related function {RoundToPrecision} for a +detailed description of the way MathPiper internally represents A.P.N.s. + +NOTE: It is important to recognize the distinction (often misused or misunderstood) +between rounding "to a specified decimal place" (which this function does) and +rounding "to a specified precision", which in MathPiper is accomplished by +the function {RoundToPrecision} (q.v.). + +For Decimal numbers and Decimal Complex numbers, the concept of Rounding to a +given decimal place to the left or right of the current decimal point is well +understood. It makes no sense to try to round further to the left than the first +digit of the number, and this function will return zero if you try. To "round" +further to the right than the last decimal place of the number just adds +trailing zeros. + +For Integers and Complex Integers (Gaussian Integers), the concept of +Rounding to a decimal position {within} the integer (place < 0 ) makes sense, +and will be accomplished by this function. Digits between the rounding digit +and the end of the integer will be replaced by zeros. +However, it makes no sense to try to round an integer to a decimal place +{outside} the integer, and this function will return unevaluated if place > 0. +*E.G. +In> dec:=123.45678 +Result: 123.45678 + +In> dec2:=RoundToPlace(dec,1) +Result: 123.5 + +In> dec3:=RoundToPlace(dec,-1) +Result: 120 + +In> dec3:=RoundToPlace(dec,-4) +Result: 0. + +In> dec3:=RoundToPlace(dec,6) +Result: 123.456780 + +In> int:=12345678 +Result: 12345678 + +In> int2:=RoundToPlace(int,-2) +Result: 12345700 + +In> int2:=RoundToPlace(int,2) +Result: RoundToPlace(12345678,2 +*SEE RoundToPrecision, RoundToN, NumberToRep, DumpNumber +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RoundToPrecision.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RoundToPrecision.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/RoundToPrecision.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/RoundToPrecision.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,217 @@ +%mathpiper,def="RoundToPrecision" + +//Retract("RoundToPrecision",*); + +10 # RoundToPrecision( N_IsDecimal, newPrec_IsPositiveInteger ) <-- +[ + //If(InVerboseMode(),Tell("RoundToPrecision_D",{N,newPrec})); + Local(rep,sgn,oldInt,oldPrec,oldScale,strOInt,LS,BIP0); + Local(newInt,newScale,newRep,ans); + BIP0 := BuiltinPrecisionGet(); + sgn := Sign(N); + rep := NumberToRep( If(sgn<0,-N,N) ); + oldInt := rep[1]; + oldPrec := rep[2]; + oldScale := rep[3]; + If( newPrec > oldPrec, BuiltinPrecisionSet(newPrec) ); + strOInt := ExpressionToString(oldInt); + LS := Length(strOInt); + //If(InVerboseMode(), + // [ + // Tell(" ",rep); + // Tell(" ",oldInt); + // Tell(" ",strOInt); + // Tell(" ",LS); + // Tell(" ",{newPrec,oldPrec}); + // ] + //); + + Local(first,secnd,rem,ad); + if ( newPrec = oldPrec ) + [ ans := N; ] + else if ( newPrec < oldPrec ) + [ + first := StringMidGet(1, newPrec, strOInt); + secnd := StringMidGet(newPrec+1, LS-newPrec, strOInt); + rem := ToAtom(ConcatStrings(".",secnd)); + ad := If(rem>=0.5, 1, 0 ); + newInt := sgn * ( ToAtom(first) + ad ); + newScale := oldScale - ( oldPrec - newPrec ); + newRep := {newInt,newPrec,newScale}; + ans := RepToNumber(newRep); + //If(InVerboseMode(), + // [ + // Tell(" ",{first,secnd}); + // Tell(" ",{rem,ad}); + // Tell(" ",newRep); + // Tell(" ",ans); + // ] + //); + ] + else + [ + //If(InVerboseMode(),Tell(" newPrec > oldPrec ")); + Local(diffPrec); + diffPrec := oldPrec - newPrec; + newInt := sgn * ToAtom(strOInt) * 10^(-diffPrec) ; + newScale := oldScale - diffPrec; + newRep := {newInt,newPrec,newScale}; + //If(InVerboseMode(),[Tell(" ",diffPrec);Tell(" ",newRep);]); + ans := RepToNumber(newRep); + ]; + BuiltinPrecisionSet(BIP0); + ans; +]; + + +15 # RoundToPrecision( N_IsInteger, newPrec_IsPositiveInteger ) <-- +[ + //If(InVerboseMode(),Tell("RoundToPrecision_I",{N,newPrec})); + Local(oldRep,oldPrec,decN,newDecN,ans); + oldRep := NumberToRep(N); + oldPrec := oldRep[2]; + decN := N*1.0; + newDecN := RoundToPrecision( decN, newPrec ); + //If(InVerboseMode(),Tell(" ",oldRep)); + //If(InVerboseMode(),Tell(" ",oldPrec)); + //If(InVerboseMode(),Tell(" ",newPrec)); + //If(InVerboseMode(),Tell(" ",newDecN)); + If( newPrec <= oldPrec, + ans := Round(newDecN), + ans := Round(newDecN*10^(newPrec-oldPrec)) + ); + ans; +]; + + +20 # RoundToPrecision( N_IsComplex, newPrec_IsPositiveInteger ) <-- +[ + //If(InVerboseMode(),Tell("RoundToPrecision_C",{N,newPrec})); + Local(rr,ii); + rr := Re(N); + ii := Im(N); + Complex(RoundToPrecision(rr,newPrec),RoundToPrecision(ii,newPrec)); +]; + +%/mathpiper + + + + + + + + +%mathpiper_docs,name="RoundToPrecision",categories="Programmer Functions;Numerical (Arbitrary Precision)" +*CMD RoundToPrecision --- Rounds or Sets a number to the specified precision +*STD +*CALL + RoundToPrecision(number,precision) +*PARMS +{number} -- a number (Decimal, Integer, or Complex) whose precision is to be changed +{precision} -- the new precision to be used + + +*DESC +This function changes the precision of an {arbitrary-precision number} (A.P.N.). +If the new precision is less than the original precision, the {significand} +will be appropriately rounded. If the new precision is greater than the +original precision, terminal zeros will be appended to the {significand} +and the indicated precision will be reset accordingly. + +Internally, MathPiper represents an A.P.N. as Java a BigIntegers or +BigDecimal. Java code handles calculations using such numbers. + +All the information needed to correctly understand the precision attached to a number, +and the rounding and comparison thereof, is contained in the Java structure. + +For a Decimal number (essentially anything with a decimal point), the representation +consists of an arbitrary-precision integer (called the {significand}) containing {all} +the significant digits of the number, and a {scale factor} telling where the implied +decimal point is supposed to be placed with respect to the end of this integer. +The {precision} of the number is usually just the number of digits in the +{significand}. + +The three components of the List representing a decimal number are, respectively, +{{BigInteger (unscaled), Precision, ScaleFactor}}. +Note that the second of these is redundent: only the BigInteger and the ScaleFactor +are needed to completely define the number. The name 'BigInteger' is Java's +terminology for the {significand}. + +For an Integer number, the integer is its own significand, and again, the number of +its digits gives its precision. The representation is still a list, with the number +as first component and its precision as second. + +For a Complex number, the representation is a List of Lists, +containing the representations of the Real and Imaginary parts of the number. + +The best way to {consistently} deal with precision and rounding issues is by making use +of the information given by the representation (or "rep" for short).. + +NOTE: It is important to recognize the distinction (often misused or misunderstood) +between rounding "to a specified precision" (which this function does) and rounding +"to a specified number of decimal places", which in MathPiper is accomplished by +the function {RoundToPlace} (q.v.). + +For Decimal numbers and Decimal Complex numbers, the concept of Rounding DOWN to a +given precision is well understood, and the concept of Rounding UP is pretty +clear also. + +However, for Integers and Complex Integers (Gaussian Integers), the +concept of Rounding down is somewhat obscure, and the concept of Rounding up +makes very little sense at all. An 8-digit integer, when rounded DOWN to 5 +digits of precision, remains an 8-digit integer still, but the last 3 digits +have become zeros; the original number is still approximated by the new one. +But an 8-digit integer, when rounded UP to 10 digits of precision, has +two trailing zeros appended to it. In the latter case, the new integer is +arguably not any kind of approximation of the old one. + +On the whole, it is probably best NOT to round integers UP. +*E.G. +In> dec:=123.45678 +Result: 123.45678 +In> NumberToRep(dec) +Result: {12345678,8,5} + +In> dec2:=RoundToPrecision(dec,5) +Result: 123.46 +In> NumberToRep(dec2) +Result: {12346,5,2} + +In> dec3:=RoundToPrecision(dec,10) +Result: 123.4567800 +In> NumberToRep(dec3) +Result: {1234567800,10,7} + +In> cmplx:=12.345-I*567.891 +Result: Complex(12.345,-567.891) +In> NumberToRep(cmplx) +Result: {{12345,5,3},{-567891,6,3}} + +In> cmplx2:=RoundToPrecision(cmplx,4) +Result: Complex(12.34,-567.9) +In> NumberToRep(cmplx2) +Result: {{1234,4,2},{-5679,4,1}} + +In> cmplx3:=RoundToPrecision(cmplx,8) +Result: Complex(12.345000,-567.89100) +In> NumberToRep(cmplx3) +Result: {{12345000,8,6},{-56789100,8,5}} + +In> int:=12345678 +Result: 12345678 +In> NumberToRep(int) +Result: {12345678,8} + +In> int2:=RoundToPrecision(int,5) +Result: 12346000 +In> NumberToRep(int2) +Result: {12346000,8} + +In> int3:=RoundToPrecision(int,10) +Result: 1234567800 +In> NumberToRep(int3) +Result: {1234567800,10} +*SEE RoundToPlace, RoundToN, NumberToRep, DumpNumber +%/mathpiper_docs + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/StirlingNumber1.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/StirlingNumber1.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/StirlingNumber1.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/StirlingNumber1.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="StirlingNumber1" + +10 # StirlingNumber1(n_IsInteger,0) <-- If(n=0,1,0); +10 # StirlingNumber1(n_IsInteger,1) <-- (-1)^(n-1)*(n-1)!; +10 # StirlingNumber1(n_IsInteger,2) <-- (-1)^n*(n-1)! * HarmonicNumber(n-1); +10 # StirlingNumber1(n_IsInteger,n-1) <-- -BinomialCoefficient(n,2); +10 # StirlingNumber1(n_IsInteger,3) <-- (-1)^(n-1)*(n-1)! * (HarmonicNumber(n-1)^2 - HarmonicNumber(n-1,2))/2; +20 # StirlingNumber1(n_IsInteger,m_IsInteger) <-- + Sum(k,0,n-m,(-1)^k*BinomialCoefficient(k+n-1,k+n-m)*BinomialCoefficient(2*n-m,n-k-m)*StirlingNumber2(k-m+n,k)); + +%/mathpiper + + + +%mathpiper_docs,name="StirlingNumber1",categories="User Functions;Number Theory" +*CMD StirlingNumber1 --- return the {n m}th Stirling Number of the first kind +*STD +*CALL + StirlingNumber1(n,m) +*PARMS + +{n}, {m} -- positive integers + +*DESC + +This function returns the signed Stirling Number of the first kind. +All Stirling Numbers are integers. If $ m > n $, then {StirlingNumber1} returns +$0$. + +*E.G. + +In> StirlingNumber1(10,5) +Result: -269325; +In> StirlingNumber1(3,6) +Result: 0; + +*SEE StirlingNumber2 +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/StirlingNumber2.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/StirlingNumber2.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/StirlingNumber2.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/StirlingNumber2.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="StirlingNumber2" + +10 # StirlingNumber2(n_IsInteger,0) <-- If(n=0,1,0); +20 # StirlingNumber2(n_IsInteger,k_IsInteger) <-- Sum(i,0,k-1,(-1)^i*BinomialCoefficient(k,i)*(k-i)^n)/ k! ; + +%/mathpiper + + + +%mathpiper_docs,name="StirlingNumber2",categories="User Functions;Number Theory" +*CMD StirlingNumber2 --- return the {n m}th Stirling Number of the second kind +*STD +*CALL + StirlingNumber1(n,m) +*PARMS + +{n}, {m} -- positive integers + +*DESC + +This function returns the Stirling Number of the second kind. +All Stirling Numbers are positive integers. If $ m > n $, then {StirlingNumber2} returns +$0$. + +*E.G. + +In> StirlingNumber2(3,6) +Result: 0; +In> StirlingNumber2(10,4) +Result: 34105; + +*SEE StirlingNumber1 +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Totient.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Totient.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/numbers/Totient.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/numbers/Totient.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,20 @@ +%mathpiper,def="Totient" + +// Algorithm adapted from: +// Elementary Number Theory, David M. Burton +// Theorem 7.3 p139 + +10 # Totient(_n) <-- +[ + Check(IsPositiveInteger(n), "Argument", "Totient: argument must be positive integer"); + Local(i,sum,factors,len); + sum:=n; + factors:=Factors(n); + len:=Length(factors); + For(i:=1,i<=len,i++)[ + sum:=sum*(1-1/factors[i][1]); + ]; + sum; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/odesolver/odesolver.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/odesolver/odesolver.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/odesolver/odesolver.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/odesolver/odesolver.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,382 @@ +%mathpiper,def="OdeSolve;OdeTest;OdeOrder" + +/* def file definitions +OdeSolve +OdeTest +OdeOrder +*/ + +/* + 1) implement more sub-solvers + 2) test code + 3) Done: documentation for OdeSolve and OdeTest + */ + +10 # OdeLeftHandSideEq(_l == _r) <-- (l-r); +20 # OdeLeftHandSideEq(_e) <-- e; + +10 # OdeNormChange(y(n_IsInteger)) <-- ListToFunction({yyy,n}); +20 # OdeNormChange(y) <-- yyy(0); +25 # OdeNormChange(y') <-- yyy(1); +25 # OdeNormChange(y'') <-- yyy(2); +30 # OdeNormChange(_e) <-- e; +OdeNormPred(_e) <-- (e != OdeNormChange(e)); + + +OdeNormalForm(_e) <-- +[ + e := Substitute(OdeLeftHandSideEq(e),"OdeNormPred","OdeNormChange"); +]; + +/*TODO better OdeNormalForm? +OdeNormalForm(_e) <-- +[ + OdeLeftHandSideEq(e) /: + { + y <- yyy(0), + y' <- yyy(1), + y'' <- yyy(2), + y(_n) <- yyy(n) + }; +]; +*/ + +10 # OdeChange(yyy(n_IsInteger)) <-- Apply(yn,{n}); +30 # OdeChange(_e) <-- e; +OdePred(_e) <-- (e != OdeChange(e)); +UnFence("OdeChange",1); +UnFence("OdePred",1); +OdeSubstitute(_e,_yn) <-- +[ + Substitute(e,"OdePred","OdeChange"); +]; +UnFence("OdeSubstitute",2); + +OdeConstantList(n_IsInteger) <-- +[ + Local(result,i); + result:=ZeroVector(n); + For (i:=1,i<=n,i++) result[i]:=UniqueConstant(); + result; +]; + + +Rulebase("OdeTerm",{px,list}); + +/*5 # OdeFlatTerm(_x)_[Echo({x});False;] <-- True; */ + +10# OdeFlatTerm(OdeTerm(_a0,_b0)+OdeTerm(_a1,_b1)) <-- OdeTerm(a0+a1,b0+b1); +10# OdeFlatTerm(OdeTerm(_a0,_b0)-OdeTerm(_a1,_b1)) <-- OdeTerm(a0-a1,b0-b1); +10# OdeFlatTerm(-OdeTerm(_a1,_b1)) <-- OdeTerm(-a1,-b1); +10# OdeFlatTerm(OdeTerm(_a0,_b0)*OdeTerm(_a1,_b1))_ + (IsZeroVector(b0) Or IsZeroVector(b1)) <-- +[ + OdeTerm(a0*a1,a1*b0+a0*b1); +]; + +10# OdeFlatTerm(OdeTerm(_a0,_b0)/OdeTerm(_a1,_b1))_ + (IsZeroVector(b1)) <-- + OdeTerm(a0/a1,b0/a1); + +10# OdeFlatTerm(OdeTerm(_a0,b0_IsZeroVector)^OdeTerm(_a1,b1_IsZeroVector)) <-- + OdeTerm(a0^a1,b0); +15 # OdeFlatTerm(OdeTerm(_a,_b)) <-- OdeTerm(a,b); + +15# OdeFlatTerm(OdeTerm(_a0,_b0)*OdeTerm(_a1,_b1)) <-- OdeTermFail(); +15# OdeFlatTerm(OdeTerm(_a0,b0)^OdeTerm(_a1,b1)) <-- OdeTermFail(); +15# OdeFlatTerm(OdeTerm(_a0,b0)/OdeTerm(_a1,b1)) <-- OdeTermFail(); +20 # OdeFlatTerm(a_IsAtom) <-- OdeTermFail(); + +20 # OdeFlatTerm(_a+_b) <-- OdeFlatTerm(OdeFlatTerm(a) + OdeFlatTerm(b)); +20 # OdeFlatTerm(_a-_b) <-- OdeFlatTerm(OdeFlatTerm(a) - OdeFlatTerm(b)); +20 # OdeFlatTerm(_a*_b) <-- OdeFlatTerm(OdeFlatTerm(a) * OdeFlatTerm(b)); +20 # OdeFlatTerm(_a^_b) <-- OdeFlatTerm(OdeFlatTerm(a) ^ OdeFlatTerm(b)); +20 # OdeFlatTerm(_a/_b) <-- OdeFlatTerm(OdeFlatTerm(a) / OdeFlatTerm(b)); + +OdeMakeTerm(xx_IsAtom) <-- OdeTerm(xx,FillList(0,10)); +OdeMakeTerm(yyy(_n)) <-- OdeTerm(0,BaseVector(n+1,10)); + + +20 # OdeMakeTerm(_xx) <-- OdeTerm(xx,FillList(0,10)); +10 # OdeMakeTermPred(_x+_y) <-- False; +10 # OdeMakeTermPred(_x-_y) <-- False; +10 # OdeMakeTermPred( -_y) <-- False; +10 # OdeMakeTermPred(_x*_y) <-- False; +10 # OdeMakeTermPred(_x/_y) <-- False; +10 # OdeMakeTermPred(_x^_y) <-- False; +20 # OdeMakeTermPred(_rest) <-- True; + + +OdeCoefList(_e) <-- +[ + Substitute(e,"OdeMakeTermPred","OdeMakeTerm"); +]; +OdeTermFail() <-- OdeTerm(Error,FillList(Error,10)); + +// should check if it is linear... +OdeAuxiliaryEquation(_e) <-- +[ + // extra conversion that should be optimized away later + e:=OdeNormalForm(e); + e:=OdeSubstitute(e,{{n},aaa^n*Exp(aaa*x)}); + e:=Subst(Exp(aaa*x),1)e; + Simplify(Subst(aaa,x)e); +]; + +/* Solving a Homogeneous linear differential equation + with real constant coefficients */ +OdeSolveLinearHomogeneousConstantCoefficients(_e) <-- +[ + Local(roots,consts,auxeqn); + + /* Try solution Exp(aaa*x), and divide by Exp(aaa*x), which + * should yield a polynomial in aaa. + e:=OdeSubstitute(e,{{n},aaa^n*Exp(aaa*x)}); + e:=Subst(Exp(aaa*x),1)e; + auxeqn:=Simplify(Subst(aaa,x)e); + e:=auxeqn; + */ + e:=OdeAuxiliaryEquation(e); + auxeqn:=e; + + If(InVerboseMode(), Echo("OdeSolve: Auxiliary Eqn ",auxeqn) ); + + + /* Solve the resulting polynomial */ + e := Apply("RootsWithMultiples",{e}); + e := RemoveDuplicates(e); + + /* Generate dummy constants */ + if( Length(e) > 0 )[ + roots:=Transpose(e); + consts:= MapSingle(Hold({{nn},Add(OdeConstantList(nn)*(x^(0 .. (nn-1))))}),roots[2]); + roots:=roots[1]; + + /* Return results */ + //Sum(consts * Exp(roots*x)); + Add( consts * Exp(roots*x) ); + ] else if ( Degree(auxeqn,x) = 2 ) [ + // we can solve second order equations without RootsWithMultiples + Local(a,b,c,roots); + roots:=ZeroVector(2); + + // this should probably be incorporated into RootsWithMultiples + {c,b,a} := Coef(auxeqn,x,0 .. 2); + + + roots := PSolve(a*x^2+b*x+c,x); + If(InVerboseMode(),Echo("OdeSolve: Roots of quadratic:",roots) ); + + // assuming real coefficients, the roots must come in a complex + // conjugate pair, so we don't have to check both + // also, we don't need to check to repeated root case, because + // RootsWithMultiples (hopefully) catches those, except for + // the case b,c=0 + + if( b=0 And c=0 )[ + Add(OdeConstantList(2)*{1,x}); + ] else if( IsNumber(N(roots[1])) )[ + If(InVerboseMode(),Echo("OdeSolve: Real roots")); + Add(OdeConstantList(2)*{Exp(roots[1]*x),Exp(roots[2]*x)}); + ] else [ + If(InVerboseMode(),Echo("OdeSolve: Complex conjugate pair roots")); + Local(alpha,beta); + alpha:=Re(roots[1]); + beta:=Im(roots[1]); + Exp(alpha*x)*Add( OdeConstantList(2)*{Sin(beta*x),Cos(beta*x)} ); + ]; + + ] else [ + Echo("OdeSolve: Could not find roots of auxilliary equation"); + ]; +]; + +// this croaks on Sin(x)*y'' because OdeMakeTerm does +10 # OdeOrder(_e) <-- [ + Local(h,i,coefs); + + coefs:=ZeroVector(10); //ugly + e:=OdeNormalForm(e); + + If(InVerboseMode(),Echo("OdeSolve: Normal form is",e)); + h:=OdeFlatTerm(OdeCoefList(e)); + If(InVerboseMode(),Echo("OdeSolve: Flatterm is",h)); + + // get the list of coefficients of the derivatives + // in decreasing order + coefs:=Reverse(FunctionToList(h)[3]); + While( First(coefs) = 0 )[ + coefs:=Rest(coefs); + ]; + Length(coefs)-1; +]; + + +10 # OdeSolve(_expr)_(OdeOrder(expr)=0) <-- Echo("OdeSolve: Not a differential equation"); + +// Solve the ever lovable seperable equation + +10 # OdeSolve(y'+_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr-a); +10 # OdeSolve(y'-_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr+a); +10 # OdeSolve(y'/_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr*a); +10 # OdeSolve(_a*y'==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr/a); +10 # OdeSolve(y'*_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr/a); +10 # OdeSolve(_a/y'==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==a/expr); + +// only works for low order equations +10 # OdeSolve(y'==_expr)_(IsFreeOf({y,y',y''},expr)) <-- +[ + If(InVerboseMode(),Echo("OdeSolve: Integral in disguise!")); + If(InVerboseMode(),Echo("OdeSolve: Attempting to integrate ",expr)); + + (Integrate(x) expr)+UniqueConstant(); +]; + +50 # OdeSolve(_e) <-- +[ + Local(h); + e:=OdeNormalForm(e); + If(InVerboseMode(),Echo("OdeSolve: Normal form is",e)); + h:=OdeFlatTerm(OdeCoefList(e)); + If(InVerboseMode(),Echo("OdeSolve: Flatterm is",h)); + if (IsFreeOf(Error,h)) + [ + OdeSolveLinear(e,h); + ] + else + OdeUnsolved(e); +]; + +10 # OdeSolveLinear(_e,OdeTerm(0,_list))_(Length(VarList(list)) = 0) <-- +[ + OdeSolveLinearHomogeneousConstantCoefficients(OdeNormalForm(e)); +]; + +100 # OdeSolveLinear(_e,_ode) <-- OdeUnsolved(e); + +OdeUnsolved(_e) <-- Subst(yyy,y)e; + + + +/* +FT3(_e) <-- +[ + e:=OdeNormalForm(e); +Echo({e}); + e:=OdeCoefList(e); +Echo({e}); + e:=OdeFlatTerm(e); +Echo({e}); + e; +]; +OdeBoundaries(_solution,bounds_IsList) <-- +[ +]; +*/ + +OdeTest(_e,_solution) <-- +[ + Local(s); + s:= `Lambda({n},if (n>0)(Differentiate(x,n)(@solution)) else (@solution)); + e:=OdeNormalForm(e); + e:=Apply("OdeSubstitute",{e,s}); + e:=Simplify(e); + e; +]; + +%/mathpiper + + + +%mathpiper_docs,name="OdeSolve",categories="User Functions;Differential Equations" +*CMD OdeSolve --- general ODE solver +*STD +*CALL + OdeSolve(expr1==expr2) +*PARMS + +{expr1,expr2} -- expressions containing a function to solve for + +*DESC + +This function currently can solve second order homogeneous linear real constant +coefficient equations. The solution is returned with unique constants +generated by {UniqueConstant}. The roots of the auxiliary equation are +used as the arguments of exponentials. If the roots are complex conjugate +pairs, then the solution returned is in the form of exponentials, sines +and cosines. + +First and second derivatives are entered as {y',y''}. Higher order derivatives +may be entered as {y(n)}, where {n} is any integer. + + +*E.G. + +In> OdeSolve( y'' + y == 0 ) +Result: C42*Sin(x)+C43*Cos(x); +In> OdeSolve( 2*y'' + 3*y' + 5*y == 0 ) +Result: Exp(((-3)*x)/4)*(C78*Sin(Sqrt(31/16)*x)+C79*Cos(Sqrt(31/16)*x)); +In> OdeSolve( y'' - 4*y == 0 ) +Result: C132*Exp((-2)*x)+C136*Exp(2*x); +In> OdeSolve( y'' +2*y' + y == 0 ) +Result: (C183+C184*x)*Exp(-x); + +*SEE Solve, RootsWithMultiples +%/mathpiper_docs + + + +%mathpiper_docs,name="OdeTest",categories="User Functions;Differential Equations" +*CMD OdeTest --- test the solution of an ODE +*STD +*CALL + OdeTest(eqn,testsol) +*PARMS + +{eqn} -- equation to test + +{testsol} -- test solution + +*DESC + +This function automates the verification of the solution of an ODE. +It can also be used to quickly see how a particular equation operates +on a function. + +*E.G. + +In> OdeTest(y''+y,Sin(x)+Cos(x)) +Result: 0; +In> OdeTest(y''+2*y,Sin(x)+Cos(x)) +Result: Sin(x)+Cos(x); + +*SEE OdeSolve +%/mathpiper_docs + + + +%mathpiper_docs,name="OdeOrder",categories="User Functions;Differential Equations" +*CMD OdeOrder --- return order of an ODE +*STD +*CALL + OdeOrder(eqn) +*PARMS + +{eqn} -- equation + +*DESC + +This function returns the order of the differential equation, which is +order of the highest derivative. If no derivatives appear, zero is returned. + +*E.G. + +In> OdeOrder(y'' + 2*y' == 0) +Result: 2; +In> OdeOrder(Sin(x)*y(5) + 2*y' == 0) +Result: 5; +In> OdeOrder(2*y + Sin(y) == 0) +Result: 0; + +*SEE OdeSolve +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/orthopoly/orthopoly.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/orthopoly/orthopoly.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/orthopoly/orthopoly.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/orthopoly/orthopoly.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,941 @@ +%mathpiper,def="OrthoP;OrthoG;OrthoH;OrthoL;OrthoT;OrthoU;OrthoPSum;OrthoGSum;OrthoHSum;OrthoLSum;OrthoTSum;OrthoUSum;EvaluateHornerScheme" + +/* def file definitions +OrthoP +OrthoG +OrthoH +OrthoL +OrthoT +OrthoU +OrthoPSum +OrthoGSum +OrthoHSum +OrthoLSum +OrthoTSum +OrthoUSum +EvaluateHornerScheme +*/ + +/* +Orthogonal polynomials +version 1.2 +(Serge Winitzki) + +Polynomials are found from direct recurrence relations. Sums of series of polynomials are found using the Clenshaw-Smith recurrence scheme. + +Reference: Yudell L. Luke. Mathematical functions and their approximations. Academic Press, N. Y., 1975. + +Usage: + The polynomials are evaluated by functions named Ortho*, where * is one of P, G, H, L, T, U. The first argument of these functions is an integer. The series of polynomials are evaluated by functions named Ortho*Sum. The first argument of these functions is a list of coefficients. The last argument is the value x at which the polynomials are to be computed; if x is numerical, a faster routine is used. + + If n is an integer, n>=0, then: + OrthoP(n, x) gives the n-th Legendre polynomial, evaluated on x + OrthoP(n, a, b, x) gives the n-th Jacobi polynomial with parameters a, b, evaluated on x + OrthoG(n, a, x) gives the n-th Gegenbauer polynomial + OrthoH(n, x) gives the n-th Hermite polynomial + OrthoL(n, a, x) gives the n-th Laguerre polynomial + OrthoT(n, x) gives the n-th Tschebyscheff polynomial of the 1st kind + OrthoU(n, x) gives the n-th Tschebyscheff polynomial of the 2nd kind + + If c is a list of coefficients c[1], c[2], ..., c[N], then Ortho*Sum(c, ...) where * is one of P, G, H, L, T, U, computes the sum of a series c[1]*P_0+c[2]*P_1+...+c[N]*P_N, where P_k is the relevant polynomial of k-th order. (For polynomials taking parameters: the parameters must remain constant throughout the summation.) Note that the intermediate polynomials are not evaluated and the recurrence relations are different for this computation, so there may be a numerical difference between Ortho*(c, ...) and computing the sum of the series directly. + + Internal functions that may be useful: + OrthoPolyCoeffs(name_IsString, n_IsInteger, parameters_IsList) returns a list of coefficients of the polynomial. Here "name" must be one of the predefined names: "Jacobi", "Gegenbauer", "Hermite", "Laguerre", "Tscheb1", "Tscheb2"; and "parameters" is a list of extra parameters for the given family of polynomials, e.g. {a,b} for the Jacobi, {a} for Laguerre and {} for Hermite polynomials. + OrthoPolySumCoeffs(name_IsString, c_IsList, parameters_IsList) returns a list of coefficients of the polynomial which is a sum of series with coefficients c. + EvaluateHornerScheme(coefficients, x) returns the Horner-evaluated polynomial on x. The "coefficients" is a list that starts at the lowest power. For example, EvaluateHornerScheme({a,b,c}, x) should return (a+x*(b+x*c)) +*/ + +10 # EvaluateHornerScheme({}, _x) <-- 0; +/* Strictly speaking, the following rule is not needed, but it doesn't hurt */ +10 # EvaluateHornerScheme({_coeffs}, _x) <-- coeffs; +20 # EvaluateHornerScheme(coeffs_IsList, _x) <-- First(coeffs)+x*EvaluateHornerScheme(Rest(coeffs), x); + +/* Plain polynomials */ +// some are computed by general routines, and some are replaced by more efficient routines below +OrthoP(n_IsInteger, _x)_(n>=0) <-- OrthoP(n, 0, 0, x); +OrthoP(n_IsInteger, a_IsRationalOrNumber, b_IsRationalOrNumber, _x)_(n>=0 And a> -1 And b> -1) <-- OrthoPoly("Jacobi", n, {a, b}, x); + +OrthoG(n_IsInteger, a_IsRationalOrNumber, _x)_(n>=0 And a> -1/2) <-- OrthoPoly("Gegenbauer", n, {a}, x); + +OrthoH(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Hermite", n, {}, x); + +OrthoL(n_IsInteger, a_IsRationalOrNumber, _x)_(n>=0 And a> -1) <-- OrthoPoly("Laguerre", n, {a}, x); + +OrthoT(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Tscheb1", n, {}, x); +OrthoU(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Tscheb2", n, {}, x); + +/* Sums of series of orthogonal polynomials */ + +OrthoPSum(c_IsList, _x) <-- OrthoP(c, 0, 0, x); +OrthoPSum(c_IsList, a_IsRationalOrNumber, b_IsRationalOrNumber, _x)_(a> -1 And b> -1) <-- OrthoPolySum("Jacobi", c, {a, b}, x); + +OrthoGSum(c_IsList, a_IsRationalOrNumber, _x)_(a> -1/2) <-- OrthoPolySum("Gegenbauer", c, {a}, x); + +OrthoHSum(c_IsList, _x) <-- OrthoPolySum("Hermite", c, {}, x); + +OrthoLSum(c_IsList, a_IsRationalOrNumber, _x)_(a> -1) <-- OrthoPolySum("Laguerre", c, {a}, x); + +OrthoTSum(c_IsList, _x) <-- OrthoPolySum("Tscheb1", c, {}, x); +OrthoUSum(c_IsList, _x) <-- OrthoPolySum("Tscheb2", c, {}, x); + +/* +Orthogonal polynomials are evaluated using a general routine OrthoPolyCoeffs that generates their coefficients recursively. + +The recurrence relations start with n=0 and n=1 (the n=0 polynomial is always identically 1) and continue for n>=2. Note that the n=1 polynomial is not always given by the n=1 recurrence formula if we assume P_{-1}=0, so the recurrence should be considered undefined at n=1. + + For Legendre/Jacobi polynomials: (a>-1, b>-1) +P(0,a,b,x):=1 +P(1,a,b,x):=(a-b)/2+x*(1+(a+b)/2) +P(n,a,b,x):=(2*n+a+b-1)*(a^2-b^2+x*(2*n+a+b-2)*(2*n+a+b))/(2*n*(n+a+b)*(2*n+a+b-2))*P(n-1,a,b,x)-(n+a-1)*(n+b-1)*(2*n+a+b)/(n*(n+a+b)*(2*n+a+b-2))*P(n-2,a,b,x) + + For Hermite polynomials: +H(0,x):=1 +H(1,x):=2*x +H(n,x):=2*x*H(n-1,x)-2*(n-1)*H(n-2,x) + + For Gegenbauer polynomials: (a>-1/2) +G(0,a,x):=1 +G(1,a,x):=2*a*x +G(n,a,x):=2*(1+(a-1)/n)*x*G(n-1,a,x)-(1+2*(a-2)/n)*G(n-2,a,x) + + For Laguerre polynomials: (a>-1) +L(0,a,x):=1 +L(1,a,x):=a+1-x +L(n,a,x):=(2+(a-1-x)/n)*L(n-1,a,x)-(1+(a-1)/n)*L(n-2,a,x) + + For Tschebycheff polynomials of the first kind: +T(0,x):=1 +T(1,x):=x +T(n,x):=2*x*T(n-1,x)-T(n-2,x) + + For Tschebycheff polynomials of the second kind: +U(0,x):=1 +U(1,x):=2*x +U(n,x):=2*x*U(n-1,x)-U(n-2,x) + +The database "KnownOrthoPoly" contains closures that return coefficients for the recurrence relations of each family of polynomials. KnownOrthoPoly["name"] is a closure that takes two arguments: the order (n) and the extra parameters (p), and returns a list of two lists: the first list contains the coefficients {A,B} of the n=1 polynomial, i.e. "A+B*x"; the second list contains the coefficients {A,B,C} in the recurrence relation, i.e. "P_n = (A+B*x)*P_{n-1}+C*P_{n-2}". (So far there are only 3 coefficients in the second list, i.e. no "C+D*x", but we don't want to be limited.) + +*/ + +LocalSymbols(knownOrthoPoly) [ + knownOrthoPoly := Hold({ + {"Jacobi", {{n, p}, {{(p[1]-p[2])/2, 1+(p[1]+p[2])/2}, {(2*n+p[1]+p[2]-1)*((p[1])^2-(p[2])^2)/(2*n*(n+p[1]+p[2])*(2*n+p[1]+p[2]-2)), (2*n+p[1]+p[2]-1)*(2*n+p[1]+p[2])/(2*n*(n+p[1]+p[2])), -(n+p[1]-1)*(n+p[2]-1)*(2*n+p[1]+p[2])/(n*(n+p[1]+p[2])*(2*n+p[1]+p[2]-2))}}}}, + {"Gegenbauer", {{n, p}, {{0, 2*p[1]}, {0, 2+2*(p[1]-1)/n, -1-2*(p[1]-1)/n}}}}, + {"Laguerre", {{n, p}, {{p[1]+1, -1}, {2+(p[1]-1)/n, -1/n, -1-(p[1]-1)/n}}}}, + {"Hermite", {{n, p}, {{0,2}, {0, 2, -2*(n-1)}}}}, + {"Tscheb1", {{n, p}, {{0,1}, {0,2,-1}}}}, + {"Tscheb2", {{n, p}, {{0,2}, {0,2,-1}}}} + }); + KnownOrthoPoly() := knownOrthoPoly; + +]; // LocalSymbols(knownOrthoPoly) + +/* +For efficiency, polynomials are represented by lists of coefficients rather than by MathPiper expressions. Polynomials are evaluated using the explicit Horner scheme. On numerical arguments, the polynomial coefficients are not computed, only the resulting value. +*/ + +/* +Sums of series of orthogonal polynomials are found using the Clenshaw-Smith recurrence scheme: + If $P_n$ satisfy $P_n = A_n p_{n-1} + B_n p_{n-2}$, $n>=2$, and if $A_1$ is defined so that $P_1 = A_1 P_0$, then $\sum _{n=0}^N c_n P_n = X_0 P_0$, where $X_n$ are found from the following backward recurrence: $X_{N+1} = X_{N+2} = 0$, $X_n = c_n + A_{n+1} X_{n+1} + B_{n+2} X_{n+2}$, $n=N, N-1, ..., 0$. +*/ + +/* Numeric arguments are processed by a faster routine */ + +10 # OrthoPoly(name_IsString, _n, p_IsList, x_IsRationalOrNumber) _ (KnownOrthoPoly()[name] != Empty) <-- OrthoPolyNumeric(name, n, p, x); +20 # OrthoPoly(name_IsString, _n, p_IsList, _x) _ (KnownOrthoPoly()[name] != Empty) <-- EvaluateHornerScheme(OrthoPolyCoeffs(name, n, p), x); + +10 # OrthoPolySum(name_IsString, c_IsList, p_IsList, x_IsRationalOrNumber) _ (KnownOrthoPoly()[name] != Empty) <-- OrthoPolySumNumeric(name, c, p, x); +20 # OrthoPolySum(name_IsString, c_IsList, p_IsList, _x) _ (KnownOrthoPoly()[name] != Empty) <-- EvaluateHornerScheme(OrthoPolySumCoeffs(name, c, p), x); + +/* +OrthoPolyNumeric computes the value of the polynomial from recurrence relations directly. Do not use with non-numeric arguments, except for testing! +*/ +OrthoPolyNumeric(name_IsString, n_IsInteger, p_IsList, _x) <-- [ + Local(value1, value2, value3, ruleCoeffs, index); + value1 := 1; + ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[1]; + value2 := ruleCoeffs[1] + x*ruleCoeffs[2]; + index := 1; + /* value1, value2, value3 is the same as P_{n-2}, P_{n-1}, P_n where n = index */ + While(index=1) [ + ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[2]; + ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; + value3 := (ruleCoeffs[1] + x*ruleCoeffs[2])*value2 + ruleCoeffs1[3]*value1 + c[index+1]; + value1 := value2; + value2 := value3; + index := index - 1; + ]; + /* Last iteration by hand: works correctly also if c has only 1 element */ + ruleCoeffs := Apply(KnownOrthoPoly()[name], {1, p})[1]; + ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {2, p})[2]; + value2 := (ruleCoeffs[1] + x*ruleCoeffs[2])*value2 + ruleCoeffs1[3]*value1 + c[1]; + value2; +]; + +/* +OrthoPolyCoeffs(name, n, p) returns the list of coefficients for orthogonal polynomials, starting with the lowest powers. +*/ + +10 # OrthoPolyCoeffs(name_IsString, 0, p_IsList) <-- {1}; +10 # OrthoPolyCoeffs(name_IsString, 1, p_IsList) <-- Apply(KnownOrthoPoly()[name], {1, p})[1]; + +/* Simple implementation, very slow, for testing only: recursive rule matches, no loops +20 # OrthoPolyCoeffs(name_IsString, n_IsInteger, p_IsList)_(n>1) <-- [ + Local(ruleCoeffs, newCoeffs); + ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[2]; + newCoeffs := OrthoPolyCoeffs(name, n-1, p); + Concat(newCoeffs,{0})*ruleCoeffs[1] + Concat(OrthoPolyCoeffs(name, n-2, p),{0,0})*ruleCoeffs[3] + Concat({0}, newCoeffs)*ruleCoeffs[2]; +]; +*/ + +/* A fast implementation that works directly with lists and saves memory. Same recurrence as in OrthoPolyNumeric() */ +/* note: here we pass "name" instead of "KnownOrthoPoly()[name]" for efficiency, but strictly speaking we don't need to use this global constant */ + +20 # OrthoPolyCoeffs(name_IsString, n_IsInteger, p_IsList)_(n>1) <-- [ + Local(ruleCoeffs, tmpCoeffs, newCoeffs, prevCoeffs, index, jndex, tmptmpCoeffs, prevCoeffsA, newCoeffsA, tmpCoeffsA); + /* For speed, allocate all lists now. Length is n+1 */ + prevCoeffsA := ZeroVector(n+1); + newCoeffsA := ZeroVector(n+1); + tmpCoeffsA := ZeroVector(n+1); + /* pointers to arrays */ + prevCoeffs := prevCoeffsA; + newCoeffs := newCoeffsA; + tmpCoeffs := tmpCoeffsA; + /* Initialize: n=0 and n=1 */ + prevCoeffs[1] := 1; + ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[1]; + newCoeffs[1] := ruleCoeffs[1]; + newCoeffs[2] := ruleCoeffs[2]; + /* Invariant: answer ready in "newCoeffs" at value of index */ + index := 1; + /* main loop */ + While(index < n) [ + index := index + 1; + /* Echo({"index ", index}); */ /* in case this is slow */ + ruleCoeffs := Apply(KnownOrthoPoly()[name], {index, p})[2]; + tmpCoeffs[1] := ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs[3]*prevCoeffs[1]; + /* The polynomial tmpCoeffs must have (index+1) coefficients now */ + For(jndex:=2, jndex <= index, jndex:=jndex+1) [ + tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; + ]; + tmpCoeffs[index+1] := ruleCoeffs[2]*newCoeffs[index]; +/* + prevCoeffs := FlatCopy(newCoeffs); + newCoeffs := FlatCopy(tmpCoeffs); +*/ +/* juggle pointers instead of copying lists */ + tmptmpCoeffs := prevCoeffs; + prevCoeffs := newCoeffs; + newCoeffs := tmpCoeffs; + tmpCoeffs := tmptmpCoeffs; + ]; + newCoeffs; +]; + +/* +OrthoPolySumCoeffs(name, c, p) returns the list of coefficients for the sum of a series of orthogonal polynomials. Same recurrence as in OrthoPolySumNumeric() +*/ + +OrthoPolySumCoeffs(name_IsString, c_IsList, p_IsList) <-- [ + Local(n, ruleCoeffs, ruleCoeffs1, tmpCoeffs, newCoeffs, prevCoeffs, index, jndex, tmptmpCoeffs, prevCoeffsA, newCoeffsA, tmpCoeffsA); + /* n is the max polynomial order we need */ + n := Length(c) - 1; + /* For speed, allocate all lists now. Length is n+1 */ + prevCoeffsA := ZeroVector(n+1); + newCoeffsA := ZeroVector(n+1); + tmpCoeffsA := ZeroVector(n+1); + /* pointers to arrays */ + prevCoeffs := prevCoeffsA; + newCoeffs := newCoeffsA; + tmpCoeffs := tmpCoeffsA; + /* Invariant: answer ready in "newCoeffs" at value of index */ + /* main loop */ + For(index:=n, index >= 1, index:=index-1) [ + /* Echo({"index ", index}); */ /* in case this is slow */ + ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[2]; + ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; + tmpCoeffs[1] := c[index+1] + ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs1[3]*prevCoeffs[1]; + /* The polynomial tmpCoeffs must have (n-index+1) coefficients now */ + For(jndex:=2, jndex <= n-index, jndex:=jndex+1) [ + tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs1[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; + ]; + If(n-index>0, tmpCoeffs[n-index+1] := ruleCoeffs[2]*newCoeffs[n-index]); +/* + prevCoeffs := FlatCopy(newCoeffs); + newCoeffs := FlatCopy(tmpCoeffs); +*/ +/* juggle pointers instead of copying lists */ + tmptmpCoeffs := prevCoeffs; + prevCoeffs := newCoeffs; + newCoeffs := tmpCoeffs; + tmpCoeffs := tmptmpCoeffs; + ]; + /* Last iteration by hand: works correctly also if c has only 1 element */ + index:=0; + ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[1]; + ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; + tmpCoeffs[1] := c[index+1] + ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs1[3]*prevCoeffs[1]; + /* The polynomial tmpCoeffs must have (n-index+1) coefficients now */ + For(jndex:=2, jndex <= n-index, jndex:=jndex+1) [ + tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs1[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; + ]; + tmpCoeffs[n-index+1] := ruleCoeffs[2]*newCoeffs[n-index]; + tmpCoeffs; +]; + +////////////////////////////////////////////////// +/// Very fast computation of Chebyshev polynomials +////////////////////////////////////////////////// +/// (This is not used now because of numerical instability, until I figure out how much to increase the working precision to get P correct digits.) +/// See: W. Koepf. Efficient computation of Chebyshev polynomials in computer algebra (unpublished preprint). Contrary to Koepf's claim (unsupported by any calculation in his paper) that the method is numerically stable, I found unsatisfactory numerical behavior for very large orders. +/// Koepf suggests to use M. Bronstein's algorithm for finding rational solutions of linear ODEs for all other orthogonal polynomials (may be faster than recursion if we want to find the analytic form of the polynomial, but still slower if an explicit formula is available). +////////////////////////////////////////////////// +/// Main formulae: T(2*n,x) = 2*T(n,x)^2-1; T(2*n+1,x) = 2*T(n+1,x)*T(n,x)-x; +/// U(2*n,x) = 2*T(n,x)*U(n,x)-1; T(2*n+1,x) = 2*T(n+1,x)*U(n,x); +/// We avoid recursive calls and build the sequence of bits of n to determine the minimal sequence of n[i] for which T(n[i], x) and U(n[i], x) need to be computed +////////////////////////////////////////////////// +/* +/// This function will return the list of binary bits, e.g. BitList(10) returns {1,0,1,0}. +BitList(n) := BitList(n, {}); +/// This will not be called on very large numbers so it's okay to use recursion +1# BitList(0, _bits) <-- bits; +2# BitList(_n, _bits) <-- BitList(Quotient(n,2), Push(bits, Modulo(n,2))); + +// Tchebyshev polynomials of 1st kind +1 # FastOrthoT(0, _x) <-- 1; +1 # FastOrthoT(1, _x) <-- x; +// Tchebyshev polynomials of 2nd kind +1 # FastOrthoU(0, _x) <-- 1; +1 # FastOrthoU(1, _x) <-- 2*x; + +// guard against user errors +2 # FastOrthoT(_n, _x) _ (IsInteger(n) And n<0) <-- Undefined; +2 # FastOrthoU(_n, _x) _ (IsInteger(n) And n<0) <-- Undefined; + +// make T(), U() of even order more efficient: delegate gruntwork to odd order +2 # FastOrthoT(n_IsEven, _x) <-- 2*FastOrthoT(Quotient(n,2), x)^2-1; +2 # FastOrthoU(n_IsEven, _x) <-- 2*FastOrthoT(Quotient(n,2), x)*FastOrthoU(Quotient(n,2), x)-1; + +// FastOrthoT() of odd order +3 # FastOrthoT(n_IsOdd, _x) <-- +[ + Local(T1, T2, i); + // first bit in the list is always 1, so initialize the pair + T1 := FastOrthoT(1, x); + T2 := FastOrthoT(2, x); + ForEach(i, Rest(BitList(n))) // skip first bit + [ + // if the current bit is 1, we need to double the second index, else double the first index. + // Invariant: n[i+1] = 2*n[i] + BitList[i] and we need to have FastOrthoT(n[i]), FastOrthoT(1+n[i]) as T1, T2. Initially n[1]=1 and after the cycle n[i]=n. + {T1, T2} := If + ( + i=1, + {2*T1*T2-x, 2*T2^2-1}, + {2*T1^2-1, 2*T1*T2-x} + ); + ]; + T1; +]; + +// FastOrthoU() of any order +3 # FastOrthoU(_n, _x) <-- +[ + Local(U1, T1, T2, i); + // first bit in the list is always 1, so initialize the pair + U1 := FastOrthoU(1, x); + T1 := FastOrthoT(1, x); + T2 := FastOrthoT(2, x); + ForEach(i, Rest(BitList(n))) // skip first bit + [ + // if the current bit is 1, we need to double the second index, else double the first index + // Invariant: n[i+1] = 2*n[i] + BitList[i] and we need to have U(n[i]), T(n[i]), T(1+n[i]) as U1, T1, T2. Initially n[1]=1 and after the cycle n[i]=n. + {U1, T1, T2} := If + ( + i=1, + {2*U1*T2, 2*T1*T2-x, 2*T2^2-1}, + {2*U1*T1-1, 2*T1^2-1, 2*T1*T2-x} + ); + ]; + U1; +]; +*/ +////////////////////////////////////////////////// +/// Fast symbolic computation of some polynomials +////////////////////////////////////////////////// + + +////////////////////////////////////////////////// +/// Fast symbolic computation of Legendre polynomials +////////////////////////////////////////////////// + +8# OrthoPolyCoeffs("Jacobi", n_IsInteger, {0,0}) <-- +[ + Local(i, result); + result := ZeroVector(n+1); + result[n+1] := (2*n-1)!! /n!; // coefficient at x^n + i := 1; + While(2*i<=n) + [ // prepare coefficient at x^(n-2*i) now + result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+1)*(n-2*i+2)) / ((2*n-2*i+1)*2*i); + i++; + ]; + result; +]; + +////////////////////////////////////////////////// +/// Fast symbolic computation of Hermite polynomials +////////////////////////////////////////////////// + +OrthoPolyCoeffs("Hermite", n_IsInteger, {}) <-- HermiteCoeffs(n); + +/// Return the list of coefficiets of Hermite polynomials. +HermiteCoeffs(n_IsEven)_(n>0) <-- +[ + Local(i, k, result); + k := Quotient(n,2); + result := ZeroVector(n+1); + result[1] := (-2)^k*(n-1)!!; // coefficient at x^0 + For(i:=1,i<=k,i++) // prepare coefficient at x^(2*i) now + result[2*i+1] := Quotient(-2*result[2*i-1] * (k-i+1), (2*i-1)*i); // this division is always integer but faster with Quotient() + result; +]; +HermiteCoeffs(n_IsOdd)_(n>0) <-- +[ + Local(i, k, result); + k := Quotient(n,2); + result := ZeroVector(n+1); + result[2] := 2*(-2)^k*(n!!); // coefficient at x^1 + For(i:=1,i<=k,i++) // prepare coefficient at x^(2*i+1) now + result[2*i+2] := Quotient(-2*result[2*i] * (k-i+1), i*(2*i+1)); // this division is always integer but faster with Quotient() + result; +]; + +////////////////////////////////////////////////// +/// Fast symbolic computation of Laguerre polynomials +////////////////////////////////////////////////// + +/// Return the list of coefficients of Laguerre polynomials. +OrthoPolyCoeffs("Laguerre", n_IsInteger, {_k}) <-- +[ + Local(i, result); + result := ZeroVector(n+1); + result[n+1] := (-1)^n/n!; // coefficient at x^n + For(i:=n,i>=1,i--) // prepare coefficient at x^(i-1) now + result[i] := -(result[i+1]*i*(k+i))/(n-i+1); + result; +]; + + +////////////////////////////////////////////////// +/// Fast symbolic computation of Chebyshev polynomials +////////////////////////////////////////////////// + +OrthoPolyCoeffs("Tscheb1", n_IsInteger, {}) <-- ChebTCoeffs(n); +OrthoPolyCoeffs("Tscheb2", n_IsInteger, {}) <-- ChebUCoeffs(n); + +1 # ChebTCoeffs(0) <-- {1}; +2 # ChebTCoeffs(n_IsInteger) <-- +[ + Local(i, result); + result := ZeroVector(n+1); + result[n+1] := 2^(n-1); // coefficient at x^n + i := 1; + While(2*i<=n) + [ // prepare coefficient at x^(n-2*i) now + result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+2)*(n-2*i+1)) / ((n-i)*4*i); + i++; + ]; + result; +]; + +1 # ChebUCoeffs(0) <-- {1}; +2 # ChebUCoeffs(n_IsInteger) <-- +[ + Local(i, result); + result := ZeroVector(n+1); + result[n+1] := 2^n; // coefficient at x^n + i := 1; + While(2*i<=n) + [ // prepare coefficient at x^(n-2*i) now + result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+2)*(n-2*i+1)) / ((n-i+1)*4*i); + i++; + ]; + result; +]; + + +%/mathpiper + + + +%mathpiper_docs,name="EvaluateHornerScheme",categories="User Functions;Polynomials (Operations)" +*CMD EvaluateHornerScheme --- fast evaluation of polynomials +*STD +*CALL + EvaluateHornerScheme(coeffs,x) + +*PARMS + +{coeffs} -- a list of coefficients + +{x} -- expression + +*DESC + +This function evaluates a polynomial given as a list of its coefficients, using +the Horner scheme. The list of coefficients starts with the $0$-th power. + +*E.G. + +In> EvaluateHornerScheme({a,b,c,d},x) +Result: a+x*(b+x*(c+x*d)); + +*SEE Horner +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoP",categories="User Functions;Polynomials (Special)" +*CMD OrthoP --- Legendre and Jacobi orthogonal polynomials +*STD +*CALL + OrthoP(n, x); + OrthoP(n, a, b, x); + +*PARMS + +{n} -- degree of polynomial + +{x} -- point to evaluate polynomial at + +{a}, {b} -- parameters for Jacobi polynomial + +*DESC + +The first calling format with two arguments evaluates the Legendre polynomial +of degree {n} at the point {x}. The second form does the same for the Jacobi +polynomial with parameters {a} and {b}, which should be both greater than -1. + +The Jacobi polynomials are orthogonal with respect to the weight +function $(1-x)^a *(1+x)^b$ on the interval [-1,1]. They satisfy the +recurrence relation +$$P(n,a,b,x) = (2*n+a+b-1)/(2*n+a+b-2) $$* +$$ ((a^2-b^2+x*(2*n+a+b-2)*(n+a+b))/(2*n*(n+a+b))) * P(n-1,a,b,x)$$ +$$ - ((n+a-1)*(n+b-1)*(2*n+a+b))/(n*(n+a+b)*(2*n+a+b-2))*P(n-2,a,b,x)$$ +for $n > 1$, with +$P(0,a,b,x) = 1$, +$$P(1,a,b,x) = (a-b)/2+x*(1+(a+b)/2)$$. + +*REM (old versions of the equations:) +// P(0,a,b,x) = 1, +// +// a - b / a + b \ +// P(1,a,b,x) = ----- + x | 1 + ----- | , +// 2 \ 2 / +// +// +// +// P(n,a,b,x) = (2n + a + b - 1) * +// +// +// 2 2 +// a - b + x (2n+a+b-2) (n+a+b) +// ---------------------------- P(n-1,a,b,x) +// 2n (2n+a+b-2) (n+a+b) +// +// (n+a-1) (n+b-1) (2n+a+b) +// - ------------------------ P(n-2,a,b,x) +// n (n+a+b) (2n+a+b-2) + +Legendre polynomials are a special case of Jacobi polynomials with the +specific parameter values $a = b = 0$. So they form an orthogonal system +with respect to the weight function identically equal to 1 on the +interval [-1,1], and they satisfy the recurrence relation +$$ P(n,x)=((2*n-1)*x/(2*n))*P(n-1,x)-(n-1)/n*P(n-2,x) $$ +for $n > 1$, with +$ P(0,x)=1 $, +$ P(1,x)=x $. + +*REM +// P(0,x) = 1 +// +// P(1,x) = x +// +// (2n - 1) x n - 1 +// P(n,x) = ---------- P(n-1,x) - ----- P(n-2,x), +// 2n n + +Most of the work is performed by the internal function {OrthoPoly}. + +*E.G. + +In> PrettyPrinterSet("PrettyForm"); + + True + +In> OrthoP(3, x); + + / 2 \ + | 5 * x 3 | + x * | ------ - - | + \ 2 2 / + +In> OrthoP(3, 1, 2, x); + + 1 / / 21 * x 7 \ 7 \ + - + x * | x * | ------ - - | - - | + 2 \ \ 2 2 / 2 / + +In> Expand(%) + + 3 2 + 21 * x - 7 * x - 7 * x + 1 + ---------------------------- + 2 + +In> OrthoP(3, 1, 2, 0.5); + + -0.8124999999 + + +*SEE OrthoPSum, OrthoG, OrthoPoly +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoH",categories="User Functions;Polynomials (Special)" +*CMD OrthoH --- Hermite orthogonal polynomials +*STD +*CALL + OrthoH(n, x); + +*PARMS + +{n} -- degree of polynomial + +{x} -- point to evaluate polynomial at + +*DESC + +This function evaluates the Hermite polynomial of degree {n} at the +point {x}. + +The Hermite polynomials are orthogonal with respect to the weight +function $Exp(-x^2/2)$ on the entire real axis. They satisfy the +recurrence relation +$$ H(n,x) = 2*x*H(n-1,x) - 2*(n-1)*H(n-2,x) $$ +for $n > 1$, with +$H(0,x) = 1$, +$H(1,x) = 2*x$. + +Most of the work is performed by the internal function {OrthoPoly}. + +*E.G. + +In> OrthoH(3, x); +Result: x*(8*x^2-12); +In> OrthoH(6, 0.5); +Result: 31; + +*SEE OrthoHSum, OrthoPoly +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoG",categories="User Functions;Polynomials (Special)" +*CMD OrthoG --- Gegenbauer orthogonal polynomials +*STD +*CALL + OrthoG(n, a, x); + +*PARMS + +{n} -- degree of polynomial + +{a} -- parameter + +{x} -- point to evaluate polynomial at + +*DESC + +This function evaluates the Gegenbauer (or ultraspherical) polynomial +with parameter {a} and degree {n} at the point {x}. The +parameter {a} should be greater than -1/2. + +The Gegenbauer polynomials are orthogonal with respect to the weight +function $(1-x^2)^(a-1/2)$ on the interval [-1,1]. Hence they are +connected to the Jacobi polynomials via +$$ G(n, a, x) = P(n, a-1/2, a-1/2, x) $$. +They satisfy the recurrence relation +$$ G(n,a,x) = 2*(1+(a-1)/n)*x*G(n-1,a,x) $$ +$$ -(1+2*(a-2)/n)*G(n-2,a,x) $$ +for $n>1$, with +$G(0,a,x) = 1$, +$G(1,a,x) = 2*x$. + +*REM +// / a - 1 \ +// G(n,a,x) = 2 | 1 + ----- | x G(n-1,a,x) +// \ n / +// +// / 2 (a-2) \ +// - | 1 + ------- | G(n-2,a,x), +// \ n / + +Most of the work is performed by the internal function {OrthoPoly}. + +*E.G. + +In> OrthoG(5, 1, x); +Result: x*((32*x^2-32)*x^2+6); +In> OrthoG(5, 2, -0.5); +Result: 2; + +*SEE OrthoP, OrthoT, OrthoU, OrthoGSum, OrthoPoly +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoL",categories="User Functions;Polynomials (Special)" +*CMD OrthoL --- Laguerre orthogonal polynomials +*STD +*CALL + OrthoL(n, a, x); + +*PARMS + +{n} -- degree of polynomial + +{a} -- parameter + +{x} -- point to evaluate polynomial at + +*DESC + +This function evaluates the Laguerre polynomial with parameter {a} +and degree {n} at the point {x}. The parameter {a} should be +greater than -1. + +The Laguerre polynomials are orthogonal with respect to the weight +function $x^a * Exp(-x)$ on the positive real axis. They satisfy the +recurrence relation +$$ L(n,a,x) = (2+(a-1-x)/n)* L(n-1,a,x) $$ +$$ -(1-(a-1)/n)*L(n-2,a,x) $$ +for $n>1$, with +$L(0,a,x) = 1$, +$L(1,a,x) = a + 1 - x$. + +*REM +// / a - 1 - x \ +// L(n,a,x) = | 2 + --------- | L(n-1,a,x) - +// \ n / +// +// / a - 1 \ +// | 1 + ----- | L(n-2,a,x), +// \ n / + + +Most of the work is performed by the internal function {OrthoPoly}. + +*E.G. + +In> OrthoL(3, 1, x); +Result: x*(x*(2-x/6)-6)+4; +In> OrthoL(3, 1/2, 0.25); +Result: 1.2005208334; + +*SEE OrthoLSum, OrthoPoly +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoT;OrthoU",categories="User Functions;Polynomials (Special)" +*CMD OrthoT --- Chebyshev polynomials +*CMD OrthoU --- Chebyshev polynomials +*STD +*CALL + OrthoT(n, x); + OrthoU(n, x); + +*PARMS + +{n} -- degree of polynomial + +{x} -- point to evaluate polynomial at + +*DESC + +These functions evaluate the Chebyshev polynomials of the first kind +$T(n,x)$ and of the second kind $U(n,x)$, of degree "n" at the point "x". (The +name of this Russian mathematician is also sometimes spelled "Tschebyscheff".) + +The Chebyshev polynomials are orthogonal with respect to the weight +function $(1-x^2)^(-1/2)$. Hence they are a special case of the Gegenbauer +polynomials $G(n,a,x)$, with $a=0$. They satisfy the recurrence relations +$$ T(n,x) = 2* x* T(n-1,x) - T(n-2,x) $$, +$$ U(n,x) = 2* x* U(n-1,x) - U(n-2,x) $$ +for $n > 1$, with +$T(0,x) = 1$, +$T(1,x) = x$, +$U(0,x) = 1$, +$U(1,x) = 2*x$. + + +*E.G. + +In> OrthoT(3, x); +Result: 2*x*(2*x^2-1)-x; +In> OrthoT(10, 0.9); +Result: -0.2007474688; +In> OrthoU(3, x); +Result: 4*x*(2*x^2-1); +In> OrthoU(10, 0.9); +Result: -2.2234571776; + + +*SEE OrthoG, OrthoTSum, OrthoUSum, OrthoPoly +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoPSum;OrthoHSum;OrthoLSum;OrthoGSum;OrthoTSum;OrthoUSum",categories="User Functions;Polynomials (Special)" +*CMD OrthoPSum --- sums of series of orthogonal polynomials +*CMD OrthoHSum --- sums of series of orthogonal polynomials +*CMD OrthoLSum --- sums of series of orthogonal polynomials +*CMD OrthoGSum --- sums of series of orthogonal polynomials +*CMD OrthoTSum --- sums of series of orthogonal polynomials +*CMD OrthoUSum --- sums of series of orthogonal polynomials +*STD +*CALL + OrthoPSum(c, x); + OrthoPSum(c, a, b, x); + OrthoHSum(c, x); + OrthoLSum(c, a, x); + OrthoGSum(c, a, x); + OrthoTSum(c, x); + OrthoUSum(c, x); + +*PARMS + +{c} -- list of coefficients + +{a}, {b} -- parameters of specific polynomials + +{x} -- point to evaluate polynomial at + +*DESC + +These functions evaluate the sum of series of orthogonal polynomials at the point {x}, with given list of coefficients {c} of the series and fixed polynomial parameters {a}, {b} (if applicable). + +The list of coefficients starts with the lowest order, so that for example +OrthoLSum(c, a, x) = c[1] L[0](a,x) + c[2] L[1](a,x) + ... + c[N] L[N-1](a,x). + +See pages for specific orthogonal polynomials for more details on the parameters of the polynomials. + +Most of the work is performed by the internal function {OrthoPolySum}. The individual polynomials entering the series are not computed, only the sum of the series. + +*E.G. + +In> Expand(OrthoPSum({1,0,0,1/7,1/8}, 3/2, \ + 2/3, x)); +Result: (7068985*x^4)/3981312+(1648577*x^3)/995328+ + (-3502049*x^2)/4644864+(-4372969*x)/6967296 + +28292143/27869184; + +*SEE OrthoP, OrthoG, OrthoH, OrthoL, OrthoT, OrthoU, OrthoPolySum +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoPoly",categories="User Functions;Polynomials (Special)" +*CMD OrthoPoly --- internal function for constructing orthogonal polynomials +*STD +*CALL + OrthoPoly(name, n, par, x) + +*PARMS + +{name} -- string containing name of orthogonal family + +{n} -- degree of the polynomial + +{par} -- list of values for the parameters + +{x} -- point to evaluate at + +*DESC + +This function is used internally to construct orthogonal +polynomials. It returns the {n}-th polynomial from the family +{name} with parameters {par} at the point {x}. + +All known families are stored in the association list returned by the function {KnownOrthoPoly()}. The name serves as key. At the moment +the following names are known to MathPiper: {"Jacobi"}, {"Gegenbauer"}, {"Laguerre"}, {"Hermite"}, {"Tscheb1"}, +and {"Tscheb2"}. The value associated to the key +is a pure function that takes two arguments: the order {n} and the +extra parameters {p}, and returns a list of two lists: the first list +contains the coefficients {A,B} of the n=1 polynomial, i.e. $A+B*x$; +the second list contains the coefficients {A,B,C} in the recurrence +relation, i.e. $P[n] = (A+B*x)*P[n-1]+C*P[n-2]$. (There are +only 3 coefficients in the second list, because none of the polynomials use $C+D*x$ instead of $C$ in the recurrence relation. This is assumed in the implementation!) + +If the argument {x} is numerical, the function {OrthoPolyNumeric} is called. Otherwise, the function {OrthoPolyCoeffs} computes a list of coefficients, and +{EvaluateHornerScheme} converts this list into a +polynomial expression. + +*SEE OrthoP, OrthoG, OrthoH, OrthoL, OrthoT, OrthoU, OrthoPolySum +%/mathpiper_docs + + + +%mathpiper_docs,name="OrthoPolySum",categories="User Functions;Polynomials (Special)" +*CMD OrthoPolySum --- internal function for computing series of orthogonal polynomials +*STD +*CALL + OrthoPolySum(name, c, par, x) + +*PARMS + +{name} -- string containing name of orthogonal family + +{c} -- list of coefficients + +{par} -- list of values for the parameters + +{x} -- point to evaluate at + +*DESC + +This function is used internally to compute series of orthogonal polynomials. +It is similar to the function {OrthoPoly} and returns the result of the +summation of series of polynomials from the family {name} with parameters {par} +at the point {x}, where {c} is the list of coefficients of the series. + +The algorithm used to compute the series without first computing the individual polynomials is the Clenshaw-Smith recurrence scheme. +(See the algorithms book for explanations.) + +If the argument {x} is numerical, the function {OrthoPolySumNumeric} is called. +Otherwise, the function {OrthoPolySumCoeffs} computes the list of coefficients +of the resulting polynomial, and {EvaluateHornerScheme} converts this list into +a polynomial expression. + +*SEE OrthoPSum, OrthoGSum, OrthoHSum, OrthoLSum, OrthoTSum, OrthoUSum, OrthoPoly +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/CForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/CForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/CForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/CForm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,264 @@ +%mathpiper,def="CForm" + +/* CForm: convert MathPiper objects to C/C++ code. */ + +/* version 0.3 */ + +/* Changelog + 0.1 CForm() derived from TeXForm() v0.4. Have basic functionality. Do not allow list manipulation, unevaluated derivatives, set operations, limits, integrals, Infinity, explicit matrices. Complex numbers and expressions are handled just like real ones. Indexed symbols are assumed to be arrays and handled literally. No declarations or prototypes are supplied. Function definitions are not handled. Sum() is left as is (can be defined as a C function). + 0.2 Fix for extra parens in Sin() and other functions; fixes for Exp(), Abs() and inverse trig functions + 0.3 Fix for indexed expressions: support a[2][3][4] + 0.3.1 Fix for CForm(integer): add a decimal point + 0.4 Support While()[]. Added IsCFormable. Use Concat() instead of Union() on lists. + 0.4.1 Support False, True + 0.4.2 Changed it so that integers are not coerced to floats any more automatically (one can coerce integers to floats manually nowadays by adding a decimal point to the string representation, eg. 1. instead of 1). +*/ + +/* To do: + 0. Find and fix bugs. + 1. Chop strings that are longer than 80 chars? + 2. Optimization of C code? +*/ + +Rulebase("CForm",{expression}); +Rulebase("CForm",{expression, precedence}); + +Function ("CFormBracketIf", {predicate, string}) +[ + Check(IsBoolean(predicate) And IsString(string), "Argument", "CForm internal error: non-boolean and/or non-string argument of CFormBracketIf"); + If(predicate, ConcatStrings("( ", string, ") "), string); +]; + +CFormDoublePrecisionNumber(x_IsNumber) <-- +[ + Local(i,n,s,f); + s := ToString(x); + n := Length(s); + f := False; + For(i := 1, i <= n, i++) + [ + If(s[i] = "e" Or s[i] = ".", f := True); + ]; + If(f, s, s : "."); +]; + +/* Proceed just like TeXForm() +*/ + +// CFormMaxPrec should perhaps only be used from within this file, it is thus not in the .def file. +CFormMaxPrec() := 60000; /* This precedence will never be bracketed. It is equal to KMaxPrec */ + +100 # CForm(_x) <-- CForm(x, CFormMaxPrec()); + +/* Replace numbers and variables -- never bracketed except explicitly */ +110 # CForm(x_IsInteger, _p) <-- ToString(x); +111 # CForm(x_IsZero, _p) <-- "0."; +112 # CForm(x_IsNumber, _p) <-- CFormDoublePrecisionNumber(x); +/* Variables are left as is, except some special ones */ +190 # CForm(False, _p) <-- "false"; +190 # CForm(True, _p) <-- "true"; +200 # CForm(x_IsAtom, _p) <-- ToString(x); + +/* Strings must be quoted but not bracketed */ +100 # CForm(x_IsString, _p) <-- ConcatStrings("\"", x, "\""); + +/* Replace operations */ + +/* arithmetic */ + +/* addition, subtraction, multiplication, all comparison and logical operations are "regular" */ + + +LocalSymbols(cformRegularOps) [ + cformRegularOps := { {"+"," + "}, {"-"," - "}, {"*"," * "}, + {"/"," / "}, {":="," = "}, {"=="," == "}, + {"="," == "}, {"!="," != "}, {"<="," <= "}, + {">="," >= "}, {"<"," < "}, {">"," > "}, + {"And"," && "}, {"Or"," || "}, {">>", " >> "}, + { "<<", " << " }, { "&", " & " }, { "|", " | " }, + { "%", " % " }, { "^", " ^ " }, + }; + + CFormRegularOps() := cformRegularOps; +]; // LocalSymbols(cformRegularOps) + + /* This is the template for "regular" binary infix operators: +100 # CForm(_x + _y, _p) <-- CFormBracketIf(p CForm(Sin(a1)+2*Cos(b1)); +Result: "sin(a1) + 2 * cos(b1)"; + +*SEE PrettyForm, TeXForm, IsCFormable +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/IsCFormable.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/IsCFormable.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/IsCFormable.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/IsCFormable.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,98 @@ +%mathpiper,def="IsCFormable" + +////////////////////////////////////////////////// +/// IsCFormable +////////////////////////////////////////////////// + +LocalSymbols(CFormAllFunctions) [ + + /// predicate to test whether an expression can be successfully exported to C code + + /// interface with empty extra function list + // need the backquote stuff b/c we have HoldArgument now + IsCFormable(_expr) <-- `IsCFormable(@expr, {}); + + // need to check that expr contains only allowed functions + IsCFormable(_expr, funclist_IsList) <-- + [ + Local(bad'functions); + bad'functions := Difference(`FuncList(@expr), Concat(CFormAllFunctions, funclist)); + If(Length(bad'functions)=0, + True, + [ + If(InVerboseMode(), + Echo(Concat({"IsCFormable: Info: unexportable function(s): "}, bad'functions)) + ); + False; + ] + ); + ]; + HoldArgumentNumber("IsCFormable", 1, 1); + HoldArgumentNumber("IsCFormable", 2, 1); + + /// This is a list of all function atoms which CForm can safely handle + CFormAllFunctions := MapSingle(ToAtom, Concat(AssocIndices(CFormMathFunctions()), AssocIndices(CFormRegularOps()), + // list of "other" (non-math) functions supported by CForm: needs to be updated when CForm is extended to handle new functions + { + "For", + "While", + "Prog", + "Nth", + "Modulo", + "Complex", + "if", + "else", + "++", + "--", + } + )); + + +]; // LocalSymbols(CFormAllFunctions) + +%/mathpiper + + + +%mathpiper_docs,name="IsCFormable",categories="User Functions;Input/Output;Predicates" +*CMD IsCFormable --- check possibility to export expression to C++ code +*STD +*CALL + IsCFormable(expr) + IsCFormable(expr, funclist) + +*PARMS + +{expr} -- expression to be exported (this argument is not evaluated) + +{funclist} -- list of "allowed" function atoms + +*DESC + +{IsCFormable} returns {True} if the MathPiper expression {expr} can be exported +into C++ code. This is a check whether the C++ exporter {CForm} can be safely +used on the expression. + +A MathPiper expression is considered exportable if it contains only functions that can be translated into C++ (e.g. {ListToFunction} cannot be exported). All variables and constants are considered exportable. + +The verbose option prints names of functions that are not exportable. + +The second calling format of {IsCFormable} can be used to "allow" certain function names that will be available in the C++ code. + +*E.G. notest + +In> IsCFormable(Sin(a1)+2*Cos(b1)) +Result: True; +In> V(IsCFormable(1+func123(b1))) + IsCFormable: Info: unexportable function(s): + func123 +Result: False; +This returned {False} because the function {func123} is not available in C++. We can +explicitly allow this function and then the expression will be considered +exportable: + +In> IsCFormable(1+func123(b1), {func123}) +Result: True; + +*SEE CForm, V +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/openmath.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/openmath.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/openmath.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/openmath.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,944 @@ +%mathpiper,def="OMREP;OMDef;OMForm;OMRead;OMParse;OMEcho;OMEchoEscape" + +/* def file definitions +OMREP +OMDef +OMForm +OMRead +OMParse +OMEcho +OMEchoEscape +*/ + +//////////////////////// +// Written by Alberto González Palomo and Ayal Pinkus. +//////////////////////// + +/* The read-eval-print loop */ +/* It can take one parameter, that is the evaluation count. If it is greater + than zero, only that number of iterations will be performed before + exiting. This is particularly useful when connecting to MathPiper via pipes. +*/ +Rulebase("OMREP",{}); +Rule("OMREP",0,1,True) +[ + OMREP(0);// 0 means keep repeating, as usual. +]; +Rulebase("OMREP",{count}); +LocalSymbols(input,stringOut,result) +Rule("OMREP",1,1,True) +[ + Local(input,stringOut,result); + While(Not(IsExitRequested())) + [ + Bind(errorObject, False); + ExceptionCatch(Bind(input, PipeFromString(ConcatStrings(ReadCmdLineString("")," "))OMRead()), Bind(errorObject,OMGetCoreError())); + + If(Not(errorObject = False), errorObject); //todo:tk:check this code. + + If (Not(IsExitRequested()) And errorObject = False, + [ + Bind(stringOut,""); + Bind(result,False); + ExceptionCatch(Bind(stringOut,PipeToString()[Secure(Bind(result,Eval(input)));]), Bind(errorObject,OMGetCoreError())); + + If(Not(errorObject = False), errorObject); //todo:tk:check this code. + + If(Not(stringOut = ""), WriteString(stringOut)); + SetGlobalLazyVariable(%,result); + If(PrettyPrinterGet()="", + [ + Apply("OMForm",{result}); + ], + Apply(PrettyPrinterGet(),{result})); + If(count > 0 And (count:=count-1) = 0, Exit()); + ]); + ]; +]; + + +LocalSymbols(omindent) [ + // Function definitions + OMIndent() := [omindent := omindent + 2;]; + OMUndent() := [omindent := omindent - 2;]; + OMClearIndent() := [omindent := 0;]; + OMIndentSpace() := Space(omindent); + + // Initialization of indentation + OMClearIndent(); +]; // LocalSymbols(omindent) + +/////////////////////////////////////////////////////////////////////// +// Output + +10 # OMForm(_expression) + <-- + [ + OMClearIndent(); + OMEcho(""); + OMIndent(); + If(IsAtom(expression), + If(expression = ToAtom("%"), + Secure(expression := Eval(expression)) + ) + ); + OMFormExpression(expression); + OMUndent(); + OMEcho(""); + ]; + +10 # OMFormExpression(i_IsString) <-- OMEcho("":i:""); +11 # OMFormExpression(i_IsInteger) <-- OMEcho("":ToString(i):""); +12 # OMFormExpression(i_IsNumber) <-- OMEcho(""); +13 # OMFormExpression(i_IsConstant)_(OMSymbol()[ ToString(i) ] != Empty) + <-- OMEcho("" + ); +14 # OMFormExpression(i_IsConstant)// Should we rather evaluate it? + <-- OMEcho(""); +15 # OMFormExpression(i_IsVariable)_(OMSymbol()[ ToString(i) ] != Empty) + <-- OMEcho("" + ); +16 # OMFormExpression(i_IsVariable) + <-- OMEcho(""); +16 # OMFormExpression(i_IsVariable)_(i = Empty) + <-- False; // This is useful for void expressions. + +10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMError") + <-- + [ + Local(cd, name); + If(IsList(function[1]), + [ cd := function[1][1]; name := function[1][2]; ], + [ cd := "error"; name := function[1]; ]); + OMEcho(""); + OMIndent(); + OMEcho(""); + ForEach(i, Rest(function)) OMFormExpression(i); + OMUndent(); + OMEcho(""); + ]; +10 # OMFormExpression(function_IsFunction)_(Type(function) = "OME") + <-- + [ + OMEcho(""); + OMIndent(); + ForEach(i, function) OMFormExpression(i); + OMUndent(); + OMEcho(""); + ]; +10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMS") + <-- OMEcho(""); +10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMBIND") + <-- + [ + OMEcho(""); + OMIndent(); + ForEach(i, function) OMFormExpression(i); + OMUndent(); + OMEcho(""); + ]; +10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMBVAR") + <-- + [ + OMEcho(""); + OMIndent(); + ForEach(i, function) OMFormExpression(i); + OMUndent(); + OMEcho(""); + ]; +10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMA") + <-- + [ + // This is not the same as the next rule: this is OMA(a,b,c,...), + // which is used for building OMA constructs in the mapping to OM. + OMEcho(""); + OMIndent(); + ForEach(i, function) OMFormExpression(i); + OMUndent(); + OMEcho(""); + ]; +11 # OMFormExpression(function_IsFunction) + <-- + [ + OMEcho(""); + OMIndent(); + OMFormFunction(function); + OMUndent(); + OMEcho(""); + ]; + +11 # OMFormFunction(function_IsFunction) + <-- + [ + Local(arity); + arity := Length(function); + OMEcho(""); + If(arity > 0, ForEach(arg, function) OMFormExpression(arg)); + ]; +10 # OMFormFunction(function_IsFunction)_(OMSymbol()[ Type(function) ] != Empty) + <-- + [ + Local(symbolDef); + // [20051016 AGP] The "signature" feature is an old attempt at pattern + // matching, but now that we have real predicates in the mappings it's + // probably obsolete. I'll think about removing it. + symbolDef := OMSymbol()[ OMSignature(function) ]; + If(symbolDef = Empty, symbolDef := OMSymbol()[ Type(function) ] ); + If(symbolDef = Empty Or Length(symbolDef) < 3 Or symbolDef[3] = {}, + [ + OMEcho(""); + ForEach(arg, function) OMFormExpression(arg); + ], + [ + Local(result); + result := OMApplyMapping(function, symbolDef[3]); + //Check(IsList(result), "Return Type", PipeToString()Echo("Mapping result is not a list: ", result)); + If(IsList(result), + [ + result := ListToFunction(Subst($, function[0]) result); + OMFormExpression(result[0]); + ForEach(i, result) OMFormExpression(i); + ], + If(result = Empty, + Echo("No rule matched ", function, symbolDef[3]), + Echo("Unexpected result value from OMApplyMapping(): ", result) + ) + ); + ] + ); + ]; + + +OMWrite(_expression) <-- +[ + Write(expression); +]; + +OMEcho(_expression) <-- +[ + OMIndentSpace(); + Write(expression); + NewLine(); +]; +OMEcho(expression_IsString) <-- +[ + OMIndentSpace(); + WriteString(expression); + NewLine(); +]; +OMEcho(expression_IsList) <-- +[ + ForEach(arg, expression) + [ + If (IsString(arg), WriteString(arg), Write(arg)); + ]; + NewLine(); +]; + +OMEscape(_expression) <-- +[ + ""; +]; +OMEscapeString(_expression_IsString) <-- +[ + ""; +]; +OMWriteEscape(_expression) <-- +[ + WriteString(OMEscape(expression)); +]; +OMWriteStringEscape(expression_IsString) <-- +[ + WriteString(OMEscapeString(expression)); +]; +OMEchoEscape(_expression) <-- +[ + OMWriteEscape(expression); + NewLine(); +]; +OMEchoEscape(expression_IsString) <-- +[ + OMWriteStringEscape(expression); + NewLine(); +]; +OMEchoEscape(expression_IsList) <-- +[ + WriteString(""); + NewLine(); +]; + + +HoldArgumentNumber("OMForm",1,1); +//HoldArgumentNumber("OMFormExpression",1,1); +//HoldArgumentNumber("OMFormFunction",1,1); + + +OMSignature(_function) <-- ""; +OMSignature(function_IsFunction) <-- +[ + Local(makeSig); + makeSig := {ConcatStrings, Type(function), "_"}; + Local(type); + type := "";// If "function" doesn't have parameters, the signature is "f_". + ForEach(arg, function) + [ + If(Type(arg) = "List", + type := "L", + If(IsFunction(arg), + type := "F", + If(IsInteger(arg), + type := "I", + type := "V" + ) + ) + ); + DestructiveAppend(makeSig, type); + ]; + Secure(Eval(ListToFunction(makeSig))); +]; +HoldArgumentNumber("OMSignature", 1, 1); + + + +/////////////////////////////////////////////////////////////////////// +// Input + +// Troubleshooting guide: +// "encodingError:unexpected closing brace": this happens in the ReadOMOBJ +// rules. It means that you forgot to call OMNextToken() from your rule. + +LocalSymbols(omtoken) [ + OMNextToken() := + [ + omtoken := XmlExplodeTag(ToString(ReadToken())); + ]; + OMToken() := omtoken; +]; // LocalSymbols(omtoken) + +OMRead():= +[ + Local(result); + ExceptionCatch( + [ + XmlTokenizer(); + OMNextToken(); + result := MatchOMOBJ(OMToken()); + DefaultTokenizer(); + ], + [ + result := OMGetCoreError(); + DefaultTokenizer(); + ]); + result; +]; + + +OMDump(str):= +PipeFromString(str:" EndOfFile") +[ + Local(result); + XmlTokenizer(); + OMNextToken(); + While(OMToken() != "EndOfFile") + [ + Echo("Exploded ",OMToken()); + OMNextToken(); + ]; + DefaultTokenizer(); + True; +]; + + + +10 # MatchClose(_x)_(x = OMToken()) <-- [OMNextToken();True;]; +20 # MatchClose(_x) <-- Check(False, "Syntax", PipeToString()Echo("encodingError:unexpected closing brace")); //@@@ TODO better error reporting + +10 # MatchOMOBJ(XmlTag("OMOBJ",_attributes,"Open")) <-- +[ + // Any attributes are ignored. + Local(result); + OMNextToken(); + result := ReadOMOBJ(OMToken()); + MatchClose(XmlTag("OMOBJ",{},"Close")); + result; +]; +10 # MatchOMOBJ(XmlTag("OMOBJ",_attributes,"OpenClose")) <-- +[ + OMNextToken(); + // Any attributes are ignored. + // This is a void expression, of the form "". + Empty; +]; +20 # MatchOMOBJ(_rest) <-- Check(False, "Type", PipeToString()Echo("encodingError:not an OMOBJ :",rest)); + +10 # ReadOMOBJ(XmlTag("OMOBJ",_attributes,"Close")) <-- +[ + // This is a void expression, of the form "". + Empty; +]; + +10 # ReadOMOBJ(XmlTag("OMI",{},"Open")) <-- +[ + Local(result); + OMNextToken(); + result := ToAtom(OMToken()); + OMNextToken(); + MatchClose(XmlTag("OMI",{},"Close")); + result; +]; + +10 # ReadOMOBJ(XmlTag("OMV",{{"NAME",_name}},"OpenClose")) <-- +[ + OMNextToken(); + ToAtom(name); +]; + +10 # ReadOMOBJ(XmlTag("OMF",{{"DEC",_dec}},"OpenClose")) <-- +[ + OMNextToken(); + ToAtom(dec); +]; + +10 # ReadOMOBJ(XmlTag("OMSTR",{},"Open")) <-- +[ + Local(result); + OMNextToken(); + If(IsString(OMToken()), [result := OMToken(); OMNextToken();], result := ""); + MatchClose(XmlTag("OMSTR",{},"Close")); + result; +]; +10 # ReadOMOBJ(XmlTag("OMSTR",{},"OpenClose")) <-- +[ + OMNextToken(); + ""; +]; + +10 # ReadOMOBJ(XmlTag("OMA",{},"Open")) <-- +[ + Local(result, new); + result:={}; + OMNextToken(); + While (OMToken() != XmlTag("OMA",{},"Close")) + [ + new:=ReadOMOBJ(OMToken()); + DestructiveAppend(result,new); + ]; + MatchClose(XmlTag("OMA",{},"Close")); + OMApplyReverseMapping(ListToFunction(result)); +]; + +10 # ReadOMOBJ(XmlTag("OMBIND",{},"Open")) <-- +[ + Local(result, new); + result:={}; + OMNextToken(); + While (OMToken() != XmlTag("OMBIND",{},"Close")) + [ + new:=ReadOMOBJ(OMToken()); + DestructiveAppend(result,new); + ]; + MatchClose(XmlTag("OMBIND",{},"Close")); + result; +]; +10 # ReadOMOBJ(XmlTag("OMBVAR",{},"Open")) <-- +[ + Local(result, new); + result:={}; + OMNextToken(); + While (OMToken() != XmlTag("OMBVAR",{},"Close")) + [ + new:=ReadOMOBJ(OMToken()); + DestructiveAppend(result,new); + ]; + MatchClose(XmlTag("OMBVAR",{},"Close")); + result; +]; + +10 # OMApplyReverseMapping(piperExp_IsFunction) <-- piperExp; +10 # OMApplyReverseMapping(piperExp_IsFunction)_(OMSymbol()[ Type(piperExp) ] != Empty) + <-- + [ + Local(symbolDef, result); + symbolDef := OMSymbol()[ Type(piperExp) ]; + If(symbolDef[4] = {}, + result := piperExp, + [ + result := OMApplyMapping(piperExp, symbolDef[4]); + result := Subst($, piperExp[0]) result; + If(IsList(result), result := ListToFunction(result)); + ] + ); + result; + ]; + +10 # OMApplyMapping(_function, _mapping) <-- +[ + Local(expandRules, result); + expandRules := { _(_path) <- OMPathSelect(path, function) }; + expandRules[1][2][2] := function;// the "function" variable is not expanded above. + + mapping := (mapping /: expandRules);// "/:" has lower precedence than ":=". + + Local(ruleMatched); + ruleMatched := False; + If(Type(mapping) = "|", + [ + mapping := Flatten(mapping, "|"); + ForEach(rule, mapping) + If(Not ruleMatched, + [ + If(Type(rule) = "_", + If( Eval(rule[2]), [ result := rule[1]; ruleMatched := True; ] ), + [ result := rule; ruleMatched := True; ] + ); + ] + ); + ], + [ + If(Type(mapping) = "_", + If(Eval(mapping[2]), + result := mapping[1], + result := FunctionToList(function) + ), + result := mapping + ); + ruleMatched := True; + ] + ); + + If(ruleMatched, + If(Type(result) = ":", + If(Length(result) = 2, + result[1]:result[2], + result),// Perhaps we should give a warning here. + result), + Empty); +]; + +11 # OMPathSelect(path_IsNumber, _expression) <-- +[ + If(path >= 0 And path <= Length(expression), + expression[path], + Undefined); +]; +11 # OMPathSelect(path_IsList, _expression) <-- +[ + ForEach(i, path) + If(IsFunction(expression) And i >= 0 And i <= Length(expression), + expression := expression[i], + Undefined); + expression; +]; +HoldArgumentNumber("OMPathSelect", 2, 2); + +// Previously, any unknown symbols where reported as errors. +// Now, we just store them as OMS(cd, name) since MathPiper is perfectly happy +// with such unknown symbols, and will handle them right: When +// producing an OpenMath result from them, they will be output back +// unmodified, forming a valid OpenMath expression. +// This way we don't have to bother defining bogus symbols for concepts that +// MathPiper does not handle. +100 # ReadOMOBJ(XmlTag("OMS", _attributes, "OpenClose")) <-- +[ + OMNextToken(); + Local(omcd, omname); + omcd := attributes["CD"]; + omname := attributes["NAME"]; + If(omcd = Empty Or omname = Empty, + OMCheck(False, "Argument", OMError({"moreerrors", "encodingError"}, PipeToString()Echo("missing \"cd\" or \"name\" attribute: ",attributes))), + [ + Local(cdTable, piperform); + cdTable := OMSymbolReverse()[ omcd ]; + If(cdTable != Empty, piperform := cdTable[ omname ]); + // We can not optimize here by checking first whether the CD is mathpiper + // and avoiding the table lookup then, because for some symbols the + // OM name have to be different from the MathPiper name (e.g. "/@"). + If(piperform = Empty, + If(cd = mathpiper, ToAtom(omname), OMS(omcd, omname)), + If(IsString(piperform), ToAtom(piperform), piperform)); + ] + ); +]; + +101 # ReadOMOBJ(_rest) <-- OMCheck(False, "Unimplemented", OMError({"moreerrors", "encodingError"}, PipeToString()Echo("unhandled tag: ",rest))); + + + +/////////////////////////////////////////////////////////////////////// +// Error reporting + +Macro(OMCheck,{predicate,error}) +[ + If(Not(@predicate), + [ + Assert("omErrorObject", @error) False; + Check(False, "Undefined", "omErrorObject"); + ] + , + True); +]; + + + +OMGetCoreError():= +[ + Local(result); + result := ExceptionGet(); //todo:tk:verify that ExceptionCheck works properly with the soft error handling functions. + If(result != False, + If( IsError("omErrorObject"), + [result := GetError("omErrorObject"); ], + [result := OMError({"moreerrors", "unexpected"}, result); ]) + ); + result; +]; + + + +/////////////////////////////////////////////////////////////////////// +// Symbol mapping tables + +LocalSymbols(omsymbol, omsymbolreverse) [ + // Initialization of the openmath symbol dictionaries + omsymbol := {}; + omsymbolreverse := {}; + + // Access to the dictionaries + OMSymbol() := omsymbol; + OMSymbolReverse() := omsymbolreverse; + +]; // LocalSymbols(omsymbol, omsymbolreverse) + +OMDef(_piperform, omcd_IsString, omname_IsString, _directMapping, _reverseMapping) <-- +[ + Local(cdTable); + If(IsString(piperform), + OMSymbol()[ piperform ] := {omcd, omname, directMapping, reverseMapping} + ); + cdTable := OMSymbolReverse()[ omcd ]; + If(cdTable = Empty, + OMSymbolReverse()[ omcd ] := {{omname, piperform}}, + [ + Local(oldMathPiperform); + oldMathPiperform := cdTable[ omname ]; + If(oldMathPiperform = Empty, + cdTable[ omname ] := piperform, + [ + If(oldMathPiperform != piperform, + [ + cdTable[ omname ] := piperform; + Echo("Warning: the mapping for ", omcd, ":", omname, + " was already defined as ", oldMathPiperform, + ", but is redefined now as ", piperform + ); + ] + ); + ] + ); + ] + ); + True; +]; + +OMDef(_piperform, omcd_IsString, omname_IsString) +<-- OMDef(piperform, omcd, omname, {}, {}); + +OMDef(piperalias_IsString, pipername_IsString) <-- +[ + OMSymbol()[ piperalias ] := OMSymbol()[ pipername ]; +]; +HoldArgumentNumber("OMDef", 5, 4); +HoldArgumentNumber("OMDef", 5, 5); + +// Many objects, such as matrices and sets, do not have a specific +// encoding in MathPiper, but are represented as lists. +OMDef( {}, "set1","emptyset" ); +OMDef( "List", "set1","set" ); +OMDef( "List", "linalg2","matrix" ); +OMDef( "List", "linalg2","matrixrow" ); +OMDef( "List", "linalg2","vector" ); +OMDef( "List", "list1","list" ); + +// [20010916 AGP] I couldn't find these symbols in the def files: +// "E" , "nums1", "e" +// "Gamma" , "nums1", "gamma" +OMDef( "Infinity" , "nums1", "infinity" ); +OMDef( "Undefined", "nums1", "NaN" ); +// [20010916 AGP] From initialization.rep/stdopers.mpi: +OMDef( "And" , "logic1", "and" ); +OMDef( "==" , "logic1", "equivalent" ); +OMDef( "!==" , "logic1", "not", + { "", + 1, + 2, + "" + } + ); +OMDef( "False", "logic1", "false" ); +OMDef( "Or" , "logic1", "or" ); +OMDef( "True" , "logic1", "true" ); +//[20010916 AGP ] Xor is not available in MathPiper. +// "Xor" , "logic1", "xor" ); +OMDef( "&" , mathpiper, "bitwise_and" ); +OMDef( "|" , mathpiper, "bitwise_or" ); +OMDef( "%" , mathpiper, "bitwise_xor" ); +OMDef( "/" , "arith1", "divide");// This definition is for OM arith1:divide to MathPiper. In all other cases, the next one will be used. +OMDef( "/" , "nums1", "rational", {$, _1, _2}_(IsRational(_1/_2)) | {OMS("arith1", "divide"), _1, _2}, {/, _1, _2}); +OMDef( "-" , "arith1", "unary_minus"); +OMDef( "-" , "arith1", "minus" );// We need a way of testing the arity. +OMDef( "+" , "arith1", "plus" ); +OMDef( "^" , "arith1", "power" ); +OMDef( "*" , "arith1", "times" ); + + +LoadScriptOnce("constants.rep/om.mpi"); +LoadScriptOnce("stdfuncs.rep/om.mpi"); +LoadScriptOnce("stubs.rep/om.mpi"); +LoadScriptOnce("logic.rep/om.mpi"); +LoadScriptOnce("complex.rep/om.mpi"); +LoadScriptOnce("integrate.rep/om.mpi"); +LoadScriptOnce("sums.rep/om.mpi"); +LoadScriptOnce("limit.rep/om.mpi"); +//LoadScriptOnce("numbers.rep/om.mpi");// Sqrt is loaded before (stubs.rep) than IntNthRoot. +LoadScriptOnce("functional.rep/om.mpi"); + + +%/mathpiper + + + +%mathpiper_docs,name="OMForm;OMRead",categories="User Functions;Input/Output" +*CMD OMForm --- convert MathPiper expression to OpenMath +*CMD OMRead --- convert expression from OpenMath to MathPiper expression +*STD +*CALL + OMForm(expression) + OMRead() + +*PARMS + +{expression} -- expression to convert + +*DESC + +{OMForm} prints an OpenMath representation of the input parameter {expression} +to standard output. {OMRead} reads an OpenMath expression from standard +input and returns a normal MathPiper expression that matches the input OpenMath +expression. + +If a MathPiper symbol does not have a mapping defined by {OMDef}, it is translated +to and from OpenMath as the OpenMath symbol in the CD "mathpiper" with the same +name as it has in MathPiper. + +*E.G. notest + +In> str:=PipeToString()OMForm(2+Sin(a*3)) +Result: " + + + 2 + + + + + + 3 + + + + + "; +In> PipeFromString(str)OMRead() +Result: 2+Sin(a*3); + +In> OMForm(NotDefinedInOpenMath(2+3)) + + + + + + 2 + 3 + + + +Result: True + +*SEE XmlTokenizer, XmlExplodeTag, OMDef +%/mathpiper_docs + + + +%mathpiper_docs,name="OMDef",categories="User Functions;Input/Output" +*CMD OMDef --- define translations from MathPiper to OpenMath and vice-versa. +*STD +*CALL + OMDef(mathpiperForm, cd, name) + OMDef(mathpiperForm, cd, name, mathpiperToOM) + OMDef(mathpiperForm, cd, name, mathpiperToOM, omToMathPiper) + +*PARMS + +{mathpiperForm} -- string with the name of a MathPiper symbol, or a MathPiper expression + +{cd} -- OpenMath Content Dictionary for the symbol + +{name} -- OpenMath name for the symbol + +{mathpiperToOM} -- rule for translating an application of that symbol in MathPiper into an OpenMath expression + +{omToMathPiper} -- rule for translating an OpenMath expression into an application of this symbol in MathPiper + +*DESC + +{OMDef} defines the translation rules for symbols between the MathPiper +representation and {OpenMath}. +The first parameter, {mathpiperForm}, can be a string or an expression. The +difference is that when giving an expression only the {omToMathPiper} translation +is defined, and it uses the exact expression given. This is used for {OpenMath} +symbols that must be translated into a whole subexpression in MathPiper, such +as {set1:emptyset} which gets translated to an empty list as follows: +In> OMDef( {}, "set1","emptyset" ) +Result: True +In> PipeFromString(" ")OMRead() +Result: {} +In> IsList(%) +Result: True +Otherwise, a symbol that is not inside an application (OMA) gets translated to +the MathPiper atom with the given name: +In> OMDef( "EmptySet", "set1","emptyset" ) + Warning: the mapping for set1:emptyset was already defined as {} , but is redefined now as EmptySet +Result: True +In> PipeFromString(" ")OMRead() +Result: EmptySet + +The definitions for the symbols in the MathPiper +library are in the {*.rep} script subdirectories. In those modules for which +the mappings are defined, there is a file called {om.ys} that contains the +{OMDef} calls. Those files are loaded in {openmath.rep/om.ys}, so any new +file must be added to the list there, at the end of the file. + +A rule is represented as a list of expressions. Since both OM and +MathPiper expressions are actually lists, the syntax is the same in both +directions. There are two template forms that are expanded before the +translation: + +* {$}: this symbol stands for the translation of the symbol applied +in the original expression. + +* {_path}: a path into the original expression (list) to extract an +element, written as an underscore applied to an integer or a list of integers. + Those integers are indexes into expressions, and integers in a list are + applied recursively starting at the original expression. + For example, {_2} means the second parameter of the expression, while + {_{3,2,1}} means the first parameter of the second parameter of the third + parameter of the original expression. + +They can appear anywhere in the rule as expressions or subexpressions. + +Finally, several alternative rules can be specified by joining them with +the {|} symbol, and each of them can be annotated with a post-predicate +applied with the underscore {_} symbol, in the style of MathPiper' simplification +rules. Only the first alternative rule that matches is applied, so the more +specific rules must be written first. + +There are special symbols recognized by {OMForm} to output {OpenMath} +constructs that have no specific parallel in MathPiper, such as an OpenMath +symbol having a {CD} and {name}: MathPiper symbols have only a name. +Those special symbols are: + +* {OMS(cd, name)}: {} +* {OMA(f x y ...)}: {f x y ...} +* {OMBIND(binderSymbol, bvars, expression)}: {binderSymbol bvars expression}, where {bvars} must be produced by using {OMBVAR(...)}. +* {OMBVAR(x y ...)}: {x y ...} +* {OME(...)}: {...} + +When translating from OpenMath to MathPiper, we just store unknown symbols as +{OMS("cd", "name")}. This way we don't have to bother defining bogus symbols +for concepts that MathPiper does not handle, and we can evaluate expressions that +contain them. + +*E.G. notest + +In> OMDef( "Sqrt" , "arith1", "root", { $, _1, 2 }, $(_1)_(_2=2) | (_1^(1/_2)) ); +Result: True +In> OMForm(Sqrt(3)) + + + + 3 + 2 + + +Result: True +In> PipeFromString("162 ")OMRead() +Result: Sqrt(16) +In> PipeFromString("163 ")OMRead() +Result: 16^(1/3) + +In> OMDef("Limit", "limit1", "limit", \ + { $, _2, OMS("limit1", "under"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) \ + |{ $, _2, OMS("limit1", "above"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) \ + |{ $, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, \ + { $, _{3,2,1}, _1, Left, _{3,3}}_(_2=OMS("limit1", "below")) \ + |{$, _{3,2,1}, _1, Right, _{3,3}}_(_2=OMS("limit1", "above")) \ + |{$, _{3,2,1}, _1, _{3,3}} \ + ); +In> OMForm(Limit(x,0) Sin(x)/x) + + + + 0 + + + + + + + + + + + + + + + + + +Result: True +In> OMForm(Limit(x,0,Right) 1/x) + + + + 0 + + + + + + + + + 1 + + + + + +Result: True +In> PipeFromString(PipeToString()OMForm(Limit(x,0,Right) 1/x))OMRead() +Result: Limit(x,0,Right)1/x +In> % +Result: Infinity + +*SEE OMForm, OMRead +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/PrettyForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/PrettyForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/PrettyForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/PrettyForm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,592 @@ +%mathpiper,def="PrettyForm;EvalFormula" + +/* def file definitions +EvalFormula +*/ + + +/* +TODO: +- Func(a=b) prematurely evaluates a=b +- clean up the code! + - document the code!!! +- prefix/postfix currently not used!!! +- some rules for rendering the formula are slooooww.... + +- bin, derivative, sqrt, integral, summation, limits, + ___ + / a | + \ / - + \/ b + + / + | + | + | + / + + d + --- f( x ) + d x + + 2 + d + ---- f( x ) + 2 + d x + + Infinity + ___ + \ + \ n + / x + /__ + n = 0 + Sin(x) + lim ------ + x -> Infinity x + + + +*/ + +/* +NLog(str):= +[ + WriteString(str); + NewLine(); +]; +*/ + + + + +CharList(length,item):= +[ + Local(line,i); + line:=""; + For(Bind(i,0),IsLessThan(i,length),Bind(i,AddN(i,1))) + Bind(line, line:item); + line; +]; + + + + +CharField(width,height) := ArrayCreate(height,CharList(width," ")); + + + + +WriteCharField(charfield):= +[ + Local(i,len); + len:=Length(charfield); + For(Bind(i,1),i<=len,Bind(i,AddN(i,1))) + [ + WriteString(charfield[i]); + NewLine(); + ]; + True; +]; + + + + +ColumnFilled(charfield,column):= +[ + Local(i,result,len); + result:=False; + len:=Length(charfield); + For(Bind(i, 1),(result = False) And (i<=len),Bind(i,AddN(i,1))) + [ + If(StringMidGet(column,1,charfield[i]) != " ",result:=True); + ]; + result; +]; + + + + +WriteCharField(charfield,width):= +[ + Local(pos,length,len); + Bind(length, Length(charfield[1])); + Bind(pos, 1); + While(pos<=length) + [ + Local(i,thiswidth); + Bind(thiswidth, width); + If(thiswidth>(length-pos)+1, + [ + Bind(thiswidth, AddN(SubtractN(length,pos),1)); + ], + [ + While (thiswidth>1 And ColumnFilled(charfield,pos+thiswidth-1)) + [ + Bind(thiswidth,SubtractN(thiswidth,1)); + ]; + If(thiswidth = 1, Bind(thiswidth, width)); + ] + ); + len:=Length(charfield); + For(Bind(i, 1),i<=len,Bind(i,AddN(i,1))) + [ + WriteString(StringMidGet(pos,thiswidth,charfield[i])); + NewLine(); + ]; + Bind(pos, AddN(pos, thiswidth)); + NewLine(); + ]; + True; +]; + + + + +PutString(charfield,x,y,string):= +[ + cf[y] := StringMidSet(x,string,cf[y]); + True; +]; + + + + +MakeOper(x,y,width,height,oper,args,base):= +[ + Local(result); + Bind(result,ArrayCreate(7,0)); + ArraySet(result,1,x); + ArraySet(result,2,y); + ArraySet(result,3,width); + ArraySet(result,4,height); + ArraySet(result,5,oper); + ArraySet(result,6,args); + ArraySet(result,7,base); + result; +]; + + + + +MoveOper(f,x,y):= +[ + f[1]:=AddN(f[1], x); /* move x */ + f[2]:=AddN(f[2], y); /* move y */ + f[7]:=AddN(f[7], y); /* move base */ +]; + + + + +AlignBase(i1,i2):= +[ + Local(base); + Bind(base, Maximum(i1[7],i2[7])); + MoveOper(i1,0,SubtractN(base,(i1[7]))); + MoveOper(i2,0,SubtractN(base,(i2[7]))); +]; + + + + +10 # BuildArgs({}) <-- Formula(ToAtom(" ")); + + + + +20 # BuildArgs({_head}) <-- head; + + + + +30 # BuildArgs(_any) <-- + [ + Local(item1,item2,comma,base,newitem); + Bind(item1, any[1]); + Bind(item2, any[2]); + Bind(comma, Formula(ToAtom(","))); + Bind(base, Maximum(item1[7],item2[7])); + MoveOper(item1,0,SubtractN(base,(item1[7]))); + MoveOper(comma,AddN(item1[3],1),base); + + MoveOper(item2,comma[1]+comma[3]+1,SubtractN(base,(item2[7]))); + Bind(newitem, MakeOper(0,0,AddN(item2[1],item2[3]),Maximum(item1[4],item2[4]),"Func",{item1,comma,item2},base)); + BuildArgs(newitem:Rest(Rest(any))); + ]; + + + + +FormulaBracket(f):= +[ + Local(left,right); + Bind(left, Formula(ToAtom("("))); + Bind(right, Formula(ToAtom(")"))); + left[4]:=f[4]; + right[4]:=f[4]; + MoveOper(left,f[1],f[2]); + MoveOper(f,2,0); + MoveOper(right,f[1]+f[3]+1,f[2]); + MakeOper(0,0,right[1]+right[3],f[4],"Func",{left,f,right},f[7]); +]; + + + + +/* Rulebase("Formula",{f}); */ + +1 # Formula(f_IsAtom) <-- + MakeOper(0,0,Length(ToString(f)),1,"ToAtom",ToString(f),0); + + + + +2 # Formula(_xx ^ _yy) <-- +[ + Local(l,r); + Bind(l, BracketOn(Formula(xx),xx,LeftPrecedenceGet("^"))); + Bind(r, BracketOn(Formula(yy),yy,RightPrecedenceGet("^"))); + MoveOper(l,0,r[4]); + MoveOper(r,l[3],0); + MakeOper(0,0,AddN(l[3],r[3]),AddN(l[4],r[4]),"Func",{l,r},l[2]+l[4]-1); +]; + + + + +10 # FormulaArrayItem(xx_IsList) <-- +[ + Local(sub,height); + sub := {}; + height := 0; + ForEach(item,xx) + [ + Local(made); + made := FormulaBracket(Formula(item)); + If(made[4] > height,Bind(height,made[4])); + DestructiveAppend(sub,made); + ]; + MakeOper(0,0,0,height,"List",sub,height>>1); +]; + + + +20 # FormulaArrayItem(_item) <-- Formula(item); + + + + +2 # Formula(xx_IsList) <-- +[ + Local(sub,width,height); + sub:={}; + width := 0; + height := 1; + + ForEach(item,xx) + [ + Local(made); + made := FormulaArrayItem(item); + + If(made[3] > width,Bind(width,made[3])); + MoveOper(made,0,height); + Bind(height,AddN(height,AddN(made[4],1))); + DestructiveAppend(sub,made); + ]; + + Local(thislength,maxlength); + maxlength:=0; + ForEach(item,xx) + [ + thislength:=0; + if(IsList(item)) [thislength:=Length(item);]; + if (maxlength0, + [ + Local(i,j); + width:=0; + For(j:=1,j<=maxlength,j++) + [ + Local(w); + w := 0; + For(i:=1,i<=Length(sub),i++) + [ + if (IsList(xx[i]) And j<=Length(xx[i])) + If(sub[i][6][j][3] > w,w := sub[i][6][j][3]); + ]; + + For(i:=1,i<=Length(sub),i++) + [ + if (IsList(xx[i]) And j<=Length(xx[i])) + MoveOper(sub[i][6][j],width,0); + ]; + width := width+w+1; + ]; + For(i:=1,i<=Length(sub),i++) + [ + sub[i][3] := width; + ]; + ] + ); + + sub := MakeOper(0,0,width,height,"List",sub,height>>1); + FormulaBracket(sub); +]; + + + + + +2 # Formula(_xx / _yy) <-- +[ + Local(l,r,dash,width); +/* + Bind(l, BracketOn(Formula(xx),xx,LeftPrecedenceGet("/"))); + Bind(r, BracketOn(Formula(yy),yy,RightPrecedenceGet("/"))); +*/ + Bind(l, Formula(xx)); + Bind(r, Formula(yy)); + Bind(width, Maximum(l[3],r[3])); + Bind(dash, Formula(ToAtom(CharList(width,"-")))); + MoveOper(dash,0,l[4]); + MoveOper(l,(SubtractN(width,l[3])>>1),0); + MoveOper(r,(SubtractN(width,r[3])>>1),AddN(dash[2], dash[4])); + MakeOper(0,0,width,AddN(r[2], r[4]),"Func",{l,r,dash},dash[2]); +]; + + + + +Rulebase("BracketOn",{op,f,prec}); + +Rule("BracketOn",3,1,IsFunction(f) And ArgumentsCount(f) = 2 + And IsInfix(Type(f)) And PrecedenceGet(Type(f)) > prec) +[ + FormulaBracket(op); +]; + + + + +Rule("BracketOn",3,2,True) +[ + op; +]; + + + + + +10 # Formula(f_IsFunction)_(ArgumentsCount(f) = 2 And IsInfix(Type(f))) <-- +[ + Local(l,r,oper,width,height,base); + Bind(l, Formula(f[1])); + Bind(r, Formula(f[2])); + + Bind(l, BracketOn(l,f[1],LeftPrecedenceGet(Type(f)))); + Bind(r, BracketOn(r,f[2],RightPrecedenceGet(Type(f)))); + + Bind(oper, Formula(f[0])); + Bind(base, Maximum(l[7],r[7])); + MoveOper(oper,AddN(l[3],1),SubtractN(base,(oper[7]))); + MoveOper(r,oper[1] + oper[3]+1,SubtractN(base,(r[7]))); + MoveOper(l,0,SubtractN(base,(l[7]))); + Bind(height, Maximum(AddN(l[2], l[4]),AddN(r[2], r[4]))); + + MakeOper(0,0,AddN(r[1], r[3]),height,"Func",{l,r,oper},base); +]; + + + + +11 # Formula(f_IsFunction) <-- +[ + Local(head,args,all); + Bind(head, Formula(f[0])); + Bind(all, Rest(FunctionToList(f))); + + Bind(args, FormulaBracket(BuildArgs(MapSingle("Formula",Apply("Hold",{all}))))); + AlignBase(head,args); + MoveOper(args,head[3],0); + + MakeOper(0,0,args[1]+args[3],Maximum(head[4],args[4]),"Func",{head,args},head[7]); +]; + + + +Rulebase("RenderFormula",{cf,f,x,y}); + +/* +/ / / +\ | | + \ | + \ +*/ + +Rule("RenderFormula",4,1,f[5] = "ToAtom" And f[6] = "(" And f[4] > 1) +[ + Local(height,i); + Bind(x, AddN(x,f[1])); + Bind(y, AddN(y,f[2])); + Bind(height, SubtractN(f[4],1)); + + cf[y] := StringMidSet(x, "/", cf[y]); + cf[AddN(y,height)] := StringMidSet(x, "\\", cf[AddN(y,height)]); + For (Bind(i,1),IsLessThan(i,height),Bind(i,AddN(i,1))) + cf[AddN(y,i)] := StringMidSet(x, "|", cf[AddN(y,i)]); +]; + + + + +Rule("RenderFormula",4,1,f[5] = "ToAtom" And f[6] = ")" And f[4] > 1) +[ + Local(height,i); + Bind(x, AddN(x,f[1])); + Bind(y, AddN(y,f[2])); + Bind(height, SubtractN(f[4],1)); + cf[y] := StringMidSet(x, "\\", cf[y]); + cf[y+height] := StringMidSet(x, "/", cf[y+height]); + For (Bind(i,1),IsLessThan(i,height),Bind(i,AddN(i,1))) + cf[AddN(y,i)] := StringMidSet(x, "|", cf[AddN(y,i)]); +]; + + + + +Rule("RenderFormula",4,5,f[5] = "ToAtom") +[ + cf[AddN(y, f[2]) ]:= + StringMidSet(AddN(x,f[1]),f[6],cf[AddN(y, f[2]) ]); +]; + + + + +Rule("RenderFormula",4,6,True) +[ + ForEach(item,f[6]) + [ + RenderFormula(cf,item,AddN(x, f[1]),AddN(y, f[2])); + ]; +]; + + + + +LocalSymbols(formulaMaxWidth) [ + SetFormulaMaxWidth(width):= + [ + formulaMaxWidth := width; + ]; + FormulaMaxWidth() := formulaMaxWidth; + SetFormulaMaxWidth(60); +]; // LocalSymbols(formulaMaxWidth) + + + + +Function("PrettyForm",{ff}) +[ + Local(cf,f); + + f:=Formula(ff); + + cf:=CharField(f[3],f[4]); + RenderFormula(cf,f,1,1); + + NewLine(); + WriteCharField(cf,FormulaMaxWidth()); + + DumpErrors(); + True; +]; +/* +HoldArgument("PrettyForm",ff); +*/ + + + + +EvalFormula(f):= +[ + Local(result); + result:= ListToFunction({ToAtom("="),f,Eval(f)}); + PrettyForm(result); + True; +]; +HoldArgument("EvalFormula",f); + +/* +{x,y,width,height,oper,args,base} +*/ + +%/mathpiper + + + +%mathpiper_docs,name="PrettyForm",categories="User Functions;Input/Output" +*CMD PrettyForm --- print an expression nicely with ASCII art +*STD +*CALL + PrettyForm(expr) + +*PARMS + +{expr} -- an expression + +*DESC + +{PrettyForm} renders an expression in a nicer way, using ascii art. +This is generally useful when the result of a calculation is more +complex than a simple number. + +*E.G. + +In> Taylor(x,0,9)Sin(x) +Result: x-x^3/6+x^5/120-x^7/5040+x^9/362880; +In> PrettyForm(%) + + 3 5 7 9 + x x x x + x - -- + --- - ---- + ------ + 6 120 5040 362880 + +Result: True; + +*SEE EvalFormula, PrettyPrinterSet +%/mathpiper_docs + + + +%mathpiper_docs,name="EvalFormula",categories="User Functions;Input/Output" +*CMD EvalFormula --- print an evaluation nicely with ASCII art +*STD +*CALL + EvalFormula(expr) + +*PARMS + +{expr} -- an expression + +*DESC + +Show an evaluation in a nice way, using {PrettyPrinterSet} +to show 'input = output'. + +*E.G. + +In> EvalFormula(Taylor(x,0,7)Sin(x)) + + 3 5 + x x + Taylor( x , 0 , 5 , Sin( x ) ) = x - -- + --- + 6 120 + + +*SEE PrettyForm +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/texform.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/texform.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/outputforms/texform.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/outputforms/texform.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,416 @@ +%mathpiper,def="TeXForm" + +/* def file definitions +TeXForm +TeXFormMaxPrec +TexForm +*/ + +/* TeXForm: convert MathPiper objects to TeX math mode strings */ + +/* version 0.4 */ + +/* Changelog + 0.1 basic functionality + 0.2 fixed bracketing of Exp, added all infix ops and math functions + 0.3 fixed bracketing of lists, changed bracketing of math functions, modified TeX representation of user-defined functions (up to two-letter functions are in italics), added TeX Greek letters + 0.4 added nth roots, Sum, Limit, Integrate, hyperbolics, set operations, Abs, Max, Min, "==", ":=", Infinity; support indexed expressions A[i] and matrices. + 0.4.1 bugfixes for [] operator, support for multiple indices a[1][2][3] + 0.4.2 fix for variable names ending on digits "a2" represented as $a_2$ + 0.4.3 bugfixes: complex I, indeterminate integration; relaxed bracketing of Sin()-like functions; implemented $TeX$ and $LaTeX$ correctly now (using \textrm{}) + 0.4.4 use ordinary instead of partial derivative if expression has only one variable + 0.4.5 fixes for bracketing of Sum(); added <> to render as \sim and <=> to render as \approx; added BinomialCoefficient() + 0.4.6 moved the <> and <=> operators to initialization.rep/stdopers.mpi + 0.4.7 added Product() i.e. Product() + 0.4.8 added Differentiate(x,n), Deriv(x,n), =>, and fixed errors with ArcSinh, ArcCosh, ArcTanh + 0.4.9 fixed omission: (fraction)^n was not put in brackets + 0.4.10 cosmetic change: insert \cdot between numbers in cases like 2*10^n + 0.4.11 added DumpErrors() to TexForm for the benefit of TeXmacs notebooks + 0.4.12 implement the % operation as Mod + 0.4.13 added Bessel{I,J,K,Y}, Ortho{H,P,T,U}, with a general framework for usual two-argument functions of the form $A_n(x)$; fix for Max, Min + 0.4.14 added mathematical notation for Floor(), Ceil() + 0.4.15 added Prog() represented by ( ) + 0.4.16 added Zeta() +*/ + +/* To do: + 0. Find and fix bugs. + 1. The current bracketing approach has limitations: can't omit extra brackets sometimes. " sin a b" is ambiguous, so need to do either "sin a sin b" or "(sin a) b" Hold((a*b)*Sqrt(x)). The current approach is *not* to bracket functions unless the enveloping operation is more binding than multiplication. This produces "sin a b" for both Sin(a*b) and Sin(a)*b but this is the current mathematical practice. + 2. Need to figure out how to deal with variable names such as "alpha3" +*/ + +//Retract("TeXForm", *); + +/// TeXmacs prettyprinter +TexForm(_expr) <-- [DumpErrors();WriteString(TeXForm(expr));NewLine();]; + +Rulebase("TeXForm",{expression}); +Rulebase("TeXForm",{expression, precedence}); + +/* Boolean predicate */ + + +/* this function will put TeX brackets around the string if predicate holds */ + +Function ("TeXFormBracketIf", {predicate, string}) +[ + Check(IsBoolean(predicate) And IsString(string), "Argument", "TeXForm internal error: non-boolean and/or non-string argument of TeXFormBracketIf"); + If(predicate, ConcatStrings("( ", string, ") "), string); +]; + + + + +Function ("TeXFormMatrixBracketIf", {predicate, string}) +[ + Check(IsBoolean(predicate) And IsString(string), "Argument", "TeXForm internal error: non-boolean and/or non-string argument of TeXFormMatrixBracketIf"); + If(predicate, ConcatStrings("\\left[ ", string, "\\right]"), string); +]; + + + +/* First, we convert TeXForm(x) to TeXForm(x, precedence). The enveloping precedence will determine whether we need to bracket the results. So TeXForm(x, TeXFormMaxPrec()) will always print "x", while TeXForm(x,-TeXFormMaxPrec()) will always print "(x)". +*/ + +TeXFormMaxPrec() := 60000; /* This precedence will never be bracketed. It is equal to KMaxPrec */ + +/// main front-end +100 # TeXForm(_x) <-- ConcatStrings("$", TeXForm(x, TeXFormMaxPrec()), "$"); + +/* Replace numbers and variables -- never bracketed except explicitly */ + +110 # TeXForm(x_IsNumber, _p) <-- ToString(x); +/* Variables */ +200 # TeXForm(x_IsAtom, _p) <-- TeXFormTeXify(ToString(x)); + + +/* Strings must be quoted but not bracketed */ +100 # TeXForm(x_IsString, _p) <-- +[ + Local(characterList); + + characterList := {}; + ForEach(character, x) + [ + If(character != " ", DestructiveAppend(characterList, character), DestructiveAppend(characterList, "\\hspace{2 mm}")); + ]; + ConcatStrings("\\mathrm{''", ListToString(characterList), "''}"); +]; + + + +/* FunctionToList(...) can generate lists with atoms that would otherwise result in unparsable expressions. */ +100 # TeXForm(x_IsAtom, _p)_(IsInfix(ToString(x))) <-- ConcatStrings("\\mathrm{", ToString(x), "}"); + + +/* Lists: make sure to have matrices processed before them. Enveloping precedence is irrelevant because lists are always bracketed. List items are never bracketed. Note that TeXFormFinishList({a,b}) generates ",a,b" */ + +100 # TeXForm(x_IsList, _p)_(Length(x)=0) <-- TeXFormBracketIf(True, ""); +110 # TeXForm(x_IsList, _p) <-- TeXFormBracketIf(True, ConcatStrings(TeXForm(First(x), TeXFormMaxPrec()), TeXFormFinishList(Rest(x)) ) ); +100 # TeXFormFinishList(x_IsList)_(Length(x)=0) <-- ""; +110 # TeXFormFinishList(x_IsList) <-- ConcatStrings(", ", TeXForm(First(x), TeXFormMaxPrec()), TeXFormFinishList(Rest(x))); + +/* Replace operations */ + + + /* Template for "regular" binary infix operators: +100 # TeXForm(_x + _y, _p) <-- TeXFormBracketIf(p=","\\geq "}, + {"<"," < "}, + {">"," > "}, + {"And","\\wedge "}, + {"Or", "\\vee "}, + {"<>", "\\sim "}, + {"<=>", "\\approx "}, + {"=>", "\\Rightarrow "}, + {"%", "\\bmod "}, + }; + + TeXFormRegularPrefixOps := { {"+"," + "}, {"-"," - "}, {"Not"," \\neg "} }; + + + + /* Unknown function: precedence 200. Leave as is, never bracket the function itself and bracket the argumentPointer(s) automatically since it's a list. Other functions are precedence 100 */ + + TeXFormGreekLetters := {"Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon", "Phi", "Psi", "Omega", "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega", "varpi", "varrho", "varsigma", "varphi", "varepsilon"}; + TeXFormSpecialNames := { + {"I", "\\imath "}, // this prevents a real uppercase I, use BesselI instead + {"Pi", "\\pi "}, // this makes it impossible to have an uppercase Pi... hopefully it's not needed + {"Infinity", "\\infty "}, + {"TeX", "\\textrm{\\TeX\\/}"}, + {"LaTeX", "\\textrm{\\LaTeX\\/}"}, + {"Maximum", "\\max "}, // this replaces these function names + {"Minimum", "\\min "}, + {"Prog", " "}, + {"Zeta", "\\zeta "}, + }; + + + /* this function will take a user-defined variable or function name and output either this name unmodified if it's only 2 characters long, or the name in normal text if it's longer, or a TeX Greek letter code */ + Function ("TeXFormTeXify", {string}) + [ + Check(IsString(string), "Argument", "TeXForm internal error: non-string argument of TeXFormTeXify"); + /* Check if it's a greek letter or a special name */ + If (Contains(AssocIndices(TeXFormSpecialNames), string), TeXFormSpecialNames[string], + If (Contains(TeXFormGreekLetters, string), ConcatStrings("\\", string, " "), + If (Contains(AssocIndices(TeXFormRegularOps), string), TeXFormRegularOps[string], + If (Contains(AssocIndices(TeXFormRegularPrefixOps), string), TeXFormRegularPrefixOps[string], + If (Length(string) >= 2 And IsNumber(ToAtom(StringMidGet(2, Length(string)-1, string))), ConcatStrings(StringMidGet(1,1,string), "_{", StringMidGet(2, Length(string)-1, string), "}"), + If (Length(string) > 2, ConcatStrings("\\mathrm{ ", string, " }"), + string + )))))); + ]; + +]; + +/* */ + +/* Unknown bodied function */ + +200 # TeXForm(x_IsFunction, _p) _ (IsBodied(Type(x))) <-- [ + Local(func, args, last'arg); + func := Type(x); + args := Rest(FunctionToList(x)); + last'arg := PopBack(args); + TeXFormBracketIf(p1, "\\frac{\\partial}{\\partial ", "\\frac{d}{d " + ), TeXForm(x, PrecedenceGet("^")), "}", TeXForm(y, PrecedenceGet("/")) ) ); + +100 # TeXForm(Deriv(_x, _n)_y, _p) <-- TeXFormBracketIf(p1, + "\\frac{\\partial^" : TeXForm(n, TeXFormMaxPrec()) : "}{\\partial ", + "\\frac{d^" : TeXForm(n, TeXFormMaxPrec()) : "}{d " + ), TeXForm(x, PrecedenceGet("^")), " ^", TeXForm(n, TeXFormMaxPrec()), "}", TeXForm(y, PrecedenceGet("/")) ) ); +100 # TeXForm(Differentiate(_x)_y, _p) <-- TeXForm(Deriv(x) y, p); +100 # TeXForm(Differentiate(_x, _n)_y, _p) <-- TeXForm(Deriv(x, n) y, p); + +/* Indexed expressions */ + +/* This seems not to work because x[i] is replaced by Nth(x,i) */ +/* +100 # TeXForm(_x [ _i ], _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); +*/ +/* Need to introduce auxiliary function, or else have trouble with arguments of Nth being lists */ +100 # TeXForm(Nth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p); +100 # TeXForm(TeXFormNth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p); +110 # TeXForm(Nth(Nth(_x, _i), _j), _p) <-- TeXForm(TeXFormNth(x, List(i,j)), p); +120 # TeXForm(Nth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); +120 # TeXForm(TeXFormNth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); + +/* Matrices are always bracketed. Precedence 80 because lists are at 100. */ + +80 # TeXForm(M_IsMatrix, _p) <-- TeXFormMatrixBracketIf(True, TeXFormPrintMatrix(M)); + +Function ("TeXFormPrintMatrix", {M}) +[ +/* + Want something like "\begin{array}{cc} a & b \\ c & d \\ e & f \end{array}" + here, "cc" is alignment and must be given for each column +*/ + Local(row, col, result, ncol); + result := "\\begin{array}{"; + ForEach(col, M[1]) result:=ConcatStrings(result, "c"); + result := ConcatStrings(result, "}"); + + ForEach(row, 1 .. Length(M)) [ + ForEach(col, 1 .. Length(M[row])) [ + result := ConcatStrings( result, " ", TeXForm(M[row][col], TeXFormMaxPrec()), If(col = Length(M[row]), If(row = Length(M), "", " \\\\"), " &")); + ]; + ]; + + ConcatStrings(result, " \\end{array} "); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="TeXForm",categories="User Functions;Input/Output" +*CMD TeXForm --- export expressions to $LaTeX$ +*STD +*CALL + TeXForm(expr) + +*PARMS + +{expr} -- an expression to be exported + +*DESC + +{TeXForm} returns a string containing a $LaTeX$ representation of the MathPiper expression {expr}. Currently the exporter handles most expression types but not all. + +*E.G. + +In> TeXForm(Sin(a1)+2*Cos(b1)) +Result: "\$\sin a_{1} + 2 \cos b_{1}\$"; + +*SEE PrettyForm, CForm +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/Apart.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/Apart.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/Apart.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/Apart.mpw 2011-04-20 20:49:14.000000000 +0000 @@ -0,0 +1,57 @@ +%mathpiper,def="Apart" + +//Retract("Apart",*); + +Apart(_f) <-- Apart(f,x); + +Apart(_f,_var) <-- +[ + Local(rat); + //rat:=RationalForm(f,var); // hso 100215 (this step seems superfluous and wrong!) + rat := {Numerator(f),Denominator(f)}; + If(Degree(rat[1],var) = 0 And Degree(rat[2],var) = 0, + [ + rat:={Coef(rat[1],var,0),Coef(rat[2],var,0)}; + Local(summed,add); + summed := Eval(PartFracExpand(Rem(rat[1],rat[2]),rat[2])); + add:=(rat[1]/rat[2] - summed); + add + summed; + ] + , + [ + /*TODO check this one! Do we have to do the same as with the + * integers? + */ + Expand(Quotient(rat[1],rat[2])) + PartFracExpand(Rem(rat[1],rat[2]),rat[2]); + ] + ); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="Apart",categories="User Functions;Number Theory" +*CMD Apart --- creates a partial fraction expansion of a polynomial +*CALL + Apart(expression) + Apart(expression, var) + +*PARMS + +{expression} -- a rational function + +{var} -- specify that all variables other than {var} are constants + +*DESC +Creates a partial fraction expansion of a rational function. + +*E.G. +In> Apart(1/(x^2-1),x); +Result: 1/(2*(x-1))+(-1)/(2*(x+1)) + +*SEE Together + +%/mathpiper_docs + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ChineseRemainderInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ChineseRemainderInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ChineseRemainderInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ChineseRemainderInteger.mpw 2010-01-06 02:51:37.000000000 +0000 @@ -0,0 +1,26 @@ +%mathpiper,def="ChineseRemainderInteger" + +/* Chinese Remaindering algorithm, as described in "Modern Computer Algebra". + */ +ChineseRemainderInteger(mlist_IsList,vlist_IsList) <-- +[ + Local(m,i,nr,result,msub,euclid,clist); + clist:={}; + m:=Product(mlist); + result:=0; + + nr:=Length(mlist); + For(i:=1,i<=nr,i++) + [ + msub:=Quotient(m,mlist[i]); + euclid := ExtendedEuclidean(msub,mlist[i]); + Local(c); + c:=vlist[i] * euclid[2]; + c:=Rem(c, mlist[i]); + DestructiveAppend(clist,c); + result:=result + msub * c; + ]; + {result,clist}; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ChineseRemainderPoly.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ChineseRemainderPoly.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ChineseRemainderPoly.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ChineseRemainderPoly.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="ChineseRemainderPoly" + +ChineseRemainderPoly(mlist_IsList,vlist_IsList) <-- +[ + Local(m,i,nr,result,msub,euclid,clist); + clist:={}; + m:=Product(mlist); + result:=0; + +/* Echo({mlist,m}); */ + + + nr:=Length(mlist); + For(i:=1,i<=nr,i++) + [ + msub:=Quotient(m,mlist[i]); + +/* Echo({Factor(msub)}); */ + + euclid := ExtendedEuclideanMonic(msub,mlist[i]); + Local(c); + + c:=vlist[i] * euclid[2]; + + c:=Modulo(c, mlist[i]); + + DestructiveAppend(clist,c); + result:=result + msub * c; + ]; + {Expand(result),clist}; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ExtendedEuclideanMonic.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ExtendedEuclideanMonic.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ExtendedEuclideanMonic.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ExtendedEuclideanMonic.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="ExtendedEuclideanMonic" + +ExtendedEuclideanMonic(_f,_g) <-- +[ + Local(rho,r,s,t,i); + +/* +Echo({f,g}); +Echo({}); +*/ + + /* Initialize the loop */ + rho:={LeadingCoef(f),LeadingCoef(g)}; + r:={Monic(f),Monic(g)}; + s:={1/(rho[1]),0}; + t:={0,1/(rho[2])}; + i:=1; + + Local(q,newr,news,newt,newrho); + newr:=r[2]; + While(newr != 0) + [ + q :=Quotient(r[i],r[i+1]); + newr:=Modulo(r[i],r[i+1]); + newrho:=LeadingCoef(newr); + + + If (newr != 0, newr:=Monic(newr)); + news :=(s[i]-q*s[i+1]); + newt :=(t[i]-q*t[i+1]); + If(newrho != 0, + [ + news:=news/newrho; + newt:=newt/newrho; + ]); + DestructiveAppend(rho,newrho); + DestructiveAppend(r ,newr); + DestructiveAppend(s,news); + DestructiveAppend(t,newt); + i++; + ]; + +/* +TableForm({i,r,s,t}); +Echo({}); +*/ + + {r[i],s[i],t[i]}; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ExtendedEuclidean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ExtendedEuclidean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/ExtendedEuclidean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/ExtendedEuclidean.mpw 2010-01-06 02:51:37.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="ExtendedEuclidean" + +/* Extended Euclidean algorithm. Algorithm taken from + * "Modern Computer Algebra". It does a Gcd calculation, but + * returns the intermediate results also. + * + * Returns {l,r,s,t} + * where + * - l the number of steps required + * - r[i] the i-th remainder + * - s[i] and t[i] the i-th bezout coefficients of f and g: + s[i]*f + t[i]*g = r[i] . + * The gcd is r[l]. + * + * This is a slightly modified version from the one described in + * "Modern Computer Algebra", where the elements in list r are not + * monic. If needed this can be done afterwards. As a consequence + * this version works on integers as well as on polynomials. + */ + +ExtendedEuclidean(_f,_g) <-- +[ + Local(r,s,t,i); + + /* Initialize the loop */ + r:={f,g}; + s:={1,0}; + t:={0,1}; + i:=1; + + Local(q,newr,news,newt); + newr:=1; + While(newr != 0) + [ + newr:=Rem(r[i],r[i+1]); + q :=Quotient(r[i],r[i+1]); + news :=(s[i]-q*s[i+1]); + newt :=(t[i]-q*t[i+1]); + DestructiveAppend(r ,newr); + DestructiveAppend(s,news); + DestructiveAppend(t,newt); + i++; + ]; + {r[i],s[i],t[i]}; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/GcdReduce.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/GcdReduce.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/GcdReduce.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/GcdReduce.mpw 2010-01-06 02:51:37.000000000 +0000 @@ -0,0 +1,20 @@ +%mathpiper,def="GcdReduce" + +/* Reduce rational function by dividing gcd away */ +GcdReduce(_f,_var)<-- +[ + Local(rat,gcd); + rat:=RationalForm(f,var); + gcd:=Gcd(rat[1],rat[2]); +/* gcd:=gcd*Gcd(Content(rat[1]),Content(rat[2]));*/ + + Local(numer,denom,lc); + numer:=Quotient(rat[1],gcd); + denom:=Quotient(rat[2],gcd); + lc:=LeadingCoef(numer,var); + numer:=numer/lc; + denom:=denom/lc; + Expand(numer)/Expand(denom); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/PAdicExpandInternal.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/PAdicExpandInternal.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/PAdicExpandInternal.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/PAdicExpandInternal.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,9 @@ +%mathpiper,def="PAdicExpandInternal" + +10 # PAdicExpandInternal(0,_y) <-- {}; +20 # PAdicExpandInternal(_x,_y) <-- +[ + Modulo(x,y) : PAdicExpandInternal(Quotient(x,y),y); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/PAdicExpand.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/PAdicExpand.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/PAdicExpand.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/PAdicExpand.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,88 @@ +%mathpiper,def="PAdicExpand" + +/* + TODO: + + + + + - example: + 20 # f(_x) <-- Sin(x); + 10 # f(Eval(_x)) <-- Sin(Eval(x)); + HoldArgumentNumber("f",1,1); + + Out( 0 ) = True; + In( 1 ) = f(2+3) + Out( 1 ) = Sin(2+3); + In( 2 ) = f(Eval(2+3)) + Out( 2 ) = Sin(5); + + Alternative: + f(x):= + [ + Unholdable(x); + Sin(x); + ]; + + this is if you don't want to use patterns. + + + Mini-module padic. This module creates a p-adic expansion of + an expression: + + expression = a0 + a1*p + a2 * p^2 + ... etc. + + PAdicExpand and PAdicExpandInternal can be called with integer + or univariate polynomial arguments. + */ + + +Expand(x); /* TODO no idea why this is needed! Mod/Div/UniVariate thing :-( */ + +10 # PAdicExpand(_x,_y) <-- +[ + Local(coefs); + coefs:=PAdicExpandInternal(x,y); + Subst(p,y)Add(coefs*(p^(0 .. Length(coefs)))); +]; + +%/mathpiper + + + +%mathpiper_docs,name="PAdicExpand",categories="User Functions;Number Theory" +*CMD PAdicExpand --- p-adic expansion +*STD +*CALL + PAdicExpand(n, p) + +*PARMS + +{n} -- number or polynomial to expand + +{p} -- base to expand in + +*DESC + +This command computes the $p$-adic expansion of $n$. In other words, +$n$ is expanded in powers of $p$. The argument $n$ can be either +an integer or a univariate polynomial. The base $p$ should be of the +same type. + +*E.G. + +In> PrettyForm(PAdicExpand(1234, 10)); + + 2 3 + 3 * 10 + 2 * 10 + 10 + 4 + +Result: True; +In> PrettyForm(PAdicExpand(x^3, x-1)); + + 2 3 + 3 * ( x - 1 ) + 3 * ( x - 1 ) + ( x - 1 ) + 1 + +Result: True; + +*SEE Mod, ContFrac, FromBase, ToBase +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/PartFracExpand.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/PartFracExpand.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/padic/PartFracExpand.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/padic/PartFracExpand.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="PartFracExpand" + +/* Partial fraction expansion of g/f with Degree(g) Together(a/b + c/d) +Result: (d*a+b*c)/(d*b) + +*SEE Apart + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/DefinePattern.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/DefinePattern.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/DefinePattern.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/DefinePattern.mpw 2010-07-14 23:26:25.000000000 +0000 @@ -0,0 +1,70 @@ +%mathpiper,def="DefinePattern",private="true" + +Rulebase("DefinePattern",{leftOperand, rightOperand, rulePrecedence, postPredicate}); + + + +Rule("DefinePattern",4,9,IsEqual(Type(leftOperand),"_")) +[ + DefinePattern(leftOperand[1], rightOperand, rulePrecedence, leftOperand[2]); +]; + + + +Rule("DefinePattern",4,10,True) +[ + Local(patternFlat,patternVariables, pattern, patternOperator, arg, arity); + + Bind(patternFlat, FunctionToList(leftOperand)); //Turn the pattern into a list. + + Bind(patternVariables, Rest(patternFlat)); //Remove the function name from the list. + + Bind(patternOperator,ToString(First(patternFlat))); //Obtain the function name. + + Bind(arity,Length(patternVariables)); //Obtain the arity of the function. + + DefLoadFunction(patternOperator); //Load the function if it exists. + + /* + If the function does not exist, create it. + */ + If(Not(RulebaseDefined(patternOperator,arity)), + [ + MacroRulebase(patternOperator,MakeVector(arg,arity)); + ] + ); + + Bind(pattern,PatternCreate(patternVariables,postPredicate)); + + MacroRulePattern(patternOperator,arity,rulePrecedence, pattern)rightOperand; + + True; +]; + +%/mathpiper + + + +DefinePattern(leftOperand[2],rightOperand,leftOperand[1],True); + + +%mathpiper_docs,name="DefinePattern",categories="Programmer Functions;Programming;Built In" +*CMD DefinePattern --- defines a rule which uses a pattern as its predicate + +*CALL + DefinePattern("operator", arity, precedence, pattern) body +*PARMS + +{"operator"} -- string, name of function + +{arity}, {precedence} -- integers + +{pattern} -- a pattern object + +{body} -- expression, body of rule + +*DESC +This function defines a rule which uses a pattern as its predicate. + +*SEE MacroRulePattern +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/lessthan_negative_negative_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/lessthan_negative_negative_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/lessthan_negative_negative_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/lessthan_negative_negative_operator.mpw 2010-08-23 07:18:42.000000000 +0000 @@ -0,0 +1,159 @@ +%mathpiper,def="<--" + +Rulebase("<--",{leftOperand,rightOperand}); + + + +Rule("<--",2,1,IsEqual(Type(leftOperand),"#")) +[ + DefinePattern(leftOperand[2],rightOperand,leftOperand[1],True); +]; + + + +Rule("<--",2,2,IsFunction(leftOperand)) +[ + DefinePattern(leftOperand,rightOperand,0,True); +]; + +HoldArgument("<--",leftOperand); +HoldArgument("<--",rightOperand); + +%/mathpiper + + + + +%mathpiper_docs,name="<--",categories="Operators" +*CMD <-- --- defines a rule which uses patterns and predicate functions to determine if it is true or not + +*CALL +fn(_arg1, _arg2) <-- expression +fn(arg1_PredicateFunction, _arg2) <-- expression +fn(arg1_PredicateFunction, arg2_PredicateFunction) <-- expression +fn(arg1_PredicateFunction, arg2_PredicateFunction)_(PredicateExpression) <-- expression +_arg1 operator _arg2 <-- expression +arg1_PredicateFunction operator _arg2 <-- expression +arg1_PredicateFunction operator arg2_PredicateFunction <-- expression +arg1_PredicateFunction operator arg2_PredicateFunction_(PredicateExpression) <-- expression + +*PARMS + +{arg} -- an expression +{operator} -- an operator + +*DESC +Mathematical calculations require versatile transformations on symbolic quantities. +Instead of trying to define all possible transformations, MathPiper provides a simple +and easy to use pattern matching scheme for manipulating expressions according to +user-defined rules. MathPiper itself is designed as a small core engine executing +a large library of rules to match and replace patterns. +One simple application of pattern-matching rules is to define new functions. (This +is actually the only way MathPiper can learn about new functions.) As an example, +let's define a function f that will evaluate factorials of non-negative integers. +We will define a predicate to check whether our argument is indeed a non-negative +integer, and we will use this predicate and the obvious recursion +f(n)=n*f(n-1) if n>0 and 1 if n=0 to evaluate the factorial. + +We start with the simple termination condition, which is that f(n) should return +one if n is zero: + +{10 # f(0) <-- 1;} + +You can verify that this already works for input value zero, with f(0). + +Now we come to the more complex line + +20 # f(n_IsIntegerGreaterThanZero) <-- n*f(n-1); + +We realize we need a function IsGreaterThanZero, so we define this function, with +IsIntegerGreaterThanZero(_n) <-- (IsInteger(n) And n>0); + +You can verify that it works by trying f(5), which should return the same value as 5!. + +In the above example we have first defined two "simplification rules" for a new +function f(). Then we realized that we need to define a predicate IsIntegerGreaterThanZero(). +A predicate equivalent to IsIntegerGreaterThanZero() is actually already defined +in the standard library and it's called IsPositiveInteger, so it was not necessary, +strictly speaking, to define our own predicate to do the same thing. We did it here +just for illustration purposes. + +The first two lines recursively define a factorial function f(n)=n*(n-1)*...*1. +The rules are given precedence values 10 and 20, so the first rule will be applied +first. Incidentally, the factorial is also defined in the standard library as a +postfix operator ! and it is bound to an internal routine much faster than the +recursion in our example. The example does show how to create your own routine with +a few lines of code. One of the design goals of MathPiper was to allow precisely +that, definition of a new function with very little effort. + +The operator <-- defines a rule to be applied to a specific function. (The <-- operation +cannot be applied to an atom.) The _n in the rule for IsIntegerGreaterThanZero() +specifies that any object which happens to be the argument of that predicate is +matched and assigned to the local variable n. The expression to the right of <-- can +use n (without the underscore) as a variable. + +Now we consider the rules for the function f. The first rule just specifies that f(0) +should be replaced by 1 in any expression. The second rule is a little more involved. +n_IsIntegerGreaterThanZero is a match for the argument of f, with the proviso that +the predicate IsIntegerGreaterThanZero(n) should return True, otherwise the pattern +is not matched. The underscore operator is to be used only on the left hand side of +the rule definition operator <--. + +There is another, slightly longer but equivalent way of writing the second rule: +20 # f(_n)_(IsIntegerGreaterThanZero(n)) <-- n*f(n-1); + +The underscore after the function object denotes a "postpredicate" that should return +True or else there is no match. This predicate may be a complicated expression involving +several logical operations, unlike the simple checking of just one predicate in the +n_IsIntegerGreaterThanZero construct. The postpredicate can also use the variable +n (without the underscore). + +Precedence values for rules are given by a number followed by the # infix operator +(and the transformation rule after it). This number determines the ordering of precedence +for the pattern matching rules, with 0 the lowest allowed precedence value, i.e. +rules with precedence 0 will be tried first. Multiple rules can have the same number: +this just means that it doesn't matter what order these patterns are tried in. If no +number is supplied, 0 is assumed. In our example, the rule f(0) <-- 1 must be applied +earlier than the recursive rule, or else the recursion will never terminate. But as +long as there are no other rules concerning the function f, the assignment of numbers +10 and 20 is arbitrary, and they could have been 500 and 501 just as well. It is +usually a good idea however to keep some space between these numbers, so you have +room to insert new transformation rules later on. + +Predicates can be combined: for example, {IsIntegerGreaterThanZero()} could also +have been defined as: +10 # IsIntegerGreaterThanZero(n_IsInteger)_(n>0) <-- True; +20 # IsIntegerGreaterThanZero(_n) <-- False; + +The first rule specifies that if n is an integer, and is greater than zero, the +result is True, and the second rule states that otherwise (when the rule with +precedence 10 did not apply) the predicate returns False. + +In the above example, the expression n > 0 is added after the pattern and allows +the pattern to match only if this predicate return True. This is a useful syntax +for defining rules with complicated predicates. There is no difference between the +rules F(n_IsPositiveInteger) <--... and F(_n)_(IsPositiveInteger(n)) <-- ... except +that the first syntax is a little more concise. + +The left hand side of a rule expression has the following form: +precedence # pattern _ postpredicate <-- replacement ; + +The optional precedence must be a positive integer. +Some more examples of rules (not made clickable because their equivalents are already +in the basic MathPiper library): +10 # _x + 0 <-- x; +20 # _x - _x <-- 0; +ArcSin(Sin(_x)) <-- x; + +The last rule has no explicit precedence specified in it (the precedence zero will +be assigned automatically by the system). MathPiper will first try to match the pattern +as a template. Names preceded or followed by an underscore can match any one object: +a number, a function, a list, etc. MathPiper will assign the relevant variables as +local variables within the rule, and try the predicates as stated in the pattern. +The post-predicate (defined after the pattern) is tried after all these matched. +As an example, the simplification rule _x - _x <--0 specifies that the two objects +at left and at right of the minus sign should be the same for this transformation +rule to apply. + +*SEE := +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/MakeVector.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/MakeVector.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/MakeVector.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/MakeVector.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="MakeVector" + +Rulebase("MakeVector",{vec,dimension}); +Rule("MakeVector",2,1,True) +[ + Local(res,i); + res:={}; + i:=1; + Bind(dimension,AddN(dimension,1)); + While(IsLessThan(i,dimension)) + [ + DestructiveInsert(res,1,ToAtom(ConcatStrings(ToString(vec),ToString(i)))); + Bind(i,AddN(i,1)); + ]; + DestructiveReverse(res); +]; + +%/mathpiper + + + +%mathpiper_docs,name="MakeVector",categories="User Functions;Lists (Operations)" +*CMD MakeVector --- vector of uniquely numbered variable names +*STD +*CALL + MakeVector(var,n) + +*PARMS + +{var} -- free variable + +{n} -- length of the vector + +*DESC + +A list of length "n" is generated. The first entry contains the +identifier "var" with the number 1 appended to it, the second entry +contains "var" with the suffix 2, and so on until the last entry +which contains "var" with the number "n" appended to it. + +*E.G. + +In> MakeVector(a,3) +Result: {a1,a2,a3}; + +*SEE RandomIntegerList, ZeroVector +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/pound_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/pound_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/patterns/pound_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/patterns/pound_operator.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not defined in the scripts. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_2d/backends.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_2d/backends.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_2d/backends.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_2d/backends.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,166 @@ +%mathpiper,def="Plot2DOutputs" + +////////////////////////////////////////////////// +/// Backends for 2D plotting +////////////////////////////////////////////////// + + +/// List of all defined backends and their symbolic labels. +/// Add any new backends here + +LocalSymbols(options) +[ + options := { + {"default", "data"}, + {"data", "Plot2DData"}, + {"java", "Plot2DJava"}, + {"geogebra", "Plot2DGeoGebra"}, + {"jfreechart", "Plot2DJFreeChart"}, +}; + + +Plot2DOutputs() := options; + +]; + +/* + How backends work: + Plot2D'(values, optionsHash) + optionsHash is a hash that contains all plotting options: + ["xrange"] - a list of {x1, x2}, ["xname"] - name of the variable to plot, ["yname"] - array of string representations of the function(s), and perhaps other options relevant to the particular backend. + {values} is a list of lists of pairs of the form {{{x1, y1}, {x2, y2}, ...}, {{x1, z1}, {x2, z2}, ...}, ...} corresponding to the functions y(x), z(x), ... to be plotted. The abscissa points x[i] are not the same for all functions. + The backend should prepare the graph of the function(s). The "datafile" backend Plot2D'datafile(values, optionsHash) may be used to output all data to file(s), in which case the file name should be given by the value optionsHash["filename"]. Multiple files are created with names obtained by appending numbers to the filename. + Note that the "data" backend does not do anything and simply returns the data. + The backend Plot2D'datafile takes care not to write "Infinity" or "Undefined" data points (it just ignores them). Custom backends should either use Plot2D'datafile or take care of this themselves. +*/ + +/// trivial backend: return data list (do not confuse with Plot2D'get'data() defined in the main code which is the middle-level plotting routine) +Plot2DData(values_IsList, _optionsHash) <-- values; + +/// The Java back-end generates a call-list that the Java graph plotter can handle +Plot2DJava(values_IsList, _optionsHash) <-- +[ + Local(result,count); + count := 0; + result:="$plot2d:"; + + result := result:" pensize 2.0 "; + ForEach(function,values) + [ + result := result:ColorForGraphNr(count); + count++; + result:=result:" lines2d ":ToString(Length(function)); + + function:=Select(function, Lambda({item},item[2] != Undefined)); + + ForEach(item,function) + [ + result := result:" ":ToString(item[1]):" ":ToString(item[2]):" "; + ]; + ]; + WriteString(result:"$"); + True; +]; + +10 # ColorForGraphNr(0) <-- " pencolor 64 64 128 "; +10 # ColorForGraphNr(1) <-- " pencolor 128 64 64 "; +10 # ColorForGraphNr(2) <-- " pencolor 64 128 64 "; +20 # ColorForGraphNr(_count) <-- ColorForGraphNr(Modulo(count,3)); + + + + +//GeoGebra backend. +Plot2DGeogebra(values_IsList, _optionsHash) <-- +[ + Local(result,count); + count := 0; + result:=""; + + + ForEach(function,values) + [ + + function:=Select(function, Lambda({item},item[2] != Undefined)); + + ForEach(item,function) + [ + result := result:"(":ToString(item[1]):",":ToString(item[2]):")":Nl(); + ]; + ]; + WriteString(result); + True; +]; + + + + +//JFreeChart backend. +//Retract("Plot2DJFreeChart", *); +Plot2DJFreeChart(values_IsList, _optionsHash) <-- +[ + Local(rangeList, domainList, function, allProcessedFunctionData, lineChartCallListForm); + + + + //Remove Plot2D's options so that they don't get passed through to LineChart(); + ForEach(name, {"xrange", "xname", "yname", "output", "precision", "points", "depth"}) + [ + AssocDelete(optionsHash, name); + ]; + + + + //Convert {x,y} pairs into {x,x,x,...} {y,y,y,...} form. + allProcessedFunctionData := {}; + + ForEach(function,values) + [ + rangeList := {}; + + domainList := {}; + + function := Select(function, Lambda({item},item[2] != Undefined)); + + ForEach(item,function) + [ + rangeList := Append(rangeList, item[1]); + + domainList := Append(domainList, item[2]); + ]; + + allProcessedFunctionData := Append(allProcessedFunctionData, rangeList); + allProcessedFunctionData := Append(allProcessedFunctionData, domainList); + + ]; + + + + //Put LineChart() function call into list form so it can be manipulated. + lineChartCallListForm := {LineChart, allProcessedFunctionData }; + + + + //Add any options to the list. + ForEach(key, AssocIndices(optionsHash)) + [ + lineChartCallListForm := Append(lineChartCallListForm, Apply("->", {key, optionsHash[key]})); + ]; + + + + //Call the LineChart() function. + Eval(ListToFunction(lineChartCallListForm)); + + +]; + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_2d/plot2d.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_2d/plot2d.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_2d/plot2d.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_2d/plot2d.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,333 @@ +%mathpiper,def="Plot2D" + +//Retract("Plot2D", *); + +////////////////////////////////////////////////// +/// Plot2D --- adaptive two-dimensional plotting +////////////////////////////////////////////////// + +/// definitions of backends +//LoadScriptOnce("plots.rep/backends_2d.mpi"); + +/* + Plot2D is an interface for various backends (Plot2D'...). It calls +Plot2D'get'data to obtain the list of points and values, and then it calls +Plot2D' on that data. + + Algorithm for Plot2D'get'data: + 1) Split the given interval into Quotient(points+3, 4) subintervals, and split each subinterval into 4 parts. + 2) For each of the parts: evaluate function values and call Plot2D'adaptive + 3) concatenate resulting lists and return +*/ + +LocalSymbols(var, func, range, option, options'list, delta, options'hash, c, fc, all'values, dummy) +[ + +// declaration of Plot2D with variable number of arguments +Function() Plot2D(func); +Function() Plot2D(func, range); +Function() Plot2D(func, range, options, ...); + +/// interface routines +1 # Plot2D(_func) <-- ("Plot2D" @ {func, -5:5}); +2 # Plot2D(_func, _range) <-- ("Plot2D" @ {func, range, {}}); +3 # Plot2D(_func, _range, option_IsFunction) _ (Type(option) = "->" ) <-- ("Plot2D" @ {func, range, {option}}); + +/// Plot a single function +5 # Plot2D(_func, _range, options'list_IsList)_(Not IsList(func)) <-- ("Plot2D" @ {{func}, range, options'list}); + +/// Top-level 2D plotting routine: +/// plot several functions sharing the same xrange and other options +4 # Plot2D(func'list_IsList, _range, options'list_IsList) <-- +[ + Local(var, func, delta, options'hash, c, fc, all'values, dummy); + all'values := {}; + options'hash := "OptionsListToHash" @ {options'list}; + + + // this will be a string - name of independent variable + options'hash["xname"] := ""; + // this will be a list of strings - printed forms of functions being plotted + options'hash["yname"] := {}; + // parse range + If ( + Type(range) = "->", // variable also specified -- ignore for now, store in options + [ + // store alternative variable name + options'hash["xname"] := ToString(range[1]); + range := range[2]; + ] + ); + If( + Type(range) = ":", // simple range + range := N(Eval({range[1], range[2]})) + ); + // set default option values + If( + options'hash["points"] = Empty, + options'hash["points"] := 23 + ); + If( + options'hash["depth"] = Empty, + options'hash["depth"] := 5 + ); + If( + options'hash["precision"] = Empty, + options'hash["precision"] := 0.0001 + ); + If( + options'hash["output"] = Empty Or IsString(options'hash["output"]) And Plot2DOutputs()[options'hash["output"]] = Empty, + options'hash["output"] := Plot2DOutputs()["default"] + ); + // a "filename" parameter is required when using data file + If( + options'hash["output"] = "datafile" And options'hash["filename"] = Empty, + options'hash["filename"] := "output.data" + ); + + // we will divide each subinterval in 4 parts, so divide number of points by 4 now + options'hash["points"] := N(Eval(Quotient(options'hash["points"]+3, 4))); + + // in case it is not a simple number but an unevaluated expression + options'hash["precision"] := N(Eval(options'hash["precision"])); + + // store range in options + options'hash["xrange"] := {range[1], range[2]}; + + // compute the separation between grid points + delta := N(Eval( (range[2] - range[1]) / (options'hash["points"]) )); + + // check that the input parameters are valid (all numbers) + Check(IsNumber(range[1]) And IsNumber(range[2]) And IsNumber(options'hash["points"]) And IsNumber(options'hash["precision"]), + "Argument", + "Plot2D: Error: plotting range '" + :(PipeToString()Write(range)) + :"' and/or the number of points '" + :(PipeToString()Write(options'hash["points"])) + :"' and/or precision '" + :(PipeToString()Write(options'hash["precision"])) + :"' is not numeric" + ); + // loop over functions in the list + ForEach(func, func'list) + [ + // obtain name of variable + var := VarList(func); // variable name in a one-element list + Check(Length(var)<=1, "Argument", "Plot2D: Error: expression is not a function of one variable: " + :(PipeToString()Write(func)) + ); + // Allow plotting of constant functions + If(Length(var)=0, var:={dummy}); + // store variable name if not already done so + If( + options'hash["xname"] = "", + options'hash["xname"] := ToString(VarList(var)[1]) + ); + // store function name in options + DestructiveAppend(options'hash["yname"], PipeToString()Write(func)); + // compute the first point to see if it's okay + c := range[1]; + fc := N(Eval(Apply({var, func}, {c}))); + Check(IsNumber(fc) Or fc=Infinity Or fc= -Infinity Or fc=Undefined, + "Argument", + "Plot2D: Error: cannot evaluate function '" + :(PipeToString()Write(func)) + :"' at point '" + :(PipeToString()Write(c)) + :"' to a number, instead got '" + :(PipeToString()Write(fc)) + :"'" + ); + // compute all other data points + DestructiveAppend(all'values, Plot2D'get'data(func, var, c, fc, delta, options'hash) ); + + If(InVerboseMode(), Echo({"Plot2D: using ", Length(all'values[Length(all'values)]), " points for function ", func}), True); + ]; + + // call the specified output backend + Plot2DOutputs()[options'hash["output"]] @ {all'values, options'hash}; +]; + +//HoldArgument("Plot2D", range); +//HoldArgument("Plot2D", options); +HoldArgumentNumber("Plot2D", 2, 2); +HoldArgumentNumber("Plot2D", 3, 2); +HoldArgumentNumber("Plot2D", 3, 3); + + + +//Retract("Plot2D'get'data", *); +/// this is the middle-level plotting routine; it generates the initial +/// grid, calls the adaptive routine, and gathers data points. +/// func must be just one function (not a list) +Plot2D'get'data(_func, _var, _x'init, _y'init, _delta'x, _options'hash) <-- +[ + Local(i, a, fa, b, fb, c, fc, result); + // initialize list by first points (later will always use Rest() to exclude first points of subintervals) + result := { {c,fc} := {x'init, y'init} }; + For(i:=0, i value) + Plot2D(f(x), a:b, option -> value, ...) + Plot2D(list, ...) + +*PARMS + +{f(x)} -- unevaluated expression containing one variables (function to be plotted) + +{list} -- list of functions to plot + +{a}, {b} -- numbers, plotting range in the $x$ coordinate + +{option} -- atom, option name + +{value} -- atom, number or string (value of option) + +*DESC +The routine {Plot2D} performs adaptive plotting of one or several functions +of one variable in the specified range. +The result is presented as a line given by the equation $y=f(x)$. +Several functions can be plotted at once. +Various plotting options can be specified. +Output can be directed to a plotting program (the default is to use +{data}) to a list of values. + +The function parameter {f(x)} must evaluate to a MathPiper expression containing +at most one variable. (The variable does not have to be called {x}.) +Also, {N(f(x))} must evaluate to a real (not complex) numerical value when given a numerical value of the argument {x}. +If the function {f(x)} does not satisfy these requirements, an error is raised. + +Several functions may be specified as a list and they do not have to depend on the same variable, for example, {{f(x), g(y)}}. +The functions will be plotted on the same graph using the same coordinate ranges. + +If you have defined a function which accepts a number but does not +accept an undefined variable, {Plot2D} will fail to plot it. +Use {NFunction} to overcome this difficulty. + +Data files are created in a temporary directory {/tmp/plot.tmp/} unless otherwise requested. +File names +and other information is printed if {InVerboseMode()} returns {True} on using {V()}. + +The current algorithm uses Newton-Cotes quadratures and some heuristics for error estimation (see <*mathpiperdoc://Algo/3/1/*>). +The initial grid of {points+1} points is refined between any grid points $a$, $b$ if the integral +$Integrate(x,a,b)f(x)$ is not approximated to the given precision by +the existing grid. + +Default plotting range is {-5:5}. Range can also be specified as {x= -5:5} (note the mandatory space separating "{=}" and "{-}"); +currently the variable name {x} is ignored in this case. + +Options are of the form {option -> value}. Currently supported option names +are: "points", "precision", "depth", "output", "filename", "yrange". Option values +are either numbers or special unevaluated atoms such as {data}. +If you need to use the names of these atoms +in your script, strings can be used. Several option/value pairs may be specified (the function {Plot2D} has a variable number of arguments). + +* {yrange}: the range of ordinates to use for plotting, e.g. +{yrange=0:20}. If no range is specified, the default is usually to +leave the choice to the plotting backend. +* {points}: initial number of points (default 23) -- at least that +many points will be plotted. The initial grid of this many points will be +adaptively refined. +* {precision}: graphing precision (default $10^(-6)$). This is interpreted as the relative precision of computing the integral of $f(x)-Minimum(f(x))$ using the grid points. For a smooth, non-oscillating function this value should be roughly 1/(number of screen pixels in the plot). +* {depth}: max. refinement depth, logarithmic (default 5) -- means there will be at most $2^depth$ extra points per initial grid point. +* {output}: name of the plotting backend. Supported names: {data} (default). +The {data} backend will return the data as a list of pairs such as {{{x1,y1}, {x2,y2}, ...}}. +* {filename}: specify name of the created data file. For example: {filename="data1.txt"}. +The default is the name {"output.data"}. +Note that if several functions are plotted, the data files will have a number appended to the given name, for example {data.txt1}, {data.txt2}. + +Other options may be supported in the future. + +The current implementation can deal with a singularity within the plotting range only if the function {f(x)} returns {Infinity}, {-Infinity} or +{Undefined} at the singularity. +If the function {f(x)} generates a numerical error and fails at a +singularity, {Plot2D} will fail if one of the grid points falls on the +singularity. +(All grid points are generated by bisection so in principle the +endpoints and the {points} parameter could be chosen to avoid numerical +singularities.) + +*WIN32 + + + +*SEE V, NFunction, Plot3DS +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_3d/backends.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_3d/backends.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_3d/backends.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_3d/backends.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="" + +////////////////////////////////////////////////// +/// Backends for 3D plotting +////////////////////////////////////////////////// + +/// List of all defined backends and their symbolic labels. +/// Add any new backends here +Plot3DS'outputs() := { + {"default", "data"}, + {"data", "Plot3DS'data"}, +}; + +/* + How backends work: + Plot3DS'(values, options'hash) + options'hash is a hash that contains all plotting options: + ["xrange"] - a list of {x1, x2}, ["xname"] - name of the variable to plot, same for "yrange"; + ["zname"] - array of string representations of the function(s), and perhaps other options relevant to the particular backend. + {values} is a list of lists of triples of the form {{{x1, y1, z1}, {x2, y2, z2}, ...}, {{x1, y1, t1}, {x2, y2, t2}, ...}, ...} corresponding to the functions z(x,y), t(x,y), ... to be plotted. The points x[i], y[i] are not necessarily the same for all functions. + The backend should prepare the graph of the function(s). The "datafile" backend Plot3DS'datafile(values, options'hash) may be used to output all data to file(s), in which case the file name should be given by the value options'hash["filename"]. Multiple files are created with names obtained by appending numbers to the filename. + Note that the "data" backend does not do anything and simply returns the data. + The backend Plot3DS'datafile takes care not to write "Infinity" or "Undefined" data points (it just ignores them). Custom backends should either use Plot3DS'datafile to prepare a file, or take care of this themselves. +*/ + +/// trivial backend: return data list (do not confuse with Plot3DS'get'data() defined in the main code which is the middle-level plotting routine) +Plot3DS'data(values_IsList, _options'hash) <-- values; + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_3d/plot3ds.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_3d/plot3ds.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/_3d/plot3ds.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/_3d/plot3ds.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,416 @@ +%mathpiper,def="Plot3DS" + +////////////////////////////////////////////////// +/// Plot3DS --- adaptive three-dimensional surface plotting +////////////////////////////////////////////////// + +/// definitions of backends +//LoadScriptOnce("plots.rep/backends_3d.mpi"); + +/* + Plot3DS is an interface for various backends (Plot3DS'...). It calls +Plot3DS'get'data to obtain the list of points and values, and then it calls +Plot3DS' on that data. + + Algorithm for Plot3DS'get'data: + 1) Split the given square into Quotient(Sqrt(points)+1, 2) subsquares, and split each subsquare into 4 parts. + 2) For each of the parts: evaluate function values and call Plot3DS'adaptive + 3) concatenate resulting lists and return +*/ + + LocalSymbols(var, func, xrange, yrange, option, options'list, xdelta, ydelta, options'hash, cx, cy, fc, all'values, dummy) +[ + +// declaration of Plot3DS with variable number of arguments +Function() Plot3DS(func); +Function() Plot3DS(func, xrange, yrange); +Function() Plot3DS(func, xrange, yrange, options, ...); + + +/// interface routines +1 # Plot3DS(_func) <-- ("Plot3DS" @ {func, -5:5, -5:5}); +2 # Plot3DS(_func, _xrange, _yrange) <-- ("Plot3DS" @ {func, xrange, yrange, {}}); +3 # Plot3DS(_func, _xrange, _yrange, option_IsFunction) _ (Type(option) = "->" ) <-- ("Plot3DS" @ {func, xrange, yrange, {option}}); + +/// Plot a single function +5 # Plot3DS(_func, _xrange, _yrange, options'list_IsList)_(Not IsList(func)) <-- ("Plot3DS" @ {{func}, xrange, yrange, options'list}); + +/// Top-level 3D plotting routine: +/// plot several functions sharing the same ranges and other options +4 # Plot3DS(func'list_IsList, _xrange, _yrange, options'list_IsList) <-- +[ + Local(var, func, xdelta, ydelta, options'hash, cx, cy, fc, all'values, dummy); + // this will be a list of all computed values + all'values := {}; + options'hash := "OptionsListToHash" @ {options'list}; + // this will be a string - name of independent variable + options'hash["xname"] := ""; + options'hash["yname"] := ""; + // this will be a list of strings - printed forms of functions being plotted + options'hash["zname"] := {}; + // parse range + If ( + Type(xrange) = "->", // variable also specified -- ignore for now, store in options + [ + // store alternative variable name + options'hash["xname"] := ToString(xrange[1]); + xrange := xrange[2]; + ] + ); + If ( + Type(yrange) = "->" , // variable also specified -- ignore for now, store in options + [ + // store alternative variable name + options'hash["yname"] := ToString(yrange[1]); + yrange := yrange[2]; + ] + ); + If( + Type(xrange) = ":", // simple range + xrange := N(Eval({xrange[1], xrange[2]})) + ); + If( + Type(yrange) = ":", // simple range + yrange := N(Eval({yrange[1], yrange[2]})) + ); + // set default option values + If( + options'hash["points"] = Empty, + options'hash["points"] := 10 // default # of points along each axis + ); + If( + options'hash["xpoints"] = Empty, + options'hash["xpoints"] := options'hash["points"] + ); + If( + options'hash["ypoints"] = Empty, + options'hash["ypoints"] := options'hash["points"] + ); + + If( + options'hash["depth"] = Empty, + options'hash["depth"] := 2 + ); + If( + options'hash["precision"] = Empty, + options'hash["precision"] := 0.0001 + ); + If( + options'hash["hidden"] = Empty Or Not IsBoolean(options'hash["hidden"]), + options'hash["hidden"] := True + ); + If( + options'hash["output"] = Empty Or IsString(options'hash["output"]) And Plot3DS'outputs()[options'hash["output"]] = Empty, + options'hash["output"] := Plot3DS'outputs()["default"] + ); + // a "filename" parameter is required when using data file + If( + options'hash["output"] = "datafile" And options'hash["filename"] = Empty, + options'hash["filename"] := "output.data" + ); + options'hash["used depth"] := options'hash["depth"]; + // we will divide each subsquare in 4 parts, so divide number of points by 2 now + options'hash["xpoints"] := N(Eval(Quotient(options'hash["xpoints"]+1, 2))); + options'hash["ypoints"] := N(Eval(Quotient(options'hash["ypoints"]+1, 2))); + // in case it is not a simple number but an unevaluated expression + options'hash["precision"] := N(Eval(options'hash["precision"])); + // store range in options + options'hash["xrange"] := {xrange[1], xrange[2]}; + options'hash["yrange"] := {yrange[1], yrange[2]}; + // compute the separation between grid points + xdelta := N(Eval( (xrange[2] - xrange[1]) / (options'hash["xpoints"]) ) ); + ydelta := N(Eval( (yrange[2] - yrange[1]) / (options'hash["ypoints"]) ) ); + // check that the input parameters are valid (all numbers) + Check(IsNumericList({xrange[1], xrange[2], options'hash["xpoints"], options'hash["ypoints"], options'hash["precision"]}), + "Argument", + "Plot3DS: Error: plotting ranges '" + :(PipeToString()Write(xrange, yrange)) + :"' and/or the number of points '" + :(PipeToString()Write(options'hash["xpoints"], options'hash["ypoints"])) + :"' and/or precision '" + :(PipeToString()Write(options'hash["precision"])) + :"' is not numeric" + ); + // loop over functions in the list + ForEach(func, func'list) + [ + // obtain name of variable + var := VarList(func); // variable names in a list + Check(Length(var)<=2, "Argument", "Plot3DS: Error: expression is not a function of at most two variables: " + :(PipeToString()Write(func)) + ); + // Allow plotting of constant functions + If(Length(var)=0, var:={dummy, dummy}); + If(Length(var)=1, var:={var[1], dummy}); + // store variable name if not already done so + If( + options'hash["xname"] = "", + options'hash["xname"] := ToString(var[1]) + ); + If( + options'hash["yname"] = "", + options'hash["yname"] := ToString(var[2]) + ); + // store function name in options + DestructiveAppend(options'hash["zname"], PipeToString()Write(func)); + // compute the first point to see if it's okay + cx := xrange[1]; cy := yrange[1]; + fc := N(Eval(Apply({var, func}, {cx, cy}))); + Check(IsNumber(fc) Or fc=Infinity Or fc= -Infinity Or fc=Undefined, + "Argument", + "Plot3DS: Error: cannot evaluate function '" + :(PipeToString()Write(func)) + :"' at point '" + :(PipeToString()Write(cx, cy)) + :"' to a number, instead got '" + :(PipeToString()Write(fc)) + :"'" + ); + // compute all other data points + DestructiveAppend(all'values, RemoveRepeated(HeapSort( Plot3DS'get'data(func, var, {cx, cy, fc}, {xdelta, ydelta}, options'hash), Hold({{x,y},x[1]value) + Plot3DS(f(x,y), a:b, c:d, option->value, ...) + Plot3DS(list, ...) + +*PARMS + +{f(x,y)} -- unevaluated expression containing two variables (function to be plotted) + +{list} -- list of functions to plot + +{a}, {b}, {c}, {d} -- numbers, plotting ranges in the $x$ and $y$ coordinates + +{option} -- atom, option name + +{value} -- atom, number or string (value of option) + +*DESC +The routine {Plot3DS} performs adaptive plotting of a function +of two variables in the specified ranges. +The result is presented as a surface given by the equation $z=f(x,y)$. +Several functions can be plotted at once, by giving a list of functions. +Various plotting options can be specified. +Output can be directed to a plotting program (the default is to use +{data}), to a list of values. + +The function parameter {f(x,y)} must evaluate to a MathPiper expression containing +at most two variables. (The variables do not have to be called {x} and {y}.) +Also, {N(f(x,y))} must evaluate to a real (not complex) numerical value when given numerical values of the arguments {x}, {y}. +If the function {f(x,y)} does not satisfy these requirements, an error is raised. + +Several functions may be specified as a list but they have to depend on the same symbolic variables, for example, {{f(x,y), g(y,x)}}, but not {{f(x,y), g(a,b)}}. +The functions will be plotted on the same graph using the same coordinate ranges. + +If you have defined a function which accepts a number but does not +accept an undefined variable, {Plot3DS} will fail to plot it. +Use {NFunction} to overcome this difficulty. + +Data files are created in a temporary directory {/tmp/plot.tmp/} unless otherwise requested. +File names +and other information is printed if {InVerboseMode()} returns {True} on using {V()}. + +The current algorithm uses Newton-Cotes cubatures and some heuristics for error estimation (see <*mathpiperdoc://Algo/3/1/*>). +The initial rectangular grid of {xpoints+1}*{ypoints+1} points is refined within any rectangle where the integral +of $f(x,y)$ is not approximated to the given precision by +the existing grid. + +Default plotting range is {-5:5} in both coordinates. +A range can also be specified with a variable name, e.g. {x= -5:5} (note the mandatory space separating "{=}" and "{-}"). +The variable name {x} should be the same as that used in the function {f(x,y)}. +If ranges are not given with variable names, the first variable encountered in the function {f(x,y)} is associated with the first of the two ranges. + +Options are of the form {option->value}. Currently supported option names +are "points", "xpoints", "ypoints", "precision", "depth", "output", "filename", "xrange", "yrange", "zrange". Option values +are either numbers or special unevaluated atoms such as {data}. +If you need to use the names of these atoms +in your script, strings can be used (e.g. {output="data"}). Several option/value pairs may be specified (the function {Plot3DS} has a variable number of arguments). + +* {xrange}, {yrange}: optionally override coordinate ranges. Note that {xrange} is always the first variable and {yrange} the second variable, regardless of the actual variable names. +* {zrange}: the range of the $z$ axis to use for plotting, e.g. +{zrange=0:20}. If no range is specified, the default is usually to +leave the choice to the plotting backend. Automatic choice based on actual values may +give visually inadequate plots if the function has a singularity. +* {points}, {xpoints}, {ypoints}: initial number of points (default 10 each) -- at least that +many points will be plotted in each coordinate. +The initial grid of this many points will be +adaptively refined. +If {points} is specified, it serves as a default for both {xpoints} and {ypoints}; this value may be overridden by {xpoints} and {ypoints} values. +* {precision}: graphing precision (default $0.01$). This is interpreted as the relative precision of computing the integral of $f(x,y)-Minimum(f(x,y))$ using the grid points. For a smooth, non-oscillating function this value should be roughly 1/(number of screen pixels in the plot). +* {depth}: max. refinement depth, logarithmic (default 3) -- means there will be at most $2^depth$ extra points per initial grid point (in each coordinate). +* {output}: name of the plotting backend. Supported names: {data} (default). +The {data} backend will return the data as a list of triples such as {{{x1, y1, z1}, {x2, y2, z2}, ...}}. + +Other options may be supported in the future. + +The current implementation can deal with a singularity within the plotting range only if the function {f(x,y)} returns {Infinity}, {-Infinity} or +{Undefined} at the singularity. +If the function {f(x,y)} generates a numerical error and fails at a +singularity, {Plot3DS} will fail only if one of the grid points falls on the +singularity. +(All grid points are generated by bisection so in principle the +endpoints and the {xpoints}, {ypoints} parameters could be chosen to avoid numerical +singularities.) + +The {filename} option is optional if using graphical backends, but can be used to specify the location of the created data file. + +*WIN32 + +Same limitations as {Plot2D}. + +*E.G. notest +In> Plot3DS(a*b^2) +Result: True; +In> V(Plot3DS(Sin(x)*Cos(y),x->0:20, y->0:20,depth->3)) + CachedConstant: Info: constant Pi is being + recalculated at precision 10 + CachedConstant: Info: constant Pi is being + recalculated at precision 11 + Plot3DS: using 1699 points for function Sin(x)*Cos(y) + Plot3DS: max. used 8 subdivisions for Sin(x)*Cos(y) + Plot3DS'datafile: created file '/tmp/plot.tmp/data1' +Result: True; + + +*SEE V, NFunction, Plot2D +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/OptionsListToHash.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/OptionsListToHash.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/OptionsListToHash.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/OptionsListToHash.mpw 2010-01-08 23:45:52.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="OptionsListToHash" + +/// utility function: convert options lists of the form +/// "{key=value, key=value}" into a hash of the same form. +/// The argument list is kept unevaluated using "HoldArgumentNumber()". +/// Note that symbolic values of type atom are automatically converted to strings, e.g. ListToHash({a -> b}) returns {{"a", "b"}} +OptionsListToHash(list) := +[ + Local(item, result); + result := {}; + ForEach(item, list) + If( + IsFunction(item) And (Type(item) = "->" ) And IsAtom(item[1]), + result[ToString(item[1])] := If( + IsAtom(item[2]) And Not IsNumber(item[2]) And Not IsString(item[2]), + ToString(item[2]), + item[2] + ), + Echo({"OptionsListToHash: Error: item ", item, " is not of the format a -> b."}) + ); + + result; +]; + +HoldArgumentNumber("OptionsListToHash", 1, 1); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/RemoveRepeated.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/RemoveRepeated.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/RemoveRepeated.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/RemoveRepeated.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="RemoveRepeated" + +10 # RemoveRepeated({}) <-- {}; +10 # RemoveRepeated({_x}) <-- {x}; +20 # RemoveRepeated(list_IsList) <-- [ + Local(i, done); + done := False; + For(i:=0, Not done, i++) + [ + While(iy And yz + ) +, 0, 1); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/WriteDataItem.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/WriteDataItem.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/plots/WriteDataItem.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/plots/WriteDataItem.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,19 @@ +%mathpiper,def="WriteDataItem" + +/// service function. WriteDataItem({1,2,3}, {}) will output "1 2 3" on a separate line. +/// Writes data points to the current output stream, omits non-numeric values. +WriteDataItem(tuple_IsList, _options'hash) <-- +[ + Local(item); + If( // do not write anything if one of the items is not a number + IsNumericList(tuple), + ForEach(item,tuple) + [ + Write(item); + Space(); + ] + ); + NewLine(); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/AllSatisfy.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/AllSatisfy.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/AllSatisfy.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/AllSatisfy.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="AllSatisfy" + +10 # AllSatisfy(pred_IsString,lst_IsList) <-- Apply("And",(MapSingle(pred,lst))); + +20 # AllSatisfy(_pred,_lst) <-- False; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + +%mathpiper_docs,name="AllSatisfy",categories="User Functions;Predicates" + + +*CMD AllSatisfy --- Check if all elements of list {lst} satisfy predicate {pred} + +*STD +*CALL + AllSatisfy(pred,lst) + +*PARMS + +{pred} -- the name of the predicate (as string, with quotes) to be tested + +{lst} -- a list + + +*DESC + +The command {AllSatisfy} returns {True} if every element of the list {lst} satisfies the predicate {pred}. +It returns {False} otherwise. +It also returns {False} if {lst} is not a list, or if {pred} is not a predicate. + +*E.G. + +In> AllSatisfy("IsInteger",{1,0,-5}) +Result> True +In> AllSatisfy("IsPositiveInteger",{1,0,-5}) +Result> False + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/FloatIsInt.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/FloatIsInt.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/FloatIsInt.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/FloatIsInt.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,23 @@ +%mathpiper,def="FloatIsInt" + +/// TODO FIXME document this: FloatIsInt returns True if the argument is integer after removing potential trailing +/// zeroes after the decimal point +// but in fact this should be a call to BigNumber::IsIntValue() +FloatIsInt(_x) <-- + [ + x:=N(Eval(x)); + Local(prec,result,n); + Bind(prec,BuiltinPrecisionGet()); + If(IsZero(x),Bind(n,2), + If(x>0, + Bind(n,2+FloorN(N(FastLog(x)/FastLog(10)))), + Bind(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) + )); + BuiltinPrecisionSet(n+prec); + Bind(result,IsZero(RoundTo(x-Floor(x),prec)) Or IsZero(RoundTo(x-Ceil(x),prec))); + BuiltinPrecisionSet(prec); + result; + ]; +// + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasExprArith.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasExprArith.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasExprArith.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasExprArith.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="HasExprArith" + +/// Analyse arithmetic expressions + +HasExprArith(expr, atom) := HasExprSome(expr, atom, {ToAtom("+"), ToAtom("-"), *, /}); + + +%/mathpiper + + + +%mathpiper_docs,name="HasExprArith",categories="User Functions;Predicates" +*CMD HasExprArith --- check for expression containing a subexpression +*STD +*CALL + HasExprArith(expr, x) + +*PARMS + +{expr} -- an expression + +{x} -- a subexpression to be found + +*DESC + +{HasExprArith} is defined through {HasExprSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> HasExprArith(x+y*Cos(Ln(x)/x), z) +Result: False; + +*SEE HasExpr, HasExprSome, FuncList, VarList, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasExpr.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasExpr.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasExpr.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasExpr.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="HasExpr" + +/// HasExpr --- test for an expression containing a subexpression +/// for checking dependence on variables, this may be faster than using VarList or IsFreeOf and this also can be used on non-variables, e.g. strings or numbers or other atoms or even on non-atoms +// an expression contains itself -- check early +10 # HasExpr(_expr, _atom) _ IsEqual(expr, atom) <-- True; +// an atom contains itself +15 # HasExpr(expr_IsAtom, _atom) <-- IsEqual(expr, atom); +// a list contains an atom if one element contains it +// we test for lists now because lists are also functions +// first take care of the empty list: +19 # HasExpr({}, _atom) <-- False; +20 # HasExpr(expr_IsList, _atom) <-- HasExpr(First(expr), atom) Or HasExpr(Rest(expr), atom); +// a function contains an atom if one of its arguments contains it +30 # HasExpr(expr_IsFunction, _atom) <-- HasExpr(Rest(FunctionToList(expr)), atom); + +%/mathpiper + + + +%mathpiper_docs,name="HasExpr",categories="User Functions;Predicates" +*CMD HasExpr --- check for expression containing a subexpression +*STD +*CALL + HasExpr(expr, x) + +*PARMS + +{expr} -- an expression + +{x} -- a subexpression to be found + + + +*DESC + +The command {HasExpr} returns {True} if the expression {expr} contains a literal subexpression {x}. The expression is recursively traversed. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> HasExpr(x+y*Cos(Ln(z)/z), z) +Result: True; +In> HasExpr(x+y*Cos(Ln(z)/z), Ln(z)) +Result: True; +In> HasExpr(x+y*Cos(Ln(z)/z), z/Ln(z)) +Result: False; + +*SEE HasExprArith, HasExprSome, FuncList, VarList, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasExprSome.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasExprSome.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasExprSome.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasExprSome.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,50 @@ +%mathpiper,def="HasExprSome" + +/// Same except only look at function arguments for functions in a given list +HasExprSome(_expr, _atom, _look'list) _ IsEqual(expr, atom) <-- True; +// an atom contains itself +15 # HasExprSome(expr_IsAtom, _atom, _look'list) <-- IsEqual(expr, atom); +// a list contains an atom if one element contains it +// we test for lists now because lists are also functions +// first take care of the empty list: +19 # HasExprSome({}, _atom, _look'list) <-- False; +20 # HasExprSome(expr_IsList, _atom, _look'list) <-- HasExprSome(First(expr), atom, look'list) Or HasExprSome(Rest(expr), atom, look'list); +// a function contains an atom if one of its arguments contains it +// first deal with functions that do not belong to the list: return False since we have already checked it at #15 +25 # HasExprSome(expr_IsFunction, _atom, _look'list)_(Not Contains(look'list, ToAtom(Type(expr)))) <-- False; +// a function contains an atom if one of its arguments contains it +30 # HasExprSome(expr_IsFunction, _atom, _look'list) <-- HasExprSome(Rest(FunctionToList(expr)), atom, look'list); + +%/mathpiper + + + +%mathpiper_docs,name="HasExprSome",categories="User Functions;Predicates" +*CMD HasExprSome --- check for expression containing a subexpression +*STD +*CALL + HasExprSome(expr, x, list) + +*PARMS + +{expr} -- an expression + +{x} -- a subexpression to be found + +{list} -- list of function atoms to be considered "transparent" + +*DESC + +The command {HasExprSome} does the same as {HasExpr}, except it only looks at arguments of a given {list} of functions. All other functions become "opaque" (as if they do not contain anything). + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> HasExprSome({a+b*2,c/d},c/d,{List}) +Result: True; +In> HasExprSome({a+b*2,c/d},c,{List}) +Result: False; + +*SEE HasExpr, HasExprArith, FuncList, VarList, HasFunc +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasFuncArith.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasFuncArith.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasFuncArith.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasFuncArith.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="HasFuncArith" + +/// Analyse arithmetic expressions + +HasFuncArith(expr, atom) := HasFuncSome(expr, atom, {ToAtom("+"), ToAtom("-"), *, /}); + +%/mathpiper + + + +%mathpiper_docs,name="HasFuncArith",categories="User Functions;Predicates" +*CMD HasFuncArith --- check for expression containing a function +*STD +*CALL + HasFuncArith(expr, func) + +*PARMS + +{expr} -- an expression + +{func} -- a function atom to be found + +*DESC + +{HasFuncArith} is defined through {HasFuncSome} to look only at arithmetic operations {+}, {-}, {*}, {/}. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> HasFuncArith(x+y*Cos(Ln(x)/x), Cos) +Result: True; +In> HasFuncArith(x+y*Cos(Ln(x)/x), Ln) +Result: False; + +*SEE HasFunc, HasFuncSome, FuncList, VarList, HasExpr +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasFunc.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasFunc.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasFunc.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasFunc.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="HasFunc" + +/// HasFunc --- test for an expression containing a function +/// function name given as string. +10 # HasFunc(_expr, string_IsString) <-- HasFunc(expr, ToAtom(string)); +/// function given as atom. +// atom contains no functions +10 # HasFunc(expr_IsAtom, atom_IsAtom) <-- False; +// a list contains the function List so we test it together with functions +// a function contains itself, or maybe an argument contains it +20 # HasFunc(expr_IsFunction, atom_IsAtom) <-- IsEqual(First(FunctionToList(expr)), atom) Or ListHasFunc(Rest(FunctionToList(expr)), atom); + +%/mathpiper + + + +%mathpiper_docs,name="HasFunc",categories="User Functions;Predicates" +*CMD HasFunc --- check for expression containing a function +*STD +*CALL + HasFunc(expr, func) + +*PARMS + +{expr} -- an expression + +{func} -- a function atom to be found + +*DESC + +The command {HasFunc} returns {True} if the expression {expr} contains a function {func}. The expression is recursively traversed. + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> HasFunc(x+y*Cos(Ln(z)/z), Ln) +Result: True; +In> HasFunc(x+y*Cos(Ln(z)/z), Sin) +Result: False; + +*SEE HasFuncArith, HasFuncSome, FuncList, VarList, HasExpr +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasFuncSome.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasFuncSome.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/HasFuncSome.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/HasFuncSome.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="HasFuncSome" + +/// function name given as string. +10 # HasFuncSome(_expr, string_IsString, _look'list) <-- HasFuncSome(expr, ToAtom(string), look'list); +/// function given as atom. +// atom contains no functions +10 # HasFuncSome(expr_IsAtom, atom_IsAtom, _look'list) <-- False; +// a list contains the function List so we test it together with functions +// a function contains itself, or maybe an argument contains it + +// first deal with functions that do not belong to the list: return top level function +15 # HasFuncSome(expr_IsFunction, atom_IsAtom, _look'list)_(Not Contains(look'list, ToAtom(Type(expr)))) <-- IsEqual(First(FunctionToList(expr)), atom); +// function belongs to the list - check its arguments +20 # HasFuncSome(expr_IsFunction, atom_IsAtom, _look'list) <-- IsEqual(First(FunctionToList(expr)), atom) Or ListHasFuncSome(Rest(FunctionToList(expr)), atom, look'list); + +%/mathpiper + + + +%mathpiper_docs,name="HasFuncSome",categories="User Functions;Predicates" +*CMD HasFuncSome --- check for expression containing a function +*STD +*CALL + HasFuncSome(expr, func, list) + +*PARMS + +{expr} -- an expression + +{func} -- a function atom to be found + +{list} -- list of function atoms to be considered "transparent" + +*DESC + +The command {HasFuncSome} does the same thing as {HasFunc}, except it only looks at arguments of a given {list} of functions. Arguments of all other functions become "opaque" (as if they do not contain anything). + +Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}". + +*E.G. + +In> HasFuncSome({a+b*2,c/d},/,{List}) +Result: True; +In> HasFuncSome({a+b*2,c/d},*,{List}) +Result: False; + +*SEE HasFunc, HasFuncArith, FuncList, VarList, HasExpr +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsBoolean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsBoolean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsBoolean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsBoolean.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="IsBoolean" + +Function ("IsBoolean", {x}) + (x=True) Or (x=False) Or IsFunction(x) And Contains({"=", ">", "<", ">=", "<=", "!=", "And", "Not", "Or"}, Type(x)); + +%/mathpiper + + + +%mathpiper_docs,name="IsBoolean",categories="User Functions;Predicates" +*CMD IsBoolean --- test for a Boolean value +*STD +*CALL + IsBoolean(expression) + +*PARMS + +{expression} -- an expression + +*DESC + +IsBoolean returns True if the argument is of a boolean type. +This means it has to be either True, False, or an expression involving +functions that return a boolean result, e.g. +{=}, {>}, {<}, {>=}, {<=}, {!=}, {And}, {Not}, {Or}. + +*E.G. + +In> IsBoolean(a) +Result: False; +In> IsBoolean(True) +Result: True; +In> IsBoolean(a And b) +Result: True; + +*SEE True, False +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsBoolType.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsBoolType.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsBoolType.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsBoolType.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="IsBoolType" + +0 # IsBoolType(True) <-- True; +0 # IsBoolType(False) <-- True; +1 # IsBoolType(_anythingelse) <-- False; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsConstant.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsConstant.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsConstant.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsConstant.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="IsConstant" + +IsConstant(_n) <-- (VarList(n) = {}); + +%/mathpiper + + + +%mathpiper_docs,name="IsConstant",categories="User Functions;Predicates" +*CMD IsConstant --- test for a constant +*STD +*CALL + IsConstant(expr) + +*PARMS + +{expr} -- some expression + +*DESC + +{IsConstant} returns {True} if the +expression is some constant or a function with constant arguments. It +does this by checking that no variables are referenced in the +expression. {Pi} is considered a constant. + +*E.G. + +In> IsConstant(Cos(x)) +Result: False; +In> IsConstant(Cos(2)) +Result: True; +In> IsConstant(Cos(2+x)) +Result: False; + +*SEE IsNumber, IsInteger, VarList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsDiagonal.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsDiagonal.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsDiagonal.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsDiagonal.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper,def="IsDiagonal" + +IsDiagonal(A_IsMatrix) <-- +[ + Local(i,j,m,n,result); + m := Length(A); + n := Length(A[1]); + result := (m=n); // must be a square matrix + + i:=2; + While(i<=m And result) + [ + j:=1; + While(j<=n And result) + [ + result:= (i=j Or A[i][j] = 0); + j++; + ]; + i++; + ]; + If(m=2, [ result := result And (A=Transpose(A)); ] ); + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="IsDiagonal",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsDiagonal --- test for a diagonal matrix +*STD +*CALL + IsDiagonal(A) + +*PARMS + +{A} -- a matrix + +*DESC + +{IsDiagonal(A)} returns {True} if {A} is a diagonal square matrix and {False} otherwise. + +*E.G. +In> IsDiagonal(Identity(5)) +Result: True; +In> IsDiagonal(HilbertMatrix(5)) +Result: False; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsEquation.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsEquation.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsEquation.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsEquation.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="IsEquation" + +//Retract("IsEquation",*); + +10 # IsEquation(expr_IsAtom) <-- False; + +12 # IsEquation(_expr) <-- FunctionToList(expr)[1] = == ; + +%/mathpiper + + + + +%mathpiper_docs,name="IsEquation",categories="User Functions;Predicates" + +*CMD IsEquation --- Return true if {expr} is an Equation False otherwise + +*STD +*CALL + IsEquation(expr) + +*PARMS + +{expr} -- mathematical expression + +*DESC + +This function returns {True} if MathPiper can determine that the expression is an equation. +Otherwise, {False}. +Equations are defined by the property that they are of the form {a==b}. + +*E.G. + +In> IsEquation(x^2==4) + +Result: True + +In> IsEquation(x^2-4) + +Result: False + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsEvenFunction.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsEvenFunction.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsEvenFunction.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsEvenFunction.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="IsEvenFunction" + +IsEvenFunction(f,x):= (f = Eval(Subst(x,-x)f)); + +%/mathpiper + + + +%mathpiper_docs,name="IsEvenFunction",categories="User Functions;Predicates" +*CMD IsEvenFunction --- Return true if function is an even function (False otherwise) + +*STD +*CALL + IsEvenFunction(expression,variable) + +*PARMS + +{expression} -- mathematical expression +{variable} -- variable + +*DESC + +This function returns True if MathPiper can determine that the +function is even. Even functions are +defined to be functions that have the property: + +$$ f(x) = f(-x) $$ + +{Cos(x)} is an example of an even function. + +As a side note, one can decompose a function into an +even and an odd part: + +$$ f(x) = f_even(x) + f_odd(x) $$ + +Where + +$$ f_even(x) = (f(x)+f(-x))/2 $$ + +and + +$$ f_odd(x) = (f(x)-f(-x))/2 $$ + +*E.G. + +In> IsEvenFunction(Cos(b*x),x) +Result: True +In> IsEvenFunction(Sin(b*x),x) +Result: False +In> IsEvenFunction(1/x^2,x) +Result: True +In> IsEvenFunction(1/x,x) +Result: False + +*SEE IsOddFunction, Sin, Cos +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsEven.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsEven.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsEven.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsEven.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsEven" + +IsEven(n) := IsInteger(n) And ( BitAnd(n,1) = 0 ); + +%/mathpiper + + + +%mathpiper_docs,name="IsEven",categories="User Functions;Predicates" +*CMD IsEven --- test for an even integer +*STD +*CALL + IsEven(n) + +*PARMS + +{n} -- integer to test + +*DESC + +This function tests whether the integer "n" is even. An integer is +even if it is divisible by two. Hence the even numbers are 0, 2, 4, 6, +8, 10, etc., and -2, -4, -6, -8, -10, etc. + +*E.G. + +In> IsEven(4); +Result: True; +In> IsEven(-1); +Result: False; + +*SEE IsOdd, IsInteger +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsHermitian.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsHermitian.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsHermitian.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsHermitian.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsHermitian" + +IsHermitian(A_IsMatrix) <-- (Conjugate(Transpose(A))=A); + +%/mathpiper + + + +%mathpiper_docs,name="IsHermitian",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsHermitian --- test for a Hermitian matrix +*STD +*CALL + IsHermitian(A) + +*PARMS + +{A} -- a square matrix + +*DESC + +IsHermitian(A) returns {True} if {A} is Hermitian and {False} +otherwise. $A$ is a Hermitian matrix iff Conjugate( Transpose $A$ )=$A$. +If $A$ is a real matrix, it must be symmetric to be Hermitian. + +*E.G. + +In> IsHermitian({{0,I},{-I,0}}) +Result: True; +In> IsHermitian({{0,I},{2,0}}) +Result: False; + +*SEE IsUnitary +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsIdempotent.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsIdempotent.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsIdempotent.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsIdempotent.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="IsIdempotent" + +IsIdempotent(A_IsMatrix) <-- (A^2 = A); + +%/mathpiper + + + +%mathpiper_docs,name="IsIdempotent",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsIdempotent --- test for an idempotent matrix +*STD +*CALL + IsIdempotent(A) + +*PARMS + +{A} -- a square matrix + +*DESC + +{IsIdempotent(A)} returns {True} if {A} is idempotent and {False} otherwise. +$A$ is idempotent iff $A^2=A$. Note that this also implies that $A$ raised +to any power is also equal to $A$. + +*E.G. + +In> IsIdempotent(ZeroMatrix(10,10)); +Result: True; +In> IsIdempotent(Identity(20)) +Result: True; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsInfinity.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsInfinity.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsInfinity.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsInfinity.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="IsInfinity" + +10 # IsInfinity(Infinity) <-- True; +10 # IsInfinity(-(_x)) <-- IsInfinity(x); + +// This is just one example, we probably need to extend this further to include all +// cases for f*Infinity where f can be guaranteed to not be zero +11 # IsInfinity(Sign(_x)*y_IsInfinity) <-- True; + +60000 # IsInfinity(_x) <-- False; + +%/mathpiper + + + +%mathpiper_docs,name="IsInfinity",categories="User Functions;Predicates" +*CMD IsInfinity --- test for an infinity +*STD +*CALL + IsInfinity(expr) + +*PARMS + +{expr} -- expression to test + +*DESC + +This function tests whether {expr} is an infinity. This is only the +case if {expr} is either {Infinity} or {-Infinity}. + +*E.G. + +In> IsInfinity(10^1000); +Result: False; +In> IsInfinity(-Infinity); +Result: True; + +*SEE Integer +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsLowerTriangular.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsLowerTriangular.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsLowerTriangular.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsLowerTriangular.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="IsLowerTriangular" + +IsLowerTriangular(A_IsMatrix) <-- (IsUpperTriangular(Transpose(A))); + +%/mathpiper + + + +%mathpiper_docs,name="IsLowerTriangular",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsLowerTriangular --- test for a lower triangular matrix +*STD +*CALL + IsLowerTriangular(A) + +*PARMS + +{A} -- a matrix + +*DESC + +A lower triangular matrix is a square matrix which has all zero entries below the diagonal. + +{IsLowerTriangular(A)} returns {True} if {A} is a lower triangular matrix and {False} otherwise. + +*E.G. +In> IsLowerTriangular(Identity(5)) +Result: True; +In> IsLowerTriangular({{1,2},{0,1}}) +Result: False; + +A non-square matrix cannot be triangular: +In> IsLowerTriangular({{1,2,3},{0,1,2}}) +Result: False; + +*SEE IsUpperTriangle, IsDiagonal +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsMonomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsMonomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsMonomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsMonomial.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,58 @@ +%mathpiper,def="IsMonomial" + +//Retract("CanBeMonomial",*); +//Retract("IsMonomial",*); + +10 # CanBeMonomial(_expr)_(Type(expr)="UniVariate") <-- False; + +10 # CanBeMonomial(_expr)<--Not (HasFunc(expr,ToAtom("+")) Or HasFunc(expr,ToAtom("-"))); + +10 # IsMonomial(expr_CanBeMonomial) <-- +[ + Local(r); + If( IsRationalFunction(expr), + r := (VarList(Denominator(expr)) = {}), + r := True + ); +]; + +15 # IsMonomial(_expr) <-- False; + +%/mathpiper + + + + + + + + +%mathpiper_docs,name="IsMonomial",categories="User Functions;Predicates" +*CMD IsMonomial --- determine if {expr} is a Monomial +*STD +*CALL + IsMonomial(expr) + +*PARMS +{expr} -- an expression + +*DESC +This function returns {True} if {expr} satisfies the definition of a {Monomial}. +Otherwise, {False}. +A {Monomial} is defined to be a single term, consisting of a product of numbers +and variables. + +*E.G. +In> IsMonomial(24) +Result: True + +In> IsMonomial(24*a*x^2*y^3) +Result: True + +In> IsMonomial(24*a*x^2*y^3/15) +Result: True + +In> IsMonomial(24*a*x^2*y^3/15+1) +Result: False + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNegativeInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNegativeInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNegativeInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNegativeInteger.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsNegativeInteger" + +IsNegativeInteger(x):= IsInteger(x) And x < 0; + +%/mathpiper + + + +%mathpiper_docs,name="IsNegativeInteger",categories="User Functions;Predicates" +*CMD IsNegativeInteger --- test for a negative integer +*STD +*CALL + IsNegativeInteger(n) + +*PARMS + +{n} -- integer to test + +*DESC + +This function tests whether the integer {n} is (strictly) +negative. The negative integers are -1, -2, -3, -4, -5, etc. If +{n} is not a integer, the function returns {False}. + +*E.G. + +In> IsNegativeInteger(31); +Result: False; +In> IsNegativeInteger(-2); +Result: True; + +*SEE IsPositiveInteger, IsNonZeroInteger, IsNegativeNumber +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNegativeNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNegativeNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNegativeNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNegativeNumber.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="IsNegativeNumber" + +IsNegativeNumber(x):= IsNumber(x) And x < 0; + +%/mathpiper + + + +%mathpiper_docs,name="IsNegativeNumber",categories="User Functions;Predicates" +*CMD IsNegativeNumber --- test for a negative number +*STD +*CALL + IsNegativeNumber(n) + +*PARMS + +{n} -- number to test + +*DESC + +{IsNegativeNumber(n)} evaluates to {True} if $n$ is (strictly) negative, i.e. +if $n<0$. If {n} is not a number, the functions return {False}. + +*E.G. + +In> IsNegativeNumber(6); +Result: False; +In> IsNegativeNumber(-2.5); +Result: True; + +*SEE IsNumber, IsPositiveNumber, IsNotZero, IsNegativeInteger, IsNegativeReal +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNegativeReal.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNegativeReal.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNegativeReal.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNegativeReal.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="IsNegativeReal" + +/* See if a number, when evaluated, would be a positive real value */ + +IsNegativeReal(_r) <-- +[ + r:=N(Eval(r)); + (IsNumber(r) And r <= 0); +]; + +%/mathpiper + + + +%mathpiper_docs,name="IsNegativeReal",categories="User Functions;Predicates" +*CMD IsNegativeReal --- test for a numerically negative value +*STD +*CALL + IsNegativeReal(expr) + +*PARMS + +{expr} -- expression to test + +*DESC + +This function tries to approximate {expr} numerically. It returns {True} if this approximation is negative. In case no +approximation can be found, the function returns {False}. Note that round-off errors may cause incorrect +results. + +*E.G. + +In> IsNegativeReal(Sin(1)-3/4); +Result: False; +In> IsNegativeReal(Sin(1)-6/7); +Result: True; +In> IsNegativeReal(Exp(x)); +Result: False; + +The last result is because {Exp(x)} cannot be +numerically approximated if {x} is not known. Hence +MathPiper can not determine the sign of this expression. + +*SEE IsPositiveReal, IsNegativeNumber, N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNonNegativeInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNonNegativeInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNonNegativeInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNonNegativeInteger.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="IsNonNegativeInteger" + +IsNonNegativeInteger(x):= IsInteger(x) And x >= 0; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNonNegativeNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNonNegativeNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNonNegativeNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNonNegativeNumber.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="IsNonNegativeNumber" + +IsNonNegativeNumber(x):= IsNumber(x) And x >= 0; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNonZeroInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNonZeroInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNonZeroInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNonZeroInteger.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="IsNonZeroInteger" + +IsNonZeroInteger(x) := (IsInteger(x) And x != 0); + +%/mathpiper + + + +%mathpiper_docs,name="IsNonZeroInteger",categories="User Functions;Predicates" +*CMD IsNonZeroInteger --- test for a nonzero integer +*STD +*CALL + IsNonZeroInteger(n) + +*PARMS + +{n} -- integer to test + +*DESC + +This function tests whether the integer {n} is not zero. If {n} is +not an integer, the result is {False}. + +*E.G. + +In> IsNonZeroInteger(0) +Result: False; +In> IsNonZeroInteger(-2) +Result: True; + +*SEE IsPositiveInteger, IsNegativeInteger, IsNotZero +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNotZero.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNotZero.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNotZero.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNotZero.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="IsNotZero" + +/* +10 # IsNotZero(x_IsNumber) <-- ( RoundTo(x,BuiltinPrecisionGet()) != 0); +*/ + + +10 # IsNotZero(x_IsNumber) <-- ( AbsN(x) >= PowerN(10, -BuiltinPrecisionGet())); +10 # IsNotZero(x_IsInfinity) <-- True; +60000 # IsNotZero(_x) <-- False; + +%/mathpiper + + + +%mathpiper_docs,name="IsNotZero",categories="User Functions;Predicates" +*CMD IsNotZero --- test for a nonzero number +*STD +*CALL + IsNotZero(n) + +*PARMS + +{n} -- number to test + +*DESC + +{IsNotZero(n)} evaluates to {True} if {n} is not zero. In case {n} is not a +number, the function returns {False}. + +*E.G. + +In> IsNotZero(3.25); +Result: True; +In> IsNotZero(0); +Result: False; + +*SEE IsNumber, IsPositiveNumber, IsNegativeNumber, IsNonZeroInteger +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNumericList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNumericList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsNumericList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsNumericList.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,25 @@ +%mathpiper,def="IsNumericList" + +// check that all items in the list are numbers +IsNumericList(_arg'list) <-- IsList(arg'list) And + ("And" @ (MapSingle(Hold({{x},IsNumber(N(Eval(x)))}), arg'list))); + +%/mathpiper + + + +%mathpiper_docs,name="IsNumericList",categories="User Functions;Predicates" +*CMD IsNumericList --- test for a list of numbers +*STD +*CALL + IsNumericList({list}) + +*PARMS + +{{list}} -- a list + +*DESC +Returns {True} when called on a list of numbers or expressions that evaluate to numbers using {N()}. Returns {False} otherwise. + +*SEE N, IsNumber +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOddFunction.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOddFunction.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOddFunction.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOddFunction.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="IsOddFunction" + +IsOddFunction(f,x):= (f = Eval(-Subst(x,-x)f)); + +%/mathpiper + + + +%mathpiper_docs,name="IsOddFunction",categories="User Functions;Predicates" +*CMD IsOddFunction --- Return true if function is an odd function (False otherwise) + +*STD +*CALL + IsOddFunction(expression,variable) + +*PARMS + +{expression} -- mathematical expression +{variable} -- variable + +*DESC + +This function returns True if MathPiper can determine that the +function is odd. Odd functions have the property: + +$$ f(x) = -f(-x) $$ + +{Sin(x)} is an example of an odd function. + +As a side note, one can decompose a function into an +even and an odd part: + +$$ f(x) = f_even(x) + f_odd(x) $$ + +Where + +$$ f_even(x) = (f(x)+f(-x))/2 $$ + +and + +$$ f_odd(x) = (f(x)-f(-x))/2 $$ + +*E.G. + +In> IsOddFunction(Cos(b*x),x) +Result: False +In> IsOddFunction(Sin(b*x),x) +Result: True +In> IsOddFunction(1/x,x) +Result: True +In> IsOddFunction(1/x^2,x) +Result: False + +*SEE IsEvenFunction, Sin, Cos +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOdd.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOdd.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOdd.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOdd.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsOdd" + +IsOdd(n) := IsInteger(n) And ( BitAnd(n,1) = 1 ); + +%/mathpiper + + + +%mathpiper_docs,name="IsOdd",categories="User Functions;Predicates" +*CMD IsOdd --- test for an odd integer +*STD +*CALL + IsOdd(n) + +*PARMS + +{n} -- integer to test + +*DESC + +This function tests whether the integer "n" is odd. An integer is +odd if it is not divisible by two. Hence the odd numbers are 1, 3, 5, +7, 9, etc., and -1, -3, -5, -7, -9, etc. + +*E.G. + +In> IsOdd(4); +Result: False; +In> IsOdd(-1); +Result: True; + +*SEE IsEven, IsInteger +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOne.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOne.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOne.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOne.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="IsOne",private="true" + +// why do we need this? Why doesn't x=1 not work? +10 # IsOne(x_IsNumber) <-- IsZero(SubtractN(x,1)); +60000 # IsOne(_x) <-- False; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOrthogonal.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOrthogonal.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsOrthogonal.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsOrthogonal.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="IsOrthogonal" + +IsOrthogonal(A_IsMatrix) <-- (Transpose(A)*A=Identity(Length(A))); + +%/mathpiper + + + +%mathpiper_docs,name="IsOrthogonal",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsOrthogonal --- test for an orthogonal matrix +*STD +*CALL + IsOrthogonal(A) + +*PARMS + +{A} -- square matrix + +*DESC + +{IsOrthogonal(A)} returns {True} if {A} is orthogonal and {False} +otherwise. $A$ is orthogonal iff $A$*Transpose($A$) = Identity, or +equivalently Inverse($A$) = Transpose($A$). + +*E.G. + +In> A := {{1,2,2},{2,1,-2},{-2,2,-1}}; +Result: {{1,2,2},{2,1,-2},{-2,2,-1}}; +In> PrettyForm(A/3) + + / \ + | / 1 \ / 2 \ / 2 \ | + | | - | | - | | - | | + | \ 3 / \ 3 / \ 3 / | + | | + | / 2 \ / 1 \ / -2 \ | + | | - | | - | | -- | | + | \ 3 / \ 3 / \ 3 / | + | | + | / -2 \ / 2 \ / -1 \ | + | | -- | | - | | -- | | + | \ 3 / \ 3 / \ 3 / | + \ / +Result: True; +In> IsOrthogonal(A/3) +Result: True; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPolynomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPolynomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPolynomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPolynomial.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,65 @@ +%mathpiper,def="IsPolynomial" + +//Retract("IsPolynomial",*); + +10 # IsPolynomial(expr_IsFunction) <-- +[ + Local(x,vars); + vars := VarList(expr); + If(Length(vars)>1,vars:=HeapSort(vars,"IsGreaterThan")); + x := vars[1]; + IsPolynomial(expr,x); +]; + +15 # IsPolynomial(_expr) <-- False; + + +10 # IsPolynomial(_expr,_var)_(CanBeUni(var,expr)) <-- True; + +15 # IsPolynomial(_expr,_var) <-- False; + +%/mathpiper + + + + +%mathpiper_docs,name="IsPolynomial",categories="Programmer Functions;Predicates" + +*CMD IsPolynomial --- Check if {expr} is a polynomial in variable {var} if {var} is specified. + +*STD +*CALL + IsPolynomial(expr,var) +or + IsPolynomial(expr) + +*PARMS + +{expr} -- an algebraic expression which may be a polynomial + +{var} -- a variable name which might be used in {expr} + +*DESC + +The command {IsPolynomial} returns {True} if {expr} is (or could be) a polynomial in {var}. +If {var} is not specified, a heuristic algorithm (which may be wrong!) is used to select a +likely variable name from among the list of "variables" returned by VarList(expr). +If you would rather not have an algorithm selecting the variable name, specify it as an +argument to the function. +It returns {False} if {expr} is not likely to be a polynomial in {var}. + +*E.G. + +In> IsPolynomial(2*x^3-3*x^2+5*x-14,x) +Result: True + +In> IsPolynomial(2*x^3-3*x^2+5*x-14) +Result: False + +In> IsPolynomial(y^2-4) +Result: True + NOTE: if variable name is omitted, a reasonable default is taken. + +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPolynomialOverIntegers.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPolynomialOverIntegers.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPolynomialOverIntegers.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPolynomialOverIntegers.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,73 @@ +%mathpiper,def="IsPolynomialOverIntegers" + +//Retract("IsPolynomialOverIntegers",*); + +10 # IsPolynomialOverIntegers(expr_IsFunction) <-- +[ + Local(x,vars); + vars := VarList(expr); + If(Length(vars)>1,vars:=HeapSort(vars,"IsGreaterThan")); + x := vars[1]; + IsPolynomialOverIntegers(expr,x); +]; + +15 # IsPolynomialOverIntegers(_expr) <-- False; + + +10 # IsPolynomialOverIntegers(_expr,_var)_(CanBeUni(var,expr)) <-- +[ + If( AllSatisfy("IsInteger",Coef(expr,var,0 .. Degree(expr,var))), + True, + False + ); +]; + +15 # IsPolynomialOverIntegers(_expr,_var) <-- False; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + +%mathpiper_docs,name="IsPolynomialOverIntegers",categories="Programmer Functions;Predicates" + +*CMD IsPolynomialOverIntegers --- Check if {expr} is a polynomial in variable {var} all of whose coefficients are integers + +*STD +*CALL + IsPolynomialOverIntegers(expr,var) + +*PARMS + +{expr} -- an algebraic expression which may be a polynomial + +{var} -- a variable name which might be used in {expr} + +*DESC + +The command {IsPolynomialOverIntegers} returns {True} if {expr} is a polynomial in {var} and all of its coefficients are integers. +It returns {False} if {expr} is not a polynomial in {var} or if any of its coefficients are not integers. + +This can be important, since many factoring theorems are applicable to such polynomials but not others. + +*E.G. + +In> IsPolynomialOverIntegers(2*x^3-3*x^2+5*x-14,x) +Result: True + +In> IsPolynomialOverIntegers(2.0*x^3-3*x^2+5*x-14,x) +Result: False + +In> IsPolynomialOverIntegers(y^2-4) +Result: True + NOTE: if variable name is omitted, a reasonable default is taken. + +In> IsPolynomialOverIntegers(x^2-a^2) +Result: False + NOTE: the unbound variable 'a' need not be an integer. + +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPositiveInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPositiveInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPositiveInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPositiveInteger.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="IsPositiveInteger" + +IsPositiveInteger(x):= IsInteger(x) And x > 0; + +%/mathpiper + + + +%mathpiper_docs,name="IsPositiveInteger",categories="User Functions;Predicates" +*CMD IsPositiveInteger --- test for a positive integer +*STD +*CALL + IsPositiveInteger(n) + +*PARMS + +{n} -- integer to test + +*DESC + +This function tests whether the integer {n} is (strictly) positive. The +positive integers are 1, 2, 3, 4, 5, etc. If {n} is not a integer, the +function returns {False}. + +*E.G. + +In> IsPositiveInteger(31); +Result: True; +In> IsPositiveInteger(-2); +Result: False; + +*SEE IsNegativeInteger, IsNonZeroInteger, IsPositiveNumber +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPositiveNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPositiveNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPositiveNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPositiveNumber.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="IsPositiveNumber" + +IsPositiveNumber(x):= IsNumber(x) And x > 0; + +%/mathpiper + + + +%mathpiper_docs,name="IsPositiveNumber",categories="User Functions;Predicates" +*CMD IsPositiveNumber --- test for a positive number +*STD +*CALL + IsPositiveNumber(n) + +*PARMS + +{n} -- number to test + +*DESC + +{IsPositiveNumber(n)} evaluates to {True} if $n$ is (strictly) positive, i.e. +if $n>0$. If {n} is not a number the function returns {False}. + +*E.G. + +In> IsPositiveNumber(6); +Result: True; +In> IsPositiveNumber(-2.5); +Result: False; + +*SEE IsNumber, IsNegativeNumber, IsNotZero, IsPositiveInteger, IsPositiveReal +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPositiveReal.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPositiveReal.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsPositiveReal.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsPositiveReal.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="IsPositiveReal" + +/* See if a number, when evaluated, would be a positive real value */ +IsPositiveReal(_r) <-- +[ + r:=N(Eval(r)); + (IsNumber(r) And r >= 0); +]; + +%/mathpiper + + + +%mathpiper_docs,name="IsPositiveReal",categories="User Functions;Predicates" +*CMD IsPositiveReal --- test for a numerically positive value +*STD +*CALL + IsPositiveReal(expr) + +*PARMS + +{expr} -- expression to test + +*DESC + +This function tries to approximate "expr" numerically. It returns {True} if this approximation is positive. In case no +approximation can be found, the function returns {False}. Note that round-off errors may cause incorrect +results. + +*E.G. + +In> IsPositiveReal(Sin(1)-3/4); +Result: True; +In> IsPositiveReal(Sin(1)-6/7); +Result: False; +In> IsPositiveReal(Exp(x)); +Result: False; + +The last result is because {Exp(x)} cannot be +numerically approximated if {x} is not known. Hence +MathPiper can not determine the sign of this expression. + +*SEE IsNegativeReal, IsPositiveNumber, N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsRationalFunction.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsRationalFunction.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsRationalFunction.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsRationalFunction.mpw 2011-02-21 20:05:36.000000000 +0000 @@ -0,0 +1,192 @@ +%mathpiper,def="IsRationalFunction" + +//Retract("IsRationalFunction",*); + +10 # IsRationalFunction(_expr)_(Length(VarList(expr))=0) <-- False; + +15 # IsRationalFunction(_expr) <-- IsRationalFunction(expr,VarList(expr)); + +10 # IsRationalFunction(expr_IsRationalOrNumber,_var) <-- False; + +15 # IsRationalFunction(_expr,var_IsAtom)_(Type(expr)="/" Or Type(-expr)="/") <-- +[ + If (IsPolynomial(Numerator(expr),var) And IsPolynomial(Denominator(expr),var), + Contains(VarList(Denominator(expr)),var), + False + ); +]; + +20 # IsRationalFunction(_expr,vars_IsList)_(Type(expr)="/" Or Type(-expr)="/") <-- +[ + If (IsPolynomial(Numerator(expr),vars) And IsPolynomial(Denominator(expr),vars), + Intersection(vars, VarList(expr)) != {}, + False + ); +]; + +60000 # IsRationalFunction(_expr,_var) <-- False; + + +%/mathpiper + + + + +%mathpiper_docs,name="IsRationalFunction",categories="Programmer Functions;Predicates",access="experimental" + +*CMD IsRationalFunction --- test for a Rational Function +*STD +*CALL + IsRationalFunction(expr) + IsRationalFunction(expr,var) + IsRationalFunction(expr,vars) + +*PARMS + +{expr} -- expression to test +{var} -- (optional) variable +{vars} -- (optional) a list of variables + +*DESC + +This function tests whether the expression {expr} is a Rational +Function of the variable {var}. If a list of variables {vars} is +provided, the test is made w.r.t. all the variables in the list, and +returns True if any one of them succeeds. If {var} is omitted, the +test is made w.r.t. the list VarList(expr). + +*E.G. + +In> IsRationalFunction(3,x) +Result: False +In> IsRationalFunction(3) +Result: False; +In> IsRationalFunction(3.5,x) +Result: False +In> IsRationalFunction(3.5) +Result: False +In> IsRationalFunction(3/5,x) +Result: False +In> IsRationalFunction(3/5) +Result: False +In> IsRationalFunction(x,y) +Result: False +In> IsRationalFunction(x) +Result: False +In> IsRationalFunction(x/y,x) +Result: False +In> IsRationalFunction(x/y,y) +Result: True +In> IsRationalFunction(x/y) +Result: True +In> IsRationalFunction(x/5,x) +Result: False +In> IsRationalFunction(x/5) +Result: False +In> IsRationalFunction(5/x,x) +Result: True +In> IsRationalFunction(-5/x,x) +Result: True +In> IsRationalFunction(5/x) +Result: True +In> IsRationalFunction(-5/x) +Result: True +In> IsRationalFunction(5/x,y) +Result: False +In> IsRationalFunction(5/x,{y}) +Result: False +In> IsRationalFunction(5/x,{y,x}) +Result: False +In> IsRationalFunction(5/y) +Result: True +In> IsRationalFunction(1-1/x,x) +Result: False +In> IsRationalFunction(1-1/x) +Result: False + +%/mathpiper_docs + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +Tell(1,IsRationalFunction(3,x)); +Tell(2,IsRationalFunction(3.5,x)); +Tell(3,IsRationalFunction(3/5,x)); +Tell(4,IsRationalFunction(x,y)); +Tell(5,IsRationalFunction(x/y,x)); +Tell(6,IsRationalFunction(x/5,x)); +Tell(7,IsRationalFunction(5/x,x)); +Tell(8,IsRationalFunction(5/y,x)); +Tell(9,IsRationalFunction(1-1/x,x)); +Tell(11,IsRationalFunction(3)); +Tell(12,IsRationalFunction(3.5)); +Tell(13,IsRationalFunction(3/5)); +Tell(14,IsRationalFunction(x)); +Tell(15,IsRationalFunction(x/y)); +Tell(16,IsRationalFunction(x/5)); +Tell(17,IsRationalFunction(5/x)); +Tell(18,IsRationalFunction(5/y)); +Tell(19,IsRationalFunction(-5/y)); +Tell(20,IsRationalFunction(1-1/x)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + << 1 >> IsRationalFunction(3,x) : False + << 2 >> IsRationalFunction(3.5,x) : False + << 3 >> IsRationalFunction(3/5,x) : False + << 4 >> IsRationalFunction(x,y) : False + << 15 >> expr : x/y + << >> var : x + << >> Denominator(expr) : y + << 5 >> IsRationalFunction(x/y,x) : False + << 15 >> expr : x/5 + << >> var : x + << >> Denominator(expr) : 5 + << 6 >> IsRationalFunction(x/5,x) : False + << 15 >> expr : 5/x + << >> var : x + << >> Denominator(expr) : x + << 7 >> IsRationalFunction(5/x,x) : True + << 15 >> expr : 5/y + << >> var : x + << >> Denominator(expr) : y + << 8 >> IsRationalFunction(5/y,x) : False + << 9 >> IsRationalFunction(1-1/x,x) : False + << 11 >> IsRationalFunction(3) : False + << 12 >> IsRationalFunction(3.5) : False + << 13 >> IsRationalFunction(3/5) : False + << 14 >> IsRationalFunction(x) : False + << 15 >> expr : x/y + << >> var : x + << >> Denominator(expr) : y + << 15 >> IsRationalFunction(x/y) : False + << 15 >> expr : x/5 + << >> var : x + << >> Denominator(expr) : 5 + << 16 >> IsRationalFunction(x/5) : False + << 15 >> expr : 5/x + << >> var : x + << >> Denominator(expr) : x + << 17 >> IsRationalFunction(5/x) : True + << 15 >> expr : 5/y + << >> var : y + << >> Denominator(expr) : y + << 18 >> IsRationalFunction(5/y) : True + << 15 >> expr : (-5)/y + << >> var : y + << >> Denominator(expr) : y + << 19 >> IsRationalFunction(-5/y) : True + << 20 >> IsRationalFunction(1-1/x) : False + +. %/output + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsRational.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsRational.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsRational.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsRational.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,57 @@ +%mathpiper,def="IsRational" + +/* changed definition of IsRational, Nobbi 030529 +Function("IsRational",{aLeft}) Type(aLeft) = "/"; + +Function("IsRationalNumeric",{aLeft}) + Type(aLeft) = "/" And + IsNumber(aLeft[1]) And + IsNumber(aLeft[2]); + +IsRationalOrNumber(_x) <-- (IsNumber(x) Or IsRationalNumeric(x)); + +10 # IsRationalOrInteger(x_IsInteger) <-- True; +10 # IsRationalOrInteger(x_IsInteger / y_IsInteger) <-- True; +20 # IsRationalOrInteger(_x) <-- False; + +*/ + +10 # IsRational(x_IsInteger) <-- True; +10 # IsRational(x_IsInteger / y_IsInteger) <-- True; +10 # IsRational(-(x_IsInteger / y_IsInteger)) <-- True; +60000 # IsRational(_x) <-- False; + +%/mathpiper + + + +%mathpiper_docs,name="IsRational",categories="User Functions;Numbers (Predicates);Predicates" +*CMD IsRational --- test whether argument is a rational +*STD +*CALL + IsRational(expr) + +*PARMS + +{expr} -- expression to test + +*DESC + +This commands tests whether the expression "expr" is a rational +number, i.e. an integer or a fraction of integers. + +*E.G. + +In> IsRational(5) +Result: True; +In> IsRational(2/7) +Result: True; +In> IsRational(0.5) +Result: False; +In> IsRational(a/b) +Result: False; +In> IsRational(x + 1/x) +Result: False; + +*SEE Numerator, Denominator +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsRationalOrNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsRationalOrNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsRationalOrNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsRationalOrNumber.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,8 @@ +%mathpiper,def="IsRationalOrNumber" + +10 # IsRationalOrNumber(x_IsNumber) <-- True; +10 # IsRationalOrNumber(x_IsNumber / y_IsNumber) <-- True; +10 # IsRationalOrNumber(-(x_IsNumber / y_IsNumber)) <-- True; +60000 # IsRationalOrNumber(_x) <-- False; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsSkewSymmetric.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsSkewSymmetric.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsSkewSymmetric.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsSkewSymmetric.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="IsSkewSymmetric" + +IsSkewSymmetric(A_IsMatrix) <-- (Transpose(A)=(-1*A)); + +%/mathpiper + + + +%mathpiper_docs,name="IsSkewSymmetric",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsSkewSymmetric --- test for a skew-symmetric matrix +*STD +*CALL + IsSkewSymmetric(A) + +*PARMS + +{A} -- a square matrix + +*DESC + +{IsSkewSymmetric(A)} returns {True} if {A} is skew symmetric and {False} otherwise. +$A$ is skew symmetric iff $Transpose(A)$ =$-A$. + +*E.G. + +In> A := {{0,-1},{1,0}} +Result: {{0,-1},{1,0}}; +In> PrettyForm(%) + + / \ + | ( 0 ) ( -1 ) | + | | + | ( 1 ) ( 0 ) | + \ / +Result: True; +In> IsSkewSymmetric(A); +Result: True; + +*SEE IsSymmetric, IsHermitian +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsSumOfTerms.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsSumOfTerms.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsSumOfTerms.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsSumOfTerms.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,85 @@ +%mathpiper,def="IsSumOfTerms" + +// an expression free of the variable -- obviously not a sum of terms in it +10 # IsSumOfTerms(_var,expr_IsFreeOf(var)) <-- False; + +// an Atom cannot be a sum of terms +12 # IsSumOfTerms(_var,expr_IsAtom()) <-- False; + +// after being "Listified", expr is a sum of terms if headed by "+" or "-" +14 # IsSumOfTerms(_var,expr_IsList())_(expr[1]=ToAtom("+") Or expr[1]=ToAtom("-")) <-- True; + +// after being "Listified", an expr headed by "*" is not considered a sum +// of terms unless one or the other operand is free of the variable +16 # IsSumOfTerms(_var,expr_IsList())_(expr[1]=ToAtom("*")) <-- Or(IsFreeOf(var,expr[2]),IsFreeOf(var,expr[3])); + +// after being "Listified", an expr headed by "/" is not considered a sum +// of terms unless the denominator (only) is free of the variable +18 # IsSumOfTerms(_var,expr_IsList())_(expr[1]=ToAtom("/")) <-- IsFreeOf(var,expr[3]); + +// after being "Listified", any other expression is not a sum of terms +20 # IsSumOfTerms(_var,expr_IsList()) <-- False; + +// if we get to this point, FunctionToList the expression and try again +22 # IsSumOfTerms(_var,_expr) <-- IsSumOfTerms(var,FunctionToList(expr)); + +%/mathpiper + +%mathpiper_docs,name="IsSumOfTerms",categories="User Functions;Predicates" +*CMD IsSumOfTerms --- check for expression being a sum of terms in variable + +*STD +*CALL + IsSumOfTerms(var,expr) + +*PARMS + +{var} -- a variable name + +{expr} -- an expression to be tested + +*DESC + +The command {IsSumOfTerms} returns {True} if the expression {expr} can be +considered to be a "sum of terms" in the given variable {var}. The criteria +are reasonable but somewhat arbitrary. The criteria were selected after +a lot of experimentation, specifically to aid the logic used in Integration. + +The criteria for {expr} to be a sum of terms in {var} are: + o {expr} is a function of variable {var} + o {expr} can best be described as a sum (or difference) of two or more + functions of {var} OR + {expr} is a monomial in {var} (this latter is to simplify the logic) + o {expr} is not better described as a product of functions of {var} + o {expr} is not better described as a quotient of functions of {var} + (i.e., is a rational function) + +Note that the last three criteria are somewhat subjective! + +*E.G. +In> IsSumOfTerms(x,23) +Result> False +In> IsSumOfTerms(x,23*x) +Result> True +In> IsSumOfTerms(x,5*y) +Result> False +In> IsSumOfTerms(x,a*x^2-b*x-c/x) +Result> True +In> IsSumOfTerms(x,Sin(x)) +Result> False +In> IsSumOfTerms(x,Sin(x)+Exp(x)) +Result> True +In> IsSumOfTerms(x,d*(x^2-1)) +Result> True +In> IsSumOfTerms(x,(x^2-1)*d) +Result> True +In> IsSumOfTerms(x,(x^2-1)/d) +Result> True +In> IsSumOfTerms(x,d/(x^2-1)) +Result> False +In> IsSumOfTerms(x,(x^2-1)*(x^2+1)) +Result> False +In> IsSumOfTerms(x,(x^2-1)/(x^2+1)) + Result> False + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsSymmetric.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsSymmetric.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsSymmetric.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsSymmetric.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="IsSymmetric" + +IsSymmetric(A_IsMatrix) <-- (Transpose(A)=A); + +%/mathpiper + + + +%mathpiper_docs,name="IsSymmetric",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsSymmetric --- test for a symmetric matrix +*STD +*CALL + IsSymmetric(A) + +*PARMS + +{A} -- a matrix + +*DESC + +{IsSymmetric(A)} returns {True} if {A} is symmetric and {False} otherwise. +$A$ is symmetric iff Transpose ($A$) =$A$. + +*E.G. + +In> A := {{1,0,0,0,1},{0,2,0,0,0},{0,0,3,0,0}, + {0,0,0,4,0},{1,0,0,0,5}}; +In> PrettyForm(A) + + / \ + | ( 1 ) ( 0 ) ( 0 ) ( 0 ) ( 1 ) | + | | + | ( 0 ) ( 2 ) ( 0 ) ( 0 ) ( 0 ) | + | | + | ( 0 ) ( 0 ) ( 3 ) ( 0 ) ( 0 ) | + | | + | ( 0 ) ( 0 ) ( 0 ) ( 4 ) ( 0 ) | + | | + | ( 1 ) ( 0 ) ( 0 ) ( 0 ) ( 5 ) | + \ / +Result: True; +In> IsSymmetric(A) +Result: True; + + +*SEE IsHermitian, IsSkewSymmetric +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsUnitary.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsUnitary.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsUnitary.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsUnitary.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="IsUnitary" + +IsUnitary(A_IsMatrix) <-- (Transpose(Conjugate(A))*A = Identity(Length(A))); + +%/mathpiper + + + +%mathpiper_docs,name="IsUnitary",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsUnitary --- test for a unitary matrix +*STD +*CALL + IsUnitary(A) + +*PARMS + +{A} -- a square matrix + +*DESC + +This function tries to find out if A is unitary. + +A matrix $A$ is orthogonal iff $A^(-1)$ = Transpose( Conjugate($A$) ). This is +equivalent to the fact that the columns of $A$ build an orthonormal system +(with respect to the scalar product defined by {InProduct}). + +*E.G. + +In> IsUnitary({{0,I},{-I,0}}) +Result: True; +In> IsUnitary({{0,I},{2,0}}) +Result: False; + +*SEE IsHermitian, IsSymmetric +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsUpperTriangular.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsUpperTriangular.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsUpperTriangular.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsUpperTriangular.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,54 @@ +%mathpiper,def="IsUpperTriangular" + +IsUpperTriangular(A_IsMatrix) <-- +[ + Local(i,j,m,n,result); + m:=Length(A); + n:=Length(A[1]); + i:=2; + result:=(m=n); + While(i<=m And result) + [ + j:=1; + While(j<=n And result) + [ + result:= (i<=j Or A[i][j] = 0); + j++; + ]; + i++; + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="IsUpperTriangular",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsUpperTriangular --- test for an upper triangular matrix +*STD +*CALL + IsUpperTriangular(A) + +*PARMS + +{A} -- a matrix + +*DESC + +An upper triangular matrix is a square matrix which has all zero entries above the diagonal. + +{IsUpperTriangular(A)} returns {True} if {A} is an upper triangular matrix and {False} otherwise. + +*E.G. +In> IsUpperTriangular(Identity(5)) +Result: True; +In> IsUpperTriangular({{1,2},{0,1}}) +Result: True; + +A non-square matrix cannot be triangular: +In> IsUpperTriangular({{1,2,3},{0,1,2}}) +Result: False; + +*SEE IsLowerTriangle, IsDiagonal +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsVariable.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsVariable.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsVariable.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsVariable.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="IsVariable" + +IsVariable(_expr) <-- (IsAtom(expr) And Not(expr=Infinity) And Not(expr= -Infinity) And Not(expr=Undefined) And Not(IsNumber(N(Eval(expr))))); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsZero.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsZero.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/IsZero.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/IsZero.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="IsZero" + +//10 # IsZero(x_IsNumber) <-- (DivideN( Round( MultiplyN(x, 10^BuiltinPrecisionGet()) ), 10^BuiltinPrecisionGet() ) = 0); + +// these should be calls to MathSign() and the math library should do this. Or it should be just MathEquals(x,0). +// for now, avoid underflow and avoid IsZero(10^(-BuiltinPrecisionGet())) returning True. +10 # IsZero(x_IsNumber) <-- ( MathSign(x) = 0 Or AbsN(x) < PowerN(10, -BuiltinPrecisionGet())); +60000 # IsZero(_x) <-- False; + +//Note:tk:moved here from univariate.rep. +20 # IsZero(UniVariate(_var,_first,_coefs)) <-- IsZeroVector(coefs); + +%/mathpiper + + + +%mathpiper_docs,name="IsZero",categories="User Functions;Numbers (Predicates);Predicates" +*CMD IsZero --- test whether argument is zero +*STD +*CALL + IsZero(n) + +*PARMS + +{n} -- number to test + +*DESC + +{IsZero(n)} evaluates to {True} if +"n" is zero. In case "n" is not a number, the function returns +{False}. + +*E.G. + +In> IsZero(3.25) +Result: False; +In> IsZero(0) +Result: True; +In> IsZero(x) +Result: False; + +*SEE IsNumber, IsNotZero +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/ListHasFunc.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/ListHasFunc.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/ListHasFunc.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/ListHasFunc.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,50 @@ +%mathpiper,def="ListHasFunc" + +/// ListHasFunc --- test for one of the elements of a list to contain a function +/// this is mainly useful to test whether a list has nested lists, +/// i.e. ListHasFunc({1,2,3}, List)=False and ListHasFunc({1,2,{3}}, List)=True. +// need to exclude the List atom itself, so don't use FunctionToList +19 # ListHasFunc({}, _atom) <-- False; +20 # ListHasFunc(expr_IsList, atom_IsAtom) <-- HasFunc(First(expr), atom) Or ListHasFunc(Rest(expr), atom); + +%/mathpiper + + + + +%mathpiper_docs,name="ListHasFunc",categories="User Functions;Predicates" +*CMD ListHasFunc --- test for one of the elements of a list to contain a function +*STD +*CALL + ListHasFunc( list, func ) + +*PARMS + +{list} - a list of expressions + +{func} - a function atom to be found + +*DESC + +Given a list of expressions and and a function name, this command returns +{True} if the list contains the function name. + +*E.G. +In> lst := {Ln(x),Sinh(a*x),ArcTan(3/x)} +Result: {Ln(x),Sinh(a*x),ArcTan(3/x)} + +In> ListHasFunc(lst,Sqrt) +Result: False + +In> ListHasFunc(lst,Ln) +Result: True + +In> ListHasFunc(lst,Sinh) +Result: True + +In> ListHasFunc(lst,ArcTan) +Result: True +*SEE HasFunc +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/ListHasFuncSome.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/ListHasFuncSome.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/ListHasFuncSome.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/ListHasFuncSome.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,6 @@ +%mathpiper,def="ListHasFuncSome" + +19 # ListHasFuncSome({}, _atom, _look'list) <-- False; +20 # ListHasFuncSome(expr_IsList, atom_IsAtom, _look'list) <-- HasFuncSome(First(expr), atom, look'list) Or ListHasFuncSome(Rest(expr), atom, look'list); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/matrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/matrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/matrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/matrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,240 @@ +%mathpiper,def="IsScalar;IsMatrix;IsVector;IsSquareMatrix" + +/* def file definitions +IsScalar +IsMatrix +IsVector +IsSquareMatrix +*/ + +LocalSymbols(p,x) +[ +// test for a scalar +Function("IsScalar",{x}) Not(IsList(x)); + + + +// test for a vector +Function("IsVector",{x}) + If(IsList(x), + Length(Select(x, IsList))=0, + False); + +// test for a vector w/ element test p +Function("IsVector",{p,x}) +[ + If(IsList(x), + [ + Local(i,n,result); + n:=Length(x); + i:=1; + result:=True; + While(i<=n And result) + [ + result:=Apply(p,{x[i]}); + i++; + ]; + result; + ], + False); +]; + +// test for a matrix (dr) +Function("IsMatrix",{x}) +If(IsList(x) And Length(x)>0, +[ + Local(n); + n:=Length(x); + If(Length(Select(x, IsVector))=n, + MapSingle(Length,x)=Length(x[1])+ZeroVector(n), + False); +], +False); + +// test for a matrix w/ element test p (dr) +Function("IsMatrix",{p,x}) +If(IsMatrix(x), +[ + Local(i,j,m,n,result); + m:=Length(x); + n:=Length(x[1]); + i:=1; + result:=True; + While(i<=m And result) + [ + j:=1; + While(j<=n And result) + [ + result:=Apply(p,{x[i][j]}); + j++; + ]; + i++; + ]; + result; +], +False); + +/* remove? (dr) +IsSquareMatrix(_x) <-- +[ + Local(d); + d:=Dimensions(x); + Length(d)=2 And d[1]=d[2]; +]; +*/ + +// test for a square matrix (dr) +Function("IsSquareMatrix",{x}) IsMatrix(x) And Length(x)=Length(x[1]); +// test for a square matrix w/ element test p (dr) +Function("IsSquareMatrix",{p,x}) IsMatrix(p,x) And Length(x)=Length(x[1]); + +]; // LocalSymbols(p,x) + +%/mathpiper + + + +%mathpiper_docs,name="IsScalar",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsScalar --- test for a scalar +*STD +*CALL + + IsScalar(expr) + +*PARMS + +{expr} -- a mathematical object + +*DESC + +{IsScalar} returns {True} if {expr} is a scalar, {False} otherwise. +Something is considered to be a scalar if it's not a list. + +*E.G. +In> IsScalar(7) +Result: True; +In> IsScalar(Sin(x)+x) +Result: True; +In> IsScalar({x,y}) +Result: False; + +*SEE IsList, IsVector, IsMatrix +%/mathpiper_docs + + + +%mathpiper_docs,name="IsVector",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsVector --- test for a vector +*STD +*CALL + + IsVector(expr) + + IsVector(pred,expr) + +*PARMS + +{expr} -- expression to test + +{pred} -- predicate test (e.g. IsNumber, IsInteger, ...) + +*DESC + +{IsVector(expr)} returns {True} if {expr} is a vector, {False} otherwise. +Something is considered to be a vector if it's a list of scalars. +{IsVector(pred,expr)} returns {True} if {expr} is a vector and if the +predicate test {pred} returns {True} when applied to every element of +the vector {expr}, {False} otherwise. + +*E.G. +In> IsVector({a,b,c}) +Result: True; +In> IsVector({a,{b},c}) +Result: False; +In> IsVector(IsInteger,{1,2,3}) +Result: True; +In> IsVector(IsInteger,{1,2.5,3}) +Result: False; + +*SEE IsList, IsScalar, IsMatrix +%/mathpiper_docs + + + +%mathpiper_docs,name="IsMatrix",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsMatrix --- test for a matrix +*STD +*CALL + IsMatrix(expr) + + IsMatrix(pred,expr) + +*PARMS + +{expr} -- expression to test + +{pred} -- predicate test (e.g. IsNumber, IsInteger, ...) + +*DESC + +{IsMatrix(expr)} returns {True} if {expr} is a matrix, {False} otherwise. +Something is considered to be a matrix if it's a list of vectors of equal +length. +{IsMatrix(pred,expr)} returns {True} if {expr} is a matrix and if the +predicate test {pred} returns {True} when applied to every element of +the matrix {expr}, {False} otherwise. + +*E.G. + +In> IsMatrix(1) +Result: False; +In> IsMatrix({1,2}) +Result: False; +In> IsMatrix({{1,2},{3,4}}) +Result: True; +In> IsMatrix(IsRational,{{1,2},{3,4}}) +Result: False; +In> IsMatrix(IsRational,{{1/2,2/3},{3/4,4/5}}) +Result: True; + +*SEE IsList, IsVector +%/mathpiper_docs + + + +%mathpiper_docs,name="IsSquareMatrix",categories="User Functions;Matrices (Predicates);Predicates" +*CMD IsSquareMatrix --- test for a square matrix +*STD +*CALL + IsSquareMatrix(expr) + + IsSquareMatrix(pred,expr) + +*PARMS + +{expr} -- expression to test + +{pred} -- predicate test (e.g. IsNumber, IsInteger, ...) + +*DESC + +{IsSquareMatrix(expr)} returns {True} if {expr} is a square matrix, +{False} otherwise. Something is considered to be a square matrix if +it's a matrix having the same number of rows and columns. +{IsMatrix(pred,expr)} returns {True} if {expr} is a square matrix and +if the predicate test {pred} returns {True} when applied to every +element of the matrix {expr}, {False} otherwise. + +*E.G. + +In> IsSquareMatrix({{1,2},{3,4}}); +Result: True; +In> IsSquareMatrix({{1,2,3},{4,5,6}}); +Result: False; +In> IsSquareMatrix(IsBoolean,{{1,2},{3,4}}); +Result: False; +In> IsSquareMatrix(IsBoolean,{{True,False},{False,True}}); +Result: True; + +*SEE IsMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/NoneSatisfy.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/NoneSatisfy.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/predicates/NoneSatisfy.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/predicates/NoneSatisfy.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="NoneSatisfy" + +10 # NoneSatisfy(pred_IsString,lst_IsList) <-- Not Apply("Or",(MapSingle(pred,lst))); + +20 # NoneSatisfy(_pred,_lst) <-- True; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + +%mathpiper_docs,name="NoneSatisfy",categories="User Functions;Predicates" + +*CMD NoneSatisfy --- Check if NO element of list {lst} satisfies predicate {pred} + +*STD +*CALL + NoneSatisfy(pred,lst) + +*PARMS + +{pred} -- the name of the predicate (as string, with quotes) to be tested + +{lst} -- a list + +*DESC + +The command {NoneSatisfy} returns {True} if NO element of the list {lst} satisfies the predicate {pred}. +It returns {False} if at least one element of the list satisfies the predicate. +It also returns {True} if {lst} is not a list, or if {pred} is not a predicate. + +*E.G. + +In> NoneSatisfy("IsNegativeInteger",{1,0,5}) +Result: True +In> NoneSatisfy("IsPositiveInteger",{-1,0,5}) +Result: False + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/probability/CDF.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/probability/CDF.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/probability/CDF.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/probability/CDF.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,98 @@ +%mathpiper,def="CDF" + +/* Evaluates distribution dst at point x + known distributions are: + 1. Discrete distributions + -- BernoulliDistribution(p) + -- BinomialDistribution(p,n) + -- DiscreteUniformDistribution(a,b) + -- PoissonDistribution(l) + -- HypergeometricDistribution(N, M) + 2. Continuous distributions + -- ExponentialDistribution(l) + -- NormalDistrobution(a,s) + -- ContinuousUniformDistribution(a,b) + -- tDistribution(m) + -- GammaDistribution(m) + -- ChiSquareDistribution(m) + + DiscreteDistribution(domain,probabilities) represent arbitrary + distribution with finite number of possible values; domain list + contains possible values such that + Pr(X=domain[i])=probabilities[i]. + TODO: Should domain contain numbers only? +*/ + + +/* Evaluates Cumulative probability function CDF(x)=Pr(X0 And x<=1, p,1)); +11 # CDF(BernoulliDistribution(_p), _x) <-- Hold(If(x<=0,0,If(x>0 And x<=1, p,1))); + +10 # CDF(BinomialDistribution(_p,_n),m_IsNumber)_(m<0) <-- 0; +10 # CDF(BinomialDistribution(_p,n_IsInteger),m_IsNumber)_(m>n) <-- 1; +10 # CDF(BinomialDistribution(_p,_n),_m) <-- Sum @ { i, 0, Floor(m), PMF(BinomialDistribution(p,n),i)}; + +10 # CDF(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(x<=a) <-- 0; +10 # CDF(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(x>b) <-- 1; +10 # CDF(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(ab,0,1/(b-a)); + +10 # PDF(DiscreteDistribution( dom_IsList, prob_IsList), _x)_( Length(dom)=Length(prob) And Simplify(Add(prob))=1) <-- + [ + Local(i); + i:=Find(dom,x); + If(i = -1,0,prob[i]); + ]; +10 # PDF( ChiSquareDistribution( _m),x_IsRationalOrNumber)_(x<=0) <-- 0; +20 # PDF( ChiSquareDistribution( _m),_x) <-- x^(m/2-1)*Exp(-x/2)/2^(m/2)/Gamma(m/2); + +10 # PDF(tDistribution(_m),x) <-- Gamma((m+1)/2)*(1+x^2/m)^(-(m+1)/2)/Gamma(m/2)/Sqrt(Pi*m); + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="PDF",categories="User Functions;Statistics & Probability" +*CMD PDF --- probability density function +*STD +*CALL + PDF(dist,x) + +*PARMS +{dist} -- a distribution type + +{x} -- a value of random variable + +*DESC +{PDF} +returns the density function at point $x$. + +The probability density function (PDF) of a continuous distribution is defined as the +derivative of the (cumulative) distribution function. + +*SEE CDF, PMF, Expectation +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/probability/PMF.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/probability/PMF.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/probability/PMF.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/probability/PMF.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,82 @@ +%mathpiper,def="PMF" + +/* Evaluates distribution dst at point x + known distributions are: + 1. Discrete distributions + -- BernoulliDistribution(p) + -- BinomialDistribution(p,n) + -- DiscreteUniformDistribution(a,b) + -- PoissonDistribution(l) + + 2. Continuous distributions + -- ExponentialDistribution(l) + -- NormalDistrobution(a,s) + -- ContinuousUniformDistribution(a,b) + -- tDistribution(m) + -- GammaDistribution(m) + -- ChiSquareDistribution(m) + + DiscreteDistribution(domain,probabilities) represent arbitrary + distribution with finite number of possible values; domain list + contains possible values such that + Pr(X=domain[i])=probabilities[i]. + TODO: Should domain contain numbers only? +*/ + +//Retract("PMF", *); + +10 # PMF(BernoulliDistribution(_p),0) <-- p; +10 # PMF(BernoulliDistribution(_p),1) <-- 1-p; +10 # PMF(BernoulliDistribution(_p),x_IsNumber)_(x != 0 And x != 1) <-- 0; +10 # PMF(BernoulliDistribution(_p),_x) <-- Hold(If(x=0,p,If(x=1,1-p,0))); + +10 # PMF(BinomialDistribution(_p,_n),_k) <-- BinomialCoefficient(n,k)*p^k*(1-p)^(n-k); + +10 # PMF(DiscreteUniformDistribution(_a,_b), x_IsNumber) <-- If(xb, 0 ,1/(b-a+1)); +11 # PMF(DiscreteUniformDistribution(_a,_b), _x) <-- Hold(If(xb, 0 ,1/(b-a+1))); + +10 # PMF(PoissonDistribution(_l), n_IsNumber) <-- If(n<0,0,Exp(-l)*l^n/n!); +11 # PMF(PoissonDistribution(_l),_n) <-- Exp(-l)*l^n/n!; + +10 # PMF(GeometricDistribution(_p),_n) <--If(n<0,0,p*(1-p)^n); + + + +10 # PMF(DiscreteDistribution( dom_IsList, prob_IsList), _x)_( Length(dom)=Length(prob) And Simplify(Add(prob))=1) <-- + [ + Local(i); + i:=Find(dom,x); + If(i = -1,0,prob[i]); + ]; + + + +10 # PMF(HypergeometricDistribution( N_IsNumber, M_IsNumber, n_IsNumber), x_IsNumber)_(M <= N And n <= N) <-- (BinomialCoefficient(M,x) * BinomialCoefficient(N-M, n-x))/BinomialCoefficient(N,n); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="PMF",categories="User Functions;Statistics & Probability" +*CMD PMF --- probability mass function +*STD +*CALL + PMF(dist,x) + +*PARMS +{dist} -- a distribution type + +{x} -- a value of random variable + +*DESC +{PMF} returns the +probability for a random variable with distribution {dist} to take a +value of {x}. + + +*SEE CDF, PDF, Expectation +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/equations/ManipEquations.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/equations/ManipEquations.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/equations/ManipEquations.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/equations/ManipEquations.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,187 @@ +%mathpiper + +//Retract("IsEquation",*); + +//Retract("*==",*); +//Retract("/==",*); +//Retract("+==",*); +//Retract("-==",*); +//Retract("==+",*); +//Retract("==-",*); + +10 # IsEquation(expr_IsAtom) <-- False; +12 # IsEquation(_expr) <-- +[ + Local(EL,res); + EL := FunctionToList(expr); + res := (EL[1] = == ); +]; + +10 # *==(_num,eqn_IsEquation) <-- +[ + Local(EL,LHS,RHS); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( num * EL[2] )); + RHS := Expand(Simplify( num * EL[3] )); + LHS == RHS; +]; + +10 # *==(eqn_IsEquation,_num) <-- +[ + Local(EL,LHS,RHS); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( num * EL[2] )); + RHS := Expand(Simplify( num * EL[3] )); + LHS == RHS; +]; + +10 # /==(eqn_IsEquation,_num) <-- +[ + Local(EL,LHS,RHS); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( EL[2] / num )); + RHS := Expand(Simplify( EL[3] / num )); + LHS == RHS; +]; + +10 # +==(_num,eqn_IsEquation) <-- +[ + Local(EL,LHS,RHS); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( EL[2] + num )); + RHS := Expand(Simplify( EL[3] + num )); + LHS == RHS; +]; + +10 # +==(eqn_IsEquation,_num) <-- +[ + Local(EL,LHS,RHS); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( EL[2] + num )); + RHS := Expand(Simplify( EL[3] + num )); + LHS == RHS; +]; + +10 # -==(eqn_IsEquation,_num) <-- +[ + Local(EL,LHS,RHS); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( EL[2] - num )); + RHS := Expand(Simplify( EL[3] - num )); + LHS == RHS; +]; + +10 # -==(_num,eqn_IsEquation) <-- +[ + Local(EL,LHS,RHS); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( num - EL[2] )); + RHS := Expand(Simplify( num - EL[3] )); + LHS == RHS; +]; + +12 # ==+(eqn1_IsEquation,eqn2_IsEquation) <-- +[ + Local(EL1,LHS,RHS,EL2); + EL1 := FunctionToList(eqn1); + EL2 := FunctionToList(eqn2); + LHS := Expand(Simplify( EL1[2] + EL2[2] )); + RHS := Expand(Simplify( EL1[3] + EL2[3] )); + LHS == RHS; +]; + +12 # ==-(eqn1_IsEquation,eqn2_IsEquation) <-- +[ + Local(EL1,LHS,RHS,EL2); + EL1 := FunctionToList(eqn1); + EL2 := FunctionToList(eqn2); + LHS := Expand(Simplify( EL1[2] - EL2[2] )); + RHS := Expand(Simplify( EL1[3] - EL2[3] )); + LHS == RHS; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +/////////////////////////////////////////////////////////////////////////////// + +%mathpiper,scope="nobuild",subtype="manual_test" + +Unbind(eqns,eq1,eq2,eq3,eq5,eq6,eq7,X,Y,solution); + +/* Wade & Taylor, page 222, Example 2 */ +// Solve the pair of equations +// 2*x + 3*y == 7 +// 3*x - 2*y == 4 + +eqns := { 2*x+3*y==7, 3*x-2*y==4 }; +Tell(0,eqns); +NewLine(); + +// multiply each side of eqns[1] by 2: +eq1 := *==(2,eqns[1]); +// multiply each side of eqns[2] by 3: +eq2 := *==(3,eqns[2]); +Tell(1,eq1); +Tell(2,eq2); +NewLine(); +// add the two equations together +eq3 := ==+(eq1,eq2); +Tell(Eq2+Eq3,eq3); +// solve eq3 for x +X := Solve(eq3,x); +Tell(4,X); +NewLine(); + +// now multiply each side of eqns[1] by 3: +eq5 := *==(3,eqns[1]); +// multiply each side of eqns[2] by 2: +eq6 := *==(2,eqns[2]); +Tell(5,eq5); +Tell(6,eq6); +NewLine(); +// subtract eq6 from eq5 +eq7 := ==-(eq5,eq6); +Tell(Eq5-Eq6,eq7); +// solve eq7 for y +Y := Solve(eq7,y); +Tell(8,Y); +NewLine(); + +solution := {X,Y}; +Tell(9,solution); + + +%/mathpiper + + %output,preserve="false" + Result: True + + Side effects: + << 0 >> eqns {2*x+3*y==7,3*x-2*y==4} + + << 1 >> eq1 4*x+6*y==14 + << 2 >> eq2 9*x-6*y==12 + + << Eq2+Eq3 >> eq3 13*x==26 + << 4 >> X {x==2} + + << 5 >> eq5 6*x+9*y==21 + << 6 >> eq6 6*x-4*y==8 + + << Eq5-Eq6 >> eq7 13*y==13 + << 8 >> Y {y==1} + + << 9 >> solution {{x==2},{y==1}} +. %/output + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/equations/Manipulate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/equations/Manipulate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/equations/Manipulate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/equations/Manipulate.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="Manipulate" + +//Retract("Manipulate",*); + +Rulebase("Manipulate",{symbolicEquation}); +HoldArgument("Manipulate",symbolicEquation); +10 # Manipulate(_symbolicEquation)_HasFunc(Eval(symbolicEquation), "==") <-- +[ + Local(listForm, operator, operand, left, right, leftManipulated, rightManipulated, operandIndex, equationIndex, leftOrder, rightOrder); + + listForm := FunctionToList(symbolicEquation); + + operator := listForm[1]; + + If(HasFunc(Eval(listForm[2]),"==" ), [operandIndex := 3; equationIndex := 2; ], [ operandIndex := 2; equationIndex := 3;]); + + operand := listForm[operandIndex]; + equation := Eval(listForm[equationIndex]); + left := EquationLeft(equation); + right := EquationRight(equation); + + If(operandIndex = 3, [ leftOrder := `({left,operand});rightOrder := `({right,operand});], [leftOrder := `({operand,left}); rightOrder := `({operand,right});]); + + + leftManipulated := ExpandBrackets(Simplify(Apply(ToString(operator), leftOrder))); + rightManipulated := ExpandBrackets(Simplify(Apply(ToString(operator), rightOrder))); + + leftManipulated == rightManipulated; + +]; + +%/mathpiper + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +Unbind(equ,a); + +equ := y == m*x+b; +Tell(1, Manipulate(2*equ)); +Tell(2, Manipulate(equ*2)); +Tell(3, Manipulate(2/equ)); +Tell(4, Manipulate(equ/2)); +Tell(5, Manipulate(equ^2)); + +equ := Sqrt(a) == 3; +Tell(6, Manipulate(equ^2)); + +%/mathpiper + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/equations/SolveSetEqns.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/equations/SolveSetEqns.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/equations/SolveSetEqns.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/equations/SolveSetEqns.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,186 @@ +%mathpiper + +LoadScriptOnce("proposed.rep/equations.mpi"); + +//Retract("SolveLinearSysViaMatrix",*); + +//Retract("SolveLinearSystemViaGauss",*); + +//Retract("CheckEquationSolution",*); + + + +10 # SolveLinearSysViaMatrix( eqns_IsList, vars_IsList ) <-- +[ + /*** NOTE: This function appears to be fully functional, and */ + /*** gives correct answers, but */ + /*** needs some more work to get answers into desired form */ + + Local(LE,LV,E,LHS,X,M,RHS,LL,eqn,row,ans,Det); + If(InVerboseMode(),Tell(SolveLinearSysViaMatrix,{eqns,vars})); + LE := Length(eqns); + LV := Length(vars); + E := Assert() LE=LV; + Check(E, "Argument", "Number of equations != Number of variables"); + + LHS := {}; + RHS := {}; + X := vars; + M := FillList(1,LE); + ForEach(eqn,eqns) + [ + E := FunctionToList(eqn); + LL := E[2]; + RHS := E[3]:RHS; + row := Map("Coef",{FillList(LL,LE),X,M}); + LHS := row:LHS; + ]; + LHS := DestructiveReverse(LHS); + RHS := DestructiveReverse(RHS); + Det := Determinant(LHS); + //Tell(det,Det); + + ans :=MatrixSolve(LHS,RHS); +]; + +12 # SolveLinearSysViaMatrix( _eqns, _vars ) <-- False; + + + + +10 # SolveLinearSystemViaGauss( eqns_IsList, vars_IsList ) <-- +[ + /***** WARNING: This version is valid for TWO equations only *****/ + + Local(LE,LV,E,E2,s,s1,s2,s3,ans); + If(InVerboseMode(),Tell(SolveLinearSysViaGauss,{eqns,vars})); + LE := Length(eqns); + LV := Length(vars); + E := Assert() LE=LV; + Check(E, "Argument", "Number of equations != Number of variables"); + + If(InVerboseMode(),Tell(0,{LE,LV,E})); + s := Solve( eqns, vars )[1]; + If(InVerboseMode(),Tell(1,s)); + s1 := s[1]; + s2 := s[2]; + s3 := s[3]; + E2 := FunctionToList(s3); + s2 := (s2 Where s3); + s1 := (s1 Where s2 And s3); + If( E2[2]=E2[3], ans:=Inconsistent-Set, ans:=List(s1,s2,s3)); + ans; +]; + +12 # SolveLinearSystemViaGauss( _eqns, _vars ) <-- False; + + + + +10 # CheckEquationSolution( eqn_IsEquation, soln_IsList ) <-- +[ + Local(EL,LHS,RHS,L,svar,sval); + If(InVerboseMode(),Tell(CheckOneEq,{eqn,soln})); + EL := FunctionToList(eqn); + LHS := Expand(Simplify( EL[2] )); + RHS := Expand(Simplify( EL[3] )); + L := FunctionToList(soln[1]); + svar := L[2]; + sval := L[3]; + If( InVerboseMode(), [Tell(2,{LHS,RHS}); Tell(3,{svar,sval});]); + V := Eliminate(svar,sval,LHS); + If(InVerboseMode(),Tell(4,V)); + V = RHS; +]; + +12 # CheckEquationSolution( eqns_IsList, solns_IsList ) <-- +[ + Tell(CheckSetOfEqns,{eqns,solns}); + Check(False, "Unimplemented", "Not implemented yet"); +]; + +14 # CheckEquationSolution( _eq, _soln ) <-- +[ + Tell(CheckEqnLeftovers,{eq,soln}); + False; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +/////////////////////////////////////////////////////////////////////////////// + +%mathpiper,scope="nobuild",subtype="manual_test" + +Unbind(eqns1,eqns2,eqns3,eqns4,eqns5,solution); + +// --- Test the new solver for sets of linear equations --- + +NewLine(); + +eqns1 := {2*x-2*y+z==(-7),3*x+y+2*z==(-2),5*x+3*y-3*z==(-7)}; // 3 eqns, 3 unknowns +Tell(Independent,eqns1); +solution := SolveLinearSysViaMatrix(eqns1,{x,y,z}); +Tell(11,solution); +NewLine(); + +eqns2 := {3*x-2*y+z==1,x-y-z==2,6*x-4*y+2*z==3}; // 3 eqns, 3 unks, inconsistent +Tell(Inconsistent,eqns2); +solution := SolveLinearSysViaMatrix(eqns2,{x,y,z}); +Tell(13,solution); +NewLine(); + +eqns3 := {2*x+3*y==12,3*x+2*y==12}; // 2 eqns, 2 unknown, independent +Tell(Independent,eqns3); +solution := SolveLinearSysViaMatrix(eqns3,{x,y}); +Tell(15,solution); +NewLine(); + +eqns4 := {2*x+3*y==6,4*x+6*y==12}; // 2 eqns, 2 unknowns, dependent +Tell(Dependent,eqns4); +solution := SolveLinearSysViaMatrix(eqns4,{x,y}); +Tell(17,solution); +NewLine(); + +eqns5 := {2*x+3*y==6,2*x+3*y==8}; // 2 eqns, 2 unknowns, parallel (inconsistent) +Tell(Inconsistent,eqns5); +solution := SolveLinearSysViaMatrix(eqns5,{x,y}); +Tell(19,solution); +NewLine(); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side effects: + << Independent >> eqns1 {2*x-2*y+z==(-7),3*x+y+2*z==(-2),5*x+3*y-3*z==(-7)} + << det >> Det -52 + << 11 >> solution {-2,2,1} + + << Inconsistent >> eqns2 {3*x-2*y+z==1,x-y-z==2,6*x-4*y+2*z==3} + << det >> Det 0 + << 13 >> solution {Undefined,Infinity,Infinity} + + << Independent >> eqns3 {2*x+3*y==12,3*x+2*y==12} + << det >> Det -5 + << 15 >> solution {12/5,12/5} + + << Dependent >> eqns4 {2*x+3*y==6,4*x+6*y==12} + << det >> Det 0 + << 17 >> solution {Undefined,Undefined} + + << Inconsistent >> eqns5 {2*x+3*y==6,2*x+3*y==8} + << det >> Det 0 + << 19 >> solution {Infinity,Infinity} +. %/output + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/ControlChart.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/ControlChart.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/ControlChart.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/ControlChart.mpw 2010-06-23 05:47:16.000000000 +0000 @@ -0,0 +1,235 @@ +%mathpiper,def="ControlChart" + + +ControlChart(data) := +[ + A2 := .577; + D3 := 0; + D4 := 2.144; + + means := {}; + meansPoints := {}; + + ranges := {}; + rangesPoints := {}; + + index := 1; + ForEach(group, data) + [ + groupMean := Mean(group); + means := N(Append(means, groupMean)); + meansPoints := N(Append(meansPoints,{index, groupMean} )); + + + groupRange := Range(group); + ranges := N(Append(ranges, groupRange)); + rangesPoints := N(Append(rangesPoints,{index, groupRange} )); + + index++; + ]; + + xBarBar := N(Mean(means)); + + rBar := N(Mean(ranges)); + + xBarUCL := N(xBarBar + A2*rBar); + + xBarLCL := N(xBarBar - A2*rBar); + + rUCL := N(D4*rBar); + + rLCL := N(D3*rBar); +]; + + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +data := GenMatrix(Lambda({m,n},Distribution(5,2)),25,5); + + + + +%/mathpiper + + %output,preserve="false" + Result: {{5.535324696,3.147460888,4.910225401,6.076869410,8.616587548},{6.783193684,3.999124035,2.070132681,2.198471456,4.689837614},{5.115861586,2.556715922,1.791504284,1.570696873,3.186504705},{6.618546432,5.058075678,6.425406544,5.440151296,2.876156767},{6.870813463,5.536460503,3.742818612,3.273049807,5.440834797},{3.476261577,4.489497315,5.362976802,4.692969850,9.302494507},{7.193172085,1.406463231,3.552659846,5.868100596,5.048939936},{5.927707889,5.330929820,7.591065070,7.721676042,4.486786941},{10.31005985,5.395145532,7.605833444,3.065209181,5.762217907},{4.372961981,2.350334458,5.060549217,1.608207367,5.655733286},{10.64165146,4.807379261,4.127881722,3.879634014,7.783716362},{7.688489023,7.943422085,6.444746912,4.878194094,6.822302753},{5.986770920,1.645611318,3.476876756,4.688580264,4.838067994},{5.819847473,2.226979256,4.577186742,3.901802467,3.643508353},{5.330135257,8.514456587,7.449548011,7.243322996,5.061887727},{8.707067795,9.918086297,5.811769283,8.427376524,4.489150866},{6.084687883,9.006779258,8.491709337,3.211253709,3.300043312},{5.609307637,5.212278303,1.740591039,4.448388564,4.149500985},{3.188763079,8.104502601,7.255061454,3.195876581,2.452227551},{4.056398335,8.168559972,1.212381947,7.235714611,4.570414194},{7.429250440,8.693442366,5.930319720,5.669600753,5.712002630},{4.830909107,4.145336311,5.837332990,2.333043187,7.248572647},{3.301122251,5.373453189,6.696566666,7.643856909,0.6769830979},{5.931296300,3.747230241,6.487956900,4.663625370,6.587462343},{4.350973859,4.126664313,5.013334724,7.941338276,3.987860776}} +. %/output + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" +ControlChart(data); +%/mathpiper + + %output,preserve="false" + Result: 0.000000000 +. %/output + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +GeoGebraPlot(meansPoints, lines -> True, pointSize -> 3); + + +GeoGebraPoint("M1",-10,xBarBar); +GeoGebraPoint("M2",-10.1,xBarBar); +ggbLine("M1","M2"); + + + +GeoGebraPoint("XBUCL1",-10,xBarUCL); +GeoGebraPoint("XBUCL2",-10.1,xBarUCL); +ggbLine("XBUCL1","XBUCL2"); + + + +GeoGebraPoint("XBLCL1",-10,xBarLCL); +GeoGebraPoint("XBLCL2",-10.1,xBarLCL); +ggbLine("XBLCL1","XBLCL2"); + + + + +/* +GeoGebraPlot(rangesPoints, lines -> True, pointSize -> 3); + +GeoGebraPoint("RM1",-10,rBar); +GeoGebraPoint("RM2",-10.1,rBar); +ggbLine("RM1","RM2"); + + + +GeoGebraPoint("RUCL1",-10,rUCL); +GeoGebraPoint("RUCL2",-10.1,rUCL); +ggbLine("RUCL1","RUCL2"); +*/ + + +//GeoGebraPoint("RLCL1",-10,rLCL); +//GeoGebraPoint("RLCL2",-10.1,rLCL); +//ggbLine("RLCL1","RLCL2"); + + +%/mathpiper + + %output,preserve="false" + Result: java.lang.Boolean +. %/output + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" +valuesList := {}; + +Repeat(100) +[ + valuesList := Append( valuesList, Distribution(5,5)); +]; + +valuesList; + +%/mathpiper + + %output,preserve="false" + Result: {3.904859738,1.291245119,11.33193219,2.125285126,2.897183574,6.404705964,2.809908112,0.8959498543,-2.246507238,2.384965110,5.531072931,1.801205670,6.167452541,-7.351081999,12.11859980,9.180652366,1.673470418,12.85119952,8.289753546,7.329728608,16.56995847,-5.806212238,-0.2918977644,-5.016981483,-1.932580558,10.22353528,4.033740000,9.522452367,9.488877976,8.212033039,11.24095104,3.149750964,-4.636901582,3.114616951,5.107259223,6.438374872,-0.6691735799,-0.8989714262,3.524368314,8.812615959,11.55612690,-3.058949624,2.848064062,0.5805488029,4.228697674,9.204665650,12.56855781,7.161728034,-7.201276121,3.702134288,12.20015166,3.319400475,1.562030448,4.665392950,-0.9897927647,2.701793362,14.99166973,3.838483238,3.285145809,0.2952079157,-5.906821377,7.049031704,-0.04361766674,6.289087138,8.640938903,15.48532166,-0.8308200551,5.264794370,6.954885186,2.721880917,10.38558697,8.861197033,5.219130424,-6.927169919,11.19627536,-3.360568640,0.6941200991,9.437604661,13.43687895,13.63578408,5.223931686,3.204927361,1.153818678,3.648579283,1.807616607,1.577352864,6.560595738,1.044125663,4.486200728,10.79969047,6.154173391,7.790004186,8.372930355,3.630221422,6.137493876,3.543304102,-1.314402929,-0.8982105160,4.992513937,2.062545116} +. %/output + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +zz1 := RandomIntegerList(1000,1,9); +Histogram(zz1); + +%/mathpiper + + %output,preserve="false" + Result: org.jfree.chart.ChartPanel +. %/output + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +/* +This is +more than one +line of +commenting! +*/ + +zz3 := GenMatrix(Lambda({m,n},m,n),4,5); + +%/mathpiper + + %output,preserve="false" + Result: {{1,1,1,1,1},{2,2,2,2,2},{3,3,3,3,3},{4,4,4,4,4}} +. %/output + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +parts := {10.225,10.290,10.193,10.187,10.097,10.116,10.149,10.128,10.032,10.071,10.089,10.090,10.105,10.091,10.137,10.140,10.071,10.077,10.020,10.057,10.107,10.075,10.139,10.170,10.150,9.937,9.908,9.927,9.911,9.862,9.823,9.400,10.145,10.007,9.026}; + +partsPoints := {}; + +index := 1; +ForEach(part, parts) +[ + partsPoints := N(Append(partsPoints,{index, part} )); + + + index++; +]; + +partsPoints; +%/mathpiper + + %output,preserve="false" + Result: {{1,10.225},{2,10.290},{3,10.193},{4,10.187},{5,10.097},{6,10.116},{7,10.149},{8,10.128},{9,10.032},{10,10.071},{11,10.089},{12,10.090},{13,10.105},{14,10.091},{15,10.137},{16,10.140},{17,10.071},{18,10.077},{19,10.020},{20,10.057},{21,10.107},{22,10.075},{23,10.139},{24,10.170},{25,10.150},{26,9.937},{27,9.908},{28,9.927},{29,9.911},{30,9.862},{31,9.823},{32,9.400},{33,10.145},{34,10.007},{35,9.026}} +. %/output + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +GeoGebraPlot(partsPoints, lines -> True, pointSize -> 3); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraHistogram.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraHistogram.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraHistogram.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraHistogram.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,94 @@ +%mathpiper,def="GeoGebraHistogram" + +//Retract("GeoGebraHistogram",*); + +GeoGebraHistogram(classBoundaries, data) := +[ + Local(command); + //todo:tk: a check must be made to make sure that all data items fit into the class boundaries. + // If they don't, GeoGebra will not accept them. + + command := PatchString("Histogram[,]"); + JavaCall(geogebra, "evalCommand", command); +]; + + + + +GeoGebraHistogram(data) := +[ + Local(command, classBoundaries, noDuplicatesSorted, largestValue, smallestValue, x, numberOfUniqueValues); + + noDuplicatesSorted := HeapSort(RemoveDuplicates(data), "<" ); + + smallestValue := Floor(noDuplicatesSorted[1]); + + numberOfUniqueValues := Length(noDuplicatesSorted); + + largestValue := Ceil(noDuplicatesSorted[Length(noDuplicatesSorted)]); + + classBoundaries := N(Table(x,x,smallestValue-.5,largestValue+.5,1)); + + command := PatchString("Histogram[,]"); + JavaCall(geogebra, "evalCommand", command); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +GeoGebraHistogram({1, 2, 3, 4}, {1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}); + +%/mathpiper + + %output,preserve="false" + Result: class java.lang.Boolean +. %/output + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +GeoGebraHistogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}); + +%/mathpiper + + %output,preserve="false" + Result: java.lang.Boolean +. %/output + + +%mathpiper,scope="nobuild",subtype="manual_test" + +GeoGebraHistogram(N({16+3/8, 16+3/8, 17+1/8, 16, 14+3/8, 17+1/4, 16+5/8, 16, 17, 17+1/4, 17, 15+7/8, 16+5/8, 16+1/8, 17+1/8, 16+7/8, 16+3/8, 16+3/8, 16+7/8, 17+1/8, 17, 16+3/4, 17+1/4, 17+1/8, 15+3/8})); + +%/mathpiper + + %output,preserve="false" + Result: class java.lang.Boolean +. %/output + + + +%mathpiper,scope="nobuild",subtype="manual_test" +classBoundaries := N(Table(x,x,14,20,1/4)); + +E := N({16+3/8, 16+3/8, 17+1/8, 16, 14+3/8, 17+1/4, 16+5/8, 16, 17, 17+1/4, 17, 15+7/8, 16+5/8, 16+1/8, 17+1/8, 16+7/8, 16+3/8, 16+3/8, 16+7/8, 17+1/8, 17, 16+3/4, 17+1/4, 17+1/8, 15+3/8}); + +D := N({18+1/4, 19+1/4, 18+1/4, 15+5/8, 17+5/8, 17+1/2, 17+1/8, 17+1/8, 17+1/2, 14+1/2, 17+3/8, 16+7/8, 17+3/4, 18+7/8, 14+7/8, 19+1/4, 18+1/8, 16+1/4, 16+1/8, 16+3/4, 17+1/4, 17+3/8, 17+1/8, 17+1/2, 16+5/8}); + +GeoGebraHistogram(classBoundaries,Concat(D,E)); + +%/mathpiper + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebra.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebra.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebra.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebra.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="GeoGebra" + +//Retract("GeoGebra",*); + +LocalSymbols(options) +[ + options := {}; + + Local(updateObjects); + + updateObjects := ""; + + options["updateObjects"] := updateObjects; + + + +GeoGebra() := options; + + +GeoGebra(list) := (options := list); + + + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +LoadScriptOnce("proposed.rep/geogebra.mpi"); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPlot.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPlot.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPlot.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPlot.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,155 @@ +%mathpiper,def="GeoGebraPlot" +//Retract("GeoGebraPlot",*); + +RulebaseListed("GeoGebraPlot",{arg1,arg2}); + + + +5 # GeoGebraPlot(_arg1) <-- GeoGebraPlot(arg1,{}); //Handle single argument call. + + +20 # GeoGebraPlot(function_IsFunction, options_IsList)_(Not IsList(function)) <-- +[ + Local(command); + + function := (Subst(==,=) function); + + command := ConcatStrings(PipeToString()Write(function)); + + JavaCall(geogebra,"evalCommand",command); +]; + + + + +10 # GeoGebraPlot(list_IsList, _options)_(IsNumericList(list) ) <-- +[ + If(IsList(options), options := OptionsToAssociativeList(options), options := OptionsToAssociativeList({options})); + + Local(length, index, labelIndex, pointTemplate, segmentCommandTemplate, segmentElementTemplate, command, code, x, y, pointSize); + + length := Length(list); + + If(IsOdd(length), list := Append(list,list[length])); //Make list even for line drawing. + + If(options["pointSize"] != Empty, pointSize := options["pointSize"], pointSize := "1"); + + index := 1; + + labelIndex := 1; + + pointTemplate := "\"> \" y=\"\" z=\"1.0\"/> \"/>"; + segmentCommandTemplate := ""; + segmentElementTemplate := "\">"; + + + //todo:tk: this does not seem to be working JavaCall(geogebra, "setRepaintingActive", "false"); + //JavaCall(geogebra, "setLayerVisible", "0", "False"); + + While(index < length+1) + [ + x := list[index]; + index++; + y := list[index]; + index++; + + + code := PatchString(pointTemplate); + + + JavaCall(geogebra,"evalXML",code); + + If(options["lines"] = "True" And labelIndex > 1, + [ + + command := PatchString("a = Segment[A,A]"); + JavaCall(geogebra, "evalCommand", command); + + + code := PatchString(segmentElementTemplate); + JavaCall(geogebra,"evalXML",code); + ] + ); + + labelIndex++; + ]; //end while. + + //todo:tk: this does not seem to be working JavaCall(geogebra, "setRepaintingActive", "true"); + //JavaCall(geogebra, "setLayerVisible", "0", "True"); + +]; + + +5 # GeoGebraPlot(list_IsList, _options)_(IsMatrix(list)) <-- +[ + Local(flatList); + + flatList := {}; + + ForEach(subList,list) + [ + DestructiveAppend(flatList,subList[1]); + DestructiveAppend(flatList, subList[2]); + ]; + + GeoGebraPlot(flatList, options); + +]; + +//HoldArgument("GeoGebraPlot",arg2); + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper,title="",scope="nobuild",subtype="manual_test" + +GeoGebraPlot({1,1,2,2,3,3,4,4,5,5,6,6}, lines -> True); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper,title="",scope="nobuild",subtype="manual_test" + +GeoGebraPlot({{0,0}, {0,-1},{0,-2},{1,-2},{1,-1},{2,-1},{3,-1},{4,-1},{4,-2},{5,-2},{6,-2},{6,-1},{6,-2},{7,-2},{7,-1},{8,-1},{8,0},{8,-1},{9,-1},{8,-1},{7,-1}},lines -> True, labels -> False); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper,title="",scope="nobuild",subtype="manual_test" +GeoGebraPlot(Hold(f(x) = x^2)); + +GeoGebraPlot(x^3); + +%/mathpiper + + %output,preserve="false" + Result: true +. %/output + + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPoint.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPoint.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPoint.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/GeoGebraPoint.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,19 @@ +%mathpiper,def="GeoGebraPoint" +//Retract("GeoGebraPoint",*); + +10 # GeoGebraPoint(name_IsString, x_IsNumber, y_IsNumber) <-- +[ + Local(command); + + command := PatchString("=(,)"); + + JavaCall(geogebra,"evalCommand",command); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/ggbLine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/ggbLine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geogebra/ggbLine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geogebra/ggbLine.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,21 @@ +%mathpiper,def="GgbLine" + +//Retract("ggbLine", *); + +ggbLine(point1Label, point2Label) := +[ + Local(command); + + command := PatchString("Line[,]"); + + + JavaCall(geogebra,"evalCommand",command); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Distance.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Distance.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Distance.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Distance.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="Distance" + +Distance(PointA_IsPoint,PointB_IsPoint) <-- +[ + Local(x1,x2,y1,y2,distance); + + x1 := PointA[1]; + x2 := PointB[1]; + y1 := PointA[2]; + y2 := PointB[2]; + + distance := Sqrt((x2 - x1)^2 + (y2 - y1)^2); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Distance",categories="User Functions;Analytic Geometry",access="experimental" +*CMD Distance --- returns the distance between two points +*STD +*CALL + Distance(p1, p2) +*PARMS + +{p1} -- the first point + +{p2} -- the second point + +*DESC + +This function calculates the distance between two points using the +distance formula. + +*E.G. + +In> PointA := Point(2,3) +Result: {2,3} + +In> PointB := Point(6,8) +Result: {6,8} + +In> Distance(PointA, PointB) +Result: Sqrt(41) + +*SEE IsPoint, Point, Midpoint, Slope, Segment +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/IsPoint.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/IsPoint.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/IsPoint.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/IsPoint.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="IsPoint" + +IsPoint(p) := If(IsList(p) And (Length(p) = 2 Or Length(p) = 3),True,False); + +%/mathpiper + + + +%mathpiper_docs,name="IsPoint",categories="User Functions;Analytic Geometry",access="experimental" +*CMD IsPoint --- test for a point +*STD +*CALL + IsPoint(p) +*PARMS + +{p} -- point to test + + +*DESC + +Tests if a value is a point. + +*E.G. + +In> p := Point(2,3) +Result: {2,3} + +In> IsPoint(p) +Result: True + +In> IsPoint(4) +Result: False + +*SEE Point, Midpoint, Distance, Slope, Segment +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/IsSegment.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/IsSegment.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/IsSegment.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/IsSegment.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="IsSegment" + +IsSegment(list_IsList) <-- +[ + If(IsList(list[1]) And Length(list[1])=2 And IsList(list[2]) And Length(list[2])=2,True,False); + +]; + +%/mathpiper + + + +%mathpiper_docs,name="IsSegment",categories="User Functions;Analytic Geometry",access="experimental" +*CMD IsSegment --- test for a segment +*STD +*CALL + IsSegment(s) +*PARMS + +{s} -- segment to test + + +*DESC + +Tests if a value is a segment. + +*E.G. + +In> IsSegment(Segment(Point(0,0), Point(3,4))) +Result: True + +In> IsSegment({3,4}) +Result: False + +*SEE Point, Midpoint, Distance, Slope, Segment +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Midpoint.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Midpoint.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Midpoint.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Midpoint.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,75 @@ +%mathpiper,def="Midpoint" + +Midpoint(PointA_IsPoint,PointB_IsPoint) <-- +[ + Local(x1,x2,y1,y2,midpointX,midpointY); + + x1 := PointA[1]; + x2 := PointB[1]; + y1 := PointA[2]; + y2 := PointB[2]; + + midpointX := (x1 + x2)/2; + midpointY := (y1 + y2)/2; + + {midpointX,midpointY}; + +]; + + + +Midpoint(segment_IsSegment) <-- +[ + Local(x1,x2,y1,y2,midpointX,midpointY); + + x1 := segment[1][1]; + x2 := segment[2][1]; + y1 := segment[1][2]; + y2 := segment[2][2]; + + midpointX := (x1 + x2)/2; + midpointY := (y1 + y2)/2; + + {midpointX,midpointY}; + +]; + +%/mathpiper + + + +%mathpiper_docs,name="Midpoint",categories="User Functions;Analytic Geometry",access="experimental" +*CMD Midpoint --- returns a Point which represents the midpoint between two points +*STD +*CALL + Midpoint(p1, p2) + Midpoint(s) +*PARMS + +{p1} -- the first point + +{p2} -- the second point + +{s} -- a segment + +*DESC + +This function calculates the midpoint between two points using the +midpoint formula. + +*E.G. + +In> PointA := Point(2,3) +Result: {2,3} + +In> PointB := Point(6,8) +Result: {6,8} + +In> Midpoint(PointA, PointB) +Result: {4,11/2} + +In> Midpoint(Segment(Point(0,0), Point(3,4))) +Result: {3/2,2} + +*SEE IsPoint, Point, Distance, Slope, Segment +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Point.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Point.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Point.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Point.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="Point" + +Point(x,y) := List(x,y); + +Point(x,y,z) := List(x,y,z); + +%/mathpiper + + + +%mathpiper_docs,name="Point",categories="User Functions;Analytic Geometry",access="experimental" +*CMD Point --- return a list which contains a point +*STD +*CALL + Point(x, y) + Point(x, y, z) +*PARMS + +{x} -- x coordinate of the point + +{y} -- y coordinatte of the point + +{z} -- z coordinate of the point + +*DESC + +Creates either a 2D point or a 3D point. + +*E.G. + +In> Point(5,2) +Result: {5,2} + +*SEE IsPoint, Midpoint, Distance, Slope, Segment +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Segment.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Segment.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Segment.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Segment.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="Segment" + +Segment(PointA_IsPoint,PointB_IsPoint) <-- +[ + Local(x1,x2,y1,y2); + + x1 := PointA[1]; + x2 := PointB[1]; + y1 := PointA[2]; + y2 := PointB[2]; + + {{x1,y1},{x2,y2}}; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Segment",categories="User Functions;Analytic Geometry",access="experimental" +*CMD Segment --- returns a list which contains the endpoints of a segment +*STD +*CALL + Segment(p1, p2) +*PARMS + +{p1} -- the first endpoint + +{p2} -- the second endpoint + +*DESC + +This function returns a list which represents a segment by its endpoints. + +*E.G. + +In> PointA := Point(2,3) +Result: {2,3} + +In> PointB := Point(6,8) +Result: {6,8} + +In> Segment(PointA,PointB) +Result: {{2,3},{6,8}} + +*SEE IsPoint, Point, Distance, Slope +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Slope.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Slope.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/geometry/Slope.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/geometry/Slope.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,70 @@ +%mathpiper,def="Slope" + +10 # Slope(PointA_IsPoint,PointB_IsPoint) <-- +[ + Local(x1,x2,y1,y2,slope); + + x1 := PointA[1]; + x2 := PointB[1]; + y1 := PointA[2]; + y2 := PointB[2]; + + slope := (y2 - y1)/(x2 - x1); +]; + + + +10 # Slope(segment_IsList)_(Length(segment) = 2 And Length(segment[1]) = 2 And Length(segment[2]) = 2) <-- +[ + Local(x1,x2,y1,y2,slope); + + x1 := segment[1][1]; //PointA[1]; + x2 := segment[2][1]; //PointB[1]; + + + y1 := segment[1][2]; //PointA[2]; + y2 := segment[2][2]; //PointB[2]; + + slope := (y2 - y1)/(x2 - x1); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Slope",categories="User Functions;Analytic Geometry",access="experimental",access="experimental" +*CMD Slope --- returns the slope of a line which is represented by two points +*STD +*CALL + Slope(p1, p2) + Slope(Segment(p1, p2)) +*PARMS + +{p1} -- the first point + +{p2} -- the second point + +*DESC + +This function calculates the slope between two points or of a +segment using the slope formula. + +*E.G. + +In> PointA := Point(2,3) +Result: {2,3} + +In> PointB := Point(6,8) +Result: {6,8} + +In> Slope(PointA,PointB) +Result: 5/4 + +In> s := Segment(PointA,PointB) +Result: {{2,3},{6,8}} + +In> Slope(s) +Result: 5/4 + +*SEE IsPoint, Point, Distance, Midpoint, Segment +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/highschool/HighschoolForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/highschool/HighschoolForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/highschool/HighschoolForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/highschool/HighschoolForm.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,21 @@ +%mathpiper,def="" + +//Retract("HighschoolForm",*); + +HighschoolForm(expression) := +[ + //Note: since := is at a higher precedence than :/, parentheses are needed. + expression := (expression /: { (x_IsNegativeNumber) / _y <- [Echo(x,/,y);]}); + + expression := (expression /: {_z^((x_IsNegativeInteger)/y_IsNumber) <- {z,x,y}}); + +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/jas/jas_test.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/jas/jas_test.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/jas/jas_test.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/jas/jas_test.mpw 2010-05-19 06:22:50.000000000 +0000 @@ -0,0 +1,130 @@ +%mathpiper,title="" +ring := Ring("Z(a,b,x,y) L"); + +gens := JavaCall(ring,"gens"); + +%/mathpiper + + %output,preserve="false" + Result: {edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial} +. %/output + + + +%mathpiper,title="" + +ForEach(variable,gens) +[ + + variableName := JavaToValue(JavaCall(variable,"toString")); + + Echo(variableName); + + If(Not IsNumber(variableName), MacroBind(variableName,MetaSet(variableName,"jas",variable)) ); + +]; + +f := 5*a*x + 5*b*x - 2*b*y - 2*a*y; + +g := a-2; + +%/mathpiper + + %output,preserve="false" + Result: a-2 + + Side Effects: + 1 + a + b + x + y + +. %/output + + + + + + +%mathpiper,title="" + +IsJas(atom) := +[ + If(MetaGet(atom,"jas") != Empty, True, False); + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper,title="" + +200 # a_IsInteger * b_IsJas <-- Echo("H"); + +201 # _a * b_IsJas <-- Echo("I"); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper,title="" + +x := (xx/yy)/zz; + +x:=( + x/::Hold({ + (_a/_b)/_c <- (a)/(b*c), + (-(_a/_b))/_c <- (-a)/(b*c), + (_a/_b)*_c <- (a*c)/b, + (_a*_b)^_m <- a^m*b^m, + (_a/_b)^_m*_c <- (a^m*c)/b^m, + _a*(_b+_c) <- a*b+a*c, + (_b+_c)*_a <- a*b+a*c, + (_b+_c)/_a <- b/a+c/a, + _a*(_b-_c) <- a*b-a*c, + (_b-_c)*_a <- a*b-a*c, + (_b-_c)/_a <- b/a-c/a + })); + +%/mathpiper + + %output,preserve="false" + Result: xx/(yy*zz) +. %/output + + + + + + +%mathpiper,title="" + +5*a*x; + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + H + I + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/jfreechart/JFreeChartHistogram.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/jfreechart/JFreeChartHistogram.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/jfreechart/JFreeChartHistogram.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/jfreechart/JFreeChartHistogram.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,71 @@ + %mathpiper + + //Retract("JFreeChartHistogram",*); + + JFreeChartHistogram(data) := + [ + histogramDataset := JavaNew("org.jfree.data.statistics.HistogramDataset"); + doubleArray := JavaCall("java.lang.reflect.Array","newInstance","java.lang.Double",ToString(Length(data)) ); + x := 0; + While(x < Length(data)) + [ + JavaCall("java.lang.reflect.Array","setDouble",doubleArray, x, data[x+1] ); + ]; + + ]; + + + %/mathpiper + + %output,preserve="false" + Result: True JavaCall( JavaNew("java.lang.String","Hello"),"toUpperCase") JavaCall("javax.swing.JOptionPane","showMessageDialog","null","hello") +. %/output + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +JFreeChartHistogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}); + +%/mathpiper + + %output,preserve="false" + Result: [Ljava.lang.Double; +. %/output + +Histogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0},line -> True, title -> "Test histogram"); + +JavaCall("java.lang.reflect.Array","setDouble",doubleArray, 0, 33.2); + +JavaCall("java.lang.reflect.Array","newInstance","java.lang.Double","3"); + + private static IntervalXYDataset createDataset() { + HistogramDataset dataset = new HistogramDataset(); + String samplesString = "16.375,16.375,17.125,16,14.375,17.25,16.625,16,17,17.25,17,15.875,16.625,16.125,17.125,16.875,16.375,16.375,16.875,17.125,17,16.75,17.25,17.125,15.375"; + String[] samples = samplesString.split(","); + double[] values = new double[samples.length]; + int i = 0; + for (String sample:samples) { + values[i] = Float.parseFloat(sample); + i++; + } + dataset.addSeries("Pile E", values, 20, 14.0, 20.0); + + + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.StandardXYBarPainter; +import org.jfree.chart.renderer.xy.XYBarRenderer; +import org.jfree.data.statistics.HistogramDataset; +import org.jfree.data.xy.IntervalXYDataset; + + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/CombinationsList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/CombinationsList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/CombinationsList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/CombinationsList.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,106 @@ +%mathpiper,def="CombinationsList" + +/* + The algorithm this function uses is on pp. 299-300 of + "Discrete Mathematics and Its Applications" (fourth edition) + by Kenneth H. Rosen. +*/ +CombinationsList(inputList, r) := +[ + Local(n,manipulatedIndexes,totalCombinations,combinationsList,combinationsLeft,combination,i,j,currentIndexes); + + Check(IsList(inputList) And Length(inputList) >= 1, "Argument", "The first argument must be a list with 1 or more elements."); + + n := Length(inputList); + + Check(r <= n , "Argument", "The second argument must be <= the length of the list."); + + manipulatedIndexes := 1 .. r; + + totalCombinations := Combinations(n,r); + + combinationsLeft := totalCombinations; + + combinationsList := {}; + + While(combinationsLeft > 0) + [ + combination := {}; + + if(combinationsLeft = totalCombinations) + [ + combinationsLeft := combinationsLeft - 1; + + currentIndexes := manipulatedIndexes; + ] + else + [ + i := r; + + While(manipulatedIndexes[i] = n - r + i) + [ + i--; + ]; + + manipulatedIndexes[i] := manipulatedIndexes[i] + 1; + + For(j := i + 1, j <= r, j++) + [ + manipulatedIndexes[j] := manipulatedIndexes[i] + j - i; + ]; + + combinationsLeft := combinationsLeft - 1; + + currentIndexes := manipulatedIndexes; + ]; + + For(i := 1, i <= Length(currentIndexes), i++) + [ + combination := Append(combination,(inputList[currentIndexes[i]])); + ]; + + combinationsList := Append(combinationsList,combination); + ]; + + combinationsList; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="CombinationsList",categories="User Functions;Combinatorics",access="experimental" +*CMD CombinationsList --- return all of the combinations from a given list taken r at a time +*CALL + CombinationsList(list,r) + +*PARMS +{list} -- a list of elements + +{r} -- the combinations from {list} are to be taken {r} at a time + +*DESC +This function returns a list which contains all of the combinations of the elements in a +given list taken r elements at a time. + +*E.G. +In> CombinationsList({1,2,3},2) +Result: {{1,2},{1,3},{2,3}} + +*SEE Combinations, PermutationsList, Permutations, LeviCivita +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/ElementCount.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/ElementCount.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/ElementCount.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/ElementCount.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,50 @@ + +%mathpiper,def="ElementCount" + +//Retract("ElementCount",*); + +ElementCount(list) := +[ + if(Length(list) = 0) + [ + 0; + ] + else if(IsAtom(list)) + [ + 1; + ] + else + [ + ElementCount(First(list)) + ElementCount(Rest(list)); + ]; + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ElementCount",categories="User Functions;Lists (Operations)",access="experimental" +*CMD ElementCount --- counts the number of elements in a list or nested list +*CALL + ElementCount(list) + +*PARMS +{list} -- a list or nested list + +*DESC +Counts the number of elements in a list or nested list. + +*E.G. +In> ElementCount({1,2,3,4}) +Result: 4 + +In> ElementCount({1,2,{3,4},5,6}) +Result: 6 +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/IsListOfLists.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/IsListOfLists.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/IsListOfLists.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/IsListOfLists.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,58 @@ +%mathpiper,def="IsListOfLists" + +IsListOfLists(listOfLists) := +[ + Local(result); + + result := True; + + if(Not IsList(listOfLists)) + [ + result := False; + ] + else + [ + ForEach(list, listOfLists) + [ + If(Not IsList(list), result := False); + ]; + ]; + + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="IsListOfLists",categories="User Functions;Predicates",access="experimental" +*CMD IsListOfLists --- determine if {list} is a list of lists +*STD +*CALL + IsList(list) + +*PARMS +{expr} -- a list + +*DESC +This function returns {True} if {list} is a list of lists and {False} otherwise. + +*E.G. +In> IsListOfLists(aa); +Result: False + +In> IsListOfLists({1,2,3}) +Result: False + +In> IsListOfLists({{1,2},{3,4},{5,6}}) +Result: True + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/JavaAccess.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/JavaAccess.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/JavaAccess.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/JavaAccess.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,title="" + +//Retract("JavaAccess",*); + +RulebaseListed("JavaAccess",{object, method, parameters}); + +//Handle no option call. +5 # JavaAccess(_object, _method) <-- JavaAccess(object, method, {}); + + +//Main routine. It will automatically accept 2 or more option calls because the +//options come in a list. +10 # JavaAccess(_object, _method, parameters_IsList) <-- +[ + JavaCall(object, method, parameters); + + +]; + + +//Handle a single option call because the option does not come in a list for some reason. +20 # JavaAccess(_object, _method, _singleParameter) <-- JavaAccess(object, method, {singleParameter}); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/ListToString.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/ListToString.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/ListToString.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/ListToString.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="ListToString" + + +//Retract("ListToString", *); + + +10 # ListToString(list_IsList)_(Length(list) = 0) <-- ""; + + + +20 # ListToString(list_IsList) <-- +[ + Local(resultString, character); + + resultString := ""; + + ForEach(element, list) + [ + If(IsString(element), character := element, character := ToString(element)); + + resultString := resultString : character; + ]; + + resultString; + +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="ListToString",categories="User Functions;Lists (Operations)",access="experimental" +*CMD ListToString --- converts a list into a string +*STD +*CALL + ListToString(list) + +*PARMS + +{list} -- a list to be converted into a string + +*DESC +This function converts each of the elementes in a list into a string and then concatenates these +strings into a single string. + +*E.G. +In> ListToString({a,b,c,d}) +Result: "abcd" + +*SEE StringToList +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/NumberLinePrintZoom.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/NumberLinePrintZoom.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/NumberLinePrintZoom.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/NumberLinePrintZoom.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,202 @@ +%mathpiper,def="NumberLinePrintZoom" + +//Retract("NumberLineZoom", *); + +//Retract("ZoomInOnce", *); + +LocalSymbols(ZoomInOnce) +[ + + 10 # NumberLinePrintZoom(_lowValue, _highValue, divisions_IsPositiveInteger, depth_IsPositiveInteger)_(lowValue < highValue) <-- + [ + + Local(numbers, stepAmount, zoomIndexes, nextZoomIndex, outputWidth, numbersString, output, randomStep, randomZoomNumber, iteration); + + iteration := 1; + + While(iteration <= depth) + [ + {numbers, stepAmount} := ZoomInOnce(lowValue, highValue, divisions); + + zoomIndexes := {}; + + outputWidth := 0; + + numbersString := ""; + + ForEach(number, numbers) + [ + output := PipeToString() Write(number); + + zoomIndexes := Append(zoomIndexes, Length(output)); + + numbersString := numbersString : output : PipeToString() Space(3); + + outputWidth := outputWidth + Length(output) + 3; + + ]; + + randomStep := RandomInteger(divisions); + + randomZoomNumber := Sum(Take(zoomIndexes, randomStep)); + + If(randomStep = 1, nextZoomIndex := randomZoomNumber + 1, nextZoomIndex := 3*(randomStep-1) + randomZoomNumber + 1); + + If(iteration > 1, Echo(ListToString(FillList("-", outputWidth-3)))); + + Echo(numbersString); + + If(iteration != depth,[Space(nextZoomIndex);Echo("|");]); + + lowValue := numbers[randomStep]; + + highValue := numbers[randomStep+1]; + + iteration++; + + ]; + + ]; + + + + + ZoomInOnce(_lowValue, _highValue, divisions_IsPositiveInteger)_(lowValue < highValue) <-- + [ + Local(stepAmount, x, numbers); + + stepAmount := If(IsDecimal(lowValue) Or IsDecimal(highValue), N((highValue-lowValue)/divisions), (highValue-lowValue)/divisions); + + x := lowValue; + + numbers := {}; + + While(x <= highValue) + [ + + numbers := Append(numbers, x); + + x := x + stepAmount; + + ]; + + {numbers, stepAmount}; + + ]; + + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +N(NumberLineZoom(0,1,8,5), 50); + +%/mathpiper + + + + + +%mathpiper_docs,name="NumberLinePrintZoom",categories="User Functions;Visualization",access="experimental" +*CMD NumberLinePrintZoom --- zooms into the number line +*STD +*CALL + NumberLinePrintZoom(low_number, high_number, divisions, depth) + +*PARMS + +{low_value} -- lowest number in the zoom range + +{high_value} -- highest number in the zoom range + +{divisions} -- how many parts to divide the range into + +{depth} -- continue the zooming process to depth levels + +*DESC + +This function allows sections of the number line to be displayed. If rational numbers are +passed to low_number and high_number, rational numbers are displayed and if decimal +numbers are passed to low_number and high_number, decimal numbers are displayed. + +*E.G. notest + +In> NumberLinePrintZoom(0/1,1/1,8,1) +Result: True +Side Effects: +0 1/8 1/4 3/8 1/2 5/8 3/4 7/8 1 + +In> NumberLinePrintZoom(0/1,1/1,10,1) +Result: True +Side Effects: +0 1/10 1/5 3/10 2/5 1/2 3/5 7/10 4/5 9/10 1 + +In> NumberLinePrintZoom(0/1,1/1,20,1) +Result: True +Side Effects: +0 1/20 1/10 3/20 1/5 1/4 3/10 7/20 2/5 9/20 1/2 11/20 3/5 13/20 7/10 3/4 4/5 17/20 9/10 19/20 1 + +In> NumberLinePrintZoom(0/1,1/1,8,4) +Result: True +Side Effects: +0 1/8 1/4 3/8 1/2 5/8 3/4 7/8 1 + | +---------------------------------------------------------------- +1/2 33/64 17/32 35/64 9/16 37/64 19/32 39/64 5/8 + | +-------------------------------------------------------------------------------- +1/2 257/512 129/256 259/512 65/128 261/512 131/256 263/512 33/64 + | +-------------------------------------------------------------------------------------------------- +263/512 2105/4096 1053/2048 2107/4096 527/1024 2109/4096 1055/2048 2111/4096 33/64 + + + +In> NumberLinePrintZoom(0.0,1.0,8,1) +Result: True +Side Effects: +0.0 0.125 0.250 0.375 0.500 0.625 0.750 0.875 1.000 + +In> NumberLinePrintZoom(0.0,1.0,10,1) +Result: True +Side Effects: +0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 + +In> NumberLinePrintZoom(0.0,1.0,20,1) +Result: True +Side Effects: +0.0 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 + +In> N(NumberLinePrintZoom(0.0,1.0,8,4),6) +Result: True +Side Effects: +0.0 0.125 0.250 0.375 0.500 0.625 0.750 0.875 1.000 + | +--------------------------------------------------------------------------------------------- +0.500 0.515625 0.531250 0.546875 0.562500 0.578125 0.593750 0.609375 0.625000 + | +------------------------------------------------------------------------------------------------ +0.546875 0.548828 0.550781 0.552734 0.554687 0.556640 0.558593 0.560546 0.562499 + | +------------------------------------------------------------------------------------------------ +0.558593 0.558837 0.559081 0.559325 0.559569 0.559813 0.560057 0.560301 0.560545 + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/OptionsToAssociativeList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/OptionsToAssociativeList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/OptionsToAssociativeList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/OptionsToAssociativeList.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="OptionsToAssociativeList" +OptionsToAssociativeList(optionList) := +[ + Local(associativeList, key, value); + + associativeList := {}; + + ForEach(option, optionList) + [ + If(option[0] = ->, + [ + If(IsString(option[1]), key := option[1], key := ToString(option[1])); + If(IsString(option[2]), value := option[2], value := ToString(option[2])); + + associativeList := {key, value} : associativeList; + + ]); + + ]; + associativeList; +]; + +%/mathpiper + + + +%mathpiper_docs,name="OptionsToAssociativeList",categories="User Functions;Lists (Operations)",access="experimental" +*CMD OptionsToAssociativeList --- converts an options list into an associative list +*CALL + OptionsToAssociativeList(optionsList) + +*PARMS +{optionsList} -- an options list to be converted into an associative list + +*DESC +This function converts a list of options in the form of {name -> value, name -> value} +into an associative list. + +*E.G. +In> OptionsToAssociativeList({a ->1, b -> 2}) +Result> {{"b","2"},{"a","1"}} + +%/mathpiper_docs + + + + +%mathpiper,title="",scope="nobuild",subtype="manual_test" + +OptionsToAssociativeList({ lines -> True, labels -> False }); + +%/mathpiper + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/PadLeft.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/PadLeft.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/PadLeft.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/PadLeft.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,65 @@ +%mathpiper,def="PadLeft" + +//Retract("PadLeft", *); + +10 # PadLeft(number_IsNumber, totalDigits_IsInteger) <-- +[ + Local(integerString, padAmount, resultString); + + integerString := ToString(number); + + padAmount := totalDigits - Length(integerString); + + If(padAmount > 0, + resultString := ListToString(FillList(0, padAmount)) : integerString, + resultString := integerString ); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="PadLeft",categories="User Functions;Input/Output",access="experimental" +*CMD PadLeft --- converts a number into a string which has a specified width +*STD +*CALL + PadLeft(number,string_width) + +*PARMS + +{number} -- an integer or a decimal number to convert to a string + +{string_width} -- the width of the string + +*DESC + +This function converts a number into a string which has a specified width. If the number +would normally be converted into a string with fewer characters than this width, zeros are +added to the left side of the string to make it the specified width. + +*E.G. +/%mathpiper,title="" + +Echo(PadLeft(.1,3)); +Echo(PadLeft(20,3)); +Echo(PadLeft(5,3)); + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + 0.1 + 020 + 005 +. /%/output +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/RForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/RForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/RForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/RForm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,404 @@ +%mathpiper,def="RForm" + +/* RForm: convert MathPiper objects to R code. */ + +//Retract("RForm",*); +//Retract("RIndent",*); +//Retract("RUndent",*); +//Retract("RNlIndented",*); + +Rulebase("RForm",{expression}); +Rulebase("RForm",{expression, precedence}); + +Function ("RFormBracketIf", {predicate, string}) +[ + Check(IsBoolean(predicate) And IsString(string), "Argument", "RForm internal error: non-boolean and/or non-string argument of RFormBracketIf"); + If(predicate, ConcatStrings("( ", string, ") "), string); +]; + +/* Proceed just like TeXForm() +*/ + +// RFormMaxPrec should perhaps only be used from within this file, it is thus not in the .def file. +RFormMaxPrec() := 60000; /* This precedence will never be bracketed. It is equal to KMaxPrec */ + +100 # RForm(_x) <-- RForm(x, RFormMaxPrec()); + +/* Replace numbers and variables -- never bracketed except explicitly */ +110 # RForm(x_IsInteger, _p) <-- ToString(x); +111 # RForm(x_IsZero, _p) <-- "0."; +112 # RForm(x_IsNumber, _p) <-- ToString(x); +/* Variables are left as is, except some special ones */ +190 # RForm(False, _p) <-- "false"; +190 # RForm(True, _p) <-- "true"; +190 # RForm(Pi, _p) <-- "pi"; +200 # RForm(x_IsAtom, _p) <-- ToString(x); + +/* Strings must be quoted but not bracketed */ +100 # RForm(x_IsString, _p) <-- ConcatStrings("\"", x, "\""); + +/* Replace operations */ + +/* arithmetic */ + +/* addition, subtraction, multiplication, all comparison and logical operations are "regular" */ + + +LocalSymbols(rFormRegularOps) [ + rFormRegularOps := + { + {"+","+"}, + {"-","-"}, + {"*","*"}, + {"/","/"}, + {"/","/"}, + {"^","^"}, + {"=","=="}, + {">=",">="}, + {">",">"}, + {"<=","<="}, + {"<","<"}, + {"!=","!="}, + {"..",":"}, + {"Not","!"}, + {":=","<-"}, + {"sequence",":"}, + {"True","TRUE"}, + {"Modulo","%%"}, + {"Quotient","%/%"}, + }; + + RFormRegularOps() := rFormRegularOps; +]; // LocalSymbols(rFormRegularOps) + + + + +LocalSymbols(rFormMathFunctions) [ + rFormMathFunctions := + { + {"NthRoot","root"}, + {"Infinite","Inf"}, + {"Undefined","NaN"}, + {"Sin","sin"}, + {"Cos","cos"}, + {"Tan","tan"}, + {"ArcSin","asin"}, + {"ArcCos","acos"}, + {"ArcTan","atan"}, + {"ArcSinh","asinh"}, + {"ArcCosh","acosh"}, + {"ArcTanh","atanh"}, + {"ArcCsc","acsc"}, + {"ArcCsch","acsch"}, + {"ArcSec","asec"}, + {"ArcSech","asech"}, + {"ArcCot","acot"}, + {"ArcCoth","acoth"}, + {"Exp","exp"}, + {"Ln","log"}, + {"Sqrt","sqrt"}, + {"Bin","choose"}, + {"Gamma","gamma"}, + {"!","factorial"}, + {"Limit","limit"}, + {"Deriv","deriv"}, + {"Integrate","integrate"}, + {"Taylor","?"}, + {"List","list"}, + }; + + RFormMathFunctions() := rFormMathFunctions; + +]; // LocalSymbols(RFormMathFunctions) + + + + +/* This is the template for "regular" binary infix operators: +100 # RForm(_x + _y, _p) <-- RFormBracketIf(p RForm(Sin(a1)+2*Cos(b1)); +Result: "sin(a1) + 2 * cos(b1)"; + +*SEE PrettyForm, TeXForm, CForm +%/mathpiper_docs + + + + + + + + +http://code.google.com/p/ryacas/source/browse/trunk/R/OpenMath2R.R +OpenMath2R <- function(x) { + out <- c() + recurse <- function( x ) { + if ("name" %in% names(xmlAttrs(x))) { + out <<- c(out, trans(xmlAttrs(x)[["name"]], from="OM", to="R"), " ") + } + if (xmlName(x) == "text") out <<- c(out, xmlValue(x), " ") + if (xmlName(x) == "OMF") out <<- c(out, xmlAttrs(x)[["dec"]], " ") + if (xmlName(x) == "OMS") { + if (xmlAttrs(x)[["cd"]] == "logic1" && "name" %in% names(xmlAttrs(x)) + && xmlAttrs(x)[["name"]] %in% c("true", "false")) {} + else if ((xmlAttrs(x)[["cd"]] != "nums1") || + (xmlAttrs(x)[["name"]] == "rational")) + out <<- c(out, xmlValue(x), "(") + } + # if (xmlName(x) == "OMS") out <<- c(out, "(") + if (xmlName(x) == "OMSTR") { + # out <<- c(out, sQuote(gsub("'", "\\\\'", xmlValue(x)))) + out <<- c(out, paste("'", gsub("'", "\\\\'", xmlValue(x)), "'", sep="")) + } else if ( length( xmlChildren(x) ) > 0 ) + for( i in seq( along = xmlChildren(x) ) ) { + Recall( x[[i]] ) + if (i > 1 && i < length(xmlChildren(x))) + out <<- c(out, ",") + } + if (xmlName(x) == "OMA" || xmlName(x) == "OMBIND") out <<- c(out, xmlValue(x), ")") + } + x <- paste(x, "\n", collapse = "") + x <- xmlTreeParse(x, asText = TRUE) + x <- xmlRoot(x) + recurse(x) + paste(out, collapse = "") +} + +trans <- function(x, ttab=transtab, from, to) { + idx <- match(x, ttab[,from], nomatch = 0) + res <- if (idx > 0) ttab[idx,to] else x + if (tolower(substr(res, 1, 1)) %in% letters) res + else paste('"', res, '"', sep="") +} + +transtab <- matrix( c( + #R OM yacas + "pi", "pi", "Pi", + + "+", "plus", "+", + "-", "minus", "-", + "*", "times", "*", + "/", "divide", "/", + "/", "rational", "/", + "^", "power", "^", + "%%", "mod", "Modulo", + "%/%", "div", "Quotient", + "root", "root", "NthRoot", + "Inf", "infinity", "Infinite", + "NaN", "undefined","Undefined", + + "sin", "Sin", "Sin", + "cos", "Cos", "Cos", + "tan", "Tan", "Tan", + + "asin", "arcsin", "ArcSin", + "acos", "arccos", "ArcCos", + "atan", "arctan", "ArcTan", + "asinh", "arcsinh", "ArcSinh", + "acosh", "arccosh", "ArcCosh", + "atanh", "arctanh", "ArcTanh", + + "acsc", "arccsc", "ArcCsc", + "acsch", "arccsch", "ArcCsch", + + "asec", "arcsec", "ArcSec", + "asech", "arcsech", "ArcSech", + + "acot", "arccot", "ArcCot", + "acoth", "arccoth", "ArcCoth", + + "exp", "exp", "Exp", + "log", "ln", "Ln", + "sqrt", "sqrt", "Sqrt", + "choose", "bin", "Bin", + "gamma", "gamma", "Gamma", + + "!", "not", "Not", + "==", "eq", "=", + "==", "equivalent","=", + ">=", "geq", ">=", + ">", "gt", ">", + "<=", "leq", "<=", + "<", "lt", "<", + "!=", "neq", "!=", + ":", "seq", "sequence", + ":", "seq", "..", + + "factorial","factorial","factorial", + "factorial","factorial","!", + "limit", "lim", "Limit", + "deriv", "deriv", "Deriv", + "integrate","integrate","Integrate", + "?", "taylor", "Taylor", + + "list", "List", "List", + "TRUE", "true", "True", + "<-", "?", ":=", + "Expr", "?", "", + "Exprq", "?", "", + "expression", "?", "" + +), byrow = TRUE, ncol = 3) +colnames(transtab) <- c("R", "OM", "yacas") + +# Used for expressions not handled by R + +root <- function(x, y) { + (x)^(1/(y)) +} + + + + + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToList.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,50 @@ +%mathpiper,def="StringToList" + +//Retract("StringToList", *); + +10 # StringToList(string_IsString)_(Length(string) = 0) <-- {}; + + +20 # StringToList(string_IsString) <-- +[ + Local(resultList); + + resultList := {}; + + ForEach(character, string) + [ + resultList := Append(resultList, character); + ]; + + resultList; + +]; + + + +%/mathpiper + + + + + +%mathpiper_docs,name="StringToList",categories="User Functions;String Manipulation",access="experimental" +*CMD StringToList --- converts a string into a list +*STD +*CALL + StringToList(string) + +*PARMS + +{string} -- a string to be converted into a list + +*DESC + +This function takes each character in a string and places it into a list. + +*E.G. +In> StringToList("Hello") +Result: {"H","e","l","l","o"} + +*SEE ListToString +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToNumber.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToNumber.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToNumber.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/StringToNumber.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="StringToNumber" +//Retract("StringToNumber",*); + +StringToNumber( str_IsString ) <-- FromBase(10,str); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="StringToNumber",categories="User Functions;String Manipulation",access="experimental" +*CMD StringToNumber --- Convert a base-10 number in string form to its numeric value +*STD +*CALL + StringToNumber(numberString) + +*PARMS + +{numberString} -- a decimal (base-10) number represented as a string + +*DESC + +{StringToNumber} Converts the string representation of a number into the value of that number + + + +*E.G. + +In> IsNumber("1234") +Result: False + +In> StringToNumber("1234") +Result: 1234 + +In> IsNumber(%) +Result: True + +In> StringToNumber("0.12345678") +Result: 0.12345678 + +In> StringToNumber("0.12345678E4") +Result: 1234.5678 + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/VerifyNumeric.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/VerifyNumeric.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/miscellaneous/VerifyNumeric.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/miscellaneous/VerifyNumeric.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,133 @@ +%mathpiper,def="VerifyNumeric" + +VerifyNumeric(expression1, expression2, optionsList) := +[ + Local(variablesList1, variablesList2, numericValue1, numericValue2, numericDifference, optionsVariableNamesList, optionsValuesList, associativeList); + + variablesList1 := VarList(expression1); + + variablesList2 := VarList(expression2); + + if(Length(variablesList1) = 0 And Length(variablesList2) = 0) + [ + numericValue1 := N(expression1); + + numericValue2 := N(expression2); + ] + else + [ + optionsList := HeapSort(optionsList, Lambda({x,y},IsLessThan(x[1],y[1]))); + + associativeList := OptionsToAssociativeList(optionsList); + + optionsVariableNamesList := MapSingle("ToAtom", AssocIndices(associativeList)); + + optionsValuesList := MapSingle("ToAtom", AssocValues(associativeList)); + + variablesList1 := HeapSort(variablesList1,"IsLessThan"); + + variablesList2 := HeapSort(variablesList2,"IsLessThan"); + + Check(variablesList1 = variablesList2 And variablesList1 = optionsVariableNamesList, "Argument", "Both expressions and the options list must have the same variable names and the same number of variables."); + + numericValue1 := N(WithValue(variablesList1, optionsValuesList, expression1)); + + numericValue2 := N(WithValue(variablesList2, optionsValuesList, expression2 )); + + Echo(Map("->",{variablesList1, optionsValuesList})); + + NewLine(); + ]; + + Echo(expression1, "-> ", numericValue1); + + NewLine(); + + Echo(expression2, "-> ", numericValue2); + + numericDifference := N(numericValue1 - numericValue2); + + NewLine(); + + Echo("Difference between the numeric values: ", numericDifference); + + numericDifference; +]; + + + + +VerifyNumeric(expression1, expression2) := +[ + VerifyNumeric(expression1, expression2, {}); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="VerifyNumeric",categories="Programmer Functions;Testing",access="experimental" +*CMD VerifyNumeric --- numerically evaluates two expressions to indicate if they may be equivalent or not +*STD +*CALL + Verify(symbolicExpression1,symbolicExpression2,variableAssignmentList) + + Verify(numericExpression1,numericExpression2) + +*PARMS +{symbolicExpression1} -- a symbolic expression + +{symbolicExpression2} -- a symbolic expression + +{variableAssignmentList} -- a list which contains variable assignments in the form {b->7,a->4} + +{numericExpression1} -- a numeric expression + +{numericExpression2} -- a numeric expression + +*DESC +The symbolic expression version of this function numerically evaluates two symbolic expressions to indicate if +they may be equivalent or not. The values to set the variables to are contained in {variableAssignmentList}. + +The numeric expression version of this function evaluates two numeric expressions to indicate if they are +equivalent or not. + +*E.G. +In> VerifyNumeric((72*a^3*b^5)^(1/2), 6*a*b^2*(2*a*b)^(1/2), {b->7,a->4}) +Result: 0.000000 +Side Effects: +a->4 b->7 + +Sqrt(72*a^3*b^5) -> 8800.378174 + +6*a*b^2*Sqrt(2*a*b) -> 8800.378174 + +Difference between the numeric values: 0.000000 + + + +In> VerifyNumeric(.5,1/2) +Result: 0.0 +Side Effects: +.5 -> 0.5 + +1/2 -> 0.5 + +Difference between the numeric values: 0.0 + + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/AlphaToChiSquareScore.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/AlphaToChiSquareScore.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/AlphaToChiSquareScore.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/AlphaToChiSquareScore.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,118 @@ +%mathpiper,def="AlphaToChiSquareScore",access="experimental" + +/* + This function was adapted from the Javascript version of function + that is located here: + + http://www.fourmilab.ch/rpkp/experiments/analysis/chiCalc.js + http://www.fourmilab.ch/rpkp/experiments/analysis/chiCalc.html + + The following JavaScript functions for calculating normal and + chi-square probabilities and critical values were adapted by + John Walker from C implementations + written by Gary Perlman of Wang Institute, Tyngsboro, MA + 01879. Both the original C code and this JavaScript edition + are in the public domain. +*/ + + + +/* CRITCHI -- Compute critical chi-square value to + produce given p. We just do a bisection + search for a value within CHI_EPSILON, + relying on the monotonicity of pochisq(). +*/ + + +AlphaToChiSquareScore(p, df) := +[ + Local(ChiEpsilon, ChiMax, minchisq, maxchisq, chisqval, result); + + ChiEpsilon := 0.000001; /* Accuracy of critchi approximation */ + + ChiMax := 99999.0; /* Maximum chi-square value */ + + minchisq := 0.0; + + maxchisq := ChiMax; + + p := N(p); + + if( p <= 0.0 Or p >= 1.0) + [ + + if (p <= 0.0) + [ + result := maxchisq; + ] + else + [ + if (p >= 1.0) + [ + result := 0.0; + ]; + ]; + + ] + else + [ + chisqval := N(df / SqrtN(p)); + + /* fair first value */ + While ((maxchisq - minchisq) > ChiEpsilon) + [ + if (ChiSquareScoreToAlpha(chisqval, df) < p) + [ + maxchisq := chisqval; + ] + else + [ + minchisq := chisqval; + ]; + chisqval := (maxchisq + minchisq) * 0.5; + ]; + + result := chisqval; + + ]; + + N(result); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="AlphaToChiSquareScore",categories="User Functions;Statistics & Probability",access="experimental" +*CMD AlphaToChiSquareScore --- calculates the chi square score of a given alpha probability +*STD +*CALL + AlphaToChiSquareScore(alphaProbability, degreesOfFreedom) + +*PARMS +{alphaProbability} -- an alpha probability +{degreesOfFreedom} -- the degrees of freedom + +*DESC +This function calculates the chi square score of a given probability. + +*E.G. +In> AlphaToChiSquareScore(.1,4) +Result: 7.779440287 + +*SEE ChiSquareScoreToProbability, ChiSquareTest +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/AnovaCompletelyRandomizedBlock.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/AnovaCompletelyRandomizedBlock.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/AnovaCompletelyRandomizedBlock.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/AnovaCompletelyRandomizedBlock.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,368 @@ +%mathpiper,def="AnovaCompletelyRandomizedBlock" + + +AnovaCompletelyRandomizedBlock(levelsList, alpha) := +[ + Check(IsMatrix(levelsList), "Argument", "The first argument must be a list of equal-length lists."); + + Check(alpha >= 0 And alpha <= 1, "Argument", "The second argument must be a number between 0 and 1."); + + Local( + topOfSummary, + anovaBlockTableRow1, + criticalFScore, + anovaBlockTableRow3, + anovaBlockTableRow2, + lengthsList, + summaryTableRow, + sumsList, + meanSquareWithin, + topOfPage, + htmlJavaString, + index, + variancesList, + grandMean, + row, + topOfAnovaBlock, + result, + fScoreBlock, + criticalFScoreBlock, + blockMeansList, + sumOfSquaresWithin', + meanSquareBetween, + sumOfSquaresBetween, + fScore, + summaryTableRows, + meansList, + sumOfSquaresBlock, + b, + blockSummaryTableRow, + bottomOfAnovaBlock, + sumOfSquaresWithin, + bottomOfPage, + k, + sumOfSquaresTotal, + meanSquareBlock, + bottomOfSummary + ); + + meansList := {}; + + variancesList := {}; + + sumsList := {}; + + lengthsList := {}; + + + //ANOVA calculations. + ForEach(levelList, levelsList) + [ + meansList := meansList : N(Mean(levelList)); + + variancesList := variancesList : N(UnbiasedVariance(levelList)); + + sumsList := sumsList : N(Sum(levelList)); + + lengthsList := lengthsList : Length(levelList); + ]; + + sumOfSquaresWithin := Sum((lengthsList - 1) * variancesList); + + grandMean := N(Mean(meansList)); + + sumOfSquaresBetween := Sum(lengthsList*(meansList - grandMean)^2); + + + + //Block calculations. + blockMeansList := {}; + + index := 1; + + While(index <= Length(First(levelsList)) ) + [ + row := MatrixColumn(levelsList, index); + + blockMeansList := Append(blockMeansList,N(Mean(row))); + + index++; + ]; + + b := Length(blockMeansList); + + k := Length(levelsList); + + sumOfSquaresBlock := Sum(j,1,b, k*(blockMeansList[j] - grandMean)^2); + + sumOfSquaresTotal := N(sumOfSquaresWithin + sumOfSquaresBetween); + + sumOfSquaresWithin' := N(sumOfSquaresTotal - sumOfSquaresBetween - sumOfSquaresBlock); + + meanSquareBetween := N(sumOfSquaresBetween/(k - 1)); + + meanSquareWithin := N(sumOfSquaresWithin'/((k - 1)*(b - 1))); + + fScore := N(meanSquareBetween/meanSquareWithin); + + meanSquareBlock := N(sumOfSquaresBlock/(b - 1)); + + fScoreBlock := N(meanSquareBlock/meanSquareWithin); + + criticalFScore := ProbabilityToFScore(k - 1, (k - 1)*(b - 1), 1-alpha); + + criticalFScoreBlock := ProbabilityToFScore(b - 1, (k - 1)*(b - 1), 1-alpha); + + + + topOfPage := +" + + + Anova: Completely Randomized Block + + + +"; + + topOfSummary := +" +

    Anova: Completely Randomized Block

    + + + + + +"; + + + summaryTableRows := ""; + + summaryTableRow := "":Nl(); + + + //Data summary. + index := 1; + + While(index <= Length(levelsList)) + [ + summaryTableRows := summaryTableRows : PatchString(summaryTableRow); + + index++; + ]; + + + //Block summary. + + blockSummaryTableRow := "":Nl(); + + index := 1; + + While(index <= Length(First(levelsList)) ) + [ + row := MatrixColumn(levelsList, index); + + summaryTableRows := summaryTableRows : PatchString(blockSummaryTableRow); + + index++; + ]; + + + + + + bottomOfSummary := +" +

    Summary

    Level Count Sum Mean Variance
    +"; + + + + topOfAnovaBlock := +" +
    +
    + + + + + +"; + + + + anovaBlockTableRow1 := PatchString("":Nl()); + + anovaBlockTableRow2 := PatchString("":Nl()); + + anovaBlockTableRow3 := PatchString("":Nl()); + + bottomOfAnovaBlock := +" +

    ANOVA: Completely Randomized Block

    Source of Variation Sum of Squares Degrees of Freedom Mean Square F F Critical
    +"; + + + + bottomOfPage := +" + + +"; + + htmlJavaString := JavaNew("java.lang.String", + topOfPage : + topOfSummary : + summaryTableRows : + bottomOfSummary : + topOfAnovaBlock : + anovaBlockTableRow1 : + anovaBlockTableRow2 : + anovaBlockTableRow3 : + bottomOfAnovaBlock : + bottomOfPage); + + + + result := {}; + + result["html"] := htmlJavaString; + + result["sumOfSquaresWithin'"] := sumOfSquaresWithin'; + + result["sumOfSquaresBetween"] := sumOfSquaresBetween; + + result["sumOfSquaresBlock"] := sumOfSquaresBlock; + + result["sumOfSquaresTotal"] := sumOfSquaresTotal; + + result["meanSquareBetween"] := meanSquareBetween; + + result["meanSquareWithin"] := meanSquareWithin; + + result["meanSquareBlock"] := meanSquareBlock; + + result["fScore"] := fScore; + + result["criticalFScore"] := criticalFScore; + + result["fScoreBlock"] := fScoreBlock; + + result["criticalFScoreBlock"] := criticalFScoreBlock; + + result; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + + + +%mathpiper_docs,name="AnovaCompletelyRandomizedBlock",categories="User Functions;Statistics & Probability",access="experimental" +*CMD AnovaCompleteRandomizedBlock --- performs an ANOVA completely randomized block analysis + +*CALL + AnovaCompletelyRandomizedBlock(2dMatrix,alpha) + +*PARMS +{2dMatrix} -- a two dimensional matrix which contain the data to be analyzed + +{alpha} -- the alpha value to use in the analysis. + +*DESC +This function performs an ANOVA completely randomized block analysis. The various values that are +calculated during the analysis are returned in an association list and these +values are listed in the keys of the returned list (see the examples section). + +If the {html} key is passed to the {ViewHtml} function, the results of the analysis +are displayed in a graphcs window as rendered HTML. + +*E.G. +/%mathpiper,scope="nobuild",subtype="manual_test" + +alpha := .05; + +factor1List := {10.2,8.5,8.4,10.5,9.0,8.1}; + +factor2List := {11.6,12.0,9.2,10.3,9.9,12.5}; + +factor3List := {8.1,9.0,10.7,9.1,10.5,9.5}; + +Echo(anovaBlock := AnovaCompletelyRandomizedBlock({factor1List,factor2List,factor3List}, alpha)); + +NewLine(); + +Echo("F-Score of the block: ", anovaBlock["fScoreBlock"]); + +ViewHtml(anovaBlock["html"]); + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + {"criticalFScoreBlock",3.325834530} {"fScoreBlock",0.08045614890} {"criticalFScore",4.102821015} {"fScore",3.078377024} + {"meanSquareBlock",0.1418888884} {"meanSquareWithin",1.763555556} {"meanSquareBetween",5.428888905} {"sumOfSquaresTotal",29.20277781} + {"sumOfSquaresBlock",0.7094444419} {"sumOfSquaresBetween",10.85777781} {"sumOfSquaresWithin'",17.63555556} {"html",java.lang.String} + + F-Score of the block: 0.08045614890 + +. /%/output + +*SEE ViewHtml, ScheffeTest +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +alpha := .05; + +factor1List := {10.2,8.5,8.4,10.5,9.0,8.1}; + +factor2List := {11.6,12.0,9.2,10.3,9.9,12.5}; + +factor3List := {8.1,9.0,10.7,9.1,10.5,9.5}; + +Echo(anovaBlock := AnovaCompletelyRandomizedBlock({factor1List,factor2List,factor3List}, alpha)); + +NewLine(); + +Echo("F-Score of the block: ", anovaBlock["fScoreBlock"]); + +ViewHtml(anovaBlock["html"]); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + {"criticalFScoreBlock",3.325834530} {"fScoreBlock",0.08045614890} {"criticalFScore",4.102821015} {"fScore",3.078377024} {"meanSquareBlock",0.1418888884} {"meanSquareWithin",1.763555556} {"meanSquareBetween",5.428888905} {"sumOfSquaresTotal",29.20277781} {"sumOfSquaresBlock",0.7094444419} {"sumOfSquaresBetween",10.85777781} {"sumOfSquaresWithin'",17.63555556} {"html",java.lang.String} + + F-Score of the block: 0.08045614890 + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/AnovaSingleFactor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/AnovaSingleFactor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/AnovaSingleFactor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/AnovaSingleFactor.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,302 @@ +%mathpiper,def="AnovaSingleFactor" + +//Retract("AnovaSingleFactor",*); + +AnovaSingleFactor(levelsList, alpha) := +[ + Check(IsListOfLists(levelsList), "Argument", "The first argument must be a list of lists."); + + Check(alpha >= 0 And alpha <= 1, "Argument", "The second argument must be a number between 0 and 1."); + + Local( + anovaTableRow1, + anovaTableRow2, + anovaTableRow3, + anovaTableTotal, + bottomOfAnova, + bottomOfPage, + bottomOfSummary, + criticalFScore, + degreesOfFreedomBetween, + degreesOfFreedomWithin, + fScore, + grandMean, + htmlJavaString, + index, + lengthsList, + meansList, + meanSquareBetween, + meanSquareWithin, + result, + summaryTableRow, + summaryTableRows, + sumOfSquaresBetween, + sumOfSquaresTotal, + sumOfSquaresWithin, + sumsList, + topOfAnova, + topOfPage, + topOfSummary, + variancesList); + + meansList := {}; + + variancesList := {}; + + sumsList := {}; + + lengthsList := {}; + + ForEach(levelList, levelsList) + [ + meansList := meansList : N(Mean(levelList)); + + variancesList := variancesList : N(UnbiasedVariance(levelList)); + + sumsList := sumsList : N(Sum(levelList)); + + lengthsList := lengthsList : Length(levelList); + ]; + + sumOfSquaresWithin := Sum((lengthsList - 1) * variancesList); + + grandMean := N(Mean(Flatten(levelsList, "List"))); + + sumOfSquaresBetween := Sum(lengthsList*(meansList - grandMean)^2); + + sumOfSquaresTotal := N(sumOfSquaresWithin + sumOfSquaresBetween); + + degreesOfFreedomBetween := (Length(levelsList)-1); + + degreesOfFreedomWithin := (ElementCount(levelsList) - Length(levelsList)); + + meanSquareBetween := N(sumOfSquaresBetween/degreesOfFreedomBetween); + + meanSquareWithin := N(sumOfSquaresWithin/degreesOfFreedomWithin); + + fScore := N(meanSquareBetween/meanSquareWithin); + + criticalFScore := ProbabilityToFScore(degreesOfFreedomBetween, degreesOfFreedomWithin, 1-alpha); + + topOfPage := +" + + + Anova: Single Factor + + + +"; + + topOfSummary := +" +

    Anova: Single Factor

    + + + + + +"; + + + summaryTableRows := ""; + + summaryTableRow := "":Nl(); + + index := 1; + While(index <= Length(levelsList)) + [ + summaryTableRows := summaryTableRows : PatchString(summaryTableRow); + + index++; + ]; + + + bottomOfSummary := +" +

    Summary

    Level Count Sum Mean Variance
    +"; + + + + topOfAnova := +" +
    +
    + + + + + +"; + + + + anovaTableRow1 := PatchString("":Nl()); + + anovaTableRow2 := PatchString("":Nl()); + + anovaTableTotal := PatchString(""); + + bottomOfAnova := +" +

    ANOVA

    Source of Variation Sum of Squares Degrees of Freedom Mean Square Between F F Critical
    Total
    +"; + + + + bottomOfPage := +" + + +"; + + htmlJavaString := JavaNew("java.lang.String", + topOfPage : + topOfSummary : + summaryTableRows : + bottomOfSummary : + topOfAnova : + anovaTableRow1 : + anovaTableRow2 : + anovaTableTotal : + bottomOfAnova : + bottomOfPage); + + + + result := {}; + + result["html"] := htmlJavaString; + + result["sumOfSquaresWithin"] := sumOfSquaresWithin; + + result["sumOfSquaresBetween"] := sumOfSquaresBetween; + + result["sumOfSquaresTotal"] := sumOfSquaresTotal; + + result["degreesOfFreedomBetween"] := degreesOfFreedomBetween; + + result["degreesOfFreedomWithin"] := degreesOfFreedomWithin; + + result["meanSquareBetween"] := meanSquareBetween; + + result["meanSquareWithin"] := meanSquareWithin; + + result["fScore"] := fScore; + + result["criticalFScore"] := criticalFScore; + + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + + + +%mathpiper_docs,name="AnovaSingleFactor",categories="User Functions;Statistics & Probability",access="experimental" +*CMD AnovaSingleFactor --- performs an ANOVA single factor analysis + +*CALL + AnovaSingleFactor(listOfLists,alpha) + +*PARMS +{listOfLists} -- a list which contains lists which contain the data to be analyzed + +{alpha} -- the alpha value to use in the analysis. + +*DESC +This function performs an ANOVA single factor analysis. The various values that are +calculated during the analysis are returned in an association list and these +values are listed in the keys of the returned list (see the examples section). + +If the {html} key is passed to the {ViewHtml} function, the results of the analysis +are displayed in a graphcs window as rendered HTML. + +*E.G. +/%mathpiper,scope="nobuild",subtype="manual_test" + +alpha := .05; + +factor1List := {10.2,8.5,8.4,10.5,9.0,8.1}; + +factor2List := {11.6,12.0,9.2,10.3,9.9,12.5}; + +factor3List := {8.1,9.0,10.7,9.1,10.5,9.5}; + +Echo(anova := AnovaSingleFactor({factor1List,factor2List,factor3List}, alpha)); + +NewLine(); + +Echo("F-Score of the data: ", anova["fScore"]); + +ViewHtml(anova["html"]); + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + {"criticalFScore",3.682320344} {"fScore",4.438993381} {"meanSquareWithin",1.22300000} + {"meanSquareBetween",5.428888905} {"degreesOfFreedomWithin",15} {"degreesOfFreedomBetween",2} + {"sumOfSquaresTotal",29.20277781} {"sumOfSquaresBetween",10.85777781} + {"sumOfSquaresWithin",18.34500000} {"html",java.lang.String} + + F-Score of the data: 4.438993381 + +. /%/output + +*SEE ViewHtml, ScheffeTest +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +alpha := .05; + +factor1List := {10.2,8.5,8.4,10.5,9.0,8.1}; + +factor2List := {11.6,12.0,9.2,10.3,9.9,12.5}; + +factor3List := {8.1,9.0,10.7,9.1,10.5,9.5}; + +Echo(anova := AnovaSingleFactor({factor1List,factor2List,factor3List}, alpha)); + +Echo("F-Score of the data: ", anova["fScore"]); + +ViewHtml(anova["html"]); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + {"criticalFScore",3.682320344} {"fScore",4.438993381} {"meanSquareWithin",1.22300000} {"meanSquareBetween",5.428888905} {"degreesOfFreedomWithin",15} {"degreesOfFreedomBetween",2} {"sumOfSquaresTotal",29.20277781} {"sumOfSquaresBetween",10.85777781} {"sumOfSquaresWithin",18.34500000} {"html",java.lang.String} + F-Score of the data: 4.438993381 + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionMean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionMean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionMean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionMean.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="BinomialDistributionMean" + + +//Retract("BinomialDistributionMean", *); + +BinomialDistributionMean(probability,numberOfTrials) := +[ + + Check(IsRationalOrNumber(probability) And p >= 0 And p <= 1, "Argument", "The first argument must be a number between 0 and 1."); + + Check(IsInteger(numberOfTrials) And numberOfTrials >= 0, "Argument", "The second argument must be an integer which is greater than 0."); + + numberOfTrials * probability; +]; + + +%/mathpiper + + + + + +%mathpiper_docs,name="BinomialDistributionMean",categories="User Functions;Statistics & Probability",access="experimental" +*CMD BinomialDistributionMean --- the mean of a binomial distribution +*STD +*CALL + BinomialDistributionMean(p,n) + +*PARMS +{p} -- number, the probability of a success in a single trial + +{n} -- number of trials + +*DESC +This function calculates the mean of a binomial distribution. + +*E.G. +In> BinomialDistributionMean(.3,5) +Result: 1.5 + +*SEE BinomialDistributionStandardDeviation +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionStandardDeviation.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionStandardDeviation.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionStandardDeviation.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/BinomialDistributionStandardDeviation.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="BinomialDistributionStandardDeviation" + + +//Retract("BinomialDistributionStandardDeviation", *); + +BinomialDistributionStandardDeviation(probability,numberOfTrials) := +[ + + Check(IsRationalOrNumber(probability) And p >= 0 And p <= 1, "Argument", "The first argument must be a number between 0 and 1."); + + Check(IsInteger(numberOfTrials) And numberOfTrials >= 0, "Argument", "The second argument must be an integer which is greater than 0."); + + SqrtN(numberOfTrials * probability * (1 - probability)); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="BinomialDistributionStandardDeviation",categories="User Functions;Statistics & Probability",access="experimental" +*CMD BinomialDistributionStandardDeviation --- the standard deviation of a binomial distribution +*STD +*CALL + BinomialDistributionStandardDeviation(p,n) + +*PARMS +{p} -- number, the probability of a success in a single trial + +{n} -- number of trials + +*DESC +This function calculates the standard deviation of a binomial distribution. + +*E.G. +In> BinomialDistributionStandardDeviation(.3,5) +Result: 1.05 + +*SEE BinomialDistributionMean +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ChiSquareScoreToAlpha.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ChiSquareScoreToAlpha.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ChiSquareScoreToAlpha.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ChiSquareScoreToAlpha.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,130 @@ +%mathpiper,def="ChiSquareScoreToAlpha" + +/* + This function was adapted from the Javascript version of function + that is located here: + + http://www.fourmilab.ch/rpkp/experiments/analysis/chiCalc.js + http://www.fourmilab.ch/rpkp/experiments/analysis/chiCalc.html + + The following JavaScript functions for calculating normal and + chi-square probabilities and critical values were adapted by + John Walker from C implementations + written by Gary Perlman of Wang Institute, Tyngsboro, MA + 01879. Both the original C code and this JavaScript edition + are in the public domain. +*/ + + +/* POCHISQ -- probability of chi-square value + + Adapted from: + Hill, I. D. and Pike, M. C. Algorithm 299 + Collected Algorithms for the CACM 1967 p. 243 + Updated for rounding errors based on remark in + ACM TOMS June 1985, page 185 +*/ + +ChiSquareScoreToAlpha(score, degreesOfFreedom) := +[ + Local(a, y, s, e, c, z, LogSqrtPi, ISqrtPi,result); + + y := 0; + + LogSqrtPi := 0.5723649429247000870717135; /* log(sqrt(pi)) */ + + ISqrtPi := 0.5641895835477562869480795; /* 1 / sqrt(pi) */ + + if(score <= 0.0 Or degreesOfFreedom < 1) + [ + result := 1.0; + ] + else + [ + a := N(0.5 * score); + + if (degreesOfFreedom > 1) + [ + y := If(-a < -20, 0, ExpN(-a)); + ]; + + s := If(IsEven(degreesOfFreedom), y , (2.0 * ZScoreToProbability(-SqrtN(score)))); + + if (degreesOfFreedom > 2) + [ + score := 0.5 * (degreesOfFreedom - 1.0); + + z := If(IsEven(degreesOfFreedom), 1.0, 0.5); + + if (a > 20) + [ + e := If(IsEven(degreesOfFreedom), 0.0, LogSqrtPi); + + c := LogN(a); + + While(z <= score) + [ + e := LogN(z) + e; + s := s + If(c * z - a - e < -20, 0, ExpN(c * z - a - e)); + z := z + 1.0; + ]; + result := s; + ] + else + [ + e := If(IsEven(degreesOfFreedom) , 1.0, (ISqrtPi / SqrtN(a))); + + c := 0.0; + + While(z <= score) + [ + e := e * (a / z); + c := c + e; + z := z + 1.0; + ]; + + result := c * y + s; + ]; + ] + else + [ + result := s; + ]; + + ]; + + N(result); +]; + + + + +%/mathpiper + + + + + + +%mathpiper_docs,name="ChiSquareScoreToAlpha",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ChiSquareScoreToAlpha --- calculates the alpha probability of a chi square score +*STD +*CALL + ChiSquareScoreToAlpha(chiSquareScore, degreesOfFreedom) + +*PARMS +{chiSquareScore} -- a chi square score +{degreesOfFreedom} -- the degrees of freedom + +*DESC +This function calculates the alpha probability of a chi square score. + +*E.G. +In> ChiSquareScoreToAlpha(7.779,4) +Result: 0.1000175159 + +*SEE AlphaToChiSquareScore, ChiSquareTest +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/CoefficientOfDetermination.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/CoefficientOfDetermination.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/CoefficientOfDetermination.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/CoefficientOfDetermination.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="CoefficientOfDetermination" + +CoefficientOfDetermination(x,y) := +[ + Check(IsList(x), "Argument", "The first argument must be a list."); + + Check(IsList(y), "Argument", "The second argument must be a list."); + + Check(Length(x) = Length(y), "Argument", "The lists for argument 1 and argument 2 must have the same length."); + + N(CorrelationCoefficient(x,y)^2); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="CoefficientOfDetermination",categories="User Functions;Statistics & Probability",access="experimental" +*CMD CoefficientOfDetermination --- calculates the correlation coefficient between two lists of values +*STD +*CALL + CoefficientOfDetermination(xList,yList) + +*PARMS + +{xList} -- the list of domain values +{yList} -- the list of range values + +*DESC +This function calculates the correlation coefficient between two lists of values. + +*E.G. +/%mathpiper + +x := {4,3,5,2,3,4,3}; +y := {83,86,92,78,82,95,80}; + +CoefficientOfDetermination(x,y); + +/%/mathpiper + + /%output,preserve="false" + Result: 0.7766185090 +. /%/output +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheMean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheMean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheMean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheMean.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,123 @@ +%mathpiper,def="ConfidenceIntervalOfTheMean" + +//Retract("ConfidenceIntervalOfTheMean",*); + +ConfidenceIntervalOfTheMean(sampleMean,standardDeviation,standardDeviationIsKnown,sampleSize,confidenceLevel) := +[ + Check(IsBoolean(standardDeviationIsKnown), "Argument", "The third argument must be True or False."); + + Local(criticalZScore,criticalTScore,standardErrorOfTheMean,upperLimitValue,lowerLimitValue,resultList); + + resultList := {}; + + If(sampleSize >= 30 Or standardDeviationIsKnown = True, + [ + criticalZScore := N(ConfidenceLevelToZScore(confidenceLevel)); + + resultList["criticalZScore"] := criticalZScore; + + standardErrorOfTheMean := N(StandardErrorOfTheMean(standardDeviation,sampleSize)); + + lowerLimitValue := N(sampleMean - criticalZScore * standardErrorOfTheMean); + + upperLimitValue := N(sampleMean + criticalZScore * standardErrorOfTheMean); + + + If(InVerboseMode(), + [ + Echo("Using the normal distribution."); + + Echo("Critical z-score: ", criticalZScore); + + Echo("Standard error of the mean: ", standardErrorOfTheMean); + ]); + ], + [ + criticalTScore := OneTailAlphaToTScore(sampleSize - 1, N((1 - confidenceLevel)/2)); + + resultList["criticalTScore"] := criticalTScore; + + standardErrorOfTheMean := N(StandardErrorOfTheMean(standardDeviation,sampleSize)); + + lowerLimitValue := N(sampleMean - criticalTScore * standardErrorOfTheMean); + + upperLimitValue := N(sampleMean + criticalTScore * standardErrorOfTheMean); + + + If(InVerboseMode(), + [ + Echo("Using the t-distribution."); + + Echo("Critical t-score: ", criticalTScore); + + Echo("Standard error of the mean: ", standardErrorOfTheMean); + ]); + + ]); + + resultList["upperLimit"] := upperLimitValue; + + resultList["lowerLimit"] := lowerLimitValue; + + resultList; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ConfidenceIntervalOfTheMean",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ConfidenceIntervalOfTheMean --- calculates a confidence interval +*STD +*CALL + ConfidenceIntervalOfTheMean(sampleMean,standardDeviation,standardDeviationIsKnown,sampleSize,confidenceLevel) +*PARMS +{sampleMean} -- the mean of the sample +{standardDeviation} -- the standard deviation of the sample +{standardDeviationIsKnown} -- True or False +{sampleSize} -- the size of the sample +{confidenceLevel} -- the desired confidence level + +*DESC +This function calculates a confidence interval for a mean. It returns an association list +which contains the lower limit, the upper limit, and either the critical Z score or the t value. +If the sample size is <30 or {standardDeviationIsKnown} is False, then +Student's t-distribution is used during the calculation. + +If the function is run in verbose mode, it returns additional information as a side effect. + +*E.G. +In> result := ConfidenceIntervalOfTheMean(78.25,37.50,True,32,.90) +Result: {{"lowerLimit",67.34605578},{"upperLimit",89.15394422},{"criticalZScore",1.644853952}} + +In> result["upperLimit"] +Result: 89.15394422 + +In> result := ConfidenceIntervalOfTheMean(78.25,37.50,False,25,.90) +Result: {{"lowerLimit",65.41838440},{"upperLimit",91.08161560},{"criticalTScore",1.710882080}} + +In> result["criticalTScore"] +Result: 1.710882080 + +In> result := V(ConfidenceIntervalOfTheMean(78.25,37.50,True,32,.90)) +Result: {{"lowerLimit",67.34605578},{"upperLimit",89.15394422},{"criticalZScore",1.644853952}} +Side Effects: +Using the normal distribution. +Critical Z-Score: 1.644853952 +Standard error of the mean: 6.629126073 + +*SEE ConfidenceIntervalOfTheProportion, V, Assoc +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheProportion.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheProportion.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheProportion.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceIntervalOfTheProportion.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,def="ConfidenceIntervalOfTheProportion" + +//Retract("ConfidenceIntervalOfTheProportion",*); + +ConfidenceIntervalOfTheProportion(numberOfSuccesses,sampleSize,confidenceLevel) := +[ + Check(IsInteger(numberOfSuccesses) And numberOfSuccesses >= 0, "Argument", "The first argument must be an integer which is >=0"); + + Check(IsInteger(sampleSize) And sampleSize >= 0, "Argument", "The second argument must be an integer which is >=0"); + + Local(criticalZScore,approximateStandardErrorOfTheProportion,upperLimit,lowerLimit,resultList,proportion); + + resultList := {}; + + criticalZScore := ConfidenceLevelToZScore(confidenceLevel); + + resultList["criticalZScore"] := criticalZScore; + + proportion := N(numberOfSuccesses/sampleSize); + + approximateStandardErrorOfTheProportion := Sqrt((proportion*(1 - proportion))/sampleSize); + + upperLimit := N(proportion + criticalZScore * approximateStandardErrorOfTheProportion); + + lowerLimit := N(proportion - criticalZScore * approximateStandardErrorOfTheProportion); + + If(InVerboseMode(), + [ + Echo("Critical z-score: ", criticalZScore); + + Echo("Proportion: ", proportion); + + Echo("Standard error of the proportion: ", N(approximateStandardErrorOfTheProportion)); + ]); + + resultList["upperLimit"] := upperLimit; + + resultList["lowerLimit"] := lowerLimit; + + resultList; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ConfidenceIntervalOfTheProportion",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ConfidenceIntervalOfTheProportion --- calculates a confidence interval for a proportion +*STD +*CALL + ConfidenceIntervalOfTheProportion(numberOfSuccesses,sampleSize,confidenceLevel) +*PARMS +{numberOfSuccesses} -- the number of successes in the sample +{sampleSize} -- the size of the sample +{confidenceLevel} -- the desired confidence level + +*DESC + +This function calculates a confidence interval for a proportion. It returns an association list +which contains the lower limit, the upper limit, and the critical Z score. + +*E.G. +In> ConfidenceIntervalOfTheProportion(110,175,.90) +Result: {{"lowerLimit",0.5684923463},{"upperLimit",0.6886505109},{"criticalZScore",1.644853952}} + +*SEE ConfidenceIntervalOfTheMean, V, Assoc +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceLevelToZScore.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceLevelToZScore.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceLevelToZScore.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ConfidenceLevelToZScore.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="ConfidenceLevelToZScore" + + +//Retract("ConfidenceLevelToZScore",*); + +ConfidenceLevelToZScore(probability) := +[ + //Shift the probability higher to turn it into a confidence interval. + probability := probability + (1 - probability)/2; + + ProbabilityToZScore(probability); +]; + + +%/mathpiper + + + + + + + +%mathpiper_docs,name="ConfidenceLevelToZScore",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ConfidenceLevelToZScore --- calculates the z-score for a given confidence level +*STD +*CALL + ConfidenceLevelToZScore(probability) + +*PARMS + +{probability} -- a probability value + +*DESC + +This function calculates the z-score for a given confidence level. + +*E.G. +In> ConfidenceLevelToZScore(.90) +Result: 1.644853952 + +*SEE NormalDistribution,ZScoreToProbability,ProbabilityToZScore +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ControlChartConstants.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ControlChartConstants.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ControlChartConstants.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ControlChartConstants.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,84 @@ +%mathpiper,def="ControlChartConstants" + +ControlChartConstants(n) := +[ + Check(n >= 2 And n <= 15, "Argument", "The argument n must be 2 <= n <= 20."); + + Local(result, table); + + result := {}; + + n--; + + table := { + {1.880, 1.128, 0.000, 3.267}, + {1.023, 1.693, 0.000, 2.574}, + {0.729, 2.059, 0.000, 2.282}, + {0.577, 2.326, 0.000, 2.114}, + {0.483, 2.534, 0.000, 2.004}, + {0.419, 2.704, 0.076, 1.924}, + {0.373, 2.847, 0.136, 1.864}, + {0.337, 2.970, 0.184, 1.816}, + {0.308, 3.078, 0.223, 1.777}, + {0.285, 3.173, 0.256, 1.744}, + {0.266, 3.258, 0.283, 1.717}, + {0.249, 3.336, 0.307, 1.693}, + {0.235, 3.407, 0.328, 1.672}, + {0.223, 3.472, 0.347, 1.653}, + {0.212, 3.532, 0.363, 1.637}, + {0.203, 3.588, 0.378, 1.622}, + {0.194, 3.640, 0.391, 1.608}, + {0.187, 3.689, 0.403, 1.597}, + {0.180, 3.735, 0.415, 1.585}, + }; + + result["D4"] := table[n][4]; + + result["D3"] := table[n][3]; + + result["d2"] := table[n][2]; + + result["A2"] := table[n][1]; + + result; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="ControlChartConstants",categories="User Functions;Statistics & Probability" +*CMD ControlChartConstants --- returns the control chart constants A2 d2 D3 D4 +*STD +*CALL + ControlChartConstants(n) + +*PARMS + +{n} -- subgroup size (2 - 20) + +*DESC +Returns the control chart constants $A_2, d_2, D_3, D_4$. + +*E.G. +In> ControlChartConstants(2) +Result: {{"A2",1.880},{"d2",1.128},{"D3",0.000},{"D4",3.267}} + +In> ControlChartConstants(2)["A2"] +Result: 1.880 + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/CorrelationCoefficient.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/CorrelationCoefficient.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/CorrelationCoefficient.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/CorrelationCoefficient.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,62 @@ +%mathpiper,def="CorrelationCoefficient" + +CorrelationCoefficient(x,y) := +[ + Check(IsList(x), "Argument", "The first argument must be a list."); + + Check(IsList(y), "Argument", "The second argument must be a list."); + + Check(Length(x) = Length(y), "Argument", "The lists for argument 1 and argument 2 must have the same length."); + + Local(n); + + n := Length(x); + + N((n*Sum(x*y)-Sum(x)*Sum(y))/Sqrt((n*Sum(x^2)-(Sum(x))^2)*(n*Sum(y^2)-(Sum(y)^2))) ); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="CorrelationCoefficient",categories="User Functions;Statistics & Probability",access="experimental" +*CMD CorrelationCoefficient --- calculates the correlation coefficient between two lists of values +*STD +*CALL + CorrelationCoefficient(xList,yList) + +*PARMS + +{xList} -- the list of domain values +{yList} -- the list of range values + +*DESC +This function calculates the correlation coefficient between two lists of values. + +*E.G. +/%mathpiper + +x := {4,3,5,2,3,4,3}; +y := {83,86,92,78,82,95,80}; + +CorrelationCoefficient(x,y); + +/%/mathpiper + + /%output,preserve="false" + Result: 0.7766185090 +. /%/output + +*SEE CorrelationMatrix +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/CorrelationMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/CorrelationMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/CorrelationMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/CorrelationMatrix.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,89 @@ +%mathpiper,def="CorrelationMatrix" + +CorrelationMatrix(dataLists) := +[ + Local(namesList, correlationMatrix); + + ForEach(dataList, dataLists) + [ + Check(IsMatrix(dataLists), "Argument", "All lists must have the same number of elements."); + ]; + + namesList := MatrixColumn(dataLists,1); + + namesList := "" : namesList; + + ForEach(dataList, dataLists) + [ + PopFront(dataList); + ]; + + correlationMatrix := ZeroMatrix(Length(dataLists)+1); + + ForEach(rowIndex, 1 .. Length(dataLists) + 1) + [ + ForEach(columnIndex, 1 .. Length(dataLists) + 1) + [ + if(rowIndex >= 2 And columnIndex >= 2) + [ + correlationMatrix[rowIndex][columnIndex] := N(CorrelationCoefficient(dataLists[rowIndex - 1],dataLists[columnIndex - 1]),2); + ] + else if(rowIndex = 1) + [ + correlationMatrix[rowIndex][columnIndex] := namesList[columnIndex]; + ] + else + [ + correlationMatrix[rowIndex][columnIndex] := namesList[rowIndex]; + ]; + ]; + ]; + + correlationMatrix; +]; + +%/mathpiper + + + + +%mathpiper_docs,name="CorrelationMatrix",categories="User Functions;Statistics & Probability",access="experimental" +*CMD CorrelationMatrix --- creates a correlation matrix +*STD +*CALL + CorrelationMatrix(listOfLists) + +*PARMS + +{listOfLists} -- a list of lists which contains data to be correlated + +*DESC +Creates a correlation coefficient matrix from a list of lists which contain data values. +The first element in each list is the title for the data in that list. The +CorrelationCoefficient function is used to calculate the individual correlations. + +*E.G. +/%mathpiper + +dataLists :={ +{"Age",25,16,8,23,31,19,15,31,21,26,24,25,36,45,16,23,31,53,11,33}, +{"Level",1,2,2,3,4,4,4,5,1,1,5,5,4,4,4,1,2,2,3,2}, +{"Score",78,66,78,89,87,90,98,76,56,72,84,87,69,87,88,92,97,69,79,69}, +}; + +CorrelationMatrix(dataLists); + +/%/mathpiper + + /%output,preserve="false" + Result: {{"","Age","Level","Score"},{"Age",1,0.056,-0.15},{"Level",0.056,1,0.39},{"Score",-0.15,0.39,1}} +. /%/output + +*SEE CorrelationCoefficient +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/D2Value.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/D2Value.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/D2Value.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/D2Value.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,72 @@ +%mathpiper,def="D2Value" + +D2Value(k,n) := +[ + Check(k >= 0 And k <= 15, "Argument", "The first argument k must be 0 <= k <= 15."); + + Check(n >= 2 And n <= 15, "Argument", "The second argument n must be 2 <= n <= 15."); + + n--; + + if(k = 0) + [ + {1.128,1.693,2.059,2.326,2.534,2.704,2.847,2.970,3.078,3.173,3.259,3.336,3.407,3.472}[n]; + ] + else + [ + { + {1.414, 1.912, 2.239, 2.481, 2.673, 2.830, 2.963, 3.078, 3.179, 3.269, 3.350, 3.424, 3.491, 3.553}, + {1.279, 1.805, 2.151, 2.405, 2.604, 2.768, 2.906, 3.025, 3.129, 3.221, 3.305, 3.380, 3.449, 3.513}, + {1.231, 1.769, 2.120, 2.379, 2.581, 2.747, 2.886, 3.006, 3.112, 3.205, 3.289, 3.366, 3.435, 3.499}, + {1.206, 1.750, 2.105, 2.366, 2.570, 2.736, 2.877, 2.997, 3.103, 3.197, 3.282, 3.358, 3.428, 3.492}, + {1.191, 1.739, 2.096, 2.358, 2.563, 2.730, 2.871, 2.992, 3.098, 3.192, 3.277, 3.354, 3.424, 3.488}, + {1.181, 1.731, 2.090, 2.353, 2.558, 2.726, 2.867, 2.988, 3.095, 3.189, 3.274, 3.351, 3.421, 3.486}, + {1.173, 1.726, 2.085, 2.349, 2.555, 2.723, 2.864, 2.986, 3.092, 3.187, 3.272, 3.349, 3.419, 3.484}, + {1.168, 1.721, 2.082, 2.346, 2.552, 2.720, 2.862, 2.984, 3.090, 3.185, 3.270, 3.347, 3.417, 3.482}, + {1.164, 1.718, 2.080, 2.344, 2.550, 2.719, 2.860, 2.982, 3.089, 3.184, 3.269, 3.346, 3.416, 3.481}, + {1.160, 1.716, 2.077, 2.342, 2.549, 2.717, 2.859, 2.981, 3.088, 3.183, 3.268, 3.345, 3.415, 3.480}, + {1.157, 1.714, 2.076, 2.340, 2.547, 2.716, 2.858, 2.980, 3.087, 3.182, 3.267, 3.344, 3.415, 3.479}, + {1.155, 1.712, 2.074, 2.344, 2.546, 2.715, 2.857, 2.979, 3.086, 3.181, 3.266, 3.343, 3.414, 3.479}, + {1.153, 1.710, 2.073, 2.338, 2.545, 2.714, 2.856, 2.978, 3.085, 3.180, 3.266, 3.343, 3.413, 3.478}, + {1.151, 1.709, 2.072, 2.337, 2.545, 2.714, 2.856, 2.978, 3.085, 3.180, 3.265, 3.342, 3.413, 3.478}, + {1.150, 1.708, 2.071, 2.337, 2.544, 2.713, 2.855, 2.977, 3.084, 3.179, 3.265, 3.342, 3.412, 3.477} + }[k][n]; + ]; + +]; + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="D2Value",categories="User Functions;Statistics & Probability" +*CMD D2Value --- converts average range $\bar{R}$ into estimated standard deviation $\hat{\sigma}_x$ +*STD +*CALL + D2Value(k,n) + +*PARMS + +{k} -- the number of times each part was measured (sample size, 1 - 15) or 0 to obtain a d2 control limits constant +{n} -- the number of parts measured (number of samples, 2 - 15) + +*DESC +Converts average range $\bar{R}$ into estimated standard deviation $\hat{\sigma}_x$. If k is set to 0, +the d2 control limits constant is returned. + +*E.G. +In> D2Value(4,7); +Result: 2.736 + +In> D2Value(0,2) +Result: 1.128 +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ErrorFunction.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ErrorFunction.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ErrorFunction.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ErrorFunction.mpw 2011-02-03 07:06:47.000000000 +0000 @@ -0,0 +1,87 @@ +%mathpiper,def="ErrorFunction" + +/* +This function came from http://www.johndcook.com/blog/2009/01/19/stand-alone-error-function-erf/ + +"This problem is typical in two ways: Abramowitz & Stegun has a solution, and +you've got to know a little background before you can use it. + +The formula given in Abramowitz & Stegun is only good for x <= 0. That's no problem if you +know that the error function is an odd function, i.e. erf(-x) = -erf(x). +But if you're an engineer who has never heard of the error function but +needs to use it, it may take a while to figure out how to handle negative inputs. + +One other thing that someone just picking up A&S might not know is the +best way to evaluate polynomials. The formula appears as +1 - (a1t1 + a2t2 + a3t3 + a4t4 + a5t5)exp(-x2), which is absolutely correct. +But directly evaluating an nth order polynomial takes O(n2) operations, +while the factorization used in the code above uses O(n) operations. This +technique is known as Horner's method. John D. Cook." + +*/ + +//Retract("ErrorFunction",*); + +ErrorFunction(x) := +[ + Local(a1,a2,a3,a4,a5,p,sign,t,y); + //constants + a1 := 0.254829592; + a2 := -0.284496736; + a3 := 1.421413741; + a4 := -1.453152027; + a5 := 1.061405429; + p := 0.3275911; + + //Save the sign of x + sign := 1; + + If(x < 0, sign := -1); + + x := AbsN(x); + + // Abramowitz & Stegun 7.1.26 + t := 1.0/(1.0 + p*x); + y := N(1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*Exp(-x*x)); + + sign*y; +]; + + + +%/mathpiper + + + +%mathpiper_docs,name="ErrorFunction",categories="User Functions;Special Functions",access="experimental" +*CMD ErrorFunction --- a special function which occurs in probability statistics and partial differential equations +*STD +*CALL + ErrorFunction(a) + +*PARMS + +{a} -- a measurement value + +*DESC + +When the results of a series of measurements are described by a normal distribution +with standard deviation \scriptstyle\sigma and expected value 0, then +${erf}\,\left(\,\frac{a}{\sigma \sqrt{2}}\,\right)$ +is the probability that the error of a single measurement lies between -a and +a, +for positive a. http://en.wikipedia.org/wiki/Error_function. + +*E.G. +In> ErrorFunction(1) +Result: 0.8427006898 + +*SEE NormalDistribution +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/IsSubset.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/IsSubset.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/IsSubset.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/IsSubset.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="IsSubset" + +//Retract("IsSubset",*); + +IsSubset(bigList, littleList) := +[ + Local(result); + result := True; + + ForEach(element, littleList) + [ + If(Not Contains(bigList,element), result := False); + ]; + + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Mode.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Mode.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Mode.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Mode.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="Mode" + +Mode(list) := +[ + Check(Length(list) > 0 And IsNumericList(list), "Argument", "Argument must be a nonempty numeric list."); + + Local(noDuplicatesList, countsList, sortedList, highestCountsList, resultList); + + noDuplicatesList := RemoveDuplicates(list); + + countsList := {}; + + ForEach(element, noDuplicatesList) + [ + countsList := Append(countsList, {Count(list, element), element} ); + ]; + + sortedList := HeapSort(countsList,Lambda({x,y},x[1] > y[1])); + + highestCountsList := Select(sortedList, Lambda({x},x[1] = sortedList[1][1])); + + resultList := MapSingle(Lambda({x},x[2]), highestCountsList); + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Mode",categories="User Functions;Statistics & Probability",access="experimental" +*CMD Mode --- calculates the mode of a list of values +*STD +*CALL + Mode(list) + +*PARMS + +{list} -- list of values + +*DESC + +This function calculates the mode of a list of values. The mode is the value +that occurs most frequently. + +*E.G. +In> Mode({73,94,80,37,57,94,40,21,94,26}) +Result: 94 + +*SEE Mean, WeightedMean, Median, Mode, GeometricMean +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Permutations.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Permutations.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Permutations.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Permutations.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="Permutations" + +//Retract("Permutations", *); + +Permutations(n) := +[ + Check(IsInteger(n), "Argument", "Argument must be an integer"); + + n!; +]; + + +Permutations(n, r) := +[ + Check(IsInteger(n), "Argument", "Argument 1 must be an integer"); + + Check(IsInteger(r), "Argument", "Argument 2 must be an integer"); + + n! /(n-r)!; +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="Permutations",categories="User Functions;Combinatorics",access="experimental" +*CMD Permutations --- number of permutations +*STD +*CALL + Permutations(n) + Permutations(n, r) + +*PARMS + +{n} -- integer - total number of objects +{r} -- integer - number of objects chosen + +*DESC + +In combinatorics, this function is thought of as being the number of ways +to choose "r" objects out of a total of "n" objects if order is taken into account. + +The single parameter version of the function is a convenience function for +calculating the number of ways to choose "n" objects out of "n" objects. + +*E.G. +In> Permutations(5) +Result> 120 + +In> Permutations(10,3) +Result> 720 + +*SEE PermutationsList, Combinations, CombinationsList, LeviCivita +%/mathpiper_docs + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +Permutations(4); + +%/mathpiper + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ProbabilityToZScore.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ProbabilityToZScore.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ProbabilityToZScore.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ProbabilityToZScore.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,98 @@ +%mathpiper,def="ProbabilityToZScore" + +/* + This function was adapted from the Javascript version of function + that is located here: + + http://www.fourmilab.ch/rpkp/experiments/analysis/zCalc.js + http://www.fourmilab.ch/rpkp/experiments/analysis/zCalc.html? + + The following JavaScript functions for calculating normal and + chi-square probabilities and critical values were adapted by + John Walker from C implementations + written by Gary Perlman of Wang Institute, Tyngsboro, MA + 01879. Both the original C code and this JavaScript edition + are in the public domain. +*/ + + +/* We just do a bisection +search for a value within CHI_EPSILON, +relying on the monotonicity of pochisq(). */ + +//Retract("ProbabilityToZScore",*); + +ProbabilityToZScore(probability) := +[ + Local(ZMAX,ZEPSILON,minimumZ,maximumZ,zValue,probabilityValue); + + probability := N(probability); + + Check(probability >= 0.0 And probability <= 1.0, "Argument", "The argument must be between 0 and 1."); + + ZMAX := 6; // Maximum �z value. + + ZEPSILON := 0.000001; /* Accuracy of z approximation */ + + minimumZ := -ZMAX; + + maximumZ := ZMAX; + + zValue := 0.0; + + While ((maximumZ - minimumZ) > ZEPSILON) + [ + probabilityValue := ZScoreToProbability(zValue); + + if (probabilityValue > probability) + [ + maximumZ := zValue; + ] + else + [ + minimumZ := zValue; + ]; + + zValue := (maximumZ + minimumZ) * 0.5; + ]; + + zValue; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ProbabilityToZScore",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ProbabilityToZScore --- calculates the z-score for a given probability +*STD +*CALL + ProbabilityToZScore(probability) + +*PARMS + +{probability} -- a probability value + +*DESC + +This function calculates the z-score for a given probability. + +*E.G. +In> ProbabilityToZScore(.90) +Result: 1.281551244 + +*SEE NormalDistribution,ZScoreToProbability,ValueToZScore,ZScoreToValue,ConfidenceLevelToZScore +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Quartile.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Quartile.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Quartile.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Quartile.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,81 @@ +%mathpiper,def="Quartile" + +//Retract("Quartile",*); + +Quartile(list) := +[ + sortedList := HeapSort(list,"<"); + + secondQuartile := Median(sortedList); + + If(IsOdd(Length(sortedList)), + [ + secondQuartileIndex := Find(sortedList, secondQuartile); + + leftList := Take(sortedList, secondQuartileIndex-1); + rightList := Take(sortedList, -(Length(sortedList) - (secondQuartileIndex) ) ); + ], + [ + + leftList := Take(sortedList, Length(sortedList)/2); + rightList := Take(sortedList, -Length(sortedList)/2); + ] + ); + + firstQuartile := Median(leftList); + + thirdQuartile := Median(rightList); + + interquartileRange := thirdQuartile - firstQuartile; + + {firstQuartile, secondQuartile, thirdQuartile, interquartileRange}; + +]; + +%/mathpiper + + + + + + +%mathpiper_docs,name="Quartile",categories="User Functions;Statistics & Probability",access="experimental" +*CMD Quartile --- returns all of the quartiles and the interquartile range of a list of values +*STD +*CALL + Quartile(list) + +*PARMS + +{list} -- a list which contains values + +*DESC +Returns all of the quartiles and the interquartile range of a list of values. The first +value in the returned list is the first quartile, the second value is the second quartile, +the third value is the third quartile, and the fourth value is the interquartile range. + +*E.G. +/%mathpiper,title="" + +samples := { +438,413,444,468,445,472,474,454,455,449, +450,450,450,459,466,470,457,441,450,445, +487,430,446,450,456,433,455,459,423,455, +451,437,444,453,434,454,448,435,432,441, +452,465,466,473,471,464,478,446,459,464, +441,444,458,454,437,443,465,435,444,457, +444,471,471,458,459,449,462,460,445,437, +461,453,452,438,445,435,454,428,454,434, +432,431,455,447,454,435,425,449,449,452, +471,458,445,463,423,451,440,442,441,439 +}; + +N(Quartile(samples)); + +/%/mathpiper + + /%output,preserve="false" + Result: {441,450,458.5,17.5} +. /%/output + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RandomPick.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RandomPick.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RandomPick.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RandomPick.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,70 @@ +%mathpiper,def="RandomPick" + +//Retract("RandomPick",*); + + +RandomPick(list) := +[ + Check(IsList(list), "Argument", "Argument must be a list."); + + Check(Length(list) > 0, "Argument", "The number of elements in the list must be greater than 0."); + + Local(pickPosition); + + pickPosition := RandomInteger(Length(list)); + + list[pickPosition]; +]; + +%/mathpiper + + + + + + + +%mathpiper_docs,name="RandomPick",categories="User Functions;Statistics & Probability",access="experimental" +*CMD RandomPick --- randomly pick an element from a list +*STD +*CALL + RandomPick(list) + +*PARMS + +{list} -- a list which contains elements + +*DESC +Randomly picks an element from the given list. + +*E.G. +In> RandomPick({HEADS, TAILS}) +Result: HEADS + +In> RandomPick({DOOR1, DOOR2, DOOR3}) +Result: DOOR2 + +In> RandomPick({DOG, CAT, BIRD, MOUSE, TURTLE}) +Result: BIRD + +In> RandomPick({23,56,87,92,15}) +Result: 56 + +*SEE RandomPickWeighted, RandomPickVector +%/mathpiper_docs + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +RandomPick({A,B,C}); + +%/mathpiper + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RandomPickVector.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RandomPickVector.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RandomPickVector.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RandomPickVector.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="RandomPickVector" + +//Retract("RandomPickVector", *); + +RandomPickVector(list, count) := +[ + Check(IsList(list), "Argument", "Argument 1 must be a list."); + + Check(IsInteger(count), "Argument", "Argument 2 must be an integer."); + + Table(RandomPick(list),x,1,count,1); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="RandomPickVector",categories="User Functions;Statistics & Probability",access="experimental" +*CMD RandomPickVector --- returns a given number of randomly picked elements from a given list +*STD +*CALL + RandomPickVector(list,count) + +*PARMS + +{list} -- a list which contains elements + +{count} -- an integer which indicates how many elements to return + +*DESC +Randomly picks {count} elements from the given list. + +*E.G. +In> RandomPickVector({ONE,TWO,THREE},7); +Result: {THREE,ONE,THREE,THREE,ONE,TWO,TWO} + +*SEE RandomPick, RandomPickWeighted +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +RandomPickVector({ONE,TWO,THREE},7); + +%/mathpiper + + %output,preserve="false" + Result: {TWO,THREE,ONE,THREE,THREE,TWO,THREE} +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RandomPickWeighted.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RandomPickWeighted.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RandomPickWeighted.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RandomPickWeighted.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,113 @@ +%mathpiper,def="RandomPickWeighted" + +//Retract("RandomPickWeighted",*); + +RandomPickWeighted(list) := +[ + + Check(IsList(list), "Argument", "Argument must be a list."); + + Local(element, probabilities, items, lastWeight, randomNumber, result); + + probabilities := 0; + + items := {}; + + lastWeight := 0; + + + + //Make sure that the probabilities sum to 1. + ForEach(element,list) + [ + probability := element[2]; + + probabilities := probabilities + probability; + ]; + + Check(probabilities = 1, "Argument", "The probabilities must sum to 1."); + + + + //Place items in a list and associate it with a subrange in the range between 0 and 1. + ForEach(element,list) + [ + probability := element[2]; + + item := element[1]; + + items := Append(items, {item, {lastWeight, lastWeight := lastWeight + N(probability)}} ); + ]; + + + + //Pick the item which is in the randomly determined range. + randomNumber := Random(); + + ForEach(itemData,items) + [ + If(randomNumber >= itemData[2][1] And randomNumber <= itemData[2][2], result := itemData[1] ); + ]; + + + + result; + +]; + +%/mathpiper + + + + + + + + +%mathpiper_docs,name="RandomPickWeighted",categories="User Functions;Statistics & Probability",access="experimental" +*CMD RandomPickWeighted --- randomly pick an element from a list using a given weight +*STD +*CALL + RandomPickWeighted(list) + +*PARMS + +{list} -- a list which contains elements and their respective weights + +*DESC +Randomly picks an element from the given list with a probability which is determined by the element's weight. + +*E.G. +In> RandomPickWeighted({{HEADS,1/2},{TAILS,1/2}}); +Result: HEADS + +In> RandomPickWeighted({{HEADS,.5},{TAILS,.5}}); +Result: TAILS + +In> RandomPickWeighted({{DOOR1,2/8}, {DOOR2,1/8}, {DOOR3,5/8}}) +Result: DOOR1 + +In> RandomPickWeighted({{DOG,.2}, {CAT,.3}, {BIRD,.1}, {MOUSE,.15}, {TURTLE,.25}}) +Result: TURTLE + +In> RandomPickWeighted({{23,5/32},{56,10/32},{87,8/32},{92,6/32},{15,3/32}}) +Result: 15 + +*SEE RandomPick, RandomPickVector +%/mathpiper_docs + + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +RandomPickWeighted({{HEADS,1/2},{TAILS,1/2}}); + +%/mathpiper + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Range.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Range.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Range.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Range.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="Range" + +Range(list) := +[ + Check(Length(list) > 0 And IsNumericList(list), "Argument", "Argument must be a nonempty numeric list."); + + Maximum(list) - Minimum(list); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Range",categories="User Functions;Statistics & Probability",access="experimental" +*CMD Range --- calculates the Range of a list of values +*STD +*CALL + Range(list) + +*PARMS + +{list} -- list of values + +*DESC + +This function calculates the Range of a list of values. The Range is the value +that occurs most frequently. + +*E.G. +In> Range({2,3,4,3,4,5,5}) +Result: 3 + +*SEE Mean, WeightedMean, Median, GeometricMean +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RegressionLineConfidenceLevel.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RegressionLineConfidenceLevel.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RegressionLineConfidenceLevel.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RegressionLineConfidenceLevel.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,74 @@ +%mathpiper,def="RegressionLineConfidenceInterval" + +RegressionLineConfidenceInterval(x,y,xValue,confidenceLevel) := +[ + Check(IsList(x), "Argument", "The first argument must be a list."); + + Check(IsList(y), "Argument", "The second argument must be a list."); + + Check(Length(x) = Length(y), "Argument", "The lists for argument 1 and argument 2 must have the same length."); + + Check(confidenceLevel >=0 And confidenceLevel <=1, "Argument", "The confidence level must be >= 0 and <= 1."); + + Local(n,a,b,xMean,part,result,criticalTScore,standardErrorOfTheEstimate/* regressionLine, todo:tk:causes an error if it is not global. */); + + regressionLine := RegressionLine(x,y); + + n := regressionLine["count"]; + + f(x) := [Eval(regressionLine["line"]);]; + + criticalTScore := OneTailAlphaToTScore(n-2, N((1 - confidenceLevel)/2)); + + standardErrorOfTheEstimate := StandardErrorOfTheEstimate(x,y); + + xMean := regressionLine["xMean"]; + + part := N(criticalTScore * standardErrorOfTheEstimate * Sqrt(1/n + ((xValue - xMean)^2)/(Sum(x^2) - Sum(x)^2/n))); + + result := {}; + + result["upper"] := f(xValue) + part; + + result["lower"] := f(xValue) - part; + + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: {{"lower",f(8)-1.954274717},{"upper",f(8)+1.954274717}} +. %/output + + + + +%mathpiper_docs,name="RegressionLineConfidenceInterval",categories="User Functions;Statistics & Probability",access="experimental" +*CMD RegressionLineConfidenceInterval --- calculates the correlation coefficient between two lists of values +*STD +*CALL + RegressionLineConfidenceInterval(xList,yList,xValue,confidenceLevel) + +*PARMS + +{xList} -- the list of domain values +{yList} -- the list of range values +{xValue} -- a value of x to calculate the confidence interval around +{confidenceLevel} -- the desired level of confidence + +*DESC +This function calculates the correlation coefficient between two lists of values. + +*E.G. +/%mathpiper,title="Confidence interval for the regression line." +xList := 1 .. 10; +yList := {5,6,10,6,11,13,9,12,15,17}; +RegressionLineConfidenceInterval(xList,yList,8,.95); +/%/mathpiper + + /%output,preserve="false" + Result: {{"lower",51.59027286},{"upper",55.49882230}} +. /%/output + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RegressionLine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RegressionLine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/RegressionLine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/RegressionLine.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,83 @@ +%mathpiper,def="RegressionLine" + +RegressionLine(x,y) := +[ + Check(IsList(x), "Argument", "The first argument must be a list."); + + Check(IsList(y), "Argument", "The second argument must be a list."); + + Check(Length(x) = Length(y), "Argument", "The lists for argument 1 and argument 2 must have the same length."); + + Local(n,a,b,xMean,yMean,line,result); + + n := Length(x); + + b := N((n*Sum(x*y) - Sum(x)*Sum(y))/(n*Sum(x^2)-(Sum(x))^2)); + + xMean := N(Mean(x)); + + yMean := N(Mean(y)); + + a := N(yMean - b*xMean); + + line := a + b*Hold(x); + + result := {}; + + result["xMean"] := xMean; + + result["yMean"] := yMean; + + result["line"] := line; + + result["yIntercept"] := a; + + result["slope"] := b; + + result["count"] := n; + + result; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="RegressionLine",categories="User Functions;Statistics & Probability",access="experimental" +*CMD RegressionLine --- calculates the correlation coefficient between two lists of values +*STD +*CALL + RegressionLine(xList,yList) + +*PARMS + +{xList} -- the list of domain values +{yList} -- the list of range values + +*DESC +This function calculates the correlation coefficient between two lists of values. + +*E.G. +/%mathpiper + +x := {4,3,5,2,3,4,3}; +y := {83,86,92,78,82,95,80}; + +RegressionLine(x,y); + +/%/mathpiper + + /%output,preserve="false" + Result: 0.7766185090 +. /%/output +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Repeat.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Repeat.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Repeat.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Repeat.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,151 @@ +%mathpiper,def="Repeat" + + + +//Retract("Repeat",*); + + +/* + These variables need to be declared as local symbols because + body is unfenced and expressions in the body could see them + otherwise. +*/ +LocalSymbols(count, iterations, body)[ + + +Rulebase("Repeat",{iterations,body}); + +/* + A Rule function needed to be used here because 10 # xxx <-- + notation did not work if Bodied was executed before the + function was defined. Bodied is evaluated in stdopers.mpw + because it needs to be evaluated for the parser to parse + Retract correctly. +*/ + +Rule("Repeat",2,10,IsInteger(iterations) And iterations > 0) +[ + Local(count); + + count := 0; + + While (iterations > 0) + [ + Eval(body); + iterations--; + count++; + ]; + + count; + +]; + + + + + +Rulebase("Repeat",{body}); + + +Rule("Repeat",1,20,True) +[ + Local(count); + + count := 0; + While (True) + [ + Eval(body); + count++; + ]; + + count; +]; + +];//end LocalSymbols + +UnFence("Repeat",2); +HoldArgumentNumber("Repeat",2,2); +UnFence("Repeat",1); +HoldArgumentNumber("Repeat",1,1); + + + +%/mathpiper + + + + + +%mathpiper_docs,name="Repeat",categories="User Functions;Control Flow",access="experimental" +*CMD Repeat --- loop a specified number of times or loop indefinitely +*STD +*CALL + Repeat(count) body + Repeat() body + +*PARMS + +{count} -- a positive integer, the number of times to loop + +{body} -- expression to loop over + +*DESC + +The first version of Repeat executes {body} the number of times +which are specified by {count}. The second version +executes {body} indefinitely and the only way to exit the loop +is to execute the Break function inside of {body}. + +Repeat returns the number of times it looped as a result. + +*E.G. +/%mathpiper + +Repeat(4) +[ + Echo("Hello"); +]; + +/%/mathpiper + + /%output,preserve="false" + Result: 4 + + Side Effects: + Hello + Hello + Hello + Hello +. /%/output + + + +/%mathpiper + +x := 1; + +loopCount := Repeat() +[ + Echo(x); + + If(x = 3, Break()); + + x := x + 1; +]; + +Echo("Loop count: ", loopCount); + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + 1 + 2 + 3 + Loop count: 2 +. /%/output + +*SEE While, For, ForEach, Break, Continue +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Sample.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Sample.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Sample.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Sample.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="Sample" + +//Retract("Sample",*); + +Sample(list, sampleSize) := +[ + Check(IsList(list), "Argument", "The first argument must be a list."); + + Check(IsInteger(sampleSize) And sampleSize > 0, "Argument", "The second argument must be an integer which is greater than 0."); + + list := Shuffle(list); + + Take(list, sampleSize); +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="Sample",categories="User Functions;Statistics & Probability",access="experimental" +*CMD Sample --- takes a random sample of elements from a list +*STD +*CALL + Sample(list,sampleSize) + +*PARMS +{list} -- a list of elements +{sampleSize} -- the size of the sample to take from the list + +*DESC +This function takes a random sample of items from a list and returns +a list which contains the sample. + +*E.G. +In> Sample({a,b,c,d,e,f,g},3) +Result: {a,c,g} + +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheMean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheMean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheMean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheMean.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="SampleSizeForTheMean" + +//Retract("SampleSizeForTheMean",*); + +SampleSizeForTheMean(standardDeviation,confidenceLevel,marginOfError) := +[ + Local(minimumSampleSize); + + zScore := ConfidenceLevelToZScore(confidenceLevel); + + minimumSampleSize := N(((zScore*standardDeviation)/marginOfError)^2); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="SampleSizeForTheMean",categories="User Functions;Statistics & Probability",access="experimental" +*CMD SampleSizeForTheMean --- calculates the sample size for the mean +*STD +*CALL + SampleSizeForTheMean(standardDeviation,confidenceLevel,marginOfError) +*PARMS +{standardDeviation} -- the standard deviation of the sample +{confidenceLevel} -- the desired level of confidence +{marginOfError} -- the desired margin of error + +*DESC +This function calculates the minimum sample size for the mean to provide +a specific margin of error for a given confidence level. + +*E.G. +In> SampleSizeForTheMean(37.50,.95,8) +Result: 84.40706911 +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheProportion.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheProportion.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheProportion.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/SampleSizeForTheProportion.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,50 @@ +%mathpiper,def="SampleSizeForTheProportion" + +//Retract("SampleSizeForTheProportion",*); + +SampleSizeForTheProportion(probabilityOfSuccess,confidenceLevel,marginOfError) := +[ + Check(probabilityOfSuccess >=0 And probabilityOfSuccess <= 1, "Argument", "The first argument must be between 0 and 1."); + + Local(minimumSampleSize,zScore); + + zScore := ConfidenceLevelToZScore(confidenceLevel); + + minimumSampleSize := N(probabilityOfSuccess*(1 - probabilityOfSuccess)*(zScore/marginOfError)^2); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="SampleSizeForTheProportion",categories="User Functions;Statistics & Probability",access="experimental" +*CMD SampleSizeForTheProportion --- calculates the sample size for the proportion +*STD +*CALL + SampleSizeForTheProportion(probabilityOfSuccess,confidenceLevel,marginOfError) +*PARMS +{probabilityOfSuccess} -- the probability of success for the sample +{confidenceLevel} -- the desired confidence level +{marginOfError} -- the desired margin of error + +*DESC +This function calculates the minimum sample size for the proportion to provide +a specific margin of error for a given confidence level. + +*E.G. +In> SampleSizeForTheProportion(.5,.99,.06) +Result: 460.7567390 +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ScheffeTest.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ScheffeTest.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ScheffeTest.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ScheffeTest.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,281 @@ +%mathpiper,def="ScheffeTest" + +ScheffeTest(levelsList, alpha) := +[ + Check(IsListOfLists(levelsList), "Argument", "The first argument must be a list of lists."); + + Check(alpha >= 0 And alpha <= 1, "Argument", "The second argument must be a number between 0 and 1."); + + Local( result, + topOfSummary, + pairsList, + xBarB, + xBarA, + summaryTableRow, + ssw, + nA, + scheffeStatisticCalculated, + nB, + summaryList, + topOfPage, + htmlJavaString, + summaryTableRows, + meansList, + index,b, + pairList, + a, + bottomOfPage, + k, + countsList, + oneComparisonList, + scheffeStatistic, + bottomOfSummary, + resultList); + + anova := AnovaSingleFactor(levelsList, alpha); + + k := Length(levelsList); + + scheffeStatisticCalculated := (k-1)*anova["criticalFScore"]; + + resultList := {}; + + resultList["scheffeStatisticCalculated"] := scheffeStatisticCalculated; + + meansList := {}; + + countsList := {}; + + ForEach(levelList,levelsList) + [ + meansList := meansList : N(Mean(levelList)); + + countsList := countsList : Length(levelList); + ]; + + pairsList := CombinationsList(1 .. Length(levelsList),2); + + summaryList := {}; + + index := 1; + + ForEach(pairList, pairsList) + [ + a := pairList[1]; + + b := pairList[2]; + + xBarA := meansList[a]; + + nA := countsList[a]; + + xBarB := meansList[b]; + + nB := countsList[b]; + + ssw := anova["sumOfSquaresWithin"]; + + scheffeStatistic := ScheffeStatistic(xBarA,nA,xBarB,nB,ssw,k,countsList); + + oneComparisonList := {}; + + oneComparisonList["conclusion"] := If(scheffeStatistic <= scheffeStatisticCalculated, "No Difference", "Difference"); + + oneComparisonList["scheffeStatistic"] := scheffeStatistic; + + oneComparisonList["pair"] := pairList; + + summaryList["pair" : ToString(index)] := oneComparisonList; + + index++; + ]; + + resultList["summary"] := summaryList; + + + + + topOfPage := +" + + + Scheffe Test Summary + + + +"; + + topOfSummary := +" +

    Scheffe Test Summary

    + + + + + +"; + + + summaryTableRows := ""; + + summaryTableRow := "":Nl(); + + + + ForEach(summary, Reverse(resultList["summary"])) + [ + summary := summary[2]; + + pairList := summary["pair"]; + + summaryTableRows := summaryTableRows : PatchString(summaryTableRow); + + index++; + ]; + + + bottomOfSummary := +" +

    Summary

    Sample Pair Measured Scheffe Statistic Calculated Scheffe Statistic Conclusion
    +"; + + + bottomOfPage := +" + + +"; + + htmlJavaString := JavaNew("java.lang.String", + topOfPage : + topOfSummary : + summaryTableRows : + bottomOfSummary : + bottomOfPage); + + + + + resultList["html"] := htmlJavaString; + + + DestructiveReverse(resultList); + +]; + + + + + + +ScheffeStatistic(xBarA,nA,xBarB,nB,ssw,k,countsList) := +[ + N(((xBarA-xBarB)^2)/((ssw/Sum(i,1,k,(countsList[i] - 1))*(1/nA + 1/nB)))); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + +%mathpiper_docs,name="ScheffeTest",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ScheffeTest --- performs a Scheffe pairwise analysis + +*CALL + ScheffeTest(listOfLists,alpha) + +*PARMS +{listOfLists} -- a list which contains lists which contain the data to be analyzed + +{alpha} -- the alpha value to use in the analysis. + +*DESC +This function performs a Scheffe pairwise analysis. The various values that are +calculated during the analysis are returned in an association list and these +values are listed in the keys of the returned list (see the examples section). + +If the {html} key is passed to the {ViewHtml} function, the results of the analysis +are displayed in a graphcs window as rendered HTML. + +*E.G. +/%mathpiper,scope="nobuild",subtype="manual_test" + +alpha := .05; + +data1List := {10.2,8.5,8.4,10.5,9.0,8.1}; + +data2List := {11.6,12.0,9.2,10.3,9.9,12.5}; + +data3List := {8.1,9.0,10.7,9.1,10.5,9.5}; + +Echo(scheffeResult := ScheffeTest({data1List,data2List,data3List}, alpha)); + +Echo("Scheffe statistic of the first pair: ", scheffeResult["scheffeStatistic"]); + +ViewHtml(scheffeResult["html"]); + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + {"scheffeStatisticCalculated",7.364640688} + {"summary", + {{"pair3",{{"pair",{2,3}},{"scheffeStatistic",5.039520331},{"conclusion","No Difference"}}}, + {"pair2",{{"pair",{1,3}},{"scheffeStatistic",0.3297901324},{"conclusion","No Difference"}}}, + {"pair1",{{"pair",{1,2}},{"scheffeStatistic",7.947669691},{"conclusion","Difference"}}}}} + {"html",java.lang.String} + + Scheffe statistic of the first pair: 7.364640688 + +. /%/output + +*SEE ViewHtml,AnovaSingleFactor +%/mathpiper_docs + + + + + + + + +%mathpiper,scope="nobuild",subtype="manual_test" + +alpha := .05; + +data1List := {10.2,8.5,8.4,10.5,9.0,8.1}; + +data2List := {11.6,12.0,9.2,10.3,9.9,12.5}; + +data3List := {8.1,9.0,10.7,9.1,10.5,9.5}; + +Echo(scheffeResult := ScheffeTest({data1List,data2List,data3List}, alpha)); + +NewLine(); + +Echo("Scheffe statistic of the first pair: ", scheffeResult["scheffeStatisticCalculated"]); + +ViewHtml(scheffeResult["html"]); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + {"scheffeStatisticCalculated",7.364640688} {"summary",{{"pair3",{{"pair",{2,3}},{"scheffeStatistic",5.039520331},{"conclusion","No Difference"}}},{"pair2",{{"pair",{1,3}},{"scheffeStatistic",0.3297901324},{"conclusion","No Difference"}}},{"pair1",{{"pair",{1,2}},{"scheffeStatistic",7.947669691},{"conclusion","Difference"}}}}} {"html",java.lang.String} + + Scheffe statistic of the first pair: 7.364640688 + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ShuffledDeckNoSuits.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ShuffledDeckNoSuits.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ShuffledDeckNoSuits.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ShuffledDeckNoSuits.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="ShuffledDeckNoSuits" + +//Retract("ShuffledDeckNoSuits",*); + + +ShuffledDeckNoSuits() := +[ + Shuffle(Concat(1 .. 13, 1 .. 13, 1 .. 13, 1 .. 13)); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Shuffle.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Shuffle.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/Shuffle.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/Shuffle.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,73 @@ +%mathpiper,def="Shuffle" + +//Retract("Shuffle",*); + +/* + This function is based on the Fisher-Yates/Knuth shuffle algorithm + which is described here at + http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle . +*/ +Shuffle(list) := +[ + Check(IsList(list), "Argument", "Argument must be a list."); + + Local(index, randomIndex, temporary); + + list := FlatCopy(list); + + index := Length(list); + + While(index > 1) + [ + randomIndex := RandomInteger(1,index); + + temporary := list[randomIndex]; + + list[randomIndex] := list[index]; + + list[index] := temporary; + + index--; + ]; + + list; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="Shuffle",categories="User Functions;Statistics & Probability",access="experimental" +*CMD Shuffle --- randomly shuffles the elements in a list +*STD +*CALL + Shuffle(list) + +*PARMS + +{list} -- a list of elements + +*DESC +This function takes a list of elements and shuffles them. A new +list with the shuffled elements is returned. + +*E.G. +In> Shuffle({1,2,3,4,5}) +Result: {5,1,2,4,3} + +In> Shuffle({one,two,three}) +Result: {two,three,one} + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheEstimate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheEstimate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheEstimate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheEstimate.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,66 @@ +%mathpiper,def="StandardErrorOfTheEstimate" + +StandardErrorOfTheEstimate(xList,yList) := +[ + Check(IsList(xList), "Argument", "The first argument must be a list."); + + Check(IsList(yList), "Argument", "The second argument must be a list."); + + Check(Length(xList) = Length(yList), "Argument", "The lists for argument 1 and argument 2 must have the same length."); + + Local(n,a,b,regressionLine); + + regressionLine := RegressionLine(xList,yList); + + n := regressionLine["count"]; + + a := regressionLine["yIntercept"]; + + b := regressionLine["slope"]; + + N(Sqrt((Sum(yList^2) - a*Sum(yList) - b*Sum(xList*yList))/(n-2))); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="StandardErrorOfTheEstimate",categories="User Functions;Statistics & Probability",access="experimental" +*CMD StandardErrorOfTheEstimate --- calculates the correlation coefficient between two lists of values +*STD +*CALL + StandardErrorOfTheEstimate(xList,yList) + +*PARMS + +{xList} -- the list of domain values +{yList} -- the list of range values + +*DESC +This function calculates the correlation coefficient between two lists of values. + +*E.G. +/%mathpiper + +x := {4,3,5,2,3,4,3}; +y := {83,86,92,78,82,95,80}; + +StandardErrorOfTheEstimate(x,y); + +/%/mathpiper + + /%output,preserve="false" + Result: 0.7766185090 +. /%/output +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheMean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheMean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheMean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheMean.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="StandardErrorOfTheMean" + +//Retract("StandardErrorOfTheMean",*); + +StandardErrorOfTheMean(sigma, sampleSize) := +[ + Check(sigma > 0, "Argument", "The first argument must be a number which is greater than 0."); + + Check(IsInteger(sampleSize) And sampleSize > 0, "Argument", "The second argument must be an integer which is greater than 0."); + + sigma/Sqrt(sampleSize); +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="StandardErrorOfTheMean",categories="User Functions;Statistics & Probability",access="experimental" +*CMD StandardErrorOfTheMean --- calculates the standard error of the mean +*STD +*CALL + StandardErrorOfTheMean(sigma,sampleSize) + +*PARMS +{sigma} -- the standard deviation of the population +{sampleSize} -- the size of the sample + +*DESC +This function calculates the standard error of the mean. + +*E.G. +In> N(StandardErrorOfTheMean(1.44,2)) +Result: 1.018233765 + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheProportion.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheProportion.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheProportion.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheProportion.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="StandardErrorOfTheProportion" + +//Retract("StandardErrorOfTheProportion",*); + +StandardErrorOfTheProportion(meanOfSampleProportions, sampleSize) := +[ + Check(IsRationalOrNumber(meanOfSampleProportions), "Argument", "The first argument must be a number."); + + Check(IsInteger(sampleSize) And sampleSize > 0, "Argument", "The second argument must be an integer which is greater than 0."); + + Sqrt((meanOfSampleProportions*(1 - meanOfSampleProportions))/sampleSize); +]; + +%/mathpiper + + + + + + +%mathpiper_docs,name="StandardErrorOfTheProportion",categories="User Functions;Statistics & Probability",access="experimental" +*CMD StandardErrorOfTheProportion --- calculates the standard error of the proportion +*STD +*CALL + StandardErrorOfTheProportion(meanOfSampleProportions,sampleSize) + +*PARMS +{meanOfSampleProportions} -- the mean of the sample proportions +{sampleSize} -- the size of the proportion samples + +*DESC +This function calculates the standard error of the proportion. + +*E.G. +In> N(StandardErrorOfTheProportion(.164,150)) +Result: 0.030232873941 +%/mathpiper_docs + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheSlope.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheSlope.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheSlope.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StandardErrorOfTheSlope.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,64 @@ +%mathpiper,def="StandardErrorOfTheSlope" + +StandardErrorOfTheSlope(xList,yList) := +[ + Check(IsList(xList), "Argument", "The first argument must be a list."); + + Check(IsList(yList), "Argument", "The second argument must be a list."); + + Check(Length(xList) = Length(yList), "Argument", "The lists for argument 1 and argument 2 must have the same length."); + + Local(standardErrorOfTheEstimate,n,xMean); + + standardErrorOfTheEstimate := StandardErrorOfTheEstimate(xList,yList); + + n := Length(xList); + + xMean := Mean(xList); + + N(standardErrorOfTheEstimate/Sqrt(Sum(xList^2) - n*xMean^2)); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="StandardErrorOfTheSlope",categories="User Functions;Statistics & Probability",access="experimental" +*CMD StandardErrorOfTheSlope --- calculates the correlation coefficient between two lists of values +*STD +*CALL + StandardErrorOfTheSlope(xList,yList) + +*PARMS + +{xList} -- the list of domain values +{yList} -- the list of range values + +*DESC +This function calculates the correlation coefficient between two lists of values. + +*E.G. +/%mathpiper + +x := {4,3,5,2,3,4,3}; +y := {83,86,92,78,82,95,80}; + +StandardErrorOfTheSlope(x,y); + +/%/mathpiper + + /%output,preserve="false" + Result: 1.813835715 +. /%/output +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StemAndLeaf.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StemAndLeaf.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/StemAndLeaf.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/StemAndLeaf.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,1019 @@ +%mathpiper +//Obtained from http://math.uc.edu/~pelikan/probandstat/stem.htm + + +trunc(x):= [ + + If(x < 0, s := -1, s := 1); +s* Floor(Abs(x)); +]; + + + + +intlabels(y1,y2,tnumint) := [ + diff :=y2-y1; + x := intervals(diff,tnumint); + bot := trunc(y1/x)*x; + yy = bot; + L = []; + //i = 0; + xx = 0; + breakLoop := False; + While (yy-x < y2 Or breakLoop = True) [ + L := Append(L, yy); + yy := yy + x; + //i++; + xx++; + If (xx > 100, breakLoop := True); + ]; + L[i] = yy; + L; +]; + + + + +intervals(diff, NumCats) := [ + t4 := trunc(N(Ln(diff))) * 0.4342945; + t4 = Power(10,t4); + T := []; + T := N(t4/10 : t4/5 : t4/2 : t4 : T); + + + A := []; + + For (i := 0,i < 4, i++) [ + A := Append(A,trunc(diff/T[i]) +1); + ]; + + D := AbsN(10 - A[0]); + + index := 1; + For (i := 1, i < 4, i++) + [ + if (A[i] <= 25) [ + if (A[i] > 2) [ + XX := AbsN(NumCats - A[i]); + if (XX < D) [ + D := XX; + index = i+1; + ]; + ]; + ]; + ]; + T[index-1]; +]; + + + + + +stemandleaf(x) := +[ + Echo("Stem and Leaf Display"); + didzero := False; + N := x.length; + + if (N<20) + [ + tNumInt := 5; + ] + else + [ + if (N < 100) + [ + tNumInt := 10; + ] + else + [ + if (N < 150) + [ + tNumInt := 15; + ] + else + [ + tNumInt := 20; + ]; + ]; + ]; + theMax := x[N-1]; + theMin := x[0]; + alldone := False; + if (theMax - theMin < 10) + [ + ratio := 1000/(theMax - theMin); + ratio := Math.max(ratio,1000); + ratio := trunc(Math.log(ratio) * 0.4342945); + ratio := Math.pow(10,ratio); + For ( i := 0, i < N , i++) + [ + x[i] := x[i] * ratio; + ]; + ] + else + [ + ratio := 1; + ]; + zcount := 0; + theMin := x[0]; + abMin := Math.abs(theMin); + theMax := x[N-1]; + Y := intervals(theMax-theMin,tNumInt); + indexA := index +0; + if (indexA= 2) + [ + Y := Y * 5; + ncats :=5 ; + newz := 1; + ] + else + [ + if(indexA=3) + [ + Y := Y * 2; + ncats := 2; + ] + else + [ + ncats := 1; + newz := 0; + ]; + ]; + + cutoffs := intlabels(x[0], x[N-1], tNumInt); + theMax := ratio * Round(theMax); + nc := cutoffs.length; + xx8:=0; + While (cutoffs[nc-2] > theMax) + [ + nc--; + ]; + theMax := cutoffs[nc-2]; + if (Y > AbsN(theMax)) + [ + nc++; + While(Y > AbsN(theMax)) + [ + xx8++; + if(xx8>100)[break;]; + if (nc > Length(cutoffs)) + [ + temp := cutoffs[nc-2] - cutoffs[nc - 3]; + temp := temp + cutoffs[nc-2]; + cutoffs[nc-1] := temp; + ]; + theMax := cutoffs[nc-1]; + nc++; + ]; + ]; + base := trunc(theMax/Y); + leftover := Round(theMax - base * Y); + While (AbsN(leftover) > 10) + [ + leftover := AbsN(Round(leftover/10)); + ]; + theMax2 := Maximum(theMax,abMin); + t4 := trunc(theMax2/base); + t4 := trunc(N(Ln(t4) * .4342945)); + t4 := Power(10,t4); + t3 := t4/10; + if (indexA = 2) + [ + if (leftover >= 8) + [ + newz := 1; + ] + else + [ + if (leftover >= 6) + [ + newz := 0; + ] + else + [ + if (leftover >= 4) + [ + newz := 4; + ] + else + [ + if (leftover >= 2) + [ + newz := 3; + ] + else + [ + newz := 2; + ]; + ]; + ]; + ]; + ] + else + [ + if (indexA = 3) + [ + if (leftover >=5) + [ + newz := 1; + ] + else + [ + newz := 0; + ]; + ]; + ]; + start := False; + LN := 1; + LN2 := 0; + nn := N; + cur := cutoffs[nc-2]; + count := nc-2; + base2 :=base; + newline := True; + stems := {base2}; + leaves := {""}; + + + For ( i := nn-1, i >= 0 , i--) + [ + it := x[i]; + dd := Round(it/t3) * t3; + b := trunc(dd/t4); + L := dd-t4*b; + leftover := AbsN(Round(L/t3)); + While (leftover >= 10) + [ + leftover := Round(leftover/10); + ]; + if (it >=0) + [ + tt := t3; + ] + else + [ + tt := -t3; + ]; + + xz := b * t4 + leftover * tt; + + if (it<0) + [ + if (xz > 0 ) + [ + xz := xz * -1; + ]; + xz := xz - .00001; + ]; + + if (xz=6)) Or ((indexA = 3) And (zcount >=3)) Or ((indexA = 1) And (zcount >1)) Or ((indexA = 4) And (zcount >1))) + [ + stems := Append(stems,"-" : ToString(base2)); + ] + else + [ + stems := Append(stems, ToString(base2)); + ]; + ] + else + [ + stems := Append(stems, ToString(base2)); + ]; + + ];//end While. + + + ];//end if + + start := True; + leftover := ToString(leftover); + + if (it>=0) + [ + + leaves[LN2] := leftover : "" : leaves[LN2]; + + ] + else + [ + leaves[LN2] := leaves[LN2] : "" : leftover; + ]; + ]; + + For ( i := 0, i < N , i++) [ + x[i] := x[i] / ratio; + ]; + + + Echo("Stems Leaves"); + For (i:=0, i + + + Stem and Leaf Plot + + + + + + + + +

    Stem and Leaf Plot

    + +

    This page contains JavaScript that will make a Stem-and-Leaf plot of the data you +paste or type into the text area below. Separate the different values by spaces, commas, or newlines + as you enter them. Then hit the "Compute" button and your browser will open a new window and display the plot. When you are done looking at the new window minimize it or close it with controls from its pull-down menus.

    + +

    Note that Microsoft has implemented a different version of scripting language in their Internet Explorer browser. Very likely, the JavaScript program on this page will not work in Microsoft's browser. To the best of my knowledge, the script does work in Netscape's internet browser 3.0.

    + +
    +
    + + +
    +

    + The code in this page for the "hard" part of making the plot was borrowed from Lane's Hyperstat. All I've done is parsed the imput data differently. +

    +
    If you find errors in this program please send email: +
    Stephan Pelikan
    + + + +Last modified: Tue Sep 30 17:09:00 EDT 1997 + + + + + + + + + + + + + + + + + +%html + +Minitab + +



    +

    +Section 2.6. http://www.math.binghamton.edu/arcones/327/2.6.html

    + +

    + +First we use the yarn strength data. We find the boxplot of these data +MTB > Retrieve 'A:\YARNSTRG.MTW'. +Retrieving worksheet from file: A:\YARNSTRG.MTW +************************************** +A boxplot consists of a box, whiskers, and outliers. A line is drawn across +the box at the median. By default, the bottom of the box is at the first +quartile (Q1), and the top is at the third quartile (Q3) value. The whiskers +are the lines that extend from the top and bottom of the box to the adjacent +values. The adjacent values are the lowest and highest observations that are +still inside the region defined by the following limits: + + Lower Limit: Q1 - 1.5 (Q3 - Q1) + Upper Limit: Q3 + 1.5 (Q3 - Q1) + +Outliers are points outside of the lower and upper limits and are plotted +with asterisks (*). +************************************** +MTB > boxplot c1 + +

    +Using that +MTB > desc c1 + N MEAN MEDIAN TRMEAN STDEV SEMEAN +Ln_YarnS 100 2.9238 2.8331 2.8982 0.9378 0.0938 + + MIN MAX Q1 Q3 +Ln_YarnS 1.1514 5.7978 2.2789 3.5732 +We have that +Minimum=1.1514; Q1=2.2789; median=2.8331; Q3=3.5732; maximum=5.7978 +In this case +Lower Limit: Q1 - 1.5 (Q3 - Q1)= 2.2789-1.5(3.5732-2.2789)=0.8903 +Upper Limit: Q3 + 1.5 (Q3 - Q1)= 3.5732+1.5(3.5732-2.2789)=5.5146 +The minimum is not an outlier, but the maximum is. +So, the lower whisker goes to the minimum. The upper whisker goes to +the biggest value in the data small than 5.5146. This value is 5.0904 +Observe that +MTB > sort c1 c2 +MTB > print c2 + + +C2 + 1.1514 1.1535 1.3436 1.4328 1.4570 1.5059 1.5219 1.5305 + 1.6438 1.6787 1.7261 1.7837 1.7902 1.8926 1.8952 2.0813 + 2.0968 2.1232 2.1306 2.1381 2.1771 2.2163 2.2364 2.2671 + 2.2762 2.2872 2.3018 2.3459 2.3483 2.4016 2.4064 2.4190 + 2.4240 2.4822 2.5000 2.5238 2.5264 2.5326 2.5364 2.5453 + 2.5654 2.5724 2.5800 2.5813 2.6266 2.6537 2.6745 2.7243 + 2.7317 2.8243 2.8418 2.8732 2.9382 2.9394 2.9908 3.0027 + 3.0164 3.0693 3.0722 3.1166 3.1412 3.1860 3.1860 3.2108 + 3.2177 3.2217 3.3077 3.3770 3.4002 3.4217 3.4603 3.4743 + 3.4866 3.5017 3.5272 3.5886 3.6152 3.6162 3.6394 3.6398 + 3.6561 3.7043 3.7071 3.7782 3.8849 3.9821 4.0017 4.0022 + 4.0126 4.1251 4.3215 4.3389 4.4382 4.4563 4.5234 4.6315 + 4.6426 4.8444 5.0904 5.7978 + +Next, we draw the quantile graph in page 37: +MTB > set c2 +DATA> 1:100 +DATA> end +MTB > let c2=c2/101 +MTB > sort c1 c3 +MTB > Plot C3*C2; +SUBC> Symbol; +SUBC> Type 5. + +

    + +Next, we get the stem-and leaf- for the strength yard data +****************************************************************** +A stem-and-leaf display shows the distribution of a variable in much the +same way as a histogram. However, the initial digits of each value are +used to construct the display, so individual values can be read from the +display. A stem-and-leaf display has three parts: + + The first column shows a cumulative count of the number of values on that +line or on lines toward the nearer edge. (The line that contains the median +shows a count of values on that line instead, enclosed in parentheses.) + + The second column of numbers holds the stems. + + The right-hand portion of the display holds the leaves. Each leaf digit +represents an individual value. The initial digits of that value are the +stem digits. This is followed by the leaf digit. Thus, a stem of 46 and a +leaf of 2 could represent the number 462, or 46.2, or .00462. The position +of the decimal point is indicated by the UNIT of the leaf digit printed at +the top of the display. +************************************************** + +MTB > stemandleaf c1 + +Stem-and-leaf of Ln_YarnS N = 100 +Leaf Unit = 0.10 + + + 5 1 11344 + 15 1 5556677788 + 34 2 0011112222233344444 + (21) 2 555555555566677888999 + 45 3 000011112223344444 + 27 3 5556666677789 + 14 4 00013344 + 6 4 5668 + 2 5 0 + 1 5 7 +Next, we find robust statistics for location and dispersion. +To find the 5 % trimmed mean we do: +MTB > descr c1 + + N MEAN MEDIAN TRMEAN STDEV SEMEAN +Ln_YarnS 100 2.9238 2.8331 2.8982 0.9378 0.0938 + + MIN MAX Q1 Q3 +Ln_YarnS 1.1514 5.7978 2.2789 3.5732 +The trimmed mean is 2.8982 +Alternatively, we could do: +MTB > sort c1 c2 +MTB > delete 1,2,3,4,5,96,97,98,99,100 c2 +MTB > mean c2 + MEAN = 2.8982 +In this way, we can also find the 5 % trimmed standard deviation: +MTB > stdev c2 + ST.DEV. = 0.75951 + + + + + + +%/html + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ValueToZScore.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ValueToZScore.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ValueToZScore.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ValueToZScore.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="ValueToZScore" + +//Retract("ValueToZScore",*); + +ValueToZScore(value,mean,standardDeviation) := +[ + (value - mean)/standardDeviation; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ValueToZScore",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ValueToZScore --- calculates the z-score of a numerical value +*STD +*CALL + ValueToZScore(numericalValue,mean,standardDeviation) + +*PARMS + +{numericalValue} -- a numerical value +{mean} -- the mean +{standardDeviation} -- the standard deviation + +*DESC +This function calculates the z-score for a given numerical value. + +*E.G. +In> N(ValueToZScore(4.74,5,.332)) +Result: -0.7831325301 + +*SEE ZScoreToValue,ZScoreToProbability,ProbabilityToZScore,ConfidenceLevelToZScore +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/WeightedMean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/WeightedMean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/WeightedMean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/WeightedMean.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="WeightedMean" + + +WeightedMean(list) := +[ + + Check(IsList(list), "Argument", "Argument must be a list."); + + Local( values, lastWeight, weights ); + + values := {}; + + weights := {}; + + + ForEach(element,list) + [ + Check(IsList(element), "Argument", "Values and their associated weights must be in a list."); + + Check(Length(element) = 2, "Argument", "Each value and its associated weight must be in a two element list."); + + values := values : element[1]; + + weights := weights : element[2]; + ]; + + Sum(values * weights)/Sum(weights); + +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="WeightedMean",categories="User Functions;Statistics & Probability",access="experimental" +*CMD WeightedMean --- weighted mean +*STD +*CALL + WeightedMean({{value, weight},...}) + +*PARMS + +{value} -- a value. + +{weight} -- the weight to associate with the value. + +*DESC +This function allows more weight to be associated with certain values and +less weight to others when calculating their mean. + +*E.G. +In> WeightedMean({{92,50}, {87,40}, {76,10}}) +Result: 442/5 + +In> N(WeightedMean({{92,50}, {87,40}, {76,10}})) +Result: 88.4 + +*SEE Mean, Median, Mode, GeometricMean +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToProbability.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToProbability.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToProbability.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToProbability.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,117 @@ +%mathpiper,def="ZScoreToProbability" + +/* + This function was adapted from the Javascript version of function + that is located here: + + http://www.fourmilab.ch/rpkp/experiments/analysis/zCalc.js + http://www.fourmilab.ch/rpkp/experiments/analysis/zCalc.html? + + The following JavaScript functions for calculating normal and + chi-square probabilities and critical values were adapted by + John Walker from C implementations + written by Gary Perlman of Wang Institute, Tyngsboro, MA + 01879. Both the original C code and this JavaScript edition + are in the public domain. +*/ + + + +/* + POZ -- probability of normal z value + + Adapted from a polynomial approximation in: + Ibbetson D, Algorithm 209 + Collected Algorithms of the CACM 1963 p. 616 + Note: + This routine has six digit accuracy, so it is only useful for absolute + z values <:= 6. For z values > to 6.0, poz() returns 1.0. +*/ + +ZScoreToProbability(zScore) := +[ + zScore := N(zScore); + + Local( y, x, w, ZMAX, result); + + ZMAX := 6; // Maximum �z value + + if(zScore = 0.0) + [ + x := 0.0; + ] + else + [ + y := 0.5 * AbsN(zScore); + + if(y > ZMAX * 0.5) + [ + x := 1.0; + ] + else if(y < 1.0) + [ + w := y * y; + x := ((((((((0.000124818987 * w + - 0.001075204047) * w + 0.005198775019) * w + - 0.019198292004) * w + 0.059054035642) * w + - 0.151968751364) * w + 0.319152932694) * w + - 0.531923007300) * w + 0.797884560593) * y * 2.0; + ] + else + [ + y := y - 2.0; + + x := (((((((((((((-0.000045255659 * y + + 0.000152529290) * y - 0.000019538132) * y + - 0.000676904986) * y + 0.001390604284) * y + - 0.000794620820) * y - 0.002034254874) * y + + 0.006549791214) * y - 0.010557625006) * y + + 0.011630447319) * y - 0.009279453341) * y + + 0.005353579108) * y - 0.002141268741) * y + + 0.000535310849) * y + 0.999936657524; + ]; + ]; + + + If(zScore > 0.0 , result := (x + 1.0) * 0.5 , result := (1.0 - x) * 0.5); + + result; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ZScoreToProbability",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ZScoreToProbability --- calculates the probability of a given z-score +*STD +*CALL + ZScoreToProbability(z_score) + +*PARMS + +{z_score} -- a z-score value + +*DESC + +This function calculates the probability of a given z-score. + +*E.G. +In> ZScoreToProbability(1.08) +Result: 0.8599289100 + +*SEE NormalDistribution,ProbabilityToZScore,ValueToZScore,ZScoreToValue,ConfidenceLevelToZScore +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToValue.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToValue.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToValue.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/statistics/ZScoreToValue.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="ZScoreToValue" + +//Retract("ZScoreToValue",*); + +ZScoreToValue(zScore) := +[ + -((-mean)/standardDeviation - zScore)*standardDeviation; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ZScoreToValue",categories="User Functions;Statistics & Probability",access="experimental" +*CMD ZScoreToValue --- calculates the numerical value for a given z-score +*STD +*CALL + ZScoreToValue(zScore,mean,standardDeviation) + +*PARMS + +{zScore} -- a z score +{mean} -- the mean +{standardDeviation} -- the standard deviation + +*DESC +This function calculates the numerical value for a given z-score. + +*E.G. +In> N(ZScoreToValue(1,5,1)) +Result: 6 + +*SEE ValueToZScore,ZScoreToProbability,ProbabilityToZScore,ConfidenceLevelToZScore +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xCheckSolution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xCheckSolution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xCheckSolution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xCheckSolution.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,114 @@ +%mathpiper,title="xCheckSolution" + +//Retract("xCheckSolution",*); +//Retract("CloseEnough",*); + +10 # CloseEnough(_expr1,_expr2,_prec) <-- + [ + If(iDebug=True,Tell("CloseEnough",{expr1,expr2,prec})); + Local(diff,ndiff,ncomp,result); + diff := expr1 - expr2; + If(diff != 0 And HasFunc(expr1,Sqrt), diff := RadSimp(expr1-expr2)); + If(diff != 0, diff := Simplify(expr1-expr2)); + If(iDebug=True,Tell(" ce1",diff)); + If(diff=0, + result:=True, + [ + ndiff := Abs(N(diff,prec+1)); + ncomp := N(10^(-prec),prec); + If(iDebug=True,Tell(" ce2",{ndiff,ncomp,ndiff/ncomp})); + If(ndiff/ncomp<1,result:=True,result:=False); + ] + ); + result; + ]; + + +10 # xCheckSolution( exprs_IsList, _var, solutions_IsList ) <-- + [ + If(iDebug=True,Tell("xCheckSolutionL",{exprs,var,solutions})); + Local(tests); + + tests := Subst(==,ToAtom("-")) (exprs Where solutions); + If(iDebug,Tell(" 1",tests)); + tests := AllSatisfy("IsZero",tests); + ]; + + +12 # xCheckSolution( _expr, _var, solution_IsList ) <-- + [ + If(iDebug=True,Tell("xCheckSolution1",{expr,var,solution})); + Local(expr0,result,s,r); + If( IsEquation(expr), + Bind(expr0,EquationLeft(expr)-EquationRight(expr)), + Bind(expr0,expr) + ); + result := {}; + ForEach(s,solution) + [ + If(iDebug=True,Tell(" cs1",s)); + r := ( expr0 Where s ); + If(iDebug=True,Tell(" cs2",{expr0,r})); + If(r=0,Push(result,s),If(CloseEnough(r,0,10),Push(result,s))); + ]; + If(iDebug=True,Tell(" cs4",result)); + Reverse(result); + ]; + + +20 # xCheckSolution( _expr, _var, _solution ) <-- False; + +%/mathpiper + + + +%mathpiper_docs,name="xCheckSolution",categories="User Functions;Solvers (Symbolic)",access="experimental" + +*CMD xCheckSolution --- Check the validity of solutions returned by the {xSolve} function. +*STD +*CALL + xCheckSolution(expr,var,solution) + +*PARMS + +{expr} -- a mathematical expression, or List of simultaneous equations +{var} -- a varible identifier, or List of variables +{solution} -- a List containing solutions to the equation(s). + + +*DESC + +The function {xSolve} will attempt to find solutions to the equation +{expr}, if {expr} is an actual equatio), or to the equivalent equation +represented by {expr==0} if {expr} is NOT an equation. +If expr is a List of simultaneous linear equations, {xSolve} will +attempt to solve the system. + +Solutions returned by {xSolve} will be in the form of a List, such as +{{var==something,var==something_else}}. + +For certain types of expressions or equation, {xSolve} might return +invalid solutions as well as valid ones in the output List. To check +the list of solutions, call the function xCheckSolutions(). This function +will return a list containing only the valid solutions from among those +in the list (if any). If none of the "solutions" is valid, this +function will return the empty list. + +*E.G. + +In> ss1 := xSolve(x^2==4,x) + +Result: {x==2,x==(-2)} + +In> xCheckSolution(x^2==4,x,ss1) + +Result: {x==2,x==(-2)} + +In> xCheckSolution(x^2==4,x,{x==2,x==3}) // Deliberately incorrect + +Result: {x==2} + +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolve.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,548 @@ +%mathpiper,title="xSolve" + +//Retract("xSolve",*); +//Retract("xSolve'Simple",*); +//Retract("xSolve'Divide",*); + + +/* + * Strategy for Solve(expr, x): + * + * 10. Call xSolve'System for systems of equations. + * 20. Check arguments. + * 30. Get rid of "==" in 'expr'. + * 40. Special cases. + * 50. If 'expr' is a polynomial in 'x', try to use PSolve. + * 60. If 'expr' is a product, solve for either factor. + * 70. If 'expr' is a quotient, solve for the denominator. + * 80. If 'expr' is a sum and one of the terms is free of 'x', + * try to use xSolve'Simple. + * 90. If every occurance of 'x' is in the same context, use this to reduce + * the equation. For example, in 'Cos(x) + Cos(x)^2 == 1', the variable + * 'x' always occurs in the context 'Cos(x)', and hence we can attack + * the equation by first solving 'y + y^2 == 1', and then 'Cos(x) == y'. + * This does not work for 'Exp(x) + Cos(x) == 2'. + * 100. Apply Simplify to 'expr', and try again. + * 110. Give up. + */ + +LocalSymbols(res) +[ + 10 # xSolve(expr_IsList, var_IsList) <-- + [ + If(iDebug=True,Tell("xSolve1",{expr,var})); + xSolve'System(expr, var); + ]; + + 20 # xSolve(_expr, _var)_(Not IsAtom(var) Or IsNumber(var) Or IsString(var)) <-- + [ + If(iDebug=True,Tell("xSolve2",{expr,var})); + Assert("xSolve'TypeError", "Second argument, ":(PipeToString() Write(var)):", is not the name of a variable") False; {}; + ]; + + 30 # xSolve(_lhs == _rhs, _var) <-- + [ + If(iDebug=True, + [ + Tell("xSolve3",{lhs,rhs,var}); + If(IsRationalFunction(lhs,var), + Tell(" 3r IsRationalFunction",lhs), + Tell(" 3r NotRationalFunction",lhs) + ); + If(IsRationalFunction(rhs,var), + Tell(" 3r IsRationalFunction",rhs), + Tell(" 3r NotRationalFunction",rhs) + ); + ] + ); + Local(simpexpression); + simpexpression := Simplify(lhs-rhs); + If(IsRationalFunction(simpexpression,var), + [ + xSolve'Rational(simpexpression, var); + ], + [ + xSolve(simpexpression, var); // new hso 090923 + ] + ); + ]; + + 40 # xSolve(0, _var) <-- + [ + If(iDebug=True,Tell("xSolve4",{0,var})); + {var == var}; + ]; + + 41 # xSolve(a_IsConstant, _var) <-- + [ + If(iDebug=True,Tell("xSolve5",{a,var})); + {}; + ]; + + 42 # xSolve(_expr, _var)_(Not HasExpr(expr,var)) <-- + [ + If(iDebug=True,Tell("xSolve6",{expr,var})); + Assert("xSolve", "expression ":(PipeToString() Write(expr)):" does not depend on ":PipeToString() Write(var)) False; {}; + ]; + + 44 # xSolve(Sqrt(_expr1) - _expr2,_var) <-- + [If(iDebug=Trfue,Tell("xSolve441",{expr1,expr2,var}));xSolve'Sqrts(expr1,expr2,var);]; + + 44 # xSolve(Sqrt(_expr1) + _expr2,_var) <-- + [If(iDebug=True,Tell("xSolve442",{expr1,expr2,var}));xSolve'Sqrts(expr1,-expr2,var);]; + + 44 # xSolve(_expr2 - Sqrt(_expr1),_var) <-- + [If(iDebug=True,Tell("xSolve443",{expr2,expr1,var}));xSolve'Sqrts(expr1,expr2,var);]; + + 44 # xSolve(-_expr2 - Sqrt(_expr1),_var) <-- + [If(iDebug=True,Tell("xSolve444",{expr2,expr1,var}));xSolve'Sqrts(expr1,-expr2,var);]; + + + 45 # xSolve(Sqrt(_expr1)-Sqrt(_expr2),_var) <-- + [ + If(iDebug=True,Tell("xSolve2Sqrts-",{expr1,expr2})); + Local(solution); + solution := xSolve(expr1-expr2,var); + xCheckSolution(Sqrt(expr1)-Sqrt(expr2),var,solution); + ]; + + 45 # xSolve(Sqrt(_expr1)+Sqrt(_expr2),_var) <-- + [ + If(iDebug=True,Tell("xSolve2Sqrts+",{expr1,expr2})); + Local(solution); + solution := xSolve(expr1-expr2,var); + xCheckSolution(Sqrt(expr1)+Sqrt(expr2),var,solution); + ]; + + 50 # xSolve(_expr, _var)_((res := xSolve'Poly(expr, var)) != Failed) <-- + [ + If(iDebug=True,Tell("xSolve7Poly",{expr,var,res})); + res; + ]; + + 60 # xSolve(_e1 * _e2, _var) <-- + [ + If(iDebug=True,Tell(8,{e1,e2,var})); + Union(xSolve(e1,var), xSolve(e2,var)); + ]; + + 70 # xSolve(_e1 / _e2, _var) <-- + [ + If(iDebug=True,Tell(9,{e1,e2,var})); + xSolve(e1, var); + ]; + + 80 # xSolve(_e1 + _e2, _var)_(Not HasExpr(e2,var) And (res := xSolve'Simple(e1,-e2,var)) != Failed) <-- + [ + If(iDebug=True,Tell(10,{e1,e2,var,res})); + res; + ]; + + 80 # xSolve(_e1 + _e2, _var)_(Not HasExpr(e1,var) And (res := xSolve'Simple(e2,-e1,var)) != Failed) <-- + [ + If(iDebug=True,Tell(11,{e1,e2,var,res})); + res; + ]; + + 80 # xSolve(_e1 - _e2, _var)_(Not HasExpr(e2,var) And (res := xSolve'Simple(e1,e2,var)) != Failed) <-- + [ + If(iDebug=True,Tell(12,{e1,e2,var,res})); + res; + ]; + + 80 # xSolve(_e1 - _e2, _var)_(Not HasExpr(e1,var) And (res := xSolve'Simple(e2,e1,var)) != Failed) <-- + [ + If(iDebug=True,Tell(13,{e1,e2,var,res})); + res; + ]; + + 85 # xSolve(_expr, _var)_((res := xSolve'Simple(expr, 0, var)) != Failed) <-- + [ + If(iDebug=True,Tell("xSolve14Simple_succeeded",{expr,var,res})); + res; + ]; + + 90 # xSolve(_expr, _var)_((res := xSolve'Reduce(expr, var)) != Failed) <-- + [ + If(iDebug=True,Tell("xSolve15Reduce_succeeded",{expr,var,res})); + res; + ]; + + 95 # xSolve(_expr, _var)_((res := xSolve'Divide(expr, var)) != Failed) <-- + [ + If(iDebug=True,Tell("xSolve16Divide_succeeded",{expr,var,res})); + res; + ]; + + 100 # xSolve(_expr, _var)_((res := Simplify(expr)) != expr) <-- + [ + If(iDebug=True,Tell("xSolve17Simplified",{expr,var,res})); + xSolve(res, var); + ]; + + 110 # xSolve(_expr, _var) <-- + [ + If(iDebug,Tell("xSolve18Fails",{expr,var})); + Assert("xSolve'Fails", "cannot solve equation ":(PipeToString() Write(expr)):" for ":PipeToString() Write(var)) False; {}; + ]; +]; // LocalSymbols + +/******************** xSolve'Simple ********************/ + +/* Simple solver of equations + * + * Returns (possibly empty) list of solutions, + * or Failed if it cannot handle the equation + * + * Calling format: xSolve'Simple(lhs, rhs, var) + * to solve 'lhs == rhs'. + * + * Note: 'rhs' should not contain 'var'. + */ + +20 # xSolve'Simple(_e1 + _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- + [ + If(iDebug=True,Tell("xSolve51aSimple",{e1,e2,rhs,var})); + { var == rhs-e2 }; + ]; + +20 # xSolve'Simple(_e1 + _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- + [ + If(iDebug=True,Tell("xSolve51bSimple",{e1,e2,rhs,var})); + { var == rhs-e1 }; + ]; + +20 # xSolve'Simple(_e1 - _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- + [ + If(iDebug=True,Tell("xSolve52aSimple",{e1,e2,rhs,var})); + { var == rhs+e2 }; + ]; + +20 # xSolve'Simple(_e1 - _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- + [ + If(iDebug=True,Tell("xSolve52bSimple",{e1,e2,rhs,var})); + { var == e1-rhs }; + ]; + +20 # xSolve'Simple(-(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug=True,Tell("xSolve53Simple",{e1,rhs,var})); + { var == -rhs }; + ]; + +20 # xSolve'Simple(_e1 * _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- + [ + If(iDebug=True,Tell("xSolve54aSimple",{e1,e2,rhs,var})); + { var == rhs/e2 }; + ]; + +20 # xSolve'Simple(_e1 * _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- + [ + If(iDebug=True,Tell("xSolve54bSimple",{e1,e2,rhs,var})); + { var == rhs/e1 }; + ]; + +20 # xSolve'Simple(_e1 / _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- + [ + If(iDebug,Tell("xSolve55aSimple",{e1,e2,rhs,var})); + { var == rhs*e2 }; + ]; + +10 # xSolve'Simple(_e1 / _e2, 0, _var)_(e2 = var And Not HasExpr(e1,var)) <-- + [ + If(iDebug,Tell("xSolve55bSimple",{e1,e2,var})); + { }; + ]; + +20 # xSolve'Simple(_e1 / _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- + [ + If(iDebug,Tell("xSolve55cSimple",{e1,e2,rhs,var})); + { var == e1/rhs }; + ]; + +LocalSymbols(x) +[ + 20 # xSolve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsPositiveInteger(n)) <-- + [ + If(iDebug,Tell("xSolve56aSimple",{e1,n,rhs,var})); + MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. n)/n)); + ]; + + 20 # xSolve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsNegativeInteger(n)) <-- + [ + If(iDebug,Tell("xSolve56bSimple",{e1,n,rhs,var})); + MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. (-n))/(-n))); + ]; + +]; + +20 # xSolve'Simple(_e1 ^ _e2, _rhs, _var) + _ (IsPositiveReal(e1) And e1 != 0 And e2 = var And IsPositiveReal(rhs) And rhs != 0) + <-- [ + If(iDebug,Tell("xSolve57Simple",{e1,e2,rhs,var})); + { var == Ln(rhs)/Ln(e1) }; + ]; + +/* Note: These rules do not take the periodicity of the trig. functions into account */ + +10 # xSolve'Simple(Sin(_e1), 1, _var)_(e1 = var) <-- + [ + If(iDebug=True,Tell("xSolve61aSimple",{e1,var})); + { var == 1/2*Pi }; + ]; + +10 # xSolve'Simple(Sin(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- + [ + If(iDebug=True,Tell("xSolve61bSimple",{e1,rhs,var})); + { var == 3/2*Pi }; + ]; + +20 # xSolve'Simple(Sin(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug=True,Tell("xSolve61cSimple",{e1,rhs,var})); + { var == ArcSin(rhs), var == Pi-ArcSin(rhs) }; + ]; + +10 # xSolve'Simple(Cos(_e1), 1, _var)_(e1 = var) <-- + [ + If(iDebug=True,Tell("xSolve62aSimple",{e1,var})); + { var == 0 }; + ]; + +10 # xSolve'Simple(Cos(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- + [ + If(iDebug,Tell("xSolve62bSimple",{e1,rhs,var})); + { var == Pi }; + ]; + +20 # xSolve'Simple(Cos(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug,Tell("xSolve62cSimple",{e1,rhs,var})); + { var == ArcCos(rhs), var == -ArcCos(rhs) }; + ]; + +20 # xSolve'Simple(Tan(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug,Tell("xSolve63aSimple",{e1,rhs,var})); + { var == ArcTan(rhs) }; + ]; + +20 # xSolve'Simple(ArcSin(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug,Tell("xSolve63bSimple",{e1,rhs,var})); + { var == Sin(rhs) }; + ]; + +20 # xSolve'Simple(ArcCos(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug,Tell("xSolve63cSimple",{e1,rhs,var})); + { var == Cos(rhs) }; + ]; + +20 # xSolve'Simple(ArcTan(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug,Tell("xSolve63dSimple",{e1,rhs,var})); + { var == Tan(rhs) }; + ]; + +/* Note: Second rule neglects (2*I*Pi)-periodicity of Exp() */ + +10 # xSolve'Simple(Exp(_e1), 0, _var)_(e1 = var) <-- + [ + If(iDebug=True,Tell("xSolve64aSimple",{e1,var})); + { }; + ]; + +20 # xSolve'Simple(Exp(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug=True,Tell("xSolve64bSimple",{e1,rhs,var})); + { var == Ln(rhs) }; + ]; + +20 # xSolve'Simple(Ln(_e1), _rhs, _var)_(e1 = var) <-- + [ + If(iDebug=True,Tell("xSolve64cSimple",{e1,rhs,var})); + { var == Exp(rhs) }; + ]; + +/* The range of Sqrt is the set of (complex) numbers with either + * positive real part, together with the pure imaginary numbers with + * nonnegative real part. */ + +20 # xSolve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsPositiveReal(Re(rhs)) And Re(rhs) != 0) <-- + [ + If(iDebug,Tell("xSolve65aSimple",{e1,rhs,var})); + { var == rhs^2 }; + ]; + +20 # xSolve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsPositiveReal(Im(rhs))) <-- + [ + If(iDebug,Tell("xSolve65bSimple",{e1,rhs,var})); + { var == rhs^2 }; + ]; + +20 # xSolve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsNegativeReal(Im(rhs)) And Im(rhs) != 0) <-- + [ + If(iDebug,Tell("xSolve65cSimple",{e1,rhs,var})); + { }; + ]; + +20 # xSolve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsNegativeReal(Re(rhs)) And Re(rhs) != 0) <-- + [ + If(iDebug,Tell("xSolve65dSimple",{e1,rhs,var})); + { }; + ]; + +30 # xSolve'Simple(_lhs, _rhs, _var) <-- + [ + If(iDebug,Tell("xSolve66Simple_failed",{lhs,rhs,var})); + Failed; + ]; + + +/******************** xSolve'Divide ********************/ + +/* For some classes of equations, it may be easier to solve them if we + * divide through by their first term. A simple example of this is the + * equation Sin(x)+Cos(x)==0 + * One problem with this is that we may lose roots if the thing we + * are dividing by shares roots with the whole equation. + * The final HasExprs are an attempt to prevent infinite recursion caused by + * the final Simplify step in xSolve undoing what we do here. It's conceivable + * though that this won't always work if the recurring loop is more than two + * steps long. I can't think of any ways this can happen though :) + */ + +10 # xSolve'Divide(_e1 + _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) + And Not (HasExpr(Simplify(1 + (e2/e1)), e1) + Or HasExpr(Simplify(1 + (e2/e1)), e2))) <-- + [ + If(iDebug,Tell("xSolve71aDivide",{e1,e2,var})); + xSolve(1 + (e2/e1), var); + ]; + +10 # xSolve'Divide(_e1 - _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) + And Not (HasExpr(Simplify(1 - (e2/e1)), e1) + Or HasExpr(Simplify(1 - (e2/e1)), e2))) <-- + [ + If(iDebug,Tell("xSolve71bDivide",{e1,e2,var})); + xSolve(1 - (e2/e1), var); + ]; + +20 # xSolve'Divide(_e, _var) <-- + [ + If(iDebug,Tell("xSolve72Divide_failed",{e,var})); + Failed; + ]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="xSolve",categories="User Functions;Solvers (Symbolic)",access="experimental" +*CMD Solve --- solve an equation or set of linear equations +*STD +*CALL + xSolve(eq, var) + +*PARMS + +{eq} -- equation to solve, or List of equations + +{var} -- variable (or List of variables) to solve for + +*DESC + +This command tries to solve an equation or system of linear equations. +If {eq} does not contain the {==} operator, it is assumed that the user +wants to solve $eq == 0$. The result is a list of equations of the form +{var == value}, each representing a solution of the given equation or +system. The {Where} operator can be used to substitute this solution +in another expression. If the given equation or system {eq} does not +have any solutions, or if {xSolve} is unable to find any, then an +empty List is returned. + +The current implementation is far from perfect. In particular, the +user should keep the following points in mind: +* {xSolve} cannot solve all equations. If it is given a equation +it can not solve, it raises an error via {Check}. Unfortunately, this +is not displayed by the inline pretty-printer; call {PrettyPrinterSet} to +change this. If an equation cannot be solved analytically, you may +want to call {Newton} to get a numerical solution. +* Systems of linear equations are handled, but the methods have not +yet been thoroughly checked-out. Systems with one or more non-linear +equations are not handled yet. The old version of {Solve}, with the name +{OldSolve} might be able to solve some nonlinear systems of equations. +* The periodicity of the trigonometric functions {Sin}, {Cos}, +and {Tan} is not taken into account. The same goes for the (imaginary) +periodicity of {Exp}. This causes {xSolve} to miss solutions. +* It is assumed that all denominators are nonzero. Hence, a +solution reported by {xSolve} may in fact fail to be a solution because +a denominator vanishes. The function {xCheckSolution} should be +able to eliminate these false "solutions". +* In general, it is wise not to have blind trust in the results +returned by {xSolve}. A good strategy is to substitute the solutions +back in the equation. + +*E.G. notest + +First a simple example, where everything works as it should. The +quadratic equation $x^2 + x == 0$ is solved. Then the result is +checked by substituting it back in the quadratic. + +In> quadratic := x^2+x; +Result: x^2+x; +In> xSolve(quadratic, x); +Result: {x==0,x==(-1)}; +In> quadratic Where %; +Result: {0,0}; + +If one tries to solve the equation $Exp(x) == Sin(x)$, one finds that +{xSolve} can not do this. + +In> PrettyPrinterSet("DefaultPrint"); +Result: True; +In> xSolve(Exp(x) == Sin(x), x); + Error: Solve'Fails: cannot solve equation Exp(x)-Sin(x) for x +Result: {}; + +The equation $Cos(x) == 1/2$ has an infinite number of solutions, +namely $x == (2*k + 1/3) * Pi$ and $x == (2*k - 1/3) * Pi$ for any +integer $k$. However, {xSolve} only reports the solutions with +$k == 0$. + +In> xSolve(Cos(x) == 1/2, x); +Result: {x==Pi/3,x== -Pi/3}; + +For the equation $x/Sin(x) == 0$, a spurious solution at $x == 0$ is +returned. However, the fraction is undefined at that point. + +In> xSolve(x / Sin(x) == 0, x); +Result: {x==0}; + +At first sight, the equation $Sqrt(x) == a$ seems to have the solution +$x == a^2$. However, this is not true for eg. $a == -1$. + +In> PrettyPrinterSet("DefaultPrint"); +Result: True; +In> xSolve(Sqrt(x) == a, x); + Error: Solve'Fails: cannot solve equation Sqrt(x)-a for x +Result: {}; +In> xSolve(Sqrt(x) == 2, x); +Result: {x==4}; +In> xSolve(Sqrt(x) == -1, x); +Result: {}; + +*SEE Check, MatrixSolve, Newton, OldSolve, PrettyPrinterSet, PSolve, xCheckSolution, Where, == +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolvePoly.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolvePoly.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolvePoly.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolvePoly.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,92 @@ +%mathpiper,title="xSolvePoly" + +//Retract("xSolve'Poly",*); + +/******************** xSolve'Poly ********************/ + +/* Tries to solve by calling PSolve */ +/* Returns Failed if this doesn't work, and the solution otherwise */ + +/* CanBeUni is not documented, but defined in univar.rep/code.mpi */ +/* It returns True iff 'expr' is or can be considered to be a univariate polynomial in 'var' */ + +10 # xSolve'Poly(_expr, _var)_(Not CanBeUni(var, expr)) <-- + [ + If(iDebug=True,Tell("xSolvePoly_NoUni",{expr,var})); + Failed; + ]; + + +20 # xSolve'Poly(_expr, _var) <-- + LocalSymbols(x) + [ + If(iDebug=True,Tell("xSolvePoly_Uni_F",{expr,var})); + Local(factors,nfactors,roots); + factors := Factors(expr); + nfactors := Length(factors); + If(iDebug=True,Tell(" sp1",{nfactors,factors})); + roots := {}; + ForEach(factor,factors) + If(Contains(VarList(factor[1]),var), + [ + Local(rs,r); + rs := PSolve(factor[1],var); + If(iDebug=True,Tell(" sp2",rs)); + If( Type(rs)="List", + ForEach(r,rs) Push(roots,r), + Push(roots,rs) + ); + ] + ); + If(iDebug=True,Tell(" sp3",roots)); + Local(result); + If(Type(roots) = "List", + [ + If(iDebug=True,Tell(" sp4_is_list",Length(roots))); + If(Length(roots) > 1, + [Tell(" >1"); result := MapSingle({{t},var==t}, roots);], + If( Type(roots[1]) = "List", + [Tell(" List"); result := MapSingle({{t},var==t}, roots[1]);], + [Tell(" Not List"); result := {var == roots[1]};] + ) + ); + ], + [ + If(iDebug=True,Tell(" sp4_not_list")); + result := {var == roots}; + ] + ); + result; + ]; + + +/* + * The call to PSolve (below) can have three kind of results + * 1) PSolve returns a single root + * 2) PSolve returns a list of roots + * 3) PSolve remains unevaluated + */ + +30 # xSolve'Poly(_expr, _var) <-- + LocalSymbols(x) + [ + If(iDebug=True,Tell("xSolvePoly_Uni_P",{expr,var})); + Local(roots); + roots := PSolve(expr, var); + If(Type(roots) = "PSolve", + Failed, /* Case 3 */ + If(Type(roots) = "List", + MapSingle({{x},var==x}, roots), /* Case 2 */ + {var == roots}) /* Case 1 */ + ); + ]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveRational.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveRational.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveRational.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveRational.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,title="xSolve'Rational" + +//Retract("xSolve'Rational",*); + +/************************* xSolve'Rational *************************/ +/* + * This expression is a rational function of its variable. + * Try to solve it with the help of that information. + */ + + +10 # xSolve'Rational( _expr, _var )_(IsRationalFunction(expr,var)) <-- +[ + If(iDebug=True,Tell(" Rational",expr==0)); + Local(n,d,fn,fd,factor,rootsn,rootsd,root,result); + n := Numerator(expr); + d := Denominator(expr); + If(iDebug=True,Tell(" 1",{n,d})); + fn := Factors(n); + fd := Factors(d); + If(iDebug=True,Tell(" 2",{fn,fd})); + rootsn := {}; + rootsd := {}; + result := {}; + ForEach(factor,fn) + If(Contains(VarList(factor[1]),var), Push(rootsn,PSolve(factor[1],var))); + ForEach(factor,fd) + If(Contains(VarList(factor[1]),var), Push(rootsd,PSolve(factor[1],var))); + If(iDebug=True,Tell(" 3",{rootsn,rootsd})); + + ForEach(root,rootsn) + [ + If(iDebug=True,Tell(" 4",root)); + If(Not Contains(rootsd,root),Push(result,root)); + If(iDebug=True,Tell(" 5",result)); + ]; + If(iDebug=True,Tell(" 6",result)); + If( Length(result)=0,result:={},MapSingle({{t},var==t}, result)); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveReduce.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveReduce.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveReduce.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveReduce.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,126 @@ +%mathpiper,title="xSolveReduce" + +//Retract("xSolve'Reduce",*); +//Retract("xSolve'Context",*); + +/***************************** xSolve'Reduce *****************************/ + +/* + * Tries to solve by reduction strategy, calling xSolve'Context(); + * Returns Failed if this doesn't work, and the solution otherwise +*/ + +10 # xSolve'Reduce(_expr, _var) <-- + [ + If(iDebug,Tell("xSolveReduce",{expr,var})); + ClearError("Solve'Fails"); // in case left-over from previous failure! + Local(context, expr2, var2, res, sol, sol2, i); + context := xSolve'Context(expr, var); + If(iDebug,Tell(" xSolveReduce",context)); + If(context = False, + [ + If(iDebug,Tell(" 31bReduce",expr)); + res := Failed; + ], + [ + expr2 := Eval(Subst(context, var2) expr); + If(iDebug,Tell(" 31cReduce",expr2)); + If(CanBeUni(var2, expr2) And (Degree(expr2, var2) = 0 Or (Degree(expr2, var2) = 1 And Coef(expr2, var2, 1) = 1)), + [ + If(iDebug=True, + [ + Tell(" 31dReduce",expr2); + Tell(" 31eReduce -- Quitting to avoid infinite recursion",Degree(expr2,var2)); + ] + ); + res := Failed; // to prevent infinite recursion + ], + [ + //Tell(" 31XReduce",GetErrorTableau()); + sol2 := Solve(expr2, var2); + If(iDebug,Tell(" 31fReduce",sol2)); + If(IsError("Solve'Fails"), + [ + If(iDebug,Tell(" 31gReduce_error")); + ClearError("Solve'Fails"); + res := Failed; + ], + [ + If(iDebug,Tell(" 31hReduce",sol2)); + res := {}; + i := 1; + While(i <= Length(sol2) And res != Failed) + [ + sol := Solve(context == (var2 Where sol2[i]), var); + If(iDebug,Tell(" 31iReduce",{i,sol})); + If(IsError("Solve'Fails"), + [ + ClearError("Solve'Fails"); + res := Failed; + ], + res := Union(res, sol) + ); + i++; + ]; + If(iDebug,Tell(" 31jReduce",{sol1,sol2,res})); + ] + ); + ] + ); + ] + ); + res; + ]; + + + +/******************** xSolve'Context ********************/ + +/* + * Returns the unique context of 'var' in 'expr', + * or {} if 'var' does not occur in 'expr', + * or False if the context is not unique. + */ + +10 # xSolve'Context(expr_IsAtom, _var) <-- + [ + If(iDebug,Tell("xSolveContext",{expr,var})); + If(expr=var, var, {}); + ]; + +20 # xSolve'Context(_expr, _var) <-- + [ + If(iDebug,Tell("xSolveContext",{expr,var})); + Local(lst, foundVarP, context, i, res); + lst := FunctionToList(expr); + If(iDebug,Tell(" 42aContext",lst)); + foundVarP := False; + i := 2; + While(i <= Length(lst) And Not foundVarP) [ + foundVarP := (lst[i] = var); + i++; + ]; + If(iDebug,Tell(" 42bContext",{foundVarP,expr})); + If(foundVarP, + [ + context := expr; + If(iDebug,Tell(" 42cContext_found",{foundVarP,context})); + ], + [ + context := {}; + i := 2; + While(i <= Length(lst) And context != False) [ + res := xSolve'Context(lst[i], var); + If(res != {} And context != {} And res != context, [context := False;If(iDebug,Tell(" 42caContext",res));]); + If(res != {} And context = {}, [context := res;If(iDebug,Tell(" 42cbContext",context));]); + i++; + ]; + If(iDebug,Tell(" 42dContext_solved",{i,context})); + ] + ); + context; + ]; + +%/mathpiper + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSqrts.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSqrts.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSqrts.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSqrts.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,115 @@ +%mathpiper,title="xSolveSqrts" + +//Retract("xSolve'Sqrts",*); + + +/************************* xSolve'Sqrts *************************/ + +/* + * To get here, the user had to have called with something + * like xSolve(Sqrt(_expr1) - _expr2,_var) where expr1 is a + * function of var, and expr2 can be anything. Depending on the + * nature of expr2, appropriate sub-functions will be invoked. + */ + + 10 # xSolve'Sqrts(_expr1,_expr2,_var)_(Contains(VarList(expr1),var) + And Not Contains(VarList(expr2),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts - no var",{expr1,expr2,var})); + Local(vars2,result); + vars2 := VarList(expr2); + If(iDebug=True,Tell(" 1",vars2)); + result := xSolve(expr1-expr2^2,var); + If(iDebug=True,Tell(" 2",result)); + Echo("HERE -- calling CheckSolution with Sqrt(",expr1,")-",expr2," and ",var," and ",result); + CheckSolution(Sqrt(expr1)-expr2,var,result); + ]; + + 10 # xSolve'Sqrts(_expr1,const_IsConstant*_var,_var)_(Contains(VarList(expr1),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts - c*var",{expr1,const,var})); + Local(rhs,result); + rhs := const*var; + If(iDebug=True,Tell(" 3",rhs)); + result := xSolve(expr1-rhs^2,var); + If(iDebug=True,Tell(" 4",result)); + CheckSolution(Sqrt(expr1)-rhs,var,result); + ]; + + 10 # xSolve'Sqrts(_expr1,-const_IsConstant*_var,_var)_(Contains(VarList(expr1),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts + c*var",{expr1,const,var})); + Local(rhs,result); + rhs := -const*var; + If(iDebug=True,Tell(" 5",rhs)); + result := xSolve(expr1-rhs^2,var); + If(iDebug=True,Tell(" 6",result)); + CheckSolution(Sqrt(expr1)-rhs,var,result); + ]; + + 10 # xSolve'Sqrts(_expr1,_var,_var)_(Contains(VarList(expr1),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts - var",{expr1,const,var})); + Local(rhs,result); + rhs := var; + If(iDebug=True,Tell(" 7",rhs)); + result := xSolve(expr1-rhs^2,var); + If(iDebug=True,Tell(" 8",result)); + CheckSolution(Sqrt(expr1)-rhs,var,result); + ]; + + 10 # xSolve'Sqrts(_expr1,-_var,_var)_(Contains(VarList(expr1),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts + var",{expr1,const,var})); + Local(rhs,result); + rhs := -var; + If(iDebug=True,Tell(" 9",rhs)); + result := xSolve(expr1-rhs^2,var); + If(iDebug=True,Tell(" 10",result)); + CheckSolution(Sqrt(expr1)-rhs,var,result); + ]; + + 10 # xSolve'Sqrts(_expr1,_expr1,_var)_(Contains(VarList(expr1),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts -expr1",{expr1,var})); + Local(rhs,result); + rhs := expr1; + If(iDebug=True,Tell(" 11",rhs)); + result := xSolve(Simplify(expr1-rhs^2),var); + If(iDebug=True,Tell(" 12",result)); + CheckSolution(Sqrt(expr1)-rhs,var,result); + ]; + + 10 # xSolve'Sqrts(_expr1,-_expr1,_var)_(Contains(VarList(expr1),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts +expr1",{expr1,var})); + Local(rhs,result); + rhs := expr1; + If(iDebug=True,Tell(" 13",rhs)); + result := xSolve(Simplify(expr1-rhs^2),var); + If(iDebug=True,Tell(" 14",result)); + CheckSolution(Sqrt(expr1)-rhs,var,result); + ]; + +10 # xSolve'Sqrts(_expr1,_expr2,_var)_(Contains(VarList(expr2),var)) <-- + [ + If(iDebug=True,Tell("xSolve'Sqrts xx",{expr1,expr2,var})); + Local(rhs,result); + rhs := expr2; + If(iDebug=True,Tell(" 15",rhs)); + result := xSolve(Simplify(expr1-rhs^2),var); + If(iDebug=True,Tell(" 16",result)); + CheckSolution(Sqrt(expr1)-rhs,var,result); + ]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + %output,preserve="false" + Processing... +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSystem.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSystem.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSystem.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xSolveSystem.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,86 @@ +%mathpiper,title="xSolveSystem" + +//Retract("xSolve'System",*); +//Retract("xSolveLinearSystemViaMatrix",*); + + +10 # xSolve'System( eqns_IsList, vars_IsList ) <-- +[ + If(iDebug=True,Tell("xSolve'System",{eqns,vars})); + Local(zeros,expr,const,newEquations); + zeros := FillList(0,Length(vars)); + newEquations := {}; + ForEach(eqn,eqns) + [ + expr := EquationLeft(eqn) - EquationRight(eqn); + //If(iDebug,Tell(" 1",expr)); + const := WithValue(vars,zeros,expr); + //Echo(" eqn: ",eqn," , const term: ",const); + Push(newEquations,Simplify(expr - const)==-const); + ForEach(var,vars) + [ + deg := Degree(expr,var); + //Echo(" var = ",var," : degree: ",deg);); + ]; + ]; + newEquations := Reverse(newEquations); + xSolveLinearSystemViaMatrix(newEquations,vars); +]; + +10 # xSolve'System( eqns_IsList ) <-- +[ + Local(vars); + If(iDebug=True,Tell("xSolve'System",eqns)); + vars := VarList(eqns); + xSolve'System(eqns,vars); +]; + + +10 # xSolveLinearSystemViaMatrix( eqns_IsList, vars_IsList ) <-- +[ + Local(LE,LV,E,LHS,X,M,RHS,LL,eqn,row,ans,Det); + If(iDebug=True,Tell(xSolveLinearSystemViaMatrix,{eqns,vars})); + LE := Length(eqns); + LV := Length(vars); + E := Assert() LE=LV; + Check(E, "Argument", "Number of equations != Number of variables"); + + LHS := {}; + RHS := {}; + X := vars; + M := FillList(1,LE); + ForEach(eqn,eqns) + [ + //If(iDebug,[Echo(EquationLeft(eqn)); Echo(EquationRight(eqn));]); + E := FunctionToList(eqn); + LL := E[2]; + RHS := E[3]:RHS; + row := Map("Coef",{FillList(LL,LE),X,M}); + LHS := row:LHS; + ]; + LHS := DestructiveReverse(LHS); + RHS := DestructiveReverse(RHS); + Det := Determinant(LHS); + /* + If(iDebug=True, + [ + Tell(" LHS",LHS); + Tell(" RHS",RHS); + Tell(" det",Det); + ] + ); + */ + ans := MatrixSolve(LHS,RHS); + //If(iDebug=True,Tell("ans ",ans)); + ans := Map("==",{vars,ans}); +]; + +12 # xSolveLinearSystemViaMatrix( _eqns, _vars ) <-- False; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xTerms.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xTerms.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/proposed/xSolve/xTerms.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/proposed/xSolve/xTerms.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,78 @@ +%mathpiper,title="xTerms" + +//Retract("xTerms",*); +//Retract("xTerms2",*); + +xTerms(_expr) <-- +[ + Local(L,n,h,s,t,f,stack,qs,topLevelPM,nTerms,firstH); + If( InVerboseMode(),[ Echo("in xTerms()"); Echo(" input expression: ",expr); ]); + If( Not IsList( stack ), stack := {} ); + topLevelPM := 0; + firstH := 0; + qs := 1; + f := expr; + + While( IsFunction(f) ) + [ + L := FunctionToList(f); + n := Length(L); + h := Head( L ); + If(h=ToAtom("+") Or h=ToAtom("-"),[If(firstH=0,firstH=1);topLevelPM++;]); + If(InVerboseMode(),Echo(" f=",f," n=",n," L=",L," h=",h," firstH=",firstH," tlpm=",topLevelPM)); + If (n=3, + [ + If( h=ToAtom("-"), s:=-1, s:=1 ); + t := s * L[3]; + If(InVerboseMode(),Echo(" t= ",t)); + If( (h=ToAtom("*") Or h=ToAtom("/") Or h=ToAtom("^")), Push(stack,f), Push(stack,t) ); + f := L[2]; + If(InVerboseMode(), [ + Echo(" new f=",f); + Echo(" stack=",stack); ] + ); + ], + [ + If( h=ToAtom("-"),[f:=L[2];qs:=-1;], + [ + Push(stack,ListToFunction(L)); + If( InVerboseMode(), [ + Echo(" n=",n," L=",L," h=",h); + Echo("DONE"); + Echo("|---> ",stack," <---|"); ] + ); + f:="STOP"; + ] + ); + ] + ); + ]; + If( (Not IsFunction(f)) And (Length(stack)=0), stack := {f}); + stack := qs * stack; + If(qs>0,nTerms:=topLevelPM+1,nTerms:=topLevelPM); + If(InVerboseMode(),Echo("========================== stack = ",stack)); + If( nTerms > Length(stack), Echo(" >>>> RESULT should be one term longer")); + //If(firstH != ToAtom("+") And firstH != ToAtom("-") And tlpm >0,Echo(" >>>> RESULT should be one term shorter")); + stack; +]; + +UnFence( "xTerms", 1 ); + +xTerms2(_expr) <-- +[ + Local(L,stack,result,lenL); + If(InVerboseMode(),[ Tell("in xTerms2()"); Tell(" input expression: ",expr); ]); + If( Not IsList( stack ), stack := {} ); + If( IsAtom(expr), L:={expr}, L:=FunctionToList(expr) ); + lenL := Length(L); + If(InVerboseMode(), Tell(" 0",{L,lenL}) ); + If( lenL = 1, [ stack := L:stack; Tell(" 1",stack); ] ); + If( lenL = 2, [ stack := L[1]:L[2]:stack; Tell(" 2",stack); ] ); + If( lenL = 3, [ stack := L[1]:L[2]:L[3]:stack; Tell(" 3",stack); ] ); + + result := stack; +]; + +UnFence( "xTerms2", 1 ); + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/pslq/Pslq.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/pslq/Pslq.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/pslq/Pslq.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/pslq/Pslq.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,368 @@ +%mathpiper,def="Pslq" + +/*********************************************************************************************# +# The PSLQ Integer Relation Algorithm # +# # +# Aut.: Helaman R.P. Ferguson and David Bailey "A Polynomial Time, Numerically Stable # +# Integer Relation Algorithm" (RNR Technical Report RNR-92-032) helaman@super.org # +# Ref.: David Bailey and Simon Plouffe "Recognizing Numerical Constants" dbailey@nas.nasa.gov # +# Cod.: Raymond Manzoni raymman@club-internet.fr # +#*********************************************************************************************# +# Creation:97/11 # +# New termination criteria:97/12/15 # +# this code is free... # + +Ported to MathPiper 2000 Ayal Pinkus. + +Given a list of constants x find coefficients sol[i] such that + sum(sol[i]*x[i], i=1..n) = 0 (where n=Length(x)) + + x is the list of real expressions + N(x[i]) must evaluate to floating point numbers! + precision is the number of digits needed for completion; + must be greater or equal to log10(max(sol[i]))*n + returns the list of solutions with initial precision + and the confidence (the lower the better) + + Example: + + In> Pslq({2*Pi-4*Exp(1),Pi,Exp(1)},20) + Result: {1,-2,4}; + +*/ + +Pslq(x, precision) := +[ + Local (ndigits, gam, A, B, H, n, i, j, k, s, y, tmp, t, m, maxi, gami, + t0, t1, t2, t3, t4, mini, Confidence, norme,result); + n:=Length(x); + ndigits:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(precision+10); // 10 is chosen arbitrarily, but should always be enough. Perhaps we can optimize by lowering this number + Confidence:=10^(-FloorN(N(Eval(precision/3)))); +//Echo("Confidence is ",Confidence); + + gam:=N(Sqrt(4/3)); + For (i:=1, i<=n,i++) x[i]:=N(Eval(x[i])); + +//Echo("1..."); + + A:=Identity(n); /*A and B are of Integer type*/ + B:=Identity(n); /*but this doesn't speed up*/ + s:=ZeroVector(n); + y:=ZeroVector(n); + +//Echo("2..."); + + For(k:=1,k<=n,k++) + [ + tmp:=0; + For (j:=k,j<=n,j++) tmp:=tmp + N(x[j]^2); +//tmp:=DivideN(tmp,1.0); +//Echo("tmp is ",tmp); +//MathDebugInfo(tmp); +/*If(Not IsPositiveNumber(tmp), + Echo("******** not a positive number: ",tmp) +); +If(Not IsNumber(tmp), + Echo("******** not a number: ",tmp) +); +If(IsLessThan(tmp,0), +[ + Echo("******** not positive: ",tmp); +] +);*/ + + s[k]:=SqrtN(tmp); + + +/*If(Not IsNumber(tmp), +[ +Echo("************** tmp = ",tmp); +]); +If(Not IsNumber(s[k]), +[ +Echo("************** s[k] = ",s[k]); +]);*/ + + ]; + +//Echo("3..."); + + tmp:=N(Eval(s[1])); +/*If(Not IsNumber(tmp), +[ +Echo("************** tmp = ",tmp); +]);*/ + + For (k:= 1,k<= n,k++) + [ + y[k]:=N(Eval(x[k]/tmp)); + s[k]:=N(Eval(s[k]/tmp)); + +//Echo("1..."," ",y[k]," ",s[k]); +/*If(Not IsNumber(y[k]), +[ +Echo("************** y[k] = ",y[k]); +]); +If(Not IsNumber(s[k]), +[ +Echo("************** s[k] = ",s[k]); +]);*/ + + ]; + H:=ZeroMatrix(n, n-1); + +//Echo("4...",n); + For (i:=1,i<= n,i++) + [ + + if (i <= n-1) [ H[i][i]:=N(s[i + 1]/s[i]); ]; + +//Echo("4.1..."); + For (j:= 1,j<=i-1,j++) + [ +//Echo("4.2..."); + H[i][j]:= N(-(y[i]*y[j])/(s[j]*s[j + 1])); +//Echo("4.3..."); + +/*If(Not IsNumber(H[i][j]), +[ +Echo("************** H[i][j] = ",H[i][j]); +] +);*/ + + ]; + ]; + +//Echo("5..."); + + For (i:=2,i<=n,i++) + [ + For (j:=i-1,j>= 1,j--) + [ +//Echo("5.1..."); + t:=Round(H[i][j]/H[j][j]); +//Echo("5.2..."); + y[j]:=y[j] + t*y[i]; +//Echo("2..."," ",y[j]); + For (k:=1,k<=j,k++) [ H[i][k]:=H[i][k]-t*H[j][k]; ]; + For (k:=1,k<=n,k++) + [ + A[i][k]:=A[i][k]-t*A[j][k]; + B[k][j]:=B[k][j] + t*B[k][i]; + ]; + ]; + ]; + Local(found); + found:=False; + +//Echo("Enter loop"); + + While (Not(found)) + [ + m:=1; +//Echo("maxi 1...",maxi); + maxi:=N(gam*Abs(H[1][1])); +//Echo("maxi 2...",maxi); + gami:=gam; +//Echo("3..."); + For (i:= 2,i<= n-1,i++) + [ + gami:=gami*gam; + tmp:=N(gami*Abs(H[i][i])); + if (maxi < tmp) + [ + maxi:=tmp; +//Echo("maxi 3...",maxi); + m:=i; + ]; + ]; +//Echo("4...",maxi); + tmp:=y[m + 1]; + y[m + 1]:=y[m]; + y[m]:=tmp; +//Echo("3..."," ",y[m]); +//Echo("5..."); + For (i:= 1,i<=n,i++) + [ + tmp:=A[m + 1][ i]; + A[m + 1][ i]:=A[m][ i]; + A[m][ i]:=tmp; + tmp:=B[i][ m + 1]; + B[i][ m + 1]:=B[i][ m]; + B[i][ m]:=tmp; + ]; + For (i:=1,i<=n-1,i++) + [ + tmp:=H[m + 1][ i]; + + H[m + 1][ i]:=H[m][ i]; + H[m][ i]:=tmp; + ]; +//Echo("7..."); + if (m < n-1) + [ + t0:=N(Eval(Sqrt(H[m][ m]^2 + H[m][ m + 1]^2))); + + t1:=H[m][ m]/t0; + t2:=H[m][ m + 1]/t0; + +// If(IsZero(t0),t0:=N(Confidence)); +//Echo(""); +//Echo("H[m][ m] = ",N(H[m][ m])); +//Echo("H[m][ m+1] = ",N(H[m][ m+1])); + +//If(IsZero(t0),[t1:=Infinity;t2:=Infinity;]); +//Echo("t0=",N(t0)); +//Echo("t1=",N(t1)); +//Echo("t2=",N(t2)); + + For (i:=m,i<=n,i++) + [ + t3:=H[i][ m]; + t4:=H[i][ m + 1]; +//Echo(" t1 = ",t1); +//Echo(" t2 = ",t2); +//Echo(" t3 = ",t3); +//Echo(" t4 = ",t4); + H[i][ m]:=t1*t3 + t2*t4; +//Echo("7.1... ",H[i][ m]); + H[i][ m + 1]:= -t2*t3 + t1*t4; +//Echo("7.2... ",H[i][ m+1]); + ]; + ]; +//Echo("8..."); + For (i:= 1,i<= n,i++) + [ + For (j := Minimum(i-1, m + 1),j>= 1,j--) + [ + t:=Round(H[i][ j]/H[j][ j]); +//Echo("MATRIX",H[i][ j]," ",H[j][ j]); +//Echo("5... before"," ",y[j]," ",t," ",y[i]); + y[j]:=y[j] + t*y[i]; +//Echo("5... after"," ",y[j]); + For (k:=1,k<=j,k++) H[i][ k]:=H[i][ k]-t*H[j][ k]; + For (k:= 1,k<=n,k++) + [ + A[i][ k]:=A[i][ k]-t*A[j][ k]; + B[k][ j]:=B[k][ j] + t*B[k][ i]; + ]; + ]; + ]; +//Echo("9...",N(H[1],10)); + + /* BuiltinPrecisionSet(10);*/ /*low precision*/ +// maxi := N(Dot(H[1], H[1]),10); + maxi := N(Dot(H[1], H[1])); +//Echo("H[1] = ",H[1]); +//Echo("N(H[1]) = ",N(H[1])); +//Echo("N(Dot(H[1], H[1])) = ",N(Dot(H[1], H[1]))); +//Echo("maxi 4...",maxi); + +//Echo("9... maxi = ",maxi); + + For (j:=2,j<=n,j++) + [ +//Echo("9.1..."); + tmp:=N(Dot(H[j], H[j]),10); +//Echo("9.2..."); + if (maxi < tmp) [ maxi:=tmp; ]; +//Echo("maxi 5...",maxi); +//Echo("9.3..."); + ]; +//Echo("10..."); + norme:=N(Eval(1/Sqrt(maxi))); + m:=1; + mini:=N(Eval(Abs(y[1]))); +//Echo("y[1] = ",y[1]," mini = ",mini); + maxi:=mini; + +//Echo("maxi 6...",maxi); +//Echo("11..."); + For (j:=2,j<=n,j++) + [ + tmp:=N(Eval(Abs(y[j]))); + if (tmp < mini) + [ + mini:=tmp; + m:=j; + ]; + if (tmp > maxi) [ maxi:=tmp; ]; +//Echo("maxi 7...",maxi); + ]; + /* following line may be commented */ +//Echo({"Norm bound:",norme," Min=",mini," Conf=",mini/maxi," required ",Confidence}); + if ((mini/maxi) < Confidence) /*prefered to : if mini < 10^(- precision) then*/ + [ + /* following line may be commented */ +/* Echo({"Found with Confidence ",mini/maxi}); */ + BuiltinPrecisionSet(ndigits); + result:=Transpose(B)[m]; + found:=True; + ] + else + [ + maxi:=Abs(A[1][ 1]); + For (i:=1,i<=n,i++) + [ +//Echo("i = ",i," n = ",n); + For (j:=1,j<=n,j++) + [ +//Echo("j = ",j," n = ",n); + tmp:=Abs(A[i][ j]); + if (maxi < tmp) [ maxi:=tmp;]; + ]; + ]; +//Echo("maxi = ",maxi); + if (maxi > 10^(precision)) + [ + BuiltinPrecisionSet(ndigits); + result:=Fail; + found:=True; + ]; + BuiltinPrecisionSet(precision+2); +//Echo("CLOSE"); + ]; + ]; + result; +]; + +/* end of file */ + +%/mathpiper + + + +%mathpiper_docs,name="Pslq",categories="User Functions;Numbers (Operations)" +*CMD Pslq --- search for integer relations between reals +*STD +*CALL + Pslq(xlist,precision) + +*PARMS + +{xlist} -- list of numbers + +{precision} -- required number of digits precision of calculation + +*DESC + +This function is an integer relation detection algorithm. This means +that, given the numbers $x[i]$ in the list "xlist", it tries +to find integer coefficients $a[i]$ such that +$a[1]*x[1]$ + ... + $a[n]*x[n] = 0$. +The list of integer coefficients is returned. + +The numbers in "xlist" must evaluate to floating point numbers if +the {N} operator is applied on them. + +*E.G. + +In> Pslq({ 2*Pi+3*Exp(1), Pi, Exp(1) },20) +Result: {1,-2,-3}; + +Note: in this example the system detects correctly that +$1 * (2*Pi+3*e) + (-2) * Pi + (-3) * e = 0$. + +*SEE N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/rabinmiller/RabinMiller.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/rabinmiller/RabinMiller.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/rabinmiller/RabinMiller.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/rabinmiller/RabinMiller.mpw 2010-08-06 22:44:03.000000000 +0000 @@ -0,0 +1,185 @@ +%mathpiper,def="RabinMiller" + +/* + * File `rabinmiller.mpi' is an implementation of the + * Rabin-Miller primality test. + */ + + +/* + * FastModularPower(a, b, n) computes a^b (mod n) efficiently. + * This function is called by IsStronglyProbablyPrime. + */ + +FastModularPower(a_IsPositiveInteger, b_IsPositiveInteger, n_IsPositiveInteger) <-- +[ + Local(p, j, r); + p := a; + j := b; + r := 1; + + While (j > 0) + [ + If (IsOdd(j), r := ModuloN(r*p, n)); + p := ModuloN(p*p, n); + j := ShiftRight(j, 1); + ]; + r; +]; + + +/* + * An integer n is `strongly-probably-prime' for base b if + * + * b^q = 1 (mod n) or + * b^(q*2^i) = -1 (mod n) for some i such that 0 <= i < r + * + * where q and r are such that n-1 = q*2^r and q is odd. + * + * If an integer is not strongly-probably-prime for a given + * base b, then it is composed. The reciprocal is false. + * Composed strongly-probably-prime numbers for base b + * are called `strong pseudoprimes' for base b. + */ +// this will return a pair {root, True/False} +IsStronglyProbablyPrime(b_IsPositiveInteger, n_IsPositiveInteger) <-- +[ + Local(m, q, r, a, flag, i, root); + m := n-1; + q := m; + r := 0; + root := 0; // will be the default return value of the "root" + While (IsEven(q)) + [ + q := ShiftRight(q, 1); + r++; + ]; + + a := FastModularPower(b, q, n); + flag := (a = 1 Or a = m); + i := 1; + + While (Not(flag) And (i < r)) + [ + root := a; // this is the value of the root if flag becomes true now + a := ModuloN(a*a, n); + flag := (a = m); + i++; + ]; + + {root, flag}; // return a root of -1 (or 0 if not found) +]; + + +/* + * For numbers less than 3.4e14, exhaustive computations have + * shown that there is no strong pseudoprime simultaneously for + * bases 2, 3, 5, 7, 11, 13 and 17. + * Function RabinMillerSmall is based on the results of these + * computations. + */ + +10 # RabinMillerSmall(1) <-- False; + +10 # RabinMillerSmall(2) <-- True; + +20 # RabinMillerSmall(n_IsEven) <-- False; + +20 # RabinMillerSmall(3) <-- True; + +30 # RabinMillerSmall(n_IsPositiveInteger) <-- +[ + Local(continue, prime, i, primetable, pseudotable, root); + continue := True; + prime := True; + i := 1; + primetable := {2, 3, 5, 7, 11, 13, 17}; + pseudotable := {2047, 1373653, 25326001, 3215031751, 2152302898747, + 3474749660383, 34155071728321}; + // if n is strongly probably prime for all bases up to and including primetable[i], then n is actually prime unless it is >= pseudotable[i]. + While (continue And prime And (i < 8)) + [ // we do not really need to collect the information about roots of -1 here, so we do not do anything with root + {root, prime} := IsStronglyProbablyPrime(primetable[i], n); + //If(InVerboseMode() And prime, Echo("RabinMiller: Info: ", n, "is spp base", primetable[i])); + continue := (n >= pseudotable[i]); + i++; + ]; + // the function returns "Overflow" when we failed to check (i.e. the number n was too large) + If (continue And (i = 8), Overflow, prime); +]; + + +/* + * RabinMillerProbabilistic(n, p) tells whether n is prime. + * If n is actually prime, the result will always be `True'. + * If n is composed the probability to obtain the wrong + * result is less than 4^(-p). + */ +// these 4 rules are not really used now because RabinMillerProbabilistic is only called for large enough n +10 # RabinMillerProbabilistic(1, _p) <-- False; + +10 # RabinMillerProbabilistic(2, _p) <-- True; + +20 # RabinMillerProbabilistic(n_IsEven, _p) <-- False; + +20 # RabinMillerProbabilistic(3, _p) <-- True; + +30 # RabinMillerProbabilistic(n_IsPositiveInteger, p_IsPositiveInteger) <-- +[ + Local(k, prime, b, roots'of'minus1, root); + k := 1+IntLog(IntLog(n,2),4)+p; // find k such that Ln(n)*4^(-k) < 4^(-p) + b := 1; + prime := True; + roots'of'minus1 := {0}; // accumulate the set of roots of -1 modulo n + While (prime And k>0) + [ + b := NextPseudoPrime(b); // use only prime bases, as suggested by Davenport; weak pseudo-primes are good enough + {root, prime} := IsStronglyProbablyPrime(b, n); + If(prime, roots'of'minus1 := Union(roots'of'minus1, {root})); + If(Length(roots'of'minus1)>3, prime := False); + //If(InVerboseMode() And prime, Echo("RabinMiller: Info: ", n, "is spp base", b)); + If( // this whole If() clause is only working when InVerboseMode() is in effect and the test is terminated in the unusual way + InVerboseMode() And Length(roots'of'minus1)>3, + [ // we can actually find a factor of n now + Local(factor); + roots'of'minus1 := Difference(roots'of'minus1,{0}); + //Echo("RabinMiller: Info: ", n, "is composite via roots of -1 ; ", roots'of'minus1); + factor := Gcd(n, If( + roots'of'minus1[1]+roots'of'minus1[2]=n, + roots'of'minus1[1]+roots'of'minus1[3], + roots'of'minus1[1]+roots'of'minus1[2] + )); + Echo(n, " = ", factor, " * ", n/factor); + ] + ); + k--; + ]; + prime; +]; + + +/* + * This is the frontend function, which uses RabinMillerSmall for + * ``small'' numbers and RabinMillerProbabilistic for bigger ones. + * + * The probability to err is set to 1e-25, hopeing this is less + * than the one to step on a rattlesnake in northern Groenland. :-) + */ + +RabinMiller(n_IsPositiveInteger) <-- +[ + //If(InVerboseMode(), Echo("RabinMiller: Info: Testing ", n)); + If( + n < 34155071728321, + RabinMillerSmall(n), + RabinMillerProbabilistic(n, 40) // 4^(-40) + ); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/radsimp/RadSimp.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/radsimp/RadSimp.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/radsimp/RadSimp.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/radsimp/RadSimp.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,129 @@ +%mathpiper,def="RadSimp" + +//Retract("RadSimp",*); + +/* Simplification of nested radicals. +*/ + +10 # RadSimp(_n)_(Length(VarList(n))<1) <-- +[ + Local(max, result); + Bind(max, CeilN(N(Eval(n^2)))); + Bind(result,0); + Bind(result,RadSimpTry(n,0,1,max)); + +//Echo("result is ",result); + if (CheckRadicals(n,result)) + result + else + n; +]; + + +20 # RadSimp(_n) <-- n; + + +/*Echo({"Try ",test}); */ + +CheckRadicals(_n,_test) <-- Abs(N(Eval(n-test),20)) < 0.000001; + +10 # ClampRadicals(_r)_(N(Eval(Abs(r)), 20)<0.000001) <-- 0; +20 # ClampRadicals(_r) <-- r; + + + +RadSimpTry(_n,_result,_current,_max)<-- +[ +//Echo(result," ",n," ",current); + if (IsLessThan(N(Eval(result-n)), 0)) + [ + Local(i); + + // First, look for perfect match + i:=BSearch(max,Hold({{try},ClampRadicals(N(Eval((result+Sqrt(try))-n),20))})); + If(i>0, + [ + Bind(result,result+Sqrt(i)); + Bind(i,AddN(max,1)); + Bind(current,AddN(max,1)); + ]); + + // Otherwise, search for another solution + if (IsLessThan(N(Eval(result-n)), 0)) + [ + For (Bind(i,current),i<=max,Bind(i,AddN(i,1))) + [ + Local(new, test); + Bind(test,result+Sqrt(i)); + +/* Echo({"Full-try ",test}); */ + + Bind(new,RadSimpTry(n,test,i,max)); + if (CheckRadicals(n,new)) + [ + Bind(result,new); + Bind(i,AddN(max,1)); + ]; + ]; + ]; + ]; + result; +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="RadSimp",categories="User Functions;Expression Simplification" +*CMD RadSimp --- simplify expression with nested radicals +*STD +*CALL + RadSimp(expr) + +*PARMS + +{expr} -- an expression containing nested radicals + +*DESC + +This function tries to write the expression "expr" as a sum of roots +of integers: $Sqrt(e1) + Sqrt(e2) + ...$, where $e1$, $e2$ and +so on are natural numbers. The expression "expr" may not contain +free variables. + +It does this by trying all possible combinations for $e1$, $e2$, ... +Every possibility is numerically evaluated using {N} and compared with the numerical evaluation of +"expr". If the approximations are equal (up to a certain margin), +this possibility is returned. Otherwise, the expression is returned +unevaluated. + +Note that due to the use of numerical approximations, there is a small +chance that the expression returned by {RadSimp} is +close but not equal to {expr}. The last example underneath +illustrates this problem. Furthermore, if the numerical value of +{expr} is large, the number of possibilities becomes exorbitantly +big so the evaluation may take very long. + +*E.G. + +In> RadSimp(Sqrt(9+4*Sqrt(2))) +Result: Sqrt(8)+1; +In> RadSimp(Sqrt(5+2*Sqrt(6)) \ + +Sqrt(5-2*Sqrt(6))) +Result: Sqrt(12); +In> RadSimp(Sqrt(14+3*Sqrt(3+2 + *Sqrt(5-12*Sqrt(3-2*Sqrt(2)))))) +Result: Sqrt(2)+3; + +But this command may yield incorrect results: + +In> RadSimp(Sqrt(1+10^(-6))) +Result: 1; + +*SEE Simplify, N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomIntegerList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomIntegerList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomIntegerList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomIntegerList.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="RandomIntegerList" + +RandomIntegerList(_count,_coefmin,_coefmax) <-- + Table(FloorN(coefmin+Random()*(coefmax+1-coefmin)),i,1,count,1); + +%/mathpiper + + + + +%mathpiper_docs,name="RandomIntegerList",categories="User Functions;Numbers (Random)" +*CMD RandomIntegerList --- generate a vector of random integers + +*STD + +*CALL + RandomIntegerList(nr, from, to) + +*PARMS + +{nr} -- number of integers to generate + +{from} -- lower bound + +{to} -- upper bound + +*DESC + +This function generates a list with "nr" random integers. All +entries lie between "from" and "to", including the boundaries, and +are uniformly distributed in this interval. + +*E.G. + +In> RandomIntegerList(4,-3,3) +Result: {0,3,2,-2}; + +*SEE Random, RandomPoly, RandomInteger, RandomIntegerMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomIntegerMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomIntegerMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomIntegerMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomIntegerMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="RandomIntegerMatrix" + +RandomIntegerMatrix(_rows,_cols,_coefmin,_coefmax) <-- + GenMatrix({{i,j}, FloorN(coefmin+Random()*(coefmax+1-coefmin))}, rows, cols ); + +%/mathpiper + + + + +%mathpiper_docs,name="RandomIntegerMatrix",categories="User Functions;Numbers (Random)" +*CMD RandomIntegerMatrix --- generate a matrix of random integers + +*STD + +*CALL + RandomIntegerMatrix(rows,cols,from,to) + +*PARMS + +{rows} -- number of rows in matrix + +{cols} -- number of cols in matrix + +{from} -- lower bound + +{to} -- upper bound + +*DESC + +This function generates a {rows x cols} matrix of random integers. All +entries lie between "from" and "to", including the boundaries, and +are uniformly distributed in this interval. + +*E.G. +In> PrettyForm( RandomIntegerMatrix(5,5,-2^10,2^10) ) + + / \ + | ( -506 ) ( 749 ) ( -574 ) ( -674 ) ( -106 ) | + | | + | ( 301 ) ( 151 ) ( -326 ) ( -56 ) ( -277 ) | + | | + | ( 777 ) ( -761 ) ( -161 ) ( -918 ) ( -417 ) | + | | + | ( -518 ) ( 127 ) ( 136 ) ( 797 ) ( -406 ) | + | | + | ( 679 ) ( 854 ) ( -78 ) ( 503 ) ( 772 ) | + \ / + +*SEE RandomPoly, Random, RandomInteger, RandomIntegerList +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomInteger.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomInteger.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomInteger.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomInteger.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,148 @@ +%mathpiper,def="RandomInteger" + +//Retract("RandomInteger", *); + + +10 # RandomInteger(_n) <-- +[ + Check(IsPositiveInteger(n), "Argument", "The argument must be a positive integer."); + + CeilN(Random() * n); +]; + + + +10 # RandomInteger(_lowerBoundInclusive, _upperBoundInclusive) <-- +[ + Check(IsInteger(lowerBoundInclusive) And IsInteger(upperBoundInclusive), "Argument", "Both arguments must be integers."); + + Check(lowerBoundInclusive < upperBoundInclusive, "Argument", "The first argument must be less than the second argument."); + + FloorN(lowerBoundInclusive + Random() * (upperBoundInclusive + 1 - lowerBoundInclusive) ); +]; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +===================== Tests ========================================== + + +%mathpiper,scope="nobuild",subtype="manual_test",title="Test arguments." + +Verify(ExceptionCatch(RandomInteger(-1), "Exception"), "Exception"); + +Verify(ExceptionCatch(RandomInteger(1.2, 4), "Exception"), "Exception"); + +Verify(ExceptionCatch(RandomInteger(1, 4.2), "Exception"), "Exception"); + +Verify(ExceptionCatch(RandomInteger(4, 1), "Exception"), "Exception"); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper,scope="nobuild",subtype="manual_test",title="Chi-square test for two argument version of RandomInteger." +[ + /* + Test that the two argument version of RandomInteger produces a + discrete uniform distribution. + */ + + + Local(randomNumbers, chiSquareTest, criticalChiSquareScore); + + randomNumbers:= Table( RandomInteger(-2, 2),x,1,10000,1); + + chiSquareTest := ChiSquareTest({ + Count(randomNumbers,-2), + Count(randomNumbers,-1), + Count(randomNumbers,0), + Count(randomNumbers,1), + Count(randomNumbers,2)}, + {2000,2000,2000,2000,2000}); + + criticalChiSquareScore := AlphaToChiSquareScore(.001, chiSquareTest["degreesOfFreedom"]); + + Echo(chiSquareTest); + + NewLine(); + + Echo("Calculated chi-squ value: ", chiSquareTest["chiSquareScore"]); + + Echo("Critical chi-square value: ", criticalChiSquareScore); + + Histogram(randomNumbers); + +]; + +%/mathpiper + + %output,preserve="false" + Result: class org.jfree.chart.ChartPanel + + Side Effects: + {{"chiSquareScore",3.357},{"pValue",0.6879909930},{"degreesOfFreedom",4}} + + Calculated chi-squ value: 3.357 + Critical chi-square value: 18.46682719 + +. %/output + + + + + +%mathpiper_docs,name="RandomInteger",categories="User Functions;Numbers (Random)" +*CMD RandomInteger --- generate a random integer + +*STD + +*CALL + RandomInteger(upper_bound) + RandomInteger(lower_bound, upper_bound) + +*PARMS + +{lower_bound} -- the smallest integer that can be generated + +{upper_bound} -- the largest integer that can be generated + + +*DESC + +The single argument version of this function generates a random integer between +1 and the given upper bound integer (inclusive). The two argument version of +the function generates a random integer between a lower bound integer and an +upper bound integer (both inclusive). + +*E.G. +In> RandomInteger(5) +Result> 4 + +In> Repeat(10) Write(RandomInteger(5),,) +Result> 10 +Side Effects>4,3,5,1,2,2,3,5,3,3, + +In> RandomInteger(5,10) +Result: 5 + +In> Repeat(10) Write(RandomInteger(5, 10),,) +Result: 10 +Side Effects: +8,9,9,5,6,8,9,10,8,7, + +*SEE Random, RandomPoly, RandomIntegerList, RandomIntegerMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomInterestingPolynomial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomInterestingPolynomial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomInterestingPolynomial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomInterestingPolynomial.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,227 @@ +%mathpiper,def="RandomInterestingPolynomial" + +//Retract("RandomInterestingPolynomial",*); +//Retract("NewRandomPoly",*); +//Retract("RandomIrreducibleQuadratic",*); +//Retract("RandomIrreducibleQuadraticWithComplexRoots",*); +//Retract("RandomIrreducibleQuadraticWithRealRoots",*); + + +10 # RandomInterestingPolynomial( deg_IsPositiveInteger, _var ) <-- +[ + RandomSeed( SystemTimer() ); // randomize random number generator + NewRandomPoly(deg,var); +]; + + +10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,1)) <-- +[ + Local(p,i1,i2); + i1 := RandomInteger(1,10); + i2 := RandomInteger(-10,10); + p := NormalForm(UniVariate(var,0,{i2,i1})); +]; + + +10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,2)) <-- +[ + Local(ii,i1,i2,p,quadPoly); + p := FillList(0,2); + For(ii:=1,ii<=2,ii++) + [ + i1 := RandomInteger(10); + i2 := RandomInteger(-10,10); + If( i1 > 1, i2 := i1*i2 ); + p[ii] := NormalForm(UniVariate(var,0,{i2,i1})); + ]; + quadPoly := ExpandBrackets(p[1]*p[2]); + quadPoly := Simplify(Quotient(quadPoly,LeadingCoef(quadPoly))); +]; + + +10 # RandomIrreducibleQuadratic( _var ) <-- +[ + Local(ii,coeffs,discrim,u,p,f); + // Use random integers for coefficients a2 and a1. Then select a0 + // in one of two ways: + // (1) so that discriminant is negative integer, or + // (2) so that discriminant is positive integer but not square. + If(RandomInteger(2)=1, + RandomIrreducibleQuadraticWithComplexRoots(var), + RandomIrreducibleQuadraticWithRealRoots(var) + ); +]; + + +10 # RandomIrreducibleQuadraticWithRealRoots(_var) <-- +[ + Local(coeffs,ijk); + coeffs := FillList(1,3); + coeffs[2] := RandomInteger(-10,10); + coeffs[3] := RandomInteger(1,10); + ijk := Floor(coeffs[2]^2 / (4*coeffs[3])); + coeffs[1] := RandomInteger(-10,ijk); + discrim := coeffs[2]^2-4*coeffs[1]*coeffs[3]; + NormalForm(UniVariate(var,0,coeffs)); +]; + + +10 # RandomIrreducibleQuadraticWithComplexRoots(_var) <-- +[ + Local(coeffs,ijk); + coeffs := {1,RandomInteger(-10,10),RandomInteger(1,10)}; + coeffs[1] := Ceil(N(coeffs[2]^2/(4*coeffs[3]))) + RandomInteger(1,5); + NormalForm(UniVariate(var,0,coeffs)); +]; + + +10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,3)) <-- +[ + Local(ii,i1,i2,i3,p,CubicPoly); + p := FillList(1,3); + If( RandomInteger(3) = 1, + [ + For(ii:=1,ii<=3,ii++) + [ + i1 := RandomInteger(2); + i2 := RandomInteger(-10,10); + If( i1 > 1, i2 := i1*i2 ); + p[ii] := NormalForm(UniVariate(var,0,{i2,i1})); + ]; + ], + [ + i1 := RandomInteger(2); + i2 := RandomInteger(-10,10); + If( i1 > 1, i2 := i1*i2 ); + p[1] := NormalForm(UniVariate(var,0,{i2,i1})); + p[2] := RandomIrreducibleQuadratic(var); + ] + ); + CubicPoly := ExpandBrackets(Product(p)); +]; + + +10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,4)) <-- +[ + Local(ii,i1,i2,i3,i4,p,QuarticPoly); + p := FillList(1,4); + If( RandomInteger(2) = 1, + [ + p[1] := NewRandomPoly(3,x); + i1 := RandomInteger(2); + i2 := RandomInteger(-10,10); + If( i1 > 1, i2 := i1*i2 ); + p[2] := NormalForm(UniVariate(var,0,{i2,i1})); + ], + [ + p[1] := NewRandomPoly(2,x); + p[2] := NewRandomPoly(2,x); + ] + ); + QuarticPoly := ExpandBrackets(Product(p)); +]; + + +10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,5)) <-- +[ + Local(ii,i1,i2,i3,i4,p,QuinticPoly); + p := FillList(1,4); + p[1] := NewRandomPoly(1,x); + p[2] := RandomIrreducibleQuadraticWithRealRoots(x); + p[3] := RandomIrreducibleQuadraticWithComplexRoots(x); + QuinticPoly := ExpandBrackets(Product(p)); +]; + + +11 # NewRandomPoly( deg_IsPositiveInteger, _var )_(deg > 5) <-- +[ + Local(p,n,m); + p := {}; + m := deg; + Until( m < 3 ) + [ + n := RandomInteger(2,Floor(N(deg/2))); + Tell(" ",{m,n}); + Push(p,NewRandomPoly(n,var)); + m := m - n; + ]; + Tell(" ",m); + If( m > 0, Push(p,NewRandomPoly(m,x))); + Expand(Product(p)); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="RandomInterestingPolynomial",categories="User Functions;Numbers (Random)" +*CMD RandomInterestingPolynomial --- construct a random "interesting" polynomial +*CMD RandomIrreducibleQuadraticWithComplexRoots --- constructs a random quadratic polynomial with complex roots +*CMD RandomIrreducibleQuadraticWithRealRoots --- constructs a random quadratic polynomial with real roots + +*STD +*CALL + RandomInterestingPolynomial(deg,var) + RandomIrreducibleQuadraticWithComplexRoots(var) + RandomIrreducibleQuadraticWithRealRoots(var) + +*PARMS + +{deg} -- degree of the resulting univariate polynomial + +{var} -- free variable for the resulting univariate polynomial + +*DESC + +RandomInterestingPolynomial generates a random "interesting" polynomial in +variable {var}, of degree {deg}, with integer coefficients. + +Unlike the similar function {RandomPoly}, which merely generates +polynomials with random integer coefficients, the current function +generates polynomials which are constructed by multiplying simpler +random polynomials (with integer coefficients). In this way, the +generated polynomials are guaranteed to be "interesting" in the sense +that they will always be factorable. It is a known fact that a polynomial +whose coefficients are integers chosen at random will almost always +turn out to be irreducible. This is not usually very "interesting", +especially in a learning context. + +If you would like to construct higher degree polynomials having certain +specific kinds of roots, you can write a custom function to do this, +using {RandomIrreducibleQuadraticWithRealRoots} or +{RandomIrreducibleQuadraticWithComplexRoots} to create quadratics +with which to compose the higher polynomial. + +*E.G. + +In> RandomInterestingPolynomial(3,x) +Result: x^3+2*x^2-12*x-48 + +In> Factor(%) +Result: (x-4)*(x^2+6*x+12) + +In> Solve(x^2+6*x+12,x) +Result: {x==Complex(-3,Sqrt(3)),x==Complex(-3,(-Sqrt(12))/2)} + +Notice that although the polynomial is indeed factorable, it is +not guaranteed to have only linear factors (over the integers), +and (some of) the roots of the polynomial may be complex. + +In> RandomIrreducibleQuadraticWithRealRoots(x) +Result: 6*x^2+2*x-7 + +In> Solve(%,x) +Result: {x==(Sqrt(172)-2)/12,x==(-(Sqrt(172)+2))/12} + +In> RandomIrreducibleQuadraticWithComplexRoots(x) +Result: 8*x^2-5*x+3 + +In> Solve(%,x) +Result: {x==Complex(5/16,Sqrt(71/256)),x==Complex(5/16,(-Sqrt(71))/16)} + +*SEE Random, RandomPoly +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/random.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/random.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/random.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/random.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,412 @@ +%mathpiper,def="RandomSeed;Random;Rng;RngSeed;RngCreate" + +/* def file definitions + +RandomSeed +Random +Rng +RngSeed +RngCreate +*/ + +/* +Random number generators implemented in an object-oriented manner. + +Old interface (still works): + + RandomSeed(123); + Random(); Random(); + +It provides only one global RNG with a globally assigned seed. + +New interface allows creating many RNG objects: + + r1:=RngCreate(); // create a default RNG object, assign structure to r1 + r2:=RngCreate(12345); // create RNG object with given seed + r3:=RngCreate(seed->0, engine->advanced, dist->gauss); // extended options: specify seed, type of RNG engine and the type of statistical distribution + Rng(r1); Rng(r1); Rng(r2); // generate some floating-point numbers + RngSeed(r1, 12345); // r1 is re-initialized with given seed, r2 is unaffected + +More "RNG engines" and "RNG distribution adaptors" can be defined later (at run time). + +RngCreate() will return an object of the following structure: + {SomeDist, SomeEngine, state } + +here SomeEngine is a function atom that describes the RNG engine, +SomeDist is a function atom that specifies the distribution adaptor, +and state is a "RNG state object", e.g. a list of all numbers that specify the current RNG state (seeds, temporaries, etc.). + +RngSeed(r1, seed) expects an integer seed. +It will re-initialize the RNG object r1 with the given seed. + +The "RNG engine API": calling RngCreate with engine->SomeEngine expects that: + SomeEngine(seed_IsInteger) will create and initialize a state object with given seed and return the new state object (a list). SomeEngine can assume that "seed" is a positive integer. + SomeEngine(state1_IsList) will update the RNG state object state1 and return the pair {new state object, new number}. + +The "RNG distribution adaptor API": calling RngCreate with distribution->SomeDist expects that: + SomeDist(r1) will update the RNG object r1 and return the pair {new state object, new number}. r1 is a full RNG object, not just a state object. + + +*/ + +////////////////////////////////////////////////// +/// lists of defined RNG entities +////////////////////////////////////////////////// + +/// The idea is that options must be easy to type, but procedure names could be long. + +LocalSymbols(knownRNGEngines, knownRNGDists) [ + knownRNGEngines := + { + { "default", "RNGEngine'LCG'2"}, + { "advanced", "RNGEngine'L'Ecuyer"}, + }; + + knownRNGDists := + { + {"default", "FlatRNGDist"}, + {"flat", "FlatRNGDist"}, + // {"uniform", "FlatRNGDist"}, // we probably don't need this alias... + {"gauss", "GaussianRNGDist"}, + }; + + KnownRNGDists() := knownRNGDists; + KnownRNGEngines() := knownRNGEngines; +]; + + +////////////////////////////////////////////////// +/// RNG object API +////////////////////////////////////////////////// + +Function() RngCreate(); +Function() RngCreate(seed, ...); +//HoldArgument("RngCreate", seed); // this is needed to prevent evaluation of = and also to prevent substitution of variables, e.g. if "seed" is defined +//UnFence("RngCreate", 0); +//UnFence("RngCreate", 1); +Function() RngSeed(r, seed); +//UnFence("RngSeed", 2); +/// accessor for RNG objects +Function() Rng(r); +//UnFence("Rng", 1); + + +RngCreate() <-- RngCreate(0); + +10 # RngCreate(a'seed_IsInteger) <-- (RngCreate @ {seed -> a'seed}); + +// a single option given: convert explicitly to a list +20 # RngCreate(_key -> _value) <-- `(RngCreate({@key -> value})); + +// expect a list of options +30 # RngCreate(options_IsList) <-- +[ + options := OptionsListToHash @ {options}; + + // check options and assign defaults + If( + options["seed"] = Empty Or options["seed"] <= 0, + options["seed"] := 76544321 // some default seed out of the blue sky + ); + If( + options["engine"] = Empty Or Not (Assert("warning", {"RngCreate: invalid engine", options["engine"]}) KnownRNGEngines()[options["engine"] ] != Empty), + options["engine"] := "default" + ); + If( + options["dist"] = Empty Or Not (Assert("warning", {"RngCreate: invalid distribution", options["dist"]}) KnownRNGDists()[options["dist"] ] != Empty), + options["dist"] := "default" + ); + + // construct a new RNG object + // a RNG object has the form {"SomeDist", "SomeEngine", {state}} + { + KnownRNGDists()[options["dist"] ], KnownRNGEngines()[options["engine"] ], + // initialize object with given seed using "SomeEngine"(seed) + KnownRNGEngines()[options["engine"] ] @ { options["seed"] } + }; +]; + +/// accessor function: will call SomeDist(r) and update r +Rng(_r) <-- +[ + Local(state, result); + {state, result} := (r[1] @ {r}); // this calls SomeDist(r) + DestructiveReplace(r, 3, state); // update RNG object + result; // return floating-point number +]; + +/// set seed: will call SomeEngine(r, seed) and update r +RngSeed(_r, seed_IsInteger) <-- +[ + Local(state); + (Assert("warning", {"RngSeed: seed must be positive", seed}) seed > 0 + ) Or (seed:=76544321); + state := (r[2] @ {seed}); // this calls SomeEngine(r) + DestructiveReplace(r, 3, state); // update object + True; +]; + +////////////////////////////////////////////////// +/// RNG distribution adaptors +////////////////////////////////////////////////// + +/// trivial distribution adaptor: flat distribution, simply calls SomeEngine(r) +/* we have to return whole objects; we can't use references b/c the core +function ApplyFast will not work properly on references, i.e. if r = {"", "", {1}} so that +r[3] = {1}, then LCG'2(r[3]) modifies r[3], but LCG'2 @ r[3] or +ApplyFast("LCG'2", {r[3]}) do not actually modify r[3]. +*/ + +// return pair {state, number} +FlatRNGDist(_r) <-- (r[2] @ {r[3]}); // this calls SomeEngine(state) + +/// Gaussian distribution adaptor, returns a complex number with normal distribution with unit variance, i.e. Re and Im are independent and both have unit variance +/* Gaussian random number, Using the Box-Muller transform, from Knuth, + "The Art of Computer Programming", + Volume 2 (Seminumerical algorithms, third edition), section 3.4.1 + */ +GaussianRNGDist(_rng) <-- +[ + // a Gaussian distributed complex number p + I*q is made up of two uniformly distributed numbers x,y according to the formula: + // a:=2*x-1, b:=2*y-1, m:=a^2+b^2; p = a*Sqrt(-2*Ln(m)/m); q:=b*Sqrt(-2*Ln(m)/m); + // here we need to make sure that m is nonzero and strictly less than 1. + Local(a,b,m, new'state, rnumber); + new'state := rng[3]; // this will be updated at the end + m:=0; + While(m=0 Or m>=1) // repeat generating new x,y - should not take more than one iteration really + [ + {new'state, rnumber} := (rng[2] @ {new'state}); + a:=2*rnumber-1; + {new'state, rnumber} := (rng[2] @ {new'state}); + b:=2*rnumber-1; + m:=a*a+b*b; + ]; + {new'state, (a+I*b)*SqrtN(-2*DivideN(Internal'LnNum(m),m))}; +]; + + +////////////////////////////////////////////////// +/// RNG engines +////////////////////////////////////////////////// + +/// default RNG engine: the LCG generator + +// first method: initialize a state object with given seed +RNGEngine'LCG'1(seed_IsInteger) <-- {seed}; +// second method: update state object and return new number +RNGEngine'LCG'1(state_IsList) <-- LCG'1(state); + +// first method: initialize a state object with given seed +RNGEngine'LCG'2(seed_IsInteger) <-- {seed}; +// second method: update state object and return new number +RNGEngine'LCG'2(state_IsList) <-- LCG'2(state); + +// first method: initialize a state object with given seed +RNGEngine'LCG'3(seed_IsInteger) <-- {seed}; +// second method: update state object and return new number +RNGEngine'LCG'3(state_IsList) <-- LCG'3(state); + +// first method: initialize a state object with given seed +RNGEngine'LCG'4(seed_IsInteger) <-- {seed}; +// second method: update state object and return new number +RNGEngine'LCG'4(state_IsList) <-- LCG'4(state); + +/// parameters from P. Hellekalek, 1994; see G. S. Fishman, Math. Comp. vol. 54, 331 (1990) +LCG'1(state) := RandomLCG(state, 2147483647,950706376,0); +LCG'2(state) := RandomLCG(state, 4294967296,1099087573,0); +LCG'3(state) := RandomLCG(state, 281474976710656,68909602460261,0); +LCG'4(state) := RandomLCG(state, 18014398509481984,2783377640906189,0); + +/// Linear congruential generator engine: backend +// state is a list with one element +RandomLCG(_state, _im, _ia, _ic) <-- +{ + DestructiveReplace(state,1, ModuloN(state[1]*ia+ic,im)), + DivideN(state[1], im) // division should never give 1 +}; + +/// Advanced RNG engine due to L'Ecuyer et al. +/// RNG from P. L'ecuyer et al (2000). Period approximately 2^191 +// state information: 6 32-bit integers, corresponding to {x3,x2,x1,y3,y2,y1} + +// first method: initialize a state object with given seed +RNGEngine'L'Ecuyer(a'seed_IsInteger) <-- +[ + // use LCG'2 as auxiliary RNG to fill the seeds + Local(rng'aux, result); + rng'aux := (RngCreate @ {a'seed}); + // this will be the state vector + result:=ZeroVector(6); + // fill the state object with random numbers + Local(i); + For(i:=1, i<=6, i++) + [ + Rng(rng'aux); + result[i] := rng'aux[3][1]; // hack to get the integer part + ]; + // return the state object + result; +]; + +// second method: update state object and return a new random number (floating-point) +RNGEngine'L'Ecuyer(state_IsList) <-- +[ + Local(new'state, result); + new'state := { + Modulo(1403580*state[2]-810728*state[3], 4294967087), state[1], state[2], + Modulo(527612*state[4]-1370589*state[6], 4294944433), state[4], state[5] + }; + result:=Modulo(state[1]-state[4], 4294967087); + { + new'state, + DivideN(If(result=0, 4294967087, result), 4294967088) + }; +]; + +////////////////////////////////////////////////// +/// old interface: using one global RNG object +////////////////////////////////////////////////// +/* this is a little slower but entirely equivalent to the code below +GlobalRNG := RngCreate(76544321); +Random() := Rng(GlobalRNG); +RandomSeed(seed) := RngSeed(GlobalRNG, seed); +*/ + +LocalSymbols(RandSeed) [ + // initial seed should be nonzero + RandSeed := SystemTimer(); //Was 76544321. + + /// assign random seed + Function("RandomSeed", {seed}) Bind(RandSeed, seed); + + /// Linear congruential generator + RandomLCG(_im, _ia, _ic) <-- + [ + RandSeed:=ModuloN(RandSeed*ia+ic,im); + DivideN(RandSeed,im); // should never give 1 + ]; +]; // LocalSymbols(RandSeed) + + +Function("Random1",{}) RandomLCG(4294967296,1103515245,12345); +Function("Random6",{}) RandomLCG(1771875,2416,374441); +/// parameters from P. Hellekalek, 1994; see G. S. Fishman, Math. Comp. vol. 54, 331 (1990) +Function("Random2",{}) RandomLCG(2147483647,950706376,0); +Function("Random3",{}) RandomLCG(4294967296,1099087573,0); +Function("Random4",{}) RandomLCG(281474976710656,68909602460261,0); +Function("Random5",{}) RandomLCG(18014398509481984,2783377640906189,0); + +// select one of them +Function("Random",{}) Random3(); + + +%/mathpiper + + + + + +%mathpiper_docs,name="Random;RandomSeed",categories="User Functions;Numbers (Random)" +*CMD Random, RandomSeed --- (pseudo-) random number generator +*STD +*CALL + Random() + RandomSeed(init) + +*PARAMS +{init} -- positive integer, initial random seed + +*DESC + +The function {Random} returns a random number, uniformly distributed in the +interval between 0 and 1. The same sequence of random numbers is +generated in every MathPiper session. + +The random number generator can be initialized by calling {RandomSeed} with an integer value. +Each seed value will result in the same sequence of pseudo-random numbers. + +*SEE RandomInteger, RandomPoly, Rng, Random, RandomIntegerList, RandomIntegerMatrix +%/mathpiper_docs + + + + + +%mathpiper_docs,name="RngCreate;RngSeed;Rng",categories="User Functions;Numbers (Random)" +*CMD RngCreate --- manipulate random number generators as objects +*CMD RngSeed --- manipulate random number generators as objects +*CMD Rng --- manipulate random number generators as objects +*STD +*CALL + RngCreate() + RngCreate(init) + RngCreate(option->value,...) + RngSeed(r, init) + Rng(r) + +*PARMS +{init} -- integer, initial seed value + +{option} -- atom, option name + +{value} -- atom, option value + +{r} -- a list, RNG object + +*DESC +These commands are an object-oriented interface to (pseudo-)random number generators (RNGs). + +{RngCreate} returns a list which is a well-formed RNG object. +Its value should be saved in a variable and used to call {Rng} and {RngSeed}. + +{Rng(r)} returns a floating-point random number between 0 and 1 and updates the RNG object {r}. +(Currently, the Gaussian option makes a RNG return a complex random number instead of a real random number.) + +{RngSeed(r,init)} re-initializes the RNG object {r} with the seed value {init}. +The seed value should be a positive integer. + +The {RngCreate} function accepts several options as arguments. +Currently the following options are available: + +* {seed} -- specify initial seed value, must be a positive integer +* {dist} -- specify the distribution of the random number; currently {flat} and {gauss} are implemented, and the default is the flat (uniform) distribution +* {engine} -- specify the RNG engine; currently {default} and {advanced} are available ("advanced" is slower but has much longer period) + +If the initial seed is not specified, the value of 76544321 will be used. + +The {gauss} option will create a RNG object that generates pairs of Gaussian distributed random numbers as a complex random number. +The real and the imaginary parts of this number are independent random numbers taken from a Gaussian (i.e. "normal") distribution with unit variance. + +For the Gaussian distribution, the Box-Muller transform method is used. +A good description of this method, along with the proof that the method +generates normally distributed random numbers, can be found in Knuth, +"The Art of Computer Programming", Volume 2 (Seminumerical algorithms, third +edition), section 3.4.1 + +Note that unlike the global {Random} function, the RNG objects created with {RngCreate} are independent RNGs and do not affect each other. +They generate independent streams of pseudo-random numbers. +However, the {Random} function is slightly faster. + +*E.G. + +In> r1:=RngCreate(seed->1,dist->gauss) +Result: {"GaussianRNGDist","RNGEngine'LCG'2",{1}} +In> Rng(r1) +Result: Complex(-1.6668466417,0.228904004); +In> Rng(r1); +Result: Complex(0.0279296109,-0.5382405341); +The second RNG gives a uniform distribution (default option) but uses a more complicated algorithm: +In> [r2:=RngCreate(engine->advanced);Rng(r2);] +Result: 0.3653615377; +The generator {r1} can be re-initialized with seed 1 again to obtain the same sequence: +In> RngSeed(r1, 1) +Result: True; +In> Rng(r1) +Result: Complex(-1.6668466417,0.228904004); + + +*SEE Random, RandomInteger, RandomIntegerList, RandomIntegerMatrix +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomPoly.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomPoly.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/random/RandomPoly.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/random/RandomPoly.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="RandomPoly" + +/* Generate a random polynomial */ + +RandomPoly(_var,_degree,_coefmin,_coefmax) <-- + NormalForm(UniVariate(var,0,RandomIntegerList(degree+1,coefmin,coefmax))); + +%/mathpiper + + + + +%mathpiper_docs,name="RandomPoly",categories="User Functions;Numbers (Random)" +*CMD RandomPoly --- construct a random polynomial +*STD +*CALL + RandomPoly(var,deg,coefmin,coefmax) + +*PARMS + +{var} -- free variable for resulting univariate polynomial + +{deg} -- degree of resulting univariate polynomial + +{coefmin} -- minimum value for coefficients + +{coefmax} -- maximum value for coefficients + +*DESC + +RandomPoly generates a random polynomial in variable "var", of +degree "deg", with integer coefficients ranging from "coefmin" to +"coefmax" (inclusive). The coefficients are uniformly distributed in +this interval, and are independent of each other. + +*E.G. + +In> RandomPoly(x,3,-10,10) +Result: 3*x^3+10*x^2-4*x-6; +In> RandomPoly(x,3,-10,10) +Result: -2*x^3-8*x^2+8; + +*SEE Random, RandomInteger, RandomIntegerList, RandomIntegerMatrix +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Combine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Combine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Combine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Combine.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,79 @@ +%mathpiper,def="Combine" + +//Retract("Combine",*); + +10 # Combine(expr_IsZero) <-- 0; + +20 # Combine(_expr) <-- +[ + Local(L); + L := ReassembleListTerms(DisassembleExpression(expr)); + UnFlatten(L,"+",0); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="Combine",categories="User Functions;Expression Simplification" +*CMD Combine --- try to simplify an expression by combining terms or factors that cancel +*STD +*CALL + Combine(expr) + +*PARMS + +{expr} -- expression to simplify + +*DESC + +This function tries to simplify the expression {expr} by combining like +terms or factors that will cancel. +Unlike the related function {Simplify}, it does not manipulate the expression +any further. + +See Issue #14 for a description of why this function may be necessary. + +At the present time, MathPiper's automatic evaluation scheme simplifies some +expressions but leaves other, similar ones, unsimplified (See examples 1 and 2 +below). +A call to Simplify() +may complete the simplification of the expression, but sometimes Simplify() does +too much (see example 3, below). + +A call to Combine() is more likely to give what is wanted than a call to Simplify(). +Until such time as we can make Combine() a part of MathPiper's automatic +expression evaluation, this is the best workaround. + +*E.G. +In> e1:=3 + x/5 - 3 +Result: x/5 (automatically simplified upon entry) + +In> e2:=3-x/5-3 +Result: 3-x/5-3 (NOT automatically simplified upon entry) + +In> Simplify(e2) +Result: (-x)/5 (Simplify() does the job) + +In> e3:=3 + x/5 + x/5 +Result: (2*x)/5+3 + +In> Simplify(e3) +Result: (2*x+15)/5 (Simplify() does more than we want, here) + +In> Combine(e3) +Result: (2*x)/5+3 (Combine() does just enough -- not too much) + +*SEE Simplify, TrigSimpCombine, RadSimp +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Eliminate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Eliminate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Eliminate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Eliminate.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="Eliminate" + +Eliminate(_var,_replace,_function) <-- Simplify(Subst(var,replace)function); + +%/mathpiper + + + +%mathpiper_docs,name="Eliminate",categories="User Functions;Solvers (Symbolic)" +*CMD Eliminate --- substitute and simplify +*STD +*CALL + Eliminate(var, value, expr) + +*PARMS + +{var} -- variable (or subexpression) to substitute + +{value} -- new value of "var" + +{expr} -- expression in which the substitution should take place + +*DESC + +This function uses {Subst} to replace all instances +of the variable (or subexpression) "var" in the expression "expr" +with "value", calls {Simplify} to simplify the +resulting expression, and returns the result. + +*E.G. + +In> Subst(Cos(b), c) (Sin(a)+Cos(b)^2/c) +Result: Sin(a)+c^2/c; +In> Eliminate(Cos(b), c, Sin(a)+Cos(b)^2/c) +Result: Sin(a)+c; + +*SEE SuchThat, Subst, Simplify +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/ExpandBrackets.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/ExpandBrackets.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/ExpandBrackets.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/ExpandBrackets.mpw 2011-04-16 16:45:46.000000000 +0000 @@ -0,0 +1,85 @@ +%mathpiper,def="ExpandBrackets" + +LocalSymbols(AssembleTerms, AssembleTermsRecursive) +[ + + AssembleTerms(list) := + [ + Check(IsList(list), "Argument", "The argument must be a list."); + + If(Length(list) = 1, + First(list), + AssembleTermsRecursive(Reverse(list)) + ); + ]; + + + AssembleTermsRecursive(list) := + [ + If(Type(list[1]) = "-" Or IsNegativeNumber(list[1]) Or Type(list[1]) = "/" And (Type(Numerator(list[1])) = "-" Or IsNegativeNumber(Numerator(list[1]))), + If(Length(list) = 2, + ListToFunction({ToAtom("-"), list[2], -list[1]} ), + ListToFunction({ToAtom("-"), AssembleTermsRecursive(Rest(list)), -First(list)} ) + ), + If(Length(list) = 2, + ListToFunction({ToAtom("+"), list[2], list[1]} ), + ListToFunction({ToAtom("+"), AssembleTermsRecursive(Rest(list)), First(list)} ) + ) + ); + ]; + + +10 # ExpandBrackets(xx_IsZero) <-- 0; + +20 # ExpandBrackets(_xx)_(Type(xx)="/" Or Type(-xx)="/") <-- +[ + Local(N,D,t); + N := ReassembleListTerms(DisassembleExpression(Numerator(xx))); + D := ExpandBrackets(Denominator(xx)); + AssembleTerms(MapSingle({{t}, t / D}, N)); +]; + + +30 # ExpandBrackets(_xx) <-- AssembleTerms(ReassembleListTerms(DisassembleExpression(xx))); + +]; + + + +//ExpandBrackets(_xx) <-- SimpExpand(SimpImplode(SimpFlatten(xx))); +//ExpandBrackets(x) := NormalForm(MM(x)); + +%/mathpiper + + + + + + +%mathpiper_docs,name="ExpandBrackets",categories="User Functions;Polynomials (Operations)" +*CMD ExpandBrackets --- expand all brackets +*STD +*CALL + ExpandBrackets(expr) + +*PARMS + +{expr} -- an expression + +*DESC + +This command tries to expand all the brackets by repeatedly using the +distributive laws $a * (b+c) = a*b + a*c$ and $(a+b) * c = a*c + b*c$. +It goes further than {Expand}, in that it expands all brackets. + +*E.G. + +In> Expand((a-x)*(b-x),x) +Result: x^2-(b+a)*x+a*b; +In> Expand((a-x)*(b-x),{x,a,b}) +Result: x^2-(b+a)*x+b*a; +In> ExpandBrackets((a-x)*(b-x)) +Result: a*b-x*b+x^2-a*x; + +*SEE Expand +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/ExpandFrac.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/ExpandFrac.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/ExpandFrac.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/ExpandFrac.mpw 2010-01-05 20:11:09.000000000 +0000 @@ -0,0 +1,16 @@ +%mathpiper,def="ExpandFrac" + +////////////////////////////////////////////////// +/// ExpandFrac --- normalize rational functions (no simplification) +////////////////////////////////////////////////// + +5 # ExpandFrac(expr_IsList) <-- MapSingle("ExpandFrac", expr); + +// expression does not contain fractions +10 # ExpandFrac(_expr)_Not(HasFuncSome(expr, "/", {ToAtom("+"), ToAtom("-"), *, /, ^})) <-- expr; +15 # ExpandFrac(a_IsRationalOrNumber) <-- a; +20 # ExpandFrac(_expr) <-- ExpandFrac'combine(GetNumerDenom(expr)); + +ExpandFrac'combine({_a, _b}) <-- a/b; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/factorial/FactorialSimplify.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/factorial/FactorialSimplify.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/factorial/FactorialSimplify.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/factorial/FactorialSimplify.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,297 @@ +%mathpiper,def="FactorialSimplify" + + +/* FactorialSimplify algorithm: + 1) expand binomials into factors + 2) expand brackets as much as possible + 3) for the remaining rational expressions x/y, + take all the factors of x and y, and match them + up one by one to determine if they can be + factored out. The algorithm will look at expressions like x^n/x^m + where (n-m) is an integer, or at expressions x!/y! where (x-y) + is an integer. The routine CommonDivisors does these steps, and + returns the new numerator and denominator factor. + FactorialSimplifyWorker does the actual O(n^2) algorithm of + matching all terms up. +*/ + +FactorialNormalForm(x):= +[ + // Substitute binomials + x:=(x/:{BinomialCoefficient(_n,_m)<- (n!)/((m!)*(n-m)!)}); + // Expand expression as much as possible so that the terms become + // simple rationals. + + x:=( + x/::Hold({ + (_a/_b)/_c <- (a)/(b*c), + (-(_a/_b))/_c <- (-a)/(b*c), + (_a/_b)*_c <- (a*c)/b, + (_a*_b)^_m <- a^m*b^m, + (_a/_b)^_m*_c <- (a^m*c)/b^m, + _a*(_b+_c) <- a*b+a*c, + (_b+_c)*_a <- a*b+a*c, + (_b+_c)/_a <- b/a+c/a, + _a*(_b-_c) <- a*b-a*c, + (_b-_c)*_a <- a*b-a*c, + (_b-_c)/_a <- b/a-c/a + })); + x; +]; + +FactorialSimplify(x):= +[ + x := FactorialNormalForm(x); + FactorialSimplifyWorker(x); +]; + + +/* CommonDivisors takes two parameters x and y as input, determines a common divisor g + and then returns {x/g,y/g,g}. + */ +10 # CommonDivisors(_x^(_n),_x^(_m)) <-- {x^Simplify(n-m),1,x^m}; +10 # CommonDivisors(_x^(_n),_x) <-- {x^Simplify(n-1),1,x}; +10 # CommonDivisors(_x,_x^(_m)) <-- {x^Simplify(1-m),1,x^m}; +10 # CommonDivisors((_x) !,_x) <-- {(x-1)!,1,x}; +10 # CommonDivisors(_x,_x) <-- {1,1,x}; +10 # CommonDivisors(- _x,_x) <-- {-1,1,x}; +10 # CommonDivisors(_x,- _x) <-- {1,-1,x}; +10 # CommonDivisors((_x),(_x)!) <-- {1,(x-1)!,x}; +10 # CommonDivisors((_x)!, (_y)!)_IsInteger(Simplify(x-y)) <-- CommonFact(Simplify(x-y),y); + + +10 # CommonDivisors((_x)! ^ _m, (_y)! ^ _m)_IsInteger(Simplify(x-y)) <-- CommonFact(Simplify(x-y),y)^m; + +10 # CommonFact(dist_IsNegativeInteger,_y) + <-- {1,Product(i,1,-dist,Simplify(y+i+dist)),Simplify(y+dist)!}; +11 # CommonFact(_dist,_y) + <-- {Product(i,1,dist,Simplify(y+i)),1,Simplify(y)!}; +60000 # CommonDivisors(_x,_y) <-- {x,y,1}; + +10 # CommonFactors((_x)!,_y)_(Simplify(y-x) = 1) <-- {y!,1}; +10 # CommonFactors((_x)!,_y)_(Simplify((-y)-x) = 1) <-- {(-y)!,-1}; + +10 # CommonFactors(_x^_n,_x^_m) <-- {x^Simplify(n+m),1}; +10 # CommonFactors(_x^_n,_x) <-- {x^Simplify(n+1),1}; + +60000 # CommonFactors(_x,_y) <-- {x,y}; + +10 # FactorialSimplifyWorker(_x+_y) <-- FactorialSimplifyWorker(x)+FactorialSimplifyWorker(y); +10 # FactorialSimplifyWorker(_x-_y) <-- FactorialSimplifyWorker(x)-FactorialSimplifyWorker(y); +10 # FactorialSimplifyWorker( -_y) <-- -FactorialSimplifyWorker(y); + +LocalSymbols(x,y,i,j,n,d)[ + +20 # FactorialSimplifyWorker(_x/_y) <-- +[ + // first separate out factors of the denominator + Local(numerCommon,numerTerms); + {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); + Local(denomCommon,denomTerms); + {denomCommon,denomTerms}:=FactorialGroupCommonDivisors(y); + Local(n,d,c); + {n,d,c} := FactorialDivideTerms(numerCommon,denomCommon); + (n/d)*Simplify((numerTerms)/(denomTerms)); +]; + + + +20 # FactorialGcd(_x,_y) <-- +[ + // first separate out factors of the denominator + Local(numerCommon,numerTerms); + {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); + Local(denomCommon,denomTerms); + {denomCommon,denomTerms}:=FactorialGroupCommonDivisors(y); + Local(n,d,c); + {n,d,c} := FactorialDivideTerms(numerCommon,denomCommon); + c; +]; + + + + + +10 # FactorialDivideTerms(- _x,- _y) <-- FactorialDivideTermsAux(x,y); +LocalSymbols(n,d,c) +[ + 20 # FactorialDivideTerms(- _x, _y) + <-- + [ + Local(n,d,c); + {n,d,c} := FactorialDivideTermsAux(x,y); + {-n,d,c}; + ]; + 30 # FactorialDivideTerms( _x,- _y) + <-- + [ + Local(n,d,c); + {n,d,c} := FactorialDivideTermsAux(x,y); + {n,-d,c}; + ]; +]; +40 # FactorialDivideTerms( _x, _y) + <-- + [ +// Echo("GOTHERE 40"); + FactorialDivideTermsAux(x,y); + ]; + +LocalSymbols(n,d,c) +[ + 10 # FactorialDivideTermsAux(_x,_y) <-- + [ + x:=Flatten(x,"*"); + y:=Flatten(y,"*"); + + Local(i,j,common); + common:=1; + For(i:=1,i<=Length(x),i++) + For(j:=1,j<=Length(y),j++) + [ + Local(n,d,c); +//Echo("inp is ",x[i]," ",y[j]); + {n,d,c} := CommonDivisors(x[i],y[j]); + +//Echo("aux is ",{n,d,c}); + x[i] := n; + y[j] := d; + common:=common*c; + ]; +//Echo("final ",{x,y,common}); +//Echo("finalor ",{Product(x),Product(y),common}); + {Product(x),Product(y),common}; + ]; +]; + +]; + +60000 # FactorialSimplifyWorker(_x) + <-- + [ + // first separate out factors of the denominator + Local(numerCommon,numerTerms); + {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); + numerCommon*numerTerms; + ]; + +/* FactorialFlattenAddition accepts an expression of form a+b+c-d+e-f+ ... +z with arbitrary additions + and subtractions, and converts it to a list of terms. Terms that need to be subtracted start with a + negation sign (useful for pattern matching). + */ +10 # FactorialFlattenAddition(_x+_y) <-- Concat(FactorialFlattenAddition(x), FactorialFlattenAddition(y)); +10 # FactorialFlattenAddition(_x-_y) <-- Concat(FactorialFlattenAddition(x),-FactorialFlattenAddition(y)); +10 # FactorialFlattenAddition( -_y) <-- -FactorialFlattenAddition(y); +20 # FactorialFlattenAddition(_x ) <-- {x}; + +LocalSymbols(n,d,c) +[ + 10 # FactorialGroupCommonDivisors(_x) <-- + [ + Local(terms,common,tail); + terms:=FactorialFlattenAddition(x); +//Echo("terms is ",terms); + common := First(terms); + tail:=Rest(terms); + While (tail != {}) + [ + Local(n,d,c); + {n,d,c} := FactorialDivideTerms(common,First(tail)); + +//Echo(common, " ",First(tail)," ",c); + common := c; + tail:=Rest(tail); + ]; + Local(i,j); + +// Echo("common is ",common); + + For(j:=1,j<=Length(terms),j++) + [ + Local(n,d,c); +// Echo("IN = ",terms[j]," ",common); +// Echo("n = ",n); + {n,d,c} := FactorialDivideTerms(terms[j],common); +// Echo("n = ",n); +// Echo("{n,d,c} = ",{n,d,c}); + Check(d = 1, "Math", + PipeToString()[ + Echo("FactorialGroupCommonDivisors failure 1 : ",d); + ]); +/* + Check(Simplify(c-common) = 0, "Math", + PipeToString() + [ + Echo("FactorialGroupCommonDivisors failure 2 : "); + Echo(c," ",common); + Echo(Simplify(c-common)); + ]); +*/ + terms[j] := n; + ]; + terms:=Add(terms); + + common:=Flatten(common,"*"); + For(j:=1,j<=Length(common),j++) + [ + Local(f1,f2); + {f1,f2}:=CommonFactors(common[j],terms); + common[j]:=f1; + terms:=f2; + + For(i:=1,i<=Length(common),i++) + If(i != j, + [ + {f1,f2}:=CommonFactors(common[j],common[i]); + common[j]:=f1; + common[i]:=f2; + ]); + ]; + common := Product(common); + {common,terms}; + ]; +]; + + + +%/mathpiper + + + +%mathpiper_docs,name="FactorialSimplify",categories="User Functions;Expression Simplification" +*CMD FactorialSimplify --- Simplify hypergeometric expressions containing factorials +*STD +*CALL + FactorialSimplify(expression) + +*PARMS + +{expression} -- expression to simplify + +*DESC + +{FactorialSimplify} takes an expression that may contain factorials, +and tries to simplify it. An expression like $ (n+1)! / n! $ would +simplify to $(n+1)$. + +The following steps are taken to simplify: + +* 1. binomials are expanded into factorials +* 2. the expression is flattened as much as possible, to reduce it to a sum of simple rational terms +* 3. expressions like $ p^n/p^m $ are reduced to $p^(n-m)$ if $n-m$ is an integer +* 4. expressions like $ n! / m! $ are simplified if $n-m$ is an integer + +The function {Simplify} is used to determine if the relevant expressions $n-m$ +are integers. + +*E.G. + +In> FactorialSimplify( (n-k+1)! / (n-k)! ) +Result: n+1-k +In> FactorialSimplify(n! / BinomialCoefficient(n,k)) +Result: k! *(n-k)! +In> FactorialSimplify(2^(n+1)/2^n) +Result: 2 + +*SEE Simplify, !, BinomialCoefficient +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Flatten.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Flatten.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Flatten.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Flatten.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="Flatten" + +Rulebase("DoFlatten",{doflattenx}); +UnFence("DoFlatten",1); + +10 # DoFlatten(_doflattenx)_(Type(doflattenx)=flattenoper) <-- + Apply("Concat",MapSingle("DoFlatten",Rest(FunctionToList(doflattenx)))); +20 # DoFlatten(_doflattenx) <-- { doflattenx }; + + +Function("Flatten",{body,flattenoper}) +[ + DoFlatten(body); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Flatten",categories="User Functions;Lists (Operations)" +*CMD Flatten --- flatten expression w.r.t. some operator +*STD +*CALL + Flatten(expression,operator) + +*PARMS + +{expression} -- an expression + +{operator} -- string with the contents of an infix operator. + +*DESC + +Flatten flattens an expression with respect to a specific +operator, converting the result into a list. +This is useful for unnesting an expression. Flatten is typically +used in simple simplification schemes. + +*E.G. + +In> Flatten(a+b*c+d,"+"); +Result: {a,b*c,d}; +In> Flatten({a,{b,c},d},"List"); +Result: {a,b,c,d}; + +*SEE UnFlatten +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/GetNumerDenom.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/GetNumerDenom.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/GetNumerDenom.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/GetNumerDenom.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,29 @@ +%mathpiper,def="GetNumerDenom" + +/// GetNumerDenom(x) returns a pair of expressions representing normalized numerator and denominator; GetNumerDenom(x, a) multiplies the numerator by the number a +GetNumerDenom(_expr, _a) <-- GetNumerDenom(expr)*{a,1}; + +// on expressions that are not fractions, we return unit denominator +10 # GetNumerDenom(_expr)_Not(HasFuncSome(expr, "/", {ToAtom("+"), ToAtom("-"), *, /, ^})) <-- {expr, 1}; +// rational numbers are not simplified +15 # GetNumerDenom(a_IsRationalOrNumber) <-- {a, 1}; +// arithmetic +20 # GetNumerDenom(_a + _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b)); +20 # GetNumerDenom(_a - _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b, -1)); +20 # GetNumerDenom(- _a) <-- GetNumerDenom(a, -1); +20 # GetNumerDenom(+ _a) <-- GetNumerDenom(a); +20 # GetNumerDenom(_a * _b) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(b)); +20 # GetNumerDenom(_a / _b) <-- ExpandFrac'divide(GetNumerDenom(a), GetNumerDenom(b)); +// integer powers +20 # GetNumerDenom(_a ^ b_IsInteger)_(b > 1) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(a^(b-1))); +20 # GetNumerDenom(_a ^ b_IsInteger)_(b < -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a^(-b))); +20 # GetNumerDenom(_a ^ b_IsInteger)_(b = -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a)); +// non-integer powers are not considered to be rational functions +25 # GetNumerDenom(_a ^ _b) <-- {a^b, 1}; + +// arithmetic on fractions; not doing any simplification here, whereas we might want to +ExpandFrac'add({_a, _b}, {_c, _d}) <-- {a*d+b*c, b*d}; +ExpandFrac'multiply({_a, _b}, {_c, _d}) <-- {a*c, b*d}; +ExpandFrac'divide({_a, _b}, {_c, _d}) <-- {a*d, b*c}; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpAdd.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpAdd.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpAdd.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpAdd.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="SimpAdd" + +Rulebase("SimpAdd",{x,y}); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpDiv.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpDiv.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpDiv.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpDiv.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="SimpDiv" + +Rulebase("SimpDiv",{x,y}); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpExpand.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpExpand.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpExpand.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpExpand.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,8 @@ +%mathpiper,def="SimpExpand" + +10 # SimpExpand(SimpAdd(_x,_y)) <-- SimpExpand(x) + SimpExpand(y); +10 # SimpExpand(SimpMul(_x,_y)) <-- SimpExpand(x) * SimpExpand(y); +10 # SimpExpand(SimpDiv(_x,_y)) <-- SimpExpand(x) / SimpExpand(y); +20 # SimpExpand(_x) <-- x; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpFlatten.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpFlatten.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpFlatten.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpFlatten.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="SimpFlatten" + +10 # SimpFlatten((_x)+(_y)) <-- SimpAdd(SimpFlatten(x),SimpFlatten(y)); +10 # SimpFlatten((_x)-(_y)) <-- SimpAdd(SimpFlatten(x),SimpMul(-1,SimpFlatten(y))); +10 # SimpFlatten( -(_y)) <-- SimpMul(-1,SimpFlatten(y)); + +10 # SimpFlatten((_x)*(_y)) <-- SimpMul(SimpFlatten(x),SimpFlatten(y)); +10 # SimpFlatten((_x)/(_y)) <-- SimpDiv(SimpFlatten(x),SimpFlatten(y)); +10 # SimpFlatten((_x)^(n_IsPositiveInteger)) <-- + SimpMul(SimpFlatten(x),SimpFlatten(x^(n-1))); + +100 # SimpFlatten(_x) <-- +[ + x; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpImplode.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpImplode.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpImplode.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpImplode.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,25 @@ +%mathpiper,def="SimpImplode" + +/* Distributed multiplication rule */ +10 # SimpImplode(SimpMul(SimpAdd(_x,_y),_z)) <-- + SimpImplode(SimpAdd(SimpImplode(SimpMul(x,z)), + SimpImplode(SimpMul(y,z)))); +10 # SimpImplode(SimpMul(_z,SimpAdd(_x,_y))) <-- + SimpImplode(SimpAdd(SimpImplode(SimpMul(z,x)), + SimpImplode(SimpMul(z,y)))); +/* Distributed division rule */ +10 # SimpImplode(SimpDiv(SimpAdd(_x,_y),_z)) <-- + SimpImplode(SimpAdd(SimpImplode(SimpDiv(x,z)), + SimpImplode(SimpDiv(y,z)))); + + + +20 # SimpImplode(SimpAdd(_x,_y)) <-- + SimpAdd(SimpImplode(x),SimpImplode(y)); +20 # SimpImplode(SimpMul(_x,_y)) <-- + SimpMul(SimpImplode(x),SimpImplode(y)); +20 # SimpImplode(SimpDiv(_x,_y)) <-- + SimpDiv(SimpImplode(x),SimpImplode(y)); +30 # SimpImplode(_x) <-- x; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Simplify.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Simplify.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/Simplify.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/Simplify.mpw 2011-02-20 07:11:28.000000000 +0000 @@ -0,0 +1,68 @@ +%mathpiper,def="Simplify" + +//Retract("Simplify",*); + +10 # Simplify(expr_IsList) <-- MapSingle("Simplify",expr); + +15 # Simplify(Complex(_r,_i)) <-- Complex(Simplify(r),Simplify(i)); + +20 # Simplify((_xex) == (_yex)) <-- (Simplify(xex-yex) == 0); + +20 # Simplify((_xex) > (_yex)) <-- (Simplify(xex-yex) > 0); +20 # Simplify((_xex) < (_yex)) <-- (Simplify(xex-yex) < 0); +20 # Simplify((_xex) >= (_yex)) <-- (Simplify(xex-yex) >= 0); +20 # Simplify((_xex) <= (_yex)) <-- (Simplify(xex-yex) <= 0); +20 # Simplify((_xex) !== (_yex)) <-- (Simplify(xex-yex) !== 0); + +// conditionals +25 # Simplify(if (_a) _b) <-- "if" @ {Simplify(a), Simplify(b)}; +25 # Simplify(_a else _b) <-- "else" @ {Simplify(a), Simplify(b)}; + +// otherwise +40 # Simplify(_expr)_(Type(expr)="Ln") <-- +[ + //If(InVerboseMode(),Tell("Simplify_Ln",expr)); + LnCombine(expr); +]; + +40 # Simplify(_expr)_(Type(expr)="Exp") <-- +[ + //If(InVerboseMode(),Tell("Simplify_Exp",expr)); + expr; +]; + +50 # Simplify(_expr) <-- +[ + //If(InVerboseMode(),Tell("Simplify_other",expr)); + MultiSimp(Eval(expr)); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Simplify",categories="User Functions;Expression Simplification" +*CMD Simplify --- try to simplify an expression +*STD +*CALL + Simplify(expr) + +*PARMS + +{expr} -- expression to simplify + +*DESC + +This function tries to simplify the expression {expr} as much +as possible. It does this by grouping powers within terms, and then +grouping similar terms. + +*E.G. + +In> a*b*a^2/b-a^3 +Result: (b*a^3)/b-a^3; +In> Simplify(a*b*a^2/b-a^3) +Result: 0; + +*SEE TrigSimpCombine, RadSimp, Combine +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpMul.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpMul.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/SimpMul.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/SimpMul.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="SimpMul" + +Rulebase("SimpMul",{x,y}); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/UnFlatten.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/UnFlatten.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/simplify/UnFlatten.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/simplify/UnFlatten.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="UnFlatten" + +10 # UnFlatten({},_op,_identity) <-- identity; +20 # UnFlatten(list_IsList,_op,_identity) <-- + Apply(op,{First(list),UnFlatten(Rest(list),op,identity)}); + +%/mathpiper + + + +%mathpiper_docs,name="UnFlatten",categories="User Functions;Lists (Operations)" +*CMD UnFlatten --- inverse operation of Flatten +*STD +*CALL + UnFlatten(list,operator,identity) + +*PARMS + +{list} -- list of objects the operator is to work on + +{operator} -- infix operator + +{identity} -- identity of the operator + +*DESC + +UnFlatten is the inverse operation of Flatten. Given +a list, it can be turned into an expression representing +for instance the addition of these elements by calling +UnFlatten with "+" as argument to operator, and 0 as +argument to identity (0 is the identity for addition, since +a+0=a). For multiplication the identity element would be 1. + +*E.G. + +In> UnFlatten({a,b,c},"+",0) +Result: a+b+c; +In> UnFlatten({a,b,c},"*",1) +Result: a*b*c; + +*SEE Flatten +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/Assume.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/Assume.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/Assume.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/Assume.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,156 @@ +%mathpiper,def="Assume" + +//Retract("Assume",*); +//Retract("AssumptionsAbout",*); +//Retract("UnAssume",*); +//Retract("IsAssumed",*); +//Retract("AssumptionsGet",*); + +LocalSymbols(assumptions) [ + +assumptions := {}; + +10 # Assume( L_IsList ) <-- +[ + If(InVerboseMode(),Tell("AssumeLst",L)); + Local(len,s); + len := Length(L); + If( len > 0, ForEach(s,L) [ Assume(s); ] ); + assumptions; +]; + + +10 # Assume( _x -> _y ) <-- +[ + If(InVerboseMode(),Tell("AssumeItem",{x,y})); + Local(key,value); + key := Hold(x); + value := Hold(y); + If(InVerboseMode(),Tell(" ",{key,value})); + + DestructiveAppend(assumptions,{Eval(key),Eval(value)}); + assumptions; +]; + + +10 # AssumptionsGet() <-- assumptions; + + +10 # AssumptionsAbout(_key) <-- +[ + Local(props); + props := Select(assumptions,Lambda({X},X[1]=key)); + If( Length(props) > 0, Transpose(props)[2], {} ); +]; + + +10 # IsAssumed( _key, _valueExpected ) <-- Contains(AssumptionsAbout(key),valueExpected); + + +10 # UnAssume( _x )_(Contains(AssocIndices(assumptions),x)) <-- +[ + Local(lst,len,jj); + lst := Lambda({X},If(IsList(X),X[1])) /@ assumptions; + jj := Find(lst,x); + If( jj > 0, DestructiveDelete(assumptions,jj) ); + lst := Lambda({X},If(IsList(X),X[1])) /@ assumptions; + jj := Find(lst,x); + If( jj > 0, UnAssume(x), True ); +]; + +]; // LocalSymbols + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="Assume",categories="User Functions;Solvers (Symbolic)" +*CMD Assume --- a suite of functions for specifying and testing "assumptions" about unbound variables +*STD +*CALL + Assume(v -> prop) + Assume({v1 -> prop1, v2 -> prop2}} + UnAssume(v) + AssumptionsGet() + AssumptionsAbout(v) + IsAssumed(v,prop) + +*PARMS + +{v} -- an unbound variable or parameter + +{v1,v2,...} -- different unbound variables or parameters + +{prop} -- a 'property' to be attached to a variable or parameter + +{prop1,prop2,...} -- different 'properties' to be attached to different variables + +{assumptions} -- a normally-hidden associative list which stores the assumptions* + +*DESC + +This is a suite of functions which permit the user to specify (or 'attach') +{properties} to unbound variables or parameters to be used in the current +MathPiper session. + +Once a property has been attached to a variable, the user, or some function +called by the user, can query or test a given variable to see what properties +it has, or whether it has a specific property. Actions may be taken based on +the results of such query or test. + +Once Assume'd, properties remain associated with their variable until the +session ends, or until the user specifically calls {UnAssume} on that variable. +Once {UnAssume'd}, the variable thereafter has no properites, unless properties +are later added using {AddAssumption} or {AddAssumptions}. + +Ordinarily, the user would specify all properties just once in a session. However, +s/he may call Assume() multiple times in a session, and each such call simply augments +the 'hidden' list of assumptions by adding the new ones. Note that new assumptions +for a given variable are {added}, and nothing is {replaced}. Therefore, it is the +user's responsibility to avoid creating mutually-contradictory lists of properties. + +NOTE: All assumptions are lost once the session ends. + +NOTE: The user can employ these property lists as s/he sees fit. Currently, none of +MathPiper's functions make any use of assumptions. However, these can be very useful +especially in certain types of {Solve} or {Integrate} situations, so MathPiper's +functions are being modified to make use of assumptions where appropriate. +*E.G. + + +In> Assume(x->real) +Result: {{x,real}} +In> AssumptionsGet() +Result: {{x,real}} +In> IsAssumed(x,real) +Result: True +In> IsAssumed(z,complex) +Result: False + +In> Assume({x->positive,y->positive}) +Result: {{x,real},{x,positive},{y,positive}} +In> AssumptionsGet() +Result: {{x,real},{x,positive},{y,positive}} +In> AssumptionsAbout(x) +Result: {real,positive} +In> UnAssume(x) +Result: True +In> AssumptionsAbout(x) +Result: {} +In> AssumptionsGet() +Result: {{y,positive}} +*SEE Solve, Integrate +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/CheckSolution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/CheckSolution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/CheckSolution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/CheckSolution.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,77 @@ +%mathpiper,def="CheckSolution" + +//Retract("CheckSolution",*); + +10 # CheckSolution( _expr, _var, solution_IsList )_(Not IsFreeOf(var,expr)) <-- + [ + Local(expr0,result,s,r); + If( IsEquation(expr), + Bind(expr0,EquationLeft(expr)-EquationRight(expr)), + Bind(expr0,expr) + ); + result := {}; + ForEach(s,solution) + [ + r := ( expr0 Where s ); + If(r=0,Push(result,s)); + ]; + Reverse(result); + ]; + + +20 # CheckSolution( _expr, _var, _solution ) <-- False; + +%/mathpiper + + + + + +%mathpiper_docs,name="CheckSolution",categories="User Functions;Solvers (Symbolic)" + +*CMD CheckSolution --- Check the validity of solutions returned by the {Solve} function. +*STD +*CALL + CheckSolution(expr,var,solution) + +*PARMS + +{expr} -- a mathematical expression +{var} -- a varible identifier +{solution} -- a List containing solutions to the equation. + + +*DESC + +The function {Solve} will attempt to find solutions to the equation +{expr}, if {expr} is an actual equatio), or to the equivalent equation +represented by {expr==0} if {expr} is NOT an equation. + +Solutions returned by {Solve} will be in the form of a List, such as +{{var==something,var==something_else}}. + +For certain types of expressions or equation, {Solve} might return +invalid solutions as well as valid ones in the output List. To check +the list of solutions, call the function CheckSolutions(). This function +will return a list containing only the valid solutions from among those +in the list (if any). If none of the "solutions" is valid, this +function will return the empty list. + +*E.G. + +In> ss1 := Solve(x^2==4,x) + +Result: {x==2,x==(-2)} + +In> CheckSolution(x^2==4,x,ss1) + +Result: {x==2,x==(-2)} + +In> CheckSolution(x^2==4,x,{x==2,x==3}) // Deliberately incorrect + +Result: {x==2} + +%/mathpiper_docs + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/jSolveUniPoly.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/jSolveUniPoly.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/jSolveUniPoly.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/jSolveUniPoly.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,70 @@ +%mathpiper,def="jSolveUniPoly" + +//Retract("jSolveUniPoly",*); + +10 # jSolveUniPoly( _lhs==_rhs, var_IsAtom ) <-- +[ + jSolveUniPoly(lhs-rhs,var); +]; + +15 # jSolveUniPoly( poly_IsPolynomial, var_IsAtom )_(Length(VarList(poly))=1) <-- +[ + If(InVerboseMode(),Tell(jSolveUniPoly,{poly,var})); + Local(factorList,f,fac,mult,ii,answer); + factorList := Factors(poly); + If(InVerboseMode(),Tell(" ",factorList)); + answer := {}; + ForEach(f,factorList) + [ + {fac,mult} := f; + soln := Solve(fac,var); + If(InVerboseMode(),[Tell(" ",{fac,mult});Tell(" ",soln);]); + ForEach(ii,1 .. mult) + [ DestructiveAppend(answer,soln); ]; + ]; + answer; +]; + +20 # jSolveUniPoly( poly_IsPolynomial, var_IsAtom ) <-- Failed; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="jSolveUniPoly",categories="User Functions;Solvers (Symbolic)" +*CMD jSolveUniPoly --- solve (find the roots of) a strictly univariate polynomial using JAS +*STD +*CALL + jSolveUniPoly(eq, var) + +*PARMS + +{eq} -- equation to solve + +{var} -- variable to solve for + +*DESC + +This command tries to solve the polynomial equation by factoring. +If {eq} does not contain the {==} operator, it is assumed that the +user wants to solve $eq ==0$. +The result is a list of equations of the form {var == value}, each +representing a solution of the given equation. The {Where} operator +can be used to substitute this solution in another expression. If the +given equation {eq} does not have any solutions, or if {jSolveUniPoly} is +unable to find any, then an empty list is returned. + +*SEE Solve, PSolve, Where, == +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/Newton.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/Newton.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/Newton.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/Newton.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,86 @@ +%mathpiper,def="Newton" + +Function("Newton",{function,variable,initial,accuracy}) +[ // since we call a function with HoldArgument(), we need to evaluate some variables by hand + `Newton(@function,@variable,initial,accuracy,-Infinity,Infinity); +]; + +Function("Newton",{function,variable,initial,accuracy,min,max}) +[ + Local(result,adjust,delta,requiredPrec); + MacroLocal(variable); + requiredPrec := BuiltinPrecisionGet(); + accuracy:=N((accuracy/10)*10); // Making sure accuracy is rounded correctly + BuiltinPrecisionSet(requiredPrec+2); + function:=N(function); + adjust:= -function/Apply("Differentiate",{variable,function}); + delta:=10000; + result:=initial; + While (result > min And result < max + // avoid numerical underflow due to fixed point math, FIXME when have real floating math + And N(Eval( Maximum(Re(delta), -Re(delta), Im(delta), -Im(delta)) ) ) > accuracy) + [ + MacroBind(variable,result); + delta:=N(Eval(adjust)); + result:=result+delta; + ]; + + BuiltinPrecisionSet(requiredPrec); + result:=N(Eval((result/10)*10)); // making sure result is rounded to correct precision + if (result <= min Or result >= max) [result := Fail;]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Newton",categories="User Functions;Solvers (Numeric) +*CMD Newton --- solve an equation numerically with Newton's method +*STD +*CALL + Newton(expr, var, initial, accuracy) + Newton(expr, var, initial, accuracy,min,max) + +*PARMS + +{expr} -- an expression to find a zero for + +{var} -- free variable to adjust to find a zero + +{initial} -- initial value for "var" to use in the search + +{accuracy} -- minimum required accuracy of the result + +{min} -- minimum value for "var" to use in the search + +{max} -- maximum value for "var" to use in the search + +*DESC + +This function tries to numerically find a zero of the expression +{expr}, which should depend only on the variable {var}. It uses +the value {initial} as an initial guess. + +The function will iterate using Newton's method until it estimates +that it has come within a distance {accuracy} of the correct +solution, and then it will return its best guess. In particular, it +may loop forever if the algorithm does not converge. + +When {min} and {max} are supplied, the Newton iteration takes them +into account by returning {Fail} if it failed to find a root in +the given range. Note this doesn't mean there isn't a root, just +that this algorithm failed to find it due to the trial values +going outside of the bounds. + +*E.G. + +In> Newton(Sin(x),x,3,0.0001) +Result: 3.1415926535; +In> Newton(x^2-1,x,2,0.0001,-5,5) +Result: 1; +In> Newton(x^2+1,x,2,0.0001,-5,5) +Result: Fail; + +*SEE Solve, NewtonNum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/OldSolve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/OldSolve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/OldSolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/OldSolve.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,229 @@ +%mathpiper,def="OldSolve" +/********** Solve'System **********/ + +// for now, just use a very simple backsubstitution scheme +Solve'System(_eqns, _vars) <-- Solve'SimpleBackSubstitution(eqns,vars); + +// Check(False, "Unimplemented", "Solve'System: not implemented"); + +10 # Solve'SimpleBackSubstitution'FindAlternativeForms((_lx) == (_rx)) <-- +[ + Local(newEq); + newEq := (Simplify(lx) == Simplify(rx)); + If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq)); + newEq := (Simplify(lx - rx) == 0); + If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq)); +]; +20 # Solve'SimpleBackSubstitution'FindAlternativeForms(_equation) <-- +[ +]; +UnFence("Solve'SimpleBackSubstitution'FindAlternativeForms",1); + +/* Solving sets of equations using simple backsubstitution. + * Solve'SimpleBackSubstitution takes all combinations of equations and + * variables to solve for, and it then uses SuchThat to find an expression + * for this variable, and then if found backsubstitutes it in the other + * equations in the hope that they become simpler, resulting in a final + * set of solutions. + */ +10 # Solve'SimpleBackSubstitution(eq_IsList,var_IsList) <-- +[ + If(InVerboseMode(), Echo({"Entering Solve'SimpleBackSubstitution"})); + + Local(result,i,j,nrvar,nreq,sub,nrSet,origEq); + eq:=FlatCopy(eq); + origEq:=FlatCopy(eq); + nrvar:=Length(var); + result:={FlatCopy(var)}; + nrSet := 0; + +//Echo("Before: ",eq); + ForEach(equation,origEq) + [ +//Echo("equation ",equation); + Solve'SimpleBackSubstitution'FindAlternativeForms(equation); + ]; +// eq:=Simplify(eq); +//Echo("After: ",eq); + + nreq:=Length(eq); + + /* Loop over each variable, solving for it */ + +/* Echo({eq}); */ + + For(j:=1,j<=nreq And nrSet < nrvar,j++) + [ + Local(vlist); + vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt))); + For(i:=1,i<=nrvar And nrSet < nrvar,i++) + [ + +//Echo("eq[",j,"] = ",eq[j]); +//Echo("var[",i,"] = ",var[i]); +//Echo("varlist = ",vlist); +//Echo(); + + If(Count(vlist,var[i]) = 1, + [ + sub := FunctionToList(eq[j]); + sub := sub[2]-sub[3]; +//Echo("using ",sub); + sub:=SuchThat(sub,var[i]); + If(InVerboseMode(), Echo({"From ",eq[j]," it follows that ",var[i]," = ",sub})); + If(SolveFullSimplify=True, + result:=Simplify(Subst(var[i],sub)result), + result[1][i]:=sub + ); +//Echo("result = ",result," i = ",i); + nrSet++; + +//Echo("current result is ",result); + Local(k,reset); + reset:=False; + For(k:=1,k<=nreq And nrSet < nrvar,k++) + If(Contains(VarListAll(eq[k],`Lambda({pt},Contains(@var,pt))),var[i]), + [ + Local(original); + original:=eq[k]; + eq[k]:=Subst(var[i],sub)eq[k]; + If(Simplify(Simplify(eq[k])) = (0 == 0), + eq[k] := (0 == 0), + Solve'SimpleBackSubstitution'FindAlternativeForms(eq[k]) + ); +// eq[k]:=Simplify(eq[k]); +// eq[k]:=Simplify(eq[k]); //@@@??? TODO I found one example where simplifying twice gives a different result from simplifying once! + If(original!=(0==0) And eq[k] = (0 == 0),reset:=True); + If(InVerboseMode(), Echo({" ",original," simplifies to ",eq[k]})); + ]); + nreq:=Length(eq); + vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt))); + i:=nrvar+1; + // restart at the beginning of the variables. + If(reset,j:=1); + ]); + ]; + ]; + + +//Echo("Finished finding results ",var," = ",result); +// eq:=origEq; +// nreq := Length(eq); + Local(zeroeq,tested); + tested:={}; +// zeroeq:=FillList(0==0,nreq); + + ForEach(item,result) + [ +/* + Local(eqSimplified); + eqSimplified := eq; + ForEach(map,Transpose({var,item})) + [ + eqSimplified := Subst(map[1],map[2])eqSimplified; + ]; + eqSimplified := Simplify(Simplify(eqSimplified)); + + Echo(eqSimplified); + + If(eqSimplified = zeroeq, + [ + DestructiveAppend(tested,Map("==",{var,item})); + ]); +*/ + DestructiveAppend(tested,Map("==",{var,item})); + ]; + + + +/* Echo({"tested is ",tested}); */ + If(InVerboseMode(), Echo({"Leaving Solve'SimpleBackSubstitution"})); + tested; +]; + + + + +/********** OldSolve **********/ +10 # OldSolve(eq_IsList,var_IsList) <-- Solve'SimpleBackSubstitution(eq,var); + + +90 # OldSolve((left_IsList) == right_IsList,_var) <-- + OldSolve(Map("==",{left,right}),var); + + +100 # OldSolve(_left == _right,_var) <-- + SuchThat(left - right , 0 , var); + +/* HoldArgument("OldSolve",arg1); */ +/* HoldArgument("OldSolve",arg2); */ + +%/mathpiper + + + +%mathpiper_docs,name="OldSolve",categories="User Functions;Solvers (Symbolic)" +*CMD OldSolve --- old version of {Solve} +*STD +*CALL + OldSolve(eq, var) + OldSolve(eqlist, varlist) + +*PARMS + +{eq} -- single identity equation + +{var} -- single variable + +{eqlist} -- list of identity equations + +{varlist} -- list of variables + +*DESC + +This is an older version of {Solve}. It is retained for two +reasons. The first one is philosophical: it is good to have multiple +algorithms available. The second reason is more practical: the newer +version cannot handle systems of equations, but {OldSolve} can. + +This command tries to solve one or more equations. Use the first form +to solve a single equation and the second one for systems of +equations. + +The first calling sequence solves the equation "eq" for the variable +"var". Use the {==} operator to form the equation. +The value of "var" which satisfies the equation, is returned. Note +that only one solution is found and returned. + +To solve a system of equations, the second form should be used. It +solves the system of equations contained in the list "eqlist" for +the variables appearing in the list "varlist". A list of results is +returned, and each result is a list containing the values of the +variables in "varlist". Again, at most a single solution is +returned. + +The task of solving a single equation is simply delegated to {SuchThat}. Multiple equations are solved recursively: +firstly, an equation is sought in which one of the variables occurs +exactly once; then this equation is solved with {SuchThat}; and finally the solution is substituted in the +other equations by {Eliminate} decreasing the number +of equations by one. This suffices for all linear equations and a +large group of simple nonlinear equations. + +*E.G. + +In> OldSolve(a+x*y==z,x) +Result: (z-a)/y; +In> OldSolve({a*x+y==0,x+z==0},{x,y}) +Result: {{-z,z*a}}; + +This means that "x = (z-a)/y" is a solution of the first equation +and that "x = -z", "y = z*a" is a solution of the systems of +equations in the second command. + +An example which {OldSolve} cannot solve: + +In> OldSolve({x^2-x == y^2-y,x^2-x == y^3+y},{x,y}); +Result: {}; + +*SEE Solve, SuchThat, Eliminate, PSolve, == +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/PSolve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/PSolve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/PSolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/PSolve.mpw 2010-08-28 23:18:05.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="PSolve" + +PSolve( _uni ) <-- YacasPSolve( uni ); + +PSolve( _uni, _var ) <-- YacasPSolve( uni, var ); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/SolveMatrix.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/SolveMatrix.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/SolveMatrix.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/SolveMatrix.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,65 @@ +%mathpiper,def="SolveMatrix" + +Function("SolveMatrix",{matrix,vector}) +[ + If(InVerboseMode(),Tell(" SolveMatrix",{matrix,vector})); + Local(perms,indices,inv,det,n); + n:=Length(matrix); + indices:=Table(i,i,1,n,1); + perms:=PermutationsList(indices); + inv:=ZeroVector(n); + det:=0; + ForEach(item,perms) + [ + Local(i,lc); + lc := LeviCivita(item); + det:=det+Product(i,1,n,matrix[i][item[i] ])* lc; + For(i:=1,i<=n,i++) + [ + inv[i] := inv[i]+ + Product(j,1,n, + If(item[j] =i,vector[j ],matrix[j][item[j] ]))*lc; + ]; + ]; + Check(det != 0, "Math", "Zero determinant"); + (1/det)*inv; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="SolveMatrix",categories="User Functions;Linear Algebra;Solvers (Symbolic)" +*CMD SolveMatrix --- solve a linear system +*STD +*CALL + SolveMatrix(M,v) + +*PARMS + +{M} -- a matrix + +{v} -- a vector + +*DESC + +{SolveMatrix} returns the vector $x$ that satisfies +the equation $M*x = v$. The determinant of $M$ should be non-zero. + +*E.G. + +In> A := {{1,2}, {3,4}}; +Result: {{1,2},{3,4}}; +In> v := {5,6}; +Result: {5,6}; +In> x := SolveMatrix(A, v); +Result: {-4,9/2}; +In> A * x; +Result: {5,6}; + +*SEE Inverse, Solve, PSolve, Determinant +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/solve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/solve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/solve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/solve.mpw 2011-04-14 12:58:17.000000000 +0000 @@ -0,0 +1,375 @@ +%mathpiper,def="Solve" + +//Retract("Solve",*); + +/* + * Strategy for Solve(expr, x): + * + * 10. Call SolveSystem for systems of equations [now in its own file] + * 20. Check arguments. + * 30. Get rid of "==" in 'expr'. + * 40. Special cases. + * 50. If 'expr' is a polynomial in 'x', try to use PSolve. + * 60. If 'expr' is a product, solve for either factor. + * 70. If 'expr' is a quotient, solve for the denominator. + * 80. If 'expr' is a sum and one of the terms is free of 'x', + * try to use Solve'Simple. + * 90. If every occurance of 'x' is in the same context, use this to reduce + * the equation. For example, in 'Cos(x) + Cos(x)^2 == 1', the variable + * 'x' always occurs in the context 'Cos(x)', and hence we can attack + * the equation by first solving 'y + y^2 == 1', and then 'Cos(x) == y'. + * This does not work for 'Exp(x) + Cos(x) == 2'. + * 100. Apply Simplify to 'expr', and try again. + * 110. Give up. + */ + +LocalSymbols(res) +[ + 10 # Solve(expr_IsList, var_IsList) <-- SolveSystem(expr, var); + 12 # Solve(_expr, var_IsList)_(Length(var)=1) <-- + [ {Solve(expr,var[1])}; ]; + + 20 # Solve(_expr, _var)_(IsNumber(var) Or IsString(var)) <-- + [ Assert("Solve'TypeError", "Second argument, ":(PipeToString() Write(var)):", is not the name of a variable") False; {}; ]; + 22 # Solve(_expr, _var)_(Not IsAtom(var) And Not HasExpr(expr,var)) <-- + [ Assert("Solve'TypeError", "Second argument, ":(PipeToString() Write(var)):", is not the name of a variable") False; {}; ]; + 24 # Solve(False,_var) <-- Check(False, "Argument", "Bad input: possibly '=' instead of '==' "); + + 30 # Solve(_lhs == _rhs, _var) <-- Solve(lhs - rhs, var); + 40 # Solve(0, _var) <-- {var == var}; + 41 # Solve(a_IsConstant, _var) <-- {}; + 42 # Solve(_expr, _var)_(Not HasExpr(expr,var)) <-- + [ Assert("Solve", "expression ":(PipeToString() Write(expr)):" does not depend on ":PipeToString() Write(var)) False; {}; ]; + 50 # Solve(_expr, _var)_((res := Solve'Poly(expr, var)) != Failed) <-- res; + 60 # Solve(_e1 * _e2, _var) <-- [ + Local(t,u,s); + t := Union(Solve(e1,var), Solve(e2,var)); + u := {}; + ForEach(s, t) [ + Local(v1,v2); + v1 := WithValue(var, s[2], e1); + v2 := WithValue(var, s[2], e2); + If(Not (IsInfinity(v1) Or (v1 = Undefined) Or + IsInfinity(v2) Or (v2 = Undefined)), + DestructiveAppend(u, s)); + ]; + u; + ]; + 70 # Solve(_e1 / _e2, _var) <-- [ + Local(tn, t, s); + tn := Solve(e1, var); + t := {}; + ForEach(s, tn) + If(Not(IsZero(WithValue(var, s[2], e2))), + DestructiveAppend(t, s) + ); + t; + ]; + 80 # Solve(_e1 + _e2, _var)_(Not HasExpr(e2,var) And (res := Solve'Simple(e1,-e2,var)) != Failed) <-- res; + 80 # Solve(_e1 + _e2, _var)_(Not HasExpr(e1,var) And (res := Solve'Simple(e2,-e1,var)) != Failed) <-- res; + 80 # Solve(_e1 - _e2, _var)_(Not HasExpr(e2,var) And (res := Solve'Simple(e1,e2,var)) != Failed) <-- res; + 80 # Solve(_e1 - _e2, _var)_(Not HasExpr(e1,var) And (res := Solve'Simple(e2,e1,var)) != Failed) <-- res; + 85 # Solve(_expr, _var)_((res := Solve'Simple(expr, 0, var)) != Failed) <-- res; + 90 # Solve(_expr, _var)_((res := Solve'Reduce(expr, var)) != Failed) <-- res; + 95 # Solve(_expr, _var)_((res := Solve'Divide(expr, var)) != Failed) <-- res; + 100 # Solve(_expr, _var)_((res := Simplify(expr)) != expr) <-- Solve(res, var); + 110 # Solve(_expr, _var) <-- + [ Assert("Solve'Fails", "cannot solve equation ":(PipeToString() Write(expr)):" for ":PipeToString() Write(var)) False; {}; ]; +]; + +/********** Solve'Poly **********/ + +/* Tries to solve by calling PSolve */ +/* Returns Failed if this doesn't work, and the solution otherwise */ + +/* CanBeUni is not documented, but defined in univar.rep/code.mpi */ +/* It returns True iff 'expr' is a polynomial in 'var' */ + +10 # Solve'Poly(_expr, _var)_(Not CanBeUni(var, expr)) <-- Failed; + +/* The call to PSolve can have three kind of results + * 1) PSolve returns a single root + * 2) PSolve returns a list of roots + * 3) PSolve remains unevaluated + */ + +20 # Solve'Poly(_expr, _var) <-- +LocalSymbols(x) +[ + Local(roots); + roots := PSolve(expr, var); + If(Type(roots) = "YacasPSolve", + If(roots = YacasPSolve(0), {var == var}, Failed), /* Case 3 */ + If(Type(roots) = "List", + MapSingle({{x},var==x}, roots), /* Case 2 */ + {var == roots})); /* Case 1 */ +]; + +/********** Solve'Reduce **********/ + +/* Tries to solve by reduction strategy */ +/* Returns Failed if this doesn't work, and the solution otherwise */ + +10 # Solve'Reduce(_expr, _var) <-- +[ + ClearError("Solve'Fails"); // ..in case one was left over from prior failure + Local(context, expr2, var2, res, sol, sol2, i); + context := Solve'Context(expr, var); + If(context = False, + res := Failed, + [ + expr2 := Eval(Subst(context, var2) expr); + If(CanBeUni(var2, expr2) And (Degree(expr2, var2) = 0 Or (Degree(expr2, var2) = 1 And Coef(expr2, var2, 1) = 1)), + res := Failed, /* to prevent infinite recursion */ + [ + sol2 := Solve(expr2, var2); + If(IsError("Solve'Fails"), + [ + ClearError("Solve'Fails"); + res := Failed; + ], + [ + res := {}; + i := 1; + While(i <= Length(sol2) And res != Failed) [ + sol := Solve(context == (var2 Where sol2[i]), var); + If(IsError("Solve'Fails"), + [ + ClearError("Solve'Fails"); + res := Failed; + ], + res := Union(res, sol)); + i++; + ]; + ]); + ]); + ]); + res; +]; + +/********** Solve'Context **********/ + +/* Returns the unique context of 'var' in 'expr', */ +/* or {} if 'var' does not occur in 'expr', */ +/* or False if the context is not unique. */ + +10 # Solve'Context(expr_IsAtom, _var) <-- If(expr=var, var, {}); + +20 # Solve'Context(_expr, _var) <-- +[ + Local(lst, foundVarP, context, i, res); + lst := FunctionToList(expr); + foundVarP := False; + i := 2; + While(i <= Length(lst) And Not foundVarP) [ + foundVarP := (lst[i] = var); + i++; + ]; + If(foundVarP, + context := expr, + [ + context := {}; + i := 2; + While(i <= Length(lst) And context != False) [ + res := Solve'Context(lst[i], var); + If(res != {} And context != {} And res != context, context := False); + If(res != {} And context = {}, context := res); + i++; + ]; + ]); + context; +]; + +/********** Solve'Simple **********/ + +/* Simple solver of equations + * + * Returns (possibly empty) list of solutions, + * or Failed if it cannot handle the equation + * + * Calling format: Solve'Simple(lhs, rhs, var) + * to solve 'lhs == rhs'. + * + * Note: 'rhs' should not contain 'var'. + */ + +20 # Solve'Simple(_e1 + _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs-e2 }; +20 # Solve'Simple(_e1 + _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == rhs-e1 }; + +20 # Solve'Simple(_e1 - _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs+e2 }; +20 # Solve'Simple(_e1 - _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == e1-rhs }; +20 # Solve'Simple(-(_e1), _rhs, _var)_(e1 = var) <-- { var == -rhs }; + +20 # Solve'Simple(_e1 * _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs/e2 }; +20 # Solve'Simple(_e1 * _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == rhs/e1 }; + +20 # Solve'Simple(_e1 / _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs*e2 }; +10 # Solve'Simple(_e1 / _e2, 0, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { }; +20 # Solve'Simple(_e1 / _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == e1/rhs }; + +LocalSymbols(x) +[ + 20 # Solve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsPositiveInteger(n)) + <-- MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. n)/n)); + 20 # Solve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsNegativeInteger(n)) + <-- MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. (-n))/(-n))); +]; + +20 # Solve'Simple(_e1 ^ _e2, _rhs, _var) + _ (IsPositiveReal(e1) And e1 != 0 And e2 = var And IsPositiveReal(rhs) And rhs != 0) + <-- { var == Ln(rhs)/Ln(e1) }; + +/* Note: These rules do not take the periodicity of the trig. functions into account */ +10 # Solve'Simple(Sin(_e1), 1, _var)_(e1 = var) <-- { var == 1/2*Pi }; +10 # Solve'Simple(Sin(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- { var == 3/2*Pi }; +20 # Solve'Simple(Sin(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcSin(rhs), var == Pi-ArcSin(rhs) }; +10 # Solve'Simple(Cos(_e1), 1, _var)_(e1 = var) <-- { var == 0 }; +10 # Solve'Simple(Cos(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- { var == Pi }; +20 # Solve'Simple(Cos(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcCos(rhs), var == -ArcCos(rhs) }; +20 # Solve'Simple(Tan(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcTan(rhs) }; + +20 # Solve'Simple(ArcSin(_e1), _rhs, _var)_(e1 = var) <-- { var == Sin(rhs) }; +20 # Solve'Simple(ArcCos(_e1), _rhs, _var)_(e1 = var) <-- { var == Cos(rhs) }; +20 # Solve'Simple(ArcTan(_e1), _rhs, _var)_(e1 = var) <-- { var == Tan(rhs) }; + +/* Note: Second rule neglects (2*I*Pi)-periodicity of Exp() */ +10 # Solve'Simple(Exp(_e1), 0, _var)_(e1 = var) <-- { }; +20 # Solve'Simple(Exp(_e1), _rhs, _var)_(e1 = var) <-- { var == Ln(rhs) }; +20 # Solve'Simple(_b^_e1, _rhs, _var)_(e1 = var And IsFreeOf(var,b) And Not IsZero(b)) <-- { var == Ln(rhs) / Ln(b) }; +20 # Solve'Simple(Ln(_e1), _rhs, _var)_(e1 = var) <-- { var == Exp(rhs) }; + +/* The range of Sqrt is the set of (complex) numbers with either + * positive real part, together with the pure imaginary numbers with + * nonnegative real part. */ +20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsPositiveReal(Re(rhs)) And Re(rhs) != 0) <-- { var == rhs^2 }; +20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsPositiveReal(Im(rhs))) <-- { var == rhs^2 }; +20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsNegativeReal(Im(rhs)) And Im(rhs) != 0) <-- { }; +20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsNegativeReal(Re(rhs)) And Re(rhs) != 0) <-- { }; + +30 # Solve'Simple(_lhs, _rhs, _var) <-- Failed; + + +/********** Solve'Divide **********/ +/* For some classes of equations, it may be easier to solve them if we + * divide through by their first term. A simple example of this is the + * equation Sin(x)+Cos(x)==0 + * One problem with this is that we may lose roots if the thing we + * are dividing by shares roots with the whole equation. + * The final HasExprs are an attempt to prevent infinite recursion caused by + * the final Simplify step in Solve undoing what we do here. It's conceivable + * though that this won't always work if the recurring loop is more than two + * steps long. I can't think of any ways this can happen though :) + */ + +10 # Solve'Divide(_e1 + _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) + And Not (HasExpr(Simplify(1 + (e2/e1)), e1) + Or HasExpr(Simplify(1 + (e2/e1)), e2))) + <-- Solve(1 + (e2/e1), var); +10 # Solve'Divide(_e1 - _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) + And Not (HasExpr(Simplify(1 - (e2/e1)), e1) + Or HasExpr(Simplify(1 - (e2/e1)), e2))) + <-- Solve(1 - (e2/e1), var); + +20 # Solve'Divide(_e, _v) <-- Failed; + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Solve",categories="User Functions;Solvers (Symbolic)" +*CMD Solve --- solve an equation +*STD +*CALL + Solve(eq, var) + +*PARMS + +{eq} -- equation to solve + +{var} -- variable to solve for + +*DESC + +This command tries to solve an equation. If {eq} does not contain the +{==} operator, it is assumed that the user wants to solve +$eq == 0$. The result is a list of equations of the form {var == value}, each +representing a solution of the given equation. The {Where} operator +can be used to substitute this solution in another expression. If the +given equation {eq} does not have any solutions, or if {Solve} is +unable to find any, then an empty list is returned. + +The current implementation is far from perfect. In particular, the +user should keep the following points in mind: +* {Solve} cannot solve all equations. If it is given a equation +it can not solve, it raises an error via {Check}. Unfortunately, this +is not displayed by the inline pretty-printer; call {PrettyPrinterSet} to +change this. If an equation cannot be solved analytically, you may +want to call {Newton} to get a numerical solution. +* Systems of equations are not handled yet. For linear systems, +{MatrixSolve} can be used. The old version of {Solve}, with the name +{OldSolve} might be able to solve nonlinear systems of equations. +* The periodicity of the trigonometric functions {Sin}, {Cos}, +and {Tan} is not taken into account. The same goes for the (imaginary) +periodicity of {Exp}. This causes {Solve} to miss solutions. +* It is assumed that all denominators are nonzero. Hence, a +solution reported by {Solve} may in fact fail to be a solution because +a denominator vanishes. +* In general, it is wise not to have blind trust in the results +returned by {Solve}. A good strategy is to substitute the solutions +back in the equation. + +*E.G. notest + +First a simple example, where everything works as it should. The +quadratic equation $x^2 + x == 0$ is solved. Then the result is +checked by substituting it back in the quadratic. + +In> quadratic := x^2+x; +Result: x^2+x; +In> Solve(quadratic, x); +Result: {x==0,x==(-1)}; +In> quadratic Where %; +Result: {0,0}; + +If one tries to solve the equation $Exp(x) == Sin(x)$, one finds that +{Solve} can not do this. + +In> PrettyPrinterSet("DefaultPrint"); +Result: True; +In> Solve(Exp(x) == Sin(x), x); + Error: Solve'Fails: cannot solve equation Exp(x)-Sin(x) for x +Result: {}; + +The equation $Cos(x) == 1/2$ has an infinite number of solutions, +namely $x == (2*k + 1/3) * Pi$ and $x == (2*k - 1/3) * Pi$ for any +integer $k$. However, {Solve} only reports the solutions with $k == 0$. + +In> Solve(Cos(x) == 1/2, x); +Result: {x==Pi/3,x== -Pi/3}; + +For the equation $x/Sin(x) == 0$, a spurious solution at $x == 0$ is +returned. However, the fraction is undefined at that point. + +In> Solve(x / Sin(x) == 0, x); +Result: {x==0}; + +At first sight, the equation $Sqrt(x) == a$ seems to have the solution +$x == a^2$. However, this is not true for eg. $a == -1$. + +In> PrettyPrinterSet("DefaultPrint"); +Result: True; +In> Solve(Sqrt(x) == a, x); + Error: Solve'Fails: cannot solve equation Sqrt(x)-a for x +Result: {}; +In> Solve(Sqrt(x) == 2, x); +Result: {x==4}; +In> Solve(Sqrt(x) == -1, x); +Result: {}; + +*SEE Check, MatrixSolve, Newton, OldSolve, PrettyPrinterSet, PSolve, Where, AddTo, == +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/SolveSystem.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/SolveSystem.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/SolveSystem.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/SolveSystem.mpw 2011-04-23 11:14:36.000000000 +0000 @@ -0,0 +1,137 @@ +%mathpiper,def="SolveSystem" + +/*------------------------------------------------------------------- + * NOTE: this is a diversion of the SolveSystem modules to a + * new file all its own. Previously, it was named "Solve'System", + * and was contained in the file OldSolve.mpw. + * + * For the time being, we are just reconnecting the new file to + * point to the same old file Solve'SimpleBackSubstitution . + * This will be changed soon. + * started hso 100630. + * begin mods 100701 + *-------------------------------------------------------------------*/ + +//Retract("SolveSystem",*); +//Retract("VarsAndDegs",*); +//Retract("MakeCoefMatrix",*); +//Retract("SolveLinearSystem",*); +//Retract("SolveNonlinearSystem",*); + +/* +10 # SolveSystem( eqns_IsList, vars_IsList ) <-- +[ + // This is the old, now obsolete method + If(InVerboseMode(),Tell("SolveSystem0",{eqns,vars})); + Solve'SimpleBackSubstitution(eqns,vars); +]; +*/ + +10 # SolveSystem( eqns_IsList, vars_IsList )_(Length(eqns)=1 And Length(vars)=1) <-- +[ + {Solve(eqns[1],vars[1])}; +]; + +12 # SolveSystem( eqns_IsList, vars_IsList ) <-- +[ + // This is the first try at a better algorithm for doing this + If(InVerboseMode(),Tell("SolveSystem",{eqns,vars})); + + Local(eq,expr,exprns,VaD,isLinearSet,ans); + // express as set of polynomials, to be equated to zero + exprns := {}; + ForEach(eq,eqns) + [ + expr := If( IsEquation(eq), EquationLeft(eq)-EquationRight(eq), eq ); + DestructiveAppend(exprns,expr); + ]; + If(InVerboseMode(),Tell(" ",exprns)); + + // are all polynomials linear in given variables? + VaD := VarsAndDegs(exprns,vars); + If(InVerboseMode(),Tell(" ",VaD)); + isLinearSet := Maximum(Flatten(VaD,"List"))=1; + If(InVerboseMode(),Tell(" ",isLinearSet)); + + If( isLinearSet, + ans:=SolveLinearSystem( exprns, vars ), + ans:=SolveNonlinearSystem( exprns, vars ) + ); + + If(ans != {}, ans := Map("==",{vars,ans})); + + If(InVerboseMode(),Tell("",ans)); + + ans; +]; + + +10 # VarsAndDegs(exs_IsList,vars_IsList) <-- +[ + Local(ex,v,result); + result := {}; + ForEach(ex,exs) + [ + Local(res); + res := {}; + ForEach(v,vars) + [ + DestructiveAppend(res,Apply("Degree",{ex,v})); + ]; + DestructiveAppend(result,res); + ]; + result; +]; + + + +10 # SolveLinearSystem( polys_IsList, vars_IsList ) <-- +[ + Local(A, E); + + If(InVerboseMode(),Tell(" SolveLinearSystem",{polys,vars})); + // note Coef(polys[1],vars[1],1) etc, to create matrix of coefficients + Local(lhs,rhs,zeros); + lhs := MakeCoefMatrix(polys,vars); + If(InVerboseMode(),Tell(" ",lhs)); + zeros := ZeroVector(Length(vars)); + rhs := -WithValue(vars,zeros,polys); + If(InVerboseMode(),Tell(" ",rhs)); + + A := Transpose(Concat(Transpose(lhs),{rhs})); + E := RREF(A); + + If(Contains(E,BaseVector(Dimensions(E)[2],Dimensions(E)[2])), + {}, + MatrixColumn(E,Dimensions(E)[2]) - (ExtractSubMatrix(E, 1, 1, Length(E), Length(E)) - Identity(Length(E))) * vars); +]; + + + +10 # MakeCoefMatrix(polys_IsList,vars_IsList) <-- +[ + If(InVerboseMode(),Tell(" MakeCoefMatrix",{polys,vars})); + Local(p,v,result); + result := {}; + ForEach(p,polys) + [ + Local(res); + res := {}; + ForEach(v,vars) + [ + DestructiveAppend(res,Apply("Coef",{p,v,1})); + ]; + DestructiveAppend(result,res); + ]; + result; +]; + + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/SuchThat.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/SuchThat.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/SuchThat.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/SuchThat.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,128 @@ +%mathpiper,def="SuchThat" + +10 # ContainsExpression(_body,_body) <-- True; +15 # ContainsExpression(body_IsAtom,_expr) <-- False; +20 # ContainsExpression(body_IsFunction,_expr) <-- +[ + Local(result,args); + result:=False; + args:=Rest(FunctionToList(body)); + While(args != {}) + [ + result:=ContainsExpression(First(args),expr); + args:=Rest(args); + if (result = True) (args:={}); + ]; + result; +]; + + +SuchThat(_function,_var) <-- SuchThat(function,0,var); + +10 # SuchThat(_left,_right,_var)_(left = var) <-- right; + +/*This interferes a little with the multi-equation solver... +15 # SuchThat(_left,_right,_var)_CanBeUni(var,left-right) <-- + PSolve(MakeUni(left-right,var)); +*/ + +20 # SuchThat(left_IsAtom,_right,_var) <-- var; + +30 # SuchThat((_x) + (_y),_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , right-y , var); +30 # SuchThat((_y) + (_x),_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , right-y , var); + +30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(r,var) <-- + SuchThat(r , right-I*i , var); +30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(i,var) <-- + SuchThat(i , right+I*r , var); + +30 # SuchThat(_x * _y,_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , right/y , var); +30 # SuchThat(_y * _x,_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , right/y , var); + +30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , right^(1/y) , var); +30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(y,var) <-- + SuchThat(y , Ln(right)/Ln(x) , var); + +30 # SuchThat(Sin(_x),_right,_var) <-- + SuchThat(x , ArcSin(right) , var); +30 # SuchThat(ArcSin(_x),_right,_var) <-- + SuchThat(x , Sin(right) , var); + +30 # SuchThat(Cos(_x),_right,_var) <-- + SuchThat(x , ArcCos(right) , var); +30 # SuchThat(ArcCos(_x),_right,_var) <-- + SuchThat(x , Cos(right) , var); + +30 # SuchThat(Tan(_x),_right,_var) <-- + SuchThat(x , ArcTan(right) , var); +30 # SuchThat(ArcTan(_x),_right,_var) <-- + SuchThat(x , Tan(right) , var); + +30 # SuchThat(Exp(_x),_right,_var) <-- + SuchThat(x , Ln(right) , var); +30 # SuchThat(Ln(_x),_right,_var) <-- + SuchThat(x , Exp(right) , var); + +30 # SuchThat(_x / _y,_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , right*y , var); +30 # SuchThat(_y / _x,_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , y/right , var); + +30 # SuchThat(- (_x),_right,_var) <-- + SuchThat(x , -right , var); + +30 # SuchThat((_x) - (_y),_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , right+y , var); +30 # SuchThat((_y) - (_x),_right,_var)_ContainsExpression(x,var) <-- + SuchThat(x , y-right , var); + +30 # SuchThat(Sqrt(_x),_right,_var) <-- + SuchThat(x , right^2 , var); + +%/mathpiper + + + +%mathpiper_docs,name="SuchThat",categories="User Functions;Solvers (Symbolic)" +*CMD SuchThat --- special purpose solver +*STD +*CALL + SuchThat(expr, var) + +*PARMS + +{expr} -- expression to make zero + +{var} -- variable (or subexpression) to solve for + +*DESC + +This functions tries to find a value of the variable "var" which +makes the expression "expr" zero. It is also possible to pass a +subexpression as "var", in which case {SuchThat} +will try to solve for that subexpression. + +Basically, only expressions in which "var" occurs only once are +handled; in fact, {SuchThat} may even give wrong +results if the variables occurs more than once. This is a consequence +of the implementation, which repeatedly applies the inverse of the top +function until the variable "var" is reached. + +*E.G. + +In> SuchThat(a+b*x, x) +Result: (-a)/b; +In> SuchThat(Cos(a)+Cos(b)^2, Cos(b)) +Result: Cos(a)^(1/2); +In> A:=Expand(a*x+b*x+c, x) +Result: (a+b)*x+c; +In> SuchThat(A, x) +Result: (-c)/(a+b); + +*SEE Solve, OldSolve, Subst, Simplify +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/xPSolve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/xPSolve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/xPSolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/xPSolve.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,393 @@ +%mathpiper,def="xPSolve" + +//Retract("xPSolve",*); +//Retract("xPSolveCubic",*); +//Retract("xPSC1",*); +//Retract("xPSC2",*); + +/*------------------------------------------------------- + * NOTES: TODO: RadSimp() may have a problem with + * roots of complex numbers + *-------------------------------------------------------*/ + + +Rulebase("xPSolve",{uni}); + +Rule("xPSolve",1,1,IsUniVar(uni) And Degree(uni) = 1) +[ + If(iDebug,Tell(" xPSolve_1",uni)); + {-Coef(uni,0)/Coef(uni,1)}; +]; + +Rule("xPSolve",1,1,IsUniVar(uni) And Degree(uni) = 2) +[ + If(iDebug,Tell(" xPSolve_2",uni)); + Local(a,b,c,d,q,r); + c:=Coef(uni,0); + b:=Coef(uni,1); + a:=Coef(uni,2); + If(iDebug,Tell(" ",{a,b,c})); + d:=b*b-4*a*c; + If(iDebug,Tell(" ",d)); + //q:=RadSimp(Sqrt(d)/(2*a)); + q:=Sqrt(d)/(2*a); + If(iDebug,Tell(" ",q)); + r:=Simplify(-b/(2*a)); + If(iDebug,Tell(" ",r)); + {r+q,r-q}; +]; + +/* + How to solve the cubic equation? + + The equation is a3 x^3 + a2 x^2 + a1 x + a0 = 0. + + Get coefficients for a new polynomial, such that the coefficient of + degree 2 is zero: + Take f(x)=a0+a1*x+a2*x^2+a3*x^3 and substitute x = x' + adjust + to get the expression g(x) = b0+b1*x+b2*x^2+b3*x^3, + where + b3 = a3; + b2 = 0 => adjust = (-a2)/(3*a3); + b1 = 2*a2*adjust+3*a3*adjust^2+a1; + b0 = a2*adjust^2+a3*adjust^3+adjust*a1+a0; + + After solving g(x') = 0, return x = x' + adjust. + + Since b2 = 0 by construction, we have the equation + g(x) = x^3 + q x + r = 0, + where + r = b0/b3 and q = b1/b3. + + Let x = a + b, so + a^3 + b^3 + 3 (a^2 b + b^2 a) + q (a + b) + r = 0 + a^3 + b^3 + (3 a b + q) x + r = 0 + + Let 3 a b + q = 0. This is permissible, for we can still find a+b == x + + a^3 + b^3 = -r + (a b)^3 = -q^3/27 + + So a^3 and b^3 are the roots of t^2 + r t - q^3/27 = 0 + + Let + a^3 = -r/2 + Sqrt(q^3/27+ r^2/4) + b^3 = -r/2 - Sqrt(q^3/27+ r^2/4) + Therefore there are three values for each of a and b. + Clearly if ab = -q/3 is true then (wa)(w^2b) == (wb)(w^2a) == -q/3 +*/ + +Rule("xPSolve",1,1,IsUniVar(uni) And Degree(uni) = 3 ) +[ + If(iDebug,Tell(" xPSolve_3",uni)); + Local(p,q,r,s,t,w1,w2,a,b); + Local(c0,c1,c3,adjust); + + // w1 and w2 are constants: the "other" two cube-roots of unity + w1 := (1/2)*Complex(-1, Sqrt(3)); + w2 := Conjugate(w1); + If( iDebug, Tell(" ",{w1,w2}) ); + + // Now we begin to find solutions + adjust := (-uni[3][3])/(3*uni[3][4]); + If( iDebug, Tell(" ",adjust)); + c3 := uni[3][4]; + c1 := (3*uni[3][4]*adjust+2*uni[3][3])*adjust+uni[3][2]; + c0 :=((uni[3][4]*adjust+uni[3][3])*adjust+uni[3][2])*adjust+uni[3][1]; + If( iDebug, Tell(" ",{c0,c1,c3})); + + // Invariant: c0, c1, c2 are all REAL + Assert("Invariant", "Coefficients Must be Real") And(Im(c0)=0,Im(c1)=0,Im(c2)=0); + If( IsError("Invariant"), DumpErrors() ); + + p :=c3; + q :=c1/p; + r :=c0/p; + If( iDebug, Tell(" ",{p,q,r})); + Local(a3,b3,qq,r1,r2,r3); + qq := Sqrt(q^3/27 + r^2/4); + a3 := -r/2 + qq; + b3 := -r/2 - qq; + // NOTE: If q < 0 and r = 0, then qq is pure imaginary, a3 = qq, b3 = -qq. + If( iDebug, [Tell(" ",{qq,a3,b3}); Tell(" ",N(a3+b3+r)); Tell(" ",N(a3-b3-2*qq));]); + a := (a3)^(1/3); + b := (b3)^(1/3); + If( iDebug, Tell(" ",{a,b})); + r1 := a+b+adjust; + r2 := w1*a+w2*b+adjust; + r3 := w2*a+w1*b+adjust; + // NOTE: If q < 0 and r = 0, then r3 = adjust and r2 = Sqrt(3)*qqi + adjust + If( iDebug, + [ + Tell(" ",r1); + Tell(" ",r2); + Tell(" ",r3); + ] + ); + {r1,r2,r3}; +]; + + +/* +How to solve the quartic equation? + +The equation is x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = 0. +The idea is to write the left-hand side as the difference of two +squares: (x^2 + p x + q)^2 - (s x + t)^2. +Eliminating the parentheses and equation coefficients yields four +equations for the four unknowns p, q, s and t: + a1 = 2p (1) + a2 = p^2 + 2q - s^2 (2) + a3 = 2pq - 2st (3) + a4 = q^2 - t^2 (4) +From the first equation, we find that p = a1/2. Substituting this in +the other three equations and rearranging gives + s^2 = a1^2/4 - a2 + 2q (5) + 2st = a1 q - a3 (6) + t^2 = q^2 - a4 (7) +We now take the square (6) and substitute (5) and (7): + 4 (a1^2/4 - a2 + 2q) (q^2 - a4) = (a1 q - a3)^2 <==> + 8 q^3 - 4 a2 q^2 + (2 a1 a3 - 8 a4) q + 4 a2 a4 - a1^2 a4 - a3^2 = 0. +Miraculously, we got a cubic equation for q. Suppose we can solve this +equation. We can then compute t from (7): t = sqrt(q^2 - a4). If t is +nonzero, we can compute s from (6). Note that we cannot compute s from +(5), since we introduced an extra solution when squaring (6). However, +if t is zero, then no extra solution was introduced and we can safely +use (5). Having found the values of p, q, s and t, we can factor the +difference of squares and solve the quartic: + x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = (x^2 + p x + q)^2 - (s x + t)^2 + = (x^2 + p x + q + s x + t) (x^2 + p x + q - sx - t). +The four roots of the quartic are the two roots of the first quadratic +factor plus the two roots of the second quadratic factor. +*/ + +Rule("xPSolve",1,1,IsUniVar(uni) And Degree(uni) = 4 ) +[ + If(iDebug,Tell(" xPSolve_4",uni)); + Local(coef4,a1,a2,a3,a4,y,y1,z,t,s); + + coef4:=Coef(uni,4); + a1:=Coef(uni,3)/coef4; + a2:=Coef(uni,2)/coef4; + a3:=Coef(uni,1)/coef4; + a4:=Coef(uni,0)/coef4; + If( iDebug, Tell(" ",{a1,a2,a3,a4})); + + /* y1 = 2q, with q as above. */ + Local(ys); + ys := xPSolveCubic(y^3-a2*y^2+(a1*a3-4*a4)*y+(4*a2*a4-a3^2-a1^2*a4)); + If( iDebug, [NewLine(); Tell(" ",ys[1]);] ); + y1:=First(ys); + If( iDebug, Tell(" ",y1)); + t := Sqrt(y1^2/4-a4); + If( iDebug, Tell(" ",t)); + If(t=0, s:=Sqrt(y1+a1^2/4-a2), s:=(a1*y1-2*a3)/(4*t)); + If( iDebug, Tell(" ",s)); + + Local(q11,q12,q21,q2,quad1,quad2); + q11 := a1/2+s; q12 := y1/2+t; + q21 := a1/2-s; q22 := y1/2-t; + If( iDebug, Tell(" ",{q11,q12})); + If( iDebug, Tell(" ",{q21,q22})); + quad1 := z^2 + q11*z + q12; + quad2 := z^2 + q21*z + q22; + If( iDebug, Tell(" ",{quad1,quad2})); + + Local(r1,r2,r3,r4); + {r1,r2} := xPSolve( quad1, z ); + {r3,r4} := xPSolve( quad2, z ); + r1 := NearRational(N(r1,10),8); + r2 := NearRational(N(r2,10),8); + r3 := NearRational(N(r3,10),8); + r4 := NearRational(N(r4,10),8); + + {r1,r2,r3,r4}; +]; + + +Function("xPSolve",{expr,var}) +[ + If( Not IsBound(iDebug), iDebug := False ); + If(iDebug,Tell("xPSolve_notUni",{expr,var})); + Local(lhs,rhs,cc,pp,uni,solnpp,solncc,soln); + If( IsEquation(expr), + [ + If(iDebug,Tell(" is Equation")); + lhs := EquationLeft(expr); + rhs := EquationRight(expr); + expr := lhs - rhs; + ] + ); + If(iDebug,Tell(" ",expr)); + cc := xContent(expr); + pp := xPrimitivePart(expr,cc); + If(iDebug,Tell(" ",{cc,pp})); + solnpp := xPSolve(MakeUni(pp,var)); + If(iDebug,Tell(" ",solnpp)); + If( Length(VarList(cc)) > 0 And Contains(VarList(cc),var ), + [ + solncc := xPSolve(MakeUni(cc,var)); + If(iDebug,Tell(" ",solncc)); + soln := Concat(solncc,solnpp); + ], + [ + soln := solnpp; + ] + ); + soln; +]; + + +10 # xPSolveCubic( poly_IsPolynomial )_ + (Length(VarList(poly))=1 And Degree(poly)=3) <-- +[ + If( iDebug, Tell(" xPSolveCubic",poly) ); + Local(var,coeffs,ans); + var := VarList(poly)[1]; + coeffs := Coef(poly,var,3 .. 0); + If( iDebug, Tell(" ",{var,coeffs})); + ans := xPSC1(coeffs); +]; +UnFence("xPSolveCubic",1); + + +10 # xPSC1( coeffs_IsList ) <-- +[ + If( iDebug, Tell(" xPSC1",coeffs) ); + /* + * This function solves a general cubic equation with REAL coefficients. + * It is based on an algorithm described in the book + * "Handbook of Applied Mathematics for Engineers and Scientists", + * by Max Curtz. + */ + Local(f,g,h,j,iType,ans); + f := coeffs[2]/coeffs[1]/3; + g := coeffs[3]/coeffs[1]/3 - f^2; + h := coeffs[4]/coeffs[1]/2 + f^3 - f * coeffs[3]/coeffs[1]/2; + j := g^3 + h^2; + If( iDebug, Tell(" ",{f,g,h,j}) ); + ans := xPSC2( {f,g,h,j} ); +]; + + +10 # xPSC2( xs_IsList )_(xs[4]=0) <-- +[ + If( iDebug, Tell(" Type 1",xs) ); + Local(f,g,h,j,m,r1,r2,r3,ans); + {f,g,h,j} := FlatCopy(xs); + m := 2*(-h)^(1/3); + r1 := NearRational(N(m - f,10),8); + r2 := NearRational(N(-m/2 - f,10),8); + r3 := NearRational(N(-m/2 - f,10),8); + ans := {r1,r2,r3}; +]; + +10 # xPSC2( xs_IsList )_(xs[4]>0) <-- +[ + If( iDebug, Tell(" Type 2",xs) ); + Local(f,g,h,j,k,l1,l2,m,n,r1,r2,r3,ans); + {f,g,h,j} := FlatCopy(xs); + k := Sqrt(j); + l1 := (-h + k)^(1/3); + l2 := (-h - k)^(1/3); + m := l1 + l2; + n := (l1 - l2)*Sqrt(3)/2; + r1 := NearRational(N(m - f,10),8); + r2 := NearRational(N(-m/2 - f + I*n,10),8); + r3 := NearRational(N(Conjugate(r2),10),8); + ans := {r1,r2,r3}; + +]; + +10 # xPSC2( xs_IsList )_(xs[4]<0 And xs[3]=0) <-- +[ + If( iDebug, Tell(" Type 3a",xs) ); + Local(f,g,h,j,p,r1,r2,r3,ans); + {f,g,h,j} := FlatCopy(xs); + p := 2*Sqrt(-g); + r1 := NearRational(N(-f,10),8); + r2 := NearRational(N( p*Sqrt(3)/2 - f,10),8); + r3 := NearRational(N(-p*Sqrt(3)/2 - f,10),8); + ans := {r1,r2,r3}; +]; + +10 # xPSC2( xs_IsList )_(xs[4]<0 And xs[3]>0) <-- +[ + If( iDebug, Tell(" Type 3b",xs) ); + Local(p,x,alpha,beta,gama,r1,r2,r3,ans); + {f,g,h,j} := FlatCopy(xs); + p := 2*Sqrt(-g); + k := Sqrt(-j); + alpha := ArcTan(k/(-h)); // alpha should be Acute + beta := Pi + alpha; + gama := beta / 3; + If( iDebug, + [ + Tell(" ",{p,k}); + Tell(" ",{alpha,beta,gama}); + Tell(" ",57.2957795*N({alpha,beta,gama})); + Tell(" ",N(Cos(gama))); + ] + ); + r1 := NearRational(N(p * Cos(gama) - f,10),8); + r2 := NearRational(N(p * Cos(gama+2*Pi/3) - f,10),8); + r3 := NearRational(N(p * Cos(gama+4*Pi/3) - f,10),8); + ans := {r1,r2,r3}; +]; + +10 # xPSC2( xs_IsList )_(xs[4]<0 And xs[3]<0) <-- +[ + If( iDebug, Tell(" Type 3c",xs) ); + Local(f,g,h,j,p,k,alpha,beta,gama,r1,r2,r3,ans); + {f,g,h,j} := FlatCopy(xs); + p := 2*Sqrt(-g); + k := Sqrt(-j); + alpha := ArcTan(k/(-h)); // alpha should be Acute + beta := alpha; + gama := beta / 3; + If(iDebug,[Tell(" ",{p,k}); Tell(" ",{alpha,beta,gama});]); + r1 := NearRational(N(p * Cos(gama) - f,10),8); + r2 := NearRational(N(p * Cos(gama+2*Pi/3) - f,10),8); + r3 := NearRational(N(p * Cos(gama+4*Pi/3) - f,10),8); + ans := {r1,r2,r3}; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="xPSolve",categories="User Functions;Solvers (Symbolic)" +*CMD xPSolve --- solve a polynomial equation +*STD +*CALL + xPSolve(poly, var) + +*PARMS + +{poly} -- a polynomial in "var" + +{var} -- a variable + +*DESC + +This commands returns a list containing the roots of "poly", +considered as a polynomial in the variable "var". If there is only +one root, it is not returned as a one-entry list but just by +itself. A double root occurs twice in the result, and similarly for +roots of higher multiplicity. All polynomials of degree up to 4 are +handled. + +*E.G. + +In> xPSolve(b*x+a,x) +Result: -a/b; +In> xPSolve(c*x^2+b*x+a,x) +Result: {(Sqrt(b^2-4*c*a)-b)/(2*c),(-(b+ + Sqrt(b^2-4*c*a)))/(2*c)}; + +*SEE Solve, Factor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/YacasPSolve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/YacasPSolve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/solve/YacasPSolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/solve/YacasPSolve.mpw 2011-02-12 16:04:16.000000000 +0000 @@ -0,0 +1,197 @@ +%mathpiper,def="YacasYacasPSolve" + +Rulebase("YacasPSolve",{uni}); + +Rule("YacasPSolve",1,1,IsUniVar(uni) And Degree(uni) = 0) + {}; + +Rule("YacasPSolve",1,1,IsUniVar(uni) And Degree(uni) = 1) + -Coef(uni,0)/Coef(uni,1); + + +Rule("YacasPSolve",1,1,IsUniVar(uni) And Degree(uni) = 2) + [ + Local(a,b,c,d,q,r); + c:=Coef(uni,0); + b:=Coef(uni,1); + a:=Coef(uni,2); + d:=b*b-4*a*c; + q:=Sqrt(d)/(2*a); + // Removed to avoid excessive time RadSimp takes for larger numbers + // If(Im(q) != 0, + // q := Complex(RadSimp(Re(q)), RadSimp(Im(q))), + // q := RadSimp(q)); + r:=-b/(2*a); + If(InVerboseMode(),[ Tell(" ",{c,b,a,d}); Tell(" ",{q,r}); ]); + {r+q,r-q}; + ]; + + +Rule("YacasPSolve",1,1,IsUniVar(uni) And Degree(uni) = 3 ) + [ + Local(p,q,r,w,ww,a,b); + Local(coef0,coef1,coef3,adjust); + +/* Get coefficients for a new polynomial, such that the coefficient of + degree 2 is zero: + Take f(x)=a0+a1*x+a2*x^2+a3*x^3 and substitute x = x' + adjust + This gives g(x) = b0+b1*x+b2*x^2+b3*x^3 where + b3 = a3; + b2 = 0 => adjust = (-a2)/(3*a3); + b1 = 2*a2*adjust+3*a3*adjust^2+a1; + b0 = a2*adjust^2+a3*adjust^3+adjust*a1+a0; + + After solving g(x') = 0, return x = x' + adjust. +*/ + + adjust := (-Coef(uni,2))/(3*Coef(uni,3)); + coef3 := Coef(uni,3); + coef1 := 2*Coef(uni,2)*adjust+3*Coef(uni,3)*adjust^2+Coef(uni,1); + coef0 := Coef(uni,2)*adjust^2+Coef(uni,3)*adjust^3+ + adjust*Coef(uni,1)+Coef(uni,0); + + p:=coef3; + q:=coef1/p; + r:=coef0/p; + w:=Complex(-1/2,Sqrt(3/4)); + ww:=Complex(-1/2,-Sqrt(3/4)); + +/* Equation is xxx + qx + r = 0 */ +/* Let x = a + b + a^3 + b^3 + 3(aab + bba) + q(a + b) + r = 0 + a^3 + b^3 + (3ab+q)x + r = 0 + + Let 3ab+q = 0. This is permissible, for we can still find a+b == x + + a^3 + b^3 = -r + (ab)^3 = -q^3/27 + + So a^3 and b^3 are the roots of t^2 + rt - q^3/27 = 0 + + Let + a^3 = -r/2 + Sqrt(q^3/27+ rr/4) + b^3 = -r/2 - Sqrt(q^3/27+ rr/4) + Therefore there are three values for each of a and b. + Clearly if ab = -q/3 is true then (wa)(wwb) == (wb)(wwa) == -q/3 +*/ + + a:=(-r/2 + Sqrt(q^3/27+ r*r/4))^(1/3); + b:=(-r/2 - Sqrt(q^3/27+ r*r/4))^(1/3); + + {a+b+adjust,w*a+ww*b+adjust,ww*a+w*b+adjust}; +]; + +/* +How to solve the quartic equation? + +The equation is x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = 0. +The idea is to write the left-hand side as the difference of two +squares: (x^2 + p x + q)^2 - (s x + t)^2. +Eliminating the parentheses and equation coefficients yields four +equations for the four unknowns p, q, s and t: + a1 = 2p (1) + a2 = p^2 + 2q - s^2 (2) + a3 = 2pq - 2st (3) + a4 = q^2 - t^2 (4) +From the first equation, we find that p = a1/2. Substituting this in +the other three equations and rearranging gives + s^2 = a1^2/4 - a2 + 2q (5) + 2st = a1 q - a3 (6) + t^2 = q^2 - a4 (7) +We now take the square (6) and substitute (5) and (7): + 4 (a1^2/4 - a2 + 2q) (q^2 - a4) = (a1 q - a3)^2 <==> + 8 q^3 - 4 a2 q^2 + (2 a1 a3 - 8 a4) q + 4 a2 a4 - a1^2 a4 - a3^2 = 0. +Miraculously, we got a cubic equation for q. Suppose we can solve this +equation. We can then compute t from (7): t = sqrt(q^2 - a4). If t is +nonzero, we can compute s from (6). Note that we cannot compute s from +(5), since we introduced an extra solution when squaring (6). However, +if t is zero, then no extra solution was introduced and we can safely +use (5). Having found the values of p, q, s and t, we can factor the +difference of squares and solve the quartic: + x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = (x^2 + p x + q)^2 - (s x + t)^2 + = (x^2 + p x + q + s x + t) (x^2 + p x + q - sx - t). +The four roots of the quartic are the two roots of the first quadratic +factor plus the two roots of the second quadratic factor. +*/ + +Rule("YacasPSolve",1,1,IsUniVar(uni) And Degree(uni) = 4 ) +[ + Local(coef4,a1,a2,a3,a4,y,y1,z,t,s); + + coef4:=Coef(uni,4); + a1:=Coef(uni,3)/coef4; + a2:=Coef(uni,2)/coef4; + a3:=Coef(uni,1)/coef4; + a4:=Coef(uni,0)/coef4; + + /* y1 = 2q, with q as above. */ + y1:=First(YacasPSolve(y^3-a2*y^2+(a1*a3-4*a4)*y+(4*a2*a4-a3^2-a1^2*a4),y)); + t := Sqrt(y1^2/4-a4); + If(t=0, s:=Sqrt(y1+a1^2/4-a2), s:=(a1*y1-2*a3)/(4*t)); + Concat(YacasPSolve(z^2+(a1/2+s)*z+y1/2+t,z), + YacasPSolve(z^2+(a1/2-s)*z+y1/2-t,z)); +]; + +Function("YacasPSolve",{uni,var}) [ + Local(u, factors, f, r, s); + + u := MakeUni(uni, var); + + If(Type(u) = "UniVariate" And (And @ (Lambda({x}, IsNumber(x) Or IsRational(x)) /@ u[3])), [ + Local(coeffs); + coeffs := Rationalize(u[3]); + coeffs := If(Length(coeffs) > 1, + Lcm(Denominator /@ coeffs) * coeffs, + (Denominator /@ coeffs) * coeffs); + DestructiveReplace(u, 3, coeffs); + factors := If(Degree(u)>0, + Factors(NormalForm(u)), + {NormalForm(u), 1}); + ], [ + factors := {{uni, 1}}; + ]); + + r := {}; + ForEach(f, factors) [ + s := YacasPSolve(MakeUni(f[1],var)); + r := Union(r, If(IsList(s), s, {s})); + ]; + + If(Length(r) = 1, r[1], r); +]; + +%/mathpiper + + + +%mathpiper_docs,name="YacasPSolve",categories="User Functions;Solvers (Symbolic)" +*CMD YacasPSolve --- solve a polynomial equation +*STD +*CALL + YacasPSolve(poly, var) + +*PARMS + +{poly} -- a polynomial in "var" + +{var} -- a variable + +*DESC + +This commands returns a list containing the roots of "poly", +considered as a polynomial in the variable "var". If there is only +one root, it is not returned as a one-entry list but just by +itself. A double root occurs twice in the result, and similarly for +roots of higher multiplicity. All polynomials of degree up to 4 are +handled. + +*E.G. + +In> YacasPSolve(b*x+a,x) +Result: -a/b; +In> YacasPSolve(c*x^2+b*x+a,x) +Result: {(Sqrt(b^2-4*c*a)-b)/(2*c),(-(b+ + Sqrt(b^2-4*c*a)))/(2*c)}; + +*SEE Solve, Factor +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/ApproxInfSum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/ApproxInfSum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/ApproxInfSum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/ApproxInfSum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="ApproxInfSum" + +//Jonathan Leto + +// Ex: +// Bessel of order n: +// ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),1,x,{n} ); + +Function("ApproxInfSum",{expr,start,x})[ + ApproxInfSum(expr,start,x,{0}); +]; + +/// FIXME this has a roundoff problem when InNumericMode()=True +// Summation must be on k +Function("ApproxInfSum",{expr,start,x,c}) +[ + Local(term,result,k); + Local(prec,eps,tmp); + prec:=BuiltinPrecisionGet(); +// BuiltinPrecisionSet(Ceil(1.2*prec)); // this is a guess + BuiltinPrecisionSet(prec+2); // this is a guess +// eps:=5*10^(-prec); + eps:=10^(-prec); +//Echo(expr); +//Echo(" eps = ",N(Eval(eps))); + + term:=1; + k:=start; + result:=0; + While( N(Abs(term) >= eps) )[ + term:=N(Eval(expr)); + //Echo({"term is ",term}); + k:=k+1; + result:=result+term; + + ]; + If(InVerboseMode(), Echo("ApproxInfSum: Info: using ", k, " terms of the series")); + BuiltinPrecisionSet(prec); + // This should not round, only truncate + // some outputs will be off by one in the last digit + +//Echo("lastterm = ",N(Eval(term))); + +//Echo("r1",result); +//Echo("r2",RoundTo(result,prec)); +//Echo("r3",N((result/10)*10)); + + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/Bernoulli1.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/Bernoulli1.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/Bernoulli1.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/Bernoulli1.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="Bernoulli1" + +/// Find one Bernoulli number for large index +/// compute Riemann's zeta function and combine with the fractional part +Bernoulli1(n_IsEven)_(n>=2) <-- [ + Local(B, prec); + prec := BuiltinPrecisionGet(); + // estimate the size of B[n] using Stirling formula + // and compute Ln(B[n])/Ln(10) to find the number of digits + BuiltinPrecisionSet(10); + BuiltinPrecisionSet( + Ceil(N((1/2*Ln(8*Pi*n)-n+n*Ln(n/2/Pi))/Ln(10)))+3 // 3 guard digits + ); + If (InVerboseMode(), Echo({"Bernoulli: using zeta funcion, precision ", BuiltinPrecisionSet(), ", n = ", n})); + B := Floor(N( // compute integer part of B + If( // use different methods to compute Zeta function + n>250, // threshold is roughly right for internal math + Internal'ZetaNum2(n, n/17+1), // with this method, a single Bernoulli number n is computed in O(n*M(P)) operations where P = O(n*Ln(n)) is the required precision + // Brent's method requires n^2*P+n*M(P) + // simple array method requires + Internal'ZetaNum1(n, n/17+1) // this gives O(n*Ln(n)*M(P)) + ) + *N(2*n! /(2*Pi)^n))) + // 2*Pi*e is approx. 17, add 1 to guard precision + * (2*Modulo(n/2,2)-1) // sign of B + + BernoulliFracPart(n); // this already has the right sign + BuiltinPrecisionSet(prec); // restore old precision + B; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/BernoulliFracPart.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/BernoulliFracPart.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/BernoulliFracPart.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/BernoulliFracPart.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,23 @@ +%mathpiper,def="BernoulliFracPart" + +/// Find the fractional part of Bernoulli number with even index >=2 +/// return negative if the sign of the Bernoulli number is negative +BernoulliFracPart(n_IsEven)_(n>=2) <-- [ + Local(p, sum); + // always 2 and 3 + sum := 1/2+1/3; + // check whether n+1 and n/2+1 are prime + If(IsPrime(n+1), sum := sum+1/(n+1)); + If(IsPrime(n/2+1), sum := sum+1/(n/2+1)); + // sum over all primes p such that n / p-1 is integer + // enough to check up to n/3 now + For(p:=5, p<=n/3+1, p:=NextPrime(p)) + If(Modulo(n, p-1)=0, sum := sum + 1/p); + // for negative Bernoulli numbers, let's change sign + // Modulo(n/2, 2) is 0 for negative Bernoulli numbers and 1 for positive ones + Quotient(Numerator(sum), Denominator(sum)) - sum + + Modulo(n/2,2); // we'll return a negative number if the Bernoulli itself is negative -- slightly against our definitions in the manual + //+ 1; // this would be exactly like the manual says +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray1.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray1.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray1.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray1.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="Internal'BernoulliArray1" + +/// Bernoulli numbers; algorithm from: R. P. Brent, "A FORTRAN multiple-precision arithmetic package", ACM TOMS vol. 4, no. 1, p. 57 (1978). +/// this may be good for floating-point (not exact) evaluation of B[n] at large n +/// but is not good at all for exact evaluation! (too slow) +/// Brent claims that the usual recurrence is numerically unstable +/// but we can't check this because MathPiper internal math is fixed-point and Brent's algorithm needs real floating point (C[k] are very small and then multiplied by (2*k)! ) +Internal'BernoulliArray1(n_IsEven) _ (n>=2) <-- +[ + Local(C, f, k, j, denom, sum); + C := ArrayCreate(n+1, 0); + f := ArrayCreate(n/2, 0); + C[1] := 1; + C[2] := -1/2; + C[3] := 1/12; // C[2*k+1] = B[2*k]/(2*k)! + f[1] := 2; // f[k] = (2k)! + For(k:=2, k<=n/2, k++) // we could start with k=1 but it would be awkward to compute f[] recursively + [ + // compute f[k] + f[k] := f[k-1] * (2*k)*(2*k-1); + // compute C[k] + C[2*k+1] := 1/(1-4^(-k))/2*( + [ + denom := 4; // = 4^1 + sum := 0; + For(j:=1, j<=k-1, j++) + [ + sum := sum + C[2*(k-j)+1]/denom/f[j]; // + C[k-j]/(2*j)! /4^j + denom := denom * 4; + ]; + (2*k-1)/denom/f[k] - sum; + ] + ); +// Echo({n, k, denom, C[k]}); + ]; + // multiply C's with factorials to get B's + For(k:=1, k<=n/2, k++) + C[2*k+1] := C[2*k+1] * f[k]; + // return array object + C; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bernou/Internal'BernoulliArray.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="Internal'BernoulliArray" + +/// Simple implementation of the recurrence relation: create an array of Bernoulli numbers +// special cases: n=0 or n=1 +10 # Internal'BernoulliArray(n_IsInteger)_(n=0 Or n=1) <-- [ + Local(B); + B:=ArrayCreate(n+1,0); + B[1] := 1; + If(n=1, B[2] := -1/2); + B; +]; +/// Assume n>=2 +20 # Internal'BernoulliArray(n_IsInteger) <-- [ + Local(B, i, k, k2, bin); + If (InVerboseMode(), Echo({"Internal'BernoulliArray: using direct recursion, n = ", n})); + B:=ArrayCreate(n+1, 0); // array of B[k], k=1,2,... where B[1] is the 0th Bernoulli number + // it would be better not to store the odd elements but let's optimize this later + // we could also maintain a global cache of Bernoulli numbers computed so far, but it won't really speed up things at large n + // all odd elements after B[2] are zero + B[1] := 1; + B[2] := -1/2; + B[3] := 1/6; + For(i:=4, i<=n, i := i+2) // compute and store B[i] + [ // maintain binomial coefficient + bin := 1; // BinomialCoefficient(i+1,0) + // do not sum over odd elements that are zero anyway - cuts time in half + B[i+1] := 1/2-1/(i+1)*(1 + Sum(k, 1, i/2-1, + [ + bin := bin * (i+3-2*k) * (i+2-2*k)/ (2*k-1) / (2*k); + B[2*k+1]*bin; // *BinomialCoefficient(i+1, 2*k) + ] + ) ); + ]; + B; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Bernoulli.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Bernoulli.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Bernoulli.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Bernoulli.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,67 @@ +%mathpiper,def="Bernoulli" + +///////////////////////////////////////////////// +/// Bernoulli numbers and polynomials +///////////////////////////////////////////////// +/// Serge Winitzki + +/// Bernoulli(n): interface to Bernoulli numbers +10 # Bernoulli(0) <-- 1; +10 # Bernoulli(1) <-- -1/2; +15 # Bernoulli(n_IsInteger)_(n<0) <-- Undefined; +30 # Bernoulli(n_IsOdd) <-- 0; + +/// numerical computations of Bernulli numbers use two different methods, one good for small numbers and one good only for very large numbers (using Zeta function) +20 # Bernoulli(n_IsEven)_(n<=Bernoulli1Threshold()) <-- Internal'BernoulliArray(n)[n+1]; +20 # Bernoulli(n_IsEven)_(n>Bernoulli1Threshold()) <-- Bernoulli1(n); + +LocalSymbols(bernoulli1Threshold) [ + /// Bernoulli1Threshold could in principle be set by the user + If(Not IsBound(bernoulli1Threshold), bernoulli1Threshold := 20); + + Bernoulli1Threshold() := bernoulli1Threshold; + SetBernoulli1Threshold(threshold) := [ bernoulli1Threshold := threshold;]; + +] ; // LocalSymbols(bernoulli1Threshold) + +/// Bernoulli polynomials of degree n in variable x +Bernoulli(n_IsInteger, _x) <-- [ + Local(B, i, result); + B := Internal'BernoulliArray(n); + result := B[1]; + For(i:=n-1, i>=0, i--) [ + result := result * x + B[n-i+1]*BinomialCoefficient(n,i); + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Bernoulli",categories="User Functions;Special Functions" +*CMD Bernoulli --- Bernoulli numbers and polynomials +*STD +*CALL + Bernoulli(index) + Bernoulli(index, x) + +*PARMS + +{x} -- expression that will be the variable in the polynomial + +{index} -- expression that can be evaluated to an integer + +*DESC + +{Bernoulli(n)} evaluates the $n$-th Bernoulli number. {Bernoulli(n, x)} returns the $n$-th Bernoulli polynomial in the variable $x$. The polynomial is returned in the Horner form. + +*E.G. + +In> Bernoulli(20); +Result: -174611/330; +In> Bernoulli(4, x); +Result: ((x-2)*x+1)*x^2-1/30; + +*SEE Gamma, Zeta +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN0.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN0.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN0.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN0.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="BesselJN0" + +/// coded by Jonathan Leto + +// Seems to get about 8 digits precision for most real numbers +// Only about 2 digits precision for complex +// This is just a temporary implementation, I would not want to +// expose users to it until it is much more robust +// I am still looking for a good arbitrary precision algorithm. +Function("BesselJN0",{x}) +[ + Local(ax,z,xx,y,result,res1,res2); + Local(c1,c2,c3,c4); + + // Coefficients of the rational polynomials to + // approx J_0 for x < 8 + c1:={57568490574.0,-13362590354.0,651619640.7, + -11214424.18,77392.33017,-184.9052456}; + c2:={57568490411.0,1029532985.0,9494680.718, + 59272.64853,267.8532712}; + // Coefficients of the rational polynomials to + // approx J_0 for x >= 8 + c3:={-0.001098628627,0.00002734510407,-0.000002073370639, + 0.0000002093887211}; + c4:={-0.01562499995,0.0001430488765,-0.000006911147651, + 0.0000007621095161,0.0000000934935152}; + ax:=Abs(x); + + If( ax < 8.0,[ + y:=x^2; + res1:=c1[1]+y*(c1[2]+y*c1[3]+y*(c1[4]+y*(c1[5]+y*(c1[6])))); + res2:=c1[1]+y*(c2[2]+y*c2[3]+y*(c2[4]+y*(c2[5]+y*1.0))); + result:=res1/res2; + ],[ + z:=8/ax; + y:=z^2; + xx:=ax-0.785398164; + res1:=1.0+y*(c3[1]+y*(c3[2]+y*(c3[3]+y*c4[4]))); + res2:=c4[1]+y*(c4[2]+y*(c4[3]+y*(c4[4]-y*c4[5]))); + result:=Sqrt(2/(Pi*x))*(Cos(xx)*res1-z*Sin(xx)*res2); + ] ); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bessel/BesselJN.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Was not implemented in the scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bessel/BesselNsmall.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bessel/BesselNsmall.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/bessel/BesselNsmall.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/bessel/BesselNsmall.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="BesselNsmall" + +/// coded by Jonathan Leto + +// When x is <= 1, the series is monotonely decreasing from the +// start, so we don't have to worry about loss of precision from the +// series definition. +// When {n} is an integer, this is fast. +// When {n} is not, it is pretty slow due to Gamma() + +Function("BesselNsmall",{n,x,modified}) +[ + Local(term,result,k); + Local(prec,eps,tmp); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(Ceil(1.2*prec)); // this is a guess + eps:=5*10^(-prec); + + term:=1; + k:=0; + result:=0; + While( Abs(term) >= eps )[ + term:=x^(2*k+n); + // The only difference between BesselJ and BesselI + // is an alternating term + If( k%2=1 And modified=0 , term:=term*-1 ); + term:=N(term/(2^(2*k+n)* k! * Gamma(k+n+1) )); + //Echo({"term is ",term}); + result:=result+term; + k:=k+1; + ]; + BuiltinPrecisionSet(prec); + // This should not round, only truncate + // some outputs will be off by one in the last digit + RoundTo(result,prec); + +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/BesselI.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/BesselI.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/BesselI.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/BesselI.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="BesselI" + +//Jonathan Leto + +10 # BesselI(0,0) <-- 1; + +10 # BesselI(_n,0)_(n>0) <-- 0; + +10 # BesselI(_n,0)_(n<0 And IsInteger(n)) <-- 0; + + +// The following should be ComplexInfinity, if/when that is implemented +10 # BesselI(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity; + + +20 # BesselI(1/2,_x) <-- Sqrt(2/(x*Pi))*Sinh(x); + + +20 # BesselI(3/2,_x) <-- Sqrt(2/(x*Pi))*(Cosh(x) - Sinh(x)/x); + + +20 # BesselI(5/2,_x) <-- Sqrt(2/(x*Pi))*((3/x^2 + 1)*Sinh(x) - 3*Cosh(x)/x ); + + +30 # BesselI(_n,_z)_(n<0 And IsInteger(n) ) <-- BesselI(-n,z); + + +// When I put "And InNumericMode()" on the next rule, I lose precision. Why ? +// Also, if I move the the "_IsComplex" to the end with "IsComplex(x)" +// I lose precision. + + +//40 # BesselI(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N(BesselNsmall(n,x,1)); + + +40 # BesselI(_n,x_IsComplex)_(IsConstant(x) And Abs(x)<= 2*Gamma(n) ) <-- +[ +ApproxInfSum((x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} ); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/BesselJ.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/BesselJ.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/BesselJ.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/BesselJ.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="BesselJ" + +//Jonathan Leto + +10 # BesselJ(0,0) <-- 1; +10 # BesselJ(_n,0)_(n>0) <-- 0; +10 # BesselJ(_n,0)_(n<0 And IsInteger(n)) <-- 0; +10 # BesselJ(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity; +10 # BesselJ(0,Infinity)<-- 0; +20 # BesselJ(1/2,_x) <-- Sqrt(2/(x*Pi))*Sin(x); +20 # BesselJ(-1/2,_x) <-- Sqrt(2/(x*Pi))*Cos(x); +20 # BesselJ(3/2,_x) <-- Sqrt(2/(x*Pi))*(Sin(x)/x - Cos(x)); +20 # BesselJ(-3/2,_x) <-- Sqrt(2/(x*Pi))*(Cos(x)/x + Sin(x)); +20 # BesselJ(5/2,_x) <-- Sqrt(2/(x*Pi))*((3/x^2 - 1)*Sin(x) - 3*Cos(x)/x ); +20 # BesselJ(-5/2,_x) <-- Sqrt(2/(x*Pi))*( (3/x^2 -1)*Cos(x) + 3*Sin(x)/x ); + + +// Forward recursion, works great, but really slow when n << x +30 # BesselJ(_n,_x)_(IsConstant(x) And IsInteger(n) And N(Abs(x) > 2*Gamma(n))) <-- N((2*(n+1)/x)*BesselJ(n+1,x) - BesselJ(n+2,x)); + +30 # BesselJ(_n,_z)_(n<0 And IsInteger(n) ) <-- (-1)^n*BesselJ(-n,z); + +// When I put "And InNumericMode()" on the next rule, I lose precision. Why ? +// Also, if I move the the "_IsComplex" to the end with "IsComplex(x)" +// I lose precision. + +//40 # BesselJ(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N(BesselNsmall(n,x,0)); + +40 # BesselJ(_n,x_IsComplex)_(N(Abs(x)<= 2*Gamma(n)) ) <-- +[ +ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} ); +]; + +50 # BesselJ(0,x_IsComplex)_(InNumericMode()) <-- N(BesselJN0(x)); + +//50 # BesselJ(_n_IsPositiveNumber,_z_IsComplex) <-- BesselJN(n,z); + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/BesselY.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/BesselY.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/BesselY.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/BesselY.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="BesselY" +//Jonathan Leto + +// This is buggy +40 # BesselY(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N((Cos(n*Pi)*BesselJ(n,x) - BesselJ(-n,x))/Sin(Pi*n)); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Beta.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Beta.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Beta.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Beta.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Beta" + +//Jonathan Leto + +10 # Beta(_n,_m) <-- Gamma(m)*Gamma(n)/Gamma(m+n); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/CatalanConstNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/CatalanConstNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/CatalanConstNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/CatalanConstNum.mpw 2010-01-06 02:51:37.000000000 +0000 @@ -0,0 +1,104 @@ +%mathpiper,def="CatalanConstNum" + +//Jonathan Leto + +///////////////////////////////////////////////// +/// Catalan's constant, various algorithms for comparison. (SW) +///////////////////////////////////////////////// + +/* Brent-Fee's method based on Ramanujan's identity and Brent's trick. + * Geometric convergence as 2^(-n). */ +CatalanConstNum1() := +[ + Local(prec,Aterm,Bterm,nterms,result,n); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(10); + // estimate the number of terms from above + nterms := 1+Floor(N((prec*Ln(10)+Ln(prec*Ln(10)/Ln(2)))/Ln(2))); + BuiltinPrecisionSet(prec+5); + Aterm:=N(1/2); + result:= Aterm; + Bterm:=Aterm; + For(n:=1, n<=nterms, n++ ) + [ +/* + Bterm := MultiplyNum(Bterm, n/(2*n+1)); + Aterm:= DivideN(MultiplyNum(Aterm,n)+Bterm, 2*n+1); +/* this is faster: */ + Bterm:=DivideN(MultiplyN(Bterm,n), 2*n+1); // Bterm = (k!)^2*2^(k-1)/(2*k+1)! + Aterm:=DivideN(MultiplyN(Aterm,n)+Bterm, 2*n+1); // Aterm = Bterm * Sum(k,0,n,1/(2*k+1)) +/**/ + result := result + Aterm; + ]; + BuiltinPrecisionSet(prec); + RoundTo(result,prec); +]; + +/* Bailey 1997's method. + * Geometric convergence as 4^(-n). */ + +CatalanConstNum() := +[ + Local(prec, n, result); + prec:=BuiltinPrecisionGet(); + + // number of terms + n := 1+Quotient(prec*1068+642,643); // prec*Ln(10)/Ln(4) + BuiltinPrecisionSet(prec+2); // 2 guard digits + + result := N(1/(2*n+1)); + While(n>0) + [ +/* + result := MultiplyNum(result, n/(4*n+2))+N(1/(2*n-1)); +/* this is faster: */ + result := DivideN(MultiplyN(result, n), 4*n+2)+DivideN(1,2*n-1); +/**/ + n := n-1; + ]; + result := MultiplyNum(result, 3/8) + N(Pi/8*Ln(2+Sqrt(3))); + BuiltinPrecisionSet(prec); + RoundTo(result,prec); +]; + +/* Broadhurst's series. + * Geometric convergence as 16^(-n). */ + +CatalanConstNum2() := +[ + Local(prec, n, result1, result2); + prec:=BuiltinPrecisionGet(); + + // first series + // number of terms + n := 1+Quotient(prec*534+642,643); // prec*Ln(10)/Ln(16) + BuiltinPrecisionSet(prec+2); // 2 guard digits + + result1 := 0; + While(n>=0) + [ + result1 := DivideN(result1, 16)+N( + +1/(8*n+1)^2 -1/(8*n+2)^2 +1/2/(8*n+3)^2 -1/4/(8*n+5)^2 +1/4/(8*n+6)^2 -1/8/(8*n+7)^2 + ); + n := n-1; + ]; + + // second series + // number of terms + n := 1+Quotient(prec*178+642,643); // prec*Ln(10)/Ln(4096) + BuiltinPrecisionSet(prec+2); // 2 guard digits + + result2 := 0; + While(n>=0) + [ + result2 := DivideN(result2, 4096)+N( + +1/(8*n+1)^2 +1/2/(8*n+2)^2 +1/8/(8*n+3)^2 -1/64/(8*n+5)^2 -1/128/(8*n+6)^2 -1/512/(8*n+7)^2 + ); + n := n-1; + ]; + result1 := MultiplyNum(result1, 3/2) - MultiplyNum(result2, 1/4); + BuiltinPrecisionSet(prec); + RoundTo(result1,prec); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DawsonIntegral.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DawsonIntegral.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DawsonIntegral.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DawsonIntegral.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="DawsonIntegral" + +//Jonathan Leto + +// needs Erf() that takes complex argument +/* +10 # DawsonIntegral(_x) <-- [ + Local(result,prec); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(prec+5); + result:=N(I*Sqrt(Pi)*Exp(-x^2)*Erf(-I*x)/2); + BuiltinPrecisionSet(prec); + RoundTo(result,prec); +]; +*/ + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Digamma.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Digamma.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Digamma.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Digamma.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Digamma" + +//Jonathan Leto + +10 # Digamma(_n)_(IsPositiveInteger(n)) <-- Sum(m,1,n-1,1/m) - gamma; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DirichletBeta.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DirichletBeta.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DirichletBeta.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DirichletBeta.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="DirichletBeta" + +//Jonathan Leto + +// This is really slow for x <= 3 +5 # DirichletBeta(1) <-- Pi/4; +5 # DirichletBeta(2) <-- Catalan; +5 # DirichletBeta(3) <-- Pi^3/32; +6 # DirichletBeta(n_IsOdd) <-- [ + Local(k); + k:=(n-1)/2; + (-1)^k*Euler(2*k)*(Pi/2)^(2*k+1)/(2*(2*k)!); +]; + + +10 # DirichletBeta(x_IsRationalOrNumber)_(InNumericMode() And x>=1 ) <-- [ + Local(prec,eps,term,result,k); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(prec+3); + eps:=10^(-prec); + result:=0; + term:=1; + For(k:=0, Abs(term) > eps, k++ )[ + term:=(-1)^k/(2*k+1)^x; + Echo("term is ",term); + result:=result+term; + ]; + BuiltinPrecisionSet(prec); + RoundTo(result,prec); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DirichletEta.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DirichletEta.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DirichletEta.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DirichletEta.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="DirichletEta" + +//Jonathan Leto + +10 # DirichletEta(_z) <-- (1-2/2^z)*Zeta(z); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DirichletLambda.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DirichletLambda.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/DirichletLambda.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/DirichletLambda.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="DirichletLambda" + +//Jonathan Leto + +10 # DirichletLambda(_z)<-- (1-1/2^z)*Zeta(z); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Erfc.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Erfc.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Erfc.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Erfc.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Erfc" + +//Jonathan Leto + +10 # Erfc(_x) <-- 1 - Erf(x); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Erfi.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Erfi.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Erfi.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Erfi.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Erfi" + +//Jonathan Leto + +10 # Erfi(_x) <-- -I*Erf(x*I); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Erf.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Erf.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Erf.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Erf.mpw 2010-01-06 01:59:24.000000000 +0000 @@ -0,0 +1,62 @@ +%mathpiper,def="Erf" + +//Jonathan Leto + +///////////////////////////////////////////////// +/// Error and complementary error functions +///////////////////////////////////////////////// + +10 # Erf(0) <-- 0; +//10 # Erfc(0) <-- 1; +10 # Erf(Infinity) <-- 1; +10 # Erf(Undefined) <-- Undefined; +//10 # Erfc(Infinity) <-- 0; +10 # Erf(x_IsNumber)_(x<0) <-- -Erf(-x); +//40 # Erf(x_IsNumber)_(Abs(x) <= 1 ) <-- N(2/Sqrt(Pi)*ApproxInfSum((-1)^k*x^(2*k+1)/((2*k+1)*k!),0,x)); + +LocalSymbols(k) +[ + 40 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x)) And Abs(x) <= 1) <-- +[ + Local(prec); + prec := BuiltinPrecisionGet(); // N(...) modifies the precision + 2 / SqrtN(Internal'Pi()) * x + * SumTaylorNum(x^2, 1, {{k}, -(2*k-1)/(2*k+1)/k}, + // the number of terms n must satisfy n*Ln(n/Exp(1))>10^prec +// Hold({{k}, [Echo(k); k;]}) @ + N(1+87/32*Exp(LambertW(prec*421/497)), 20) + ); + +]; + +]; // LocalSymbols(k) + +// asymptotic expansion, can be used only for low enough precision or large enough |x| (see predicates). Also works for complex x. +LocalSymbols(n'max, k) +[ + + 50 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x)) + And ( + [ // strongest condition: the exp(-x^2) asymptotic is already good + n'max := 0; + Re(x^2) > BuiltinPrecisionGet()*3295/1431+0.121; + ] + Or + [ // next condition: the exp(-x^2) helps but we need a few terms of the series too + n'max := N(Minimum((BuiltinPrecisionGet()*3295/1431+0.121)/Internal'LnNum(Abs(x)), 2*Internal'LnNum(Abs(x))), 10); + 2*Abs(x)+Re(x^2) > BuiltinPrecisionGet()*3295/1431+0.121; + ] + Or + [ // worst case: exp(-x^2) does not help and we need the full series + // hack: save a value computed in the predicate to use in the body of rule + n'max := N(({{k}, k+Internal'LnNum(k)} @ BuiltinPrecisionGet()*3295/1431)/2 - 3/2, 10); + Abs(x) > n'max+3/2; + ] + ) + ) <-- If(Re(x)!=0, Sign(Re(x)), 0) - Exp(-x^2)/x/SqrtN(Internal'Pi()) + // the series is 1 - 1/2/x^2 + 1*3/2^2/x^4 - 1*3*5/2^3/x^6 + ... + * SumTaylorNum(1/x^2, 1, {{k}, -(2*k-1)/2 }, Maximum(0, Floor(n'max))); + +]; // LocalSymbols(n'max, k) + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/FresnelCos.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/FresnelCos.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/FresnelCos.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/FresnelCos.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper,def="FresnelCos" + +//Jonathan Leto + +10 # FresnelCos(0) <-- 0; +10 # FresnelCos(Infinity) <-- 1/2; +10 # FresnelCos(x_IsNumber)_(x<0) <-- -FresnelCos(x); + +40 # FresnelCos(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(4*k-3)/((4*k-3) * (2*k-2)! ),1,x)); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/FresnelSin.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/FresnelSin.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/FresnelSin.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/FresnelSin.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,16 @@ +%mathpiper,def="FresnelSin" + +//Jonathan Leto + +///////////////////////////////////////////////// +/// Fresnel integrals +///////////////////////////////////////////////// + +10 # FresnelSin(0) <-- 0; +10 # FresnelSin(Infinity) <-- 1/2; +10 # FresnelSin(x_IsNumber)_(x<0) <-- -FresnelSin(x); + +40 # FresnelSin(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(2*k+1)/(k! * (2*k+1)),1,x)); + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/gamma/Internal'GammaNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/gamma/Internal'GammaNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/gamma/Internal'GammaNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/gamma/Internal'GammaNum.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="Internal'GammaNum" + +//Serge Winitzki + +Internal'GammaNum(z) := N(Exp(Internal'LnGammaNum(z))); + +/// this should not be used by applications +Internal'GammaNum(z,a) := N(Exp(Internal'LnGammaNum(z,a))); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/gamma/Internal'LnGammaNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/gamma/Internal'LnGammaNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/gamma/Internal'LnGammaNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/gamma/Internal'LnGammaNum.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,54 @@ +%mathpiper,def="Internal'LnGammaNum" + +///////////////////////////////////////////////// +/// Euler's Gamma function +///////////////////////////////////////////////// + +//Serge Winitzki + +/// This procedure computes the uniform approximation for the Gamma function +/// due to Lanczos and Spouge (the so-called "less precise coefficients") +/// evaluated at arbitrary precision by using a large number of terms +/// See J. L. Spouge, SIAM J. of Num. Anal. 31, 931 (1994) +/// See also Paul Godfrey 2001 (unpublished): http://winnie.fit.edu/~gabdo/gamma.txt for a discussion + +/// Calculate the uniform approximation to the logarithm of the Gamma function +/// in the Re z > 0 half-plane; argument z may be symbolic or complex +/// but current value of precision is used +/// Note that we return LnGamma(z), not of z+1 +/// This function should not be used directly by applications +10 # Internal'LnGammaNum(_z, _a)_(N(Re(z))<0) <-- [ + If (InVerboseMode(), Echo({"Internal'LnGammaNum: using 1-z identity"})); + N(Ln(Pi/Sin(Pi*z)) - Internal'LnGammaNum(1-z, a)); +]; +20 # Internal'LnGammaNum(_z, _a) <-- [ + Local(e, k, tmpcoeff, coeff, result); + a := Maximum(a, 4); // guard against low values + If (InVerboseMode(), Echo({"Internal'LnGammaNum: precision parameter = ", a})); + e := N(Exp(1)); + k:=Ceil(a); // prepare k=N+1; the k=N term is probably never significant but we don't win much by excluding it + result := 0; // prepare for last term + // use Horner scheme to prevent loss of precision + While(k>1) [ // 'result' will accumulate just the sum for now + k:=k-1; + result := N( PowerN(a-k,k)/((z+k)*Sqrt(a-k))-result/(e*k) ); + ]; + N(Ln(1+Exp(a-1)/Sqrt(2*Pi)*result) + Ln(2*Pi)/2 -a-z+(z+1/2)*Ln(z+a) - Ln(z)); +]; + +Internal'LnGammaNum(z) := [ + Local(a, prec, result); + prec := BuiltinPrecisionGet(); + a:= Quotient((prec-IntLog(prec,10))*659, 526) + 0.4; // see algorithm docs + /// same as parameter "g" in Godfrey 2001. + /// Chosen to satisfy Spouge's error bound: + /// error < Sqrt(a)/Real(a+z)/(2*Pi)^(a+1/2) +// Echo({"parameter a = ", a, " setting precision to ", Ceil(prec*1.4)}); + BuiltinPrecisionSet(Ceil(prec*1.4)); // need more precision b/c of roundoff errors but don't know exactly how many digits + result := Internal'LnGammaNum(z,a); + BuiltinPrecisionSet(prec); + result; +]; + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/gammaconst/GammaConstNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/gammaconst/GammaConstNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/gammaconst/GammaConstNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/gammaconst/GammaConstNum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="GammaConstNum" + +GammaConstNum() := +[ + Local(k, n, A, B, U'old, U, V'old, V, prec, result); + prec:=BuiltinPrecisionGet(); + NonN([ + BuiltinPrecisionSet(prec+IntLog(prec,10)+3); // 2 guard digits and 1 to compensate IntLog + n:= 1+Ceil(prec*0.5757+0.2862); // n>(P*Ln(10)+Ln(Pi))/4 + A:= -Internal'LnNum(n); + B:=1; + U:=A; + V:=1; + k:=0; + U'old := 0; // these variables are for precision control + V'old := 0; + While(U'old-U != 0 Or V'old-V != 0) + [ + k++; + U'old:=U; + V'old:=V; + // B:=N( B*n^2/k^2 ); + B:=MultiplyNum(B,n^2/k^2); // slightly faster + // A:=N( (A*n^2/k+B)/k ); + A:=MultiplyNum(MultiplyNum(A,n^2/k)+B, 1/k); // slightly faster + U:=U+A; + V:=V+B; + ]; + If(InVerboseMode(), Echo("GammaConstNum: Info: used", k, "iterations at working precision", BuiltinPrecisionGet())); + result:=DivideN(U,V); // N(U/V) + ]); + BuiltinPrecisionSet(prec); // restore precision + RoundTo(result, prec); // return correctly rounded result +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Gamma.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Gamma.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Gamma.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Gamma.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,55 @@ +%mathpiper,def="Gamma" + +///////////////////////////////////////////////// +/// Euler's Gamma function +//////////////////////////////////////////////////// +/// Serge Winitzki + +/// User visible functions: Gamma(x), LnGamma(x) + +5 # Gamma(Infinity) <-- Infinity; + +10 # Gamma(_n)_(IsInteger(n) And n<=0) <-- Infinity; + + +20 # Gamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- (Round(2*n)/2-1)!; + + +30 # Gamma(x_IsConstant)_(InNumericMode()) <-- Internal'GammaNum(N(Eval(x))); + + +%/mathpiper + + + +%mathpiper_docs,name="Gamma",categories="User Functions;Special Functions" +*CMD Gamma --- Euler's Gamma function +*STD +*CALL + Gamma(x) + +*PARMS + +{x} -- expression + +{number} -- expression that can be evaluated to a number + +*DESC + +{Gamma(x)} is an interface to Euler's Gamma function $Gamma(x)$. It returns exact values on integer and half-integer arguments. {N(Gamma(x)} takes a numeric parameter and always returns a floating-point number in the current precision. + +Note that Euler's constant $gamma<=>0.57722$ is the lowercase {gamma} in MathPiper. + +*E.G. + +In> Gamma(1.3) +Result: Gamma(1.3); +In> N(Gamma(1.3),30) +Result: 0.897470696306277188493754954771; +In> Gamma(1.5) +Result: Sqrt(Pi)/2; +In> N(Gamma(1.5),30); +Result: 0.88622692545275801364908374167; + +*SEE !, N, gamma +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/LambertW.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/LambertW.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/LambertW.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/LambertW.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,def="LambertW" + +//Jonathan Leto + +///////////////////////////////////////////////// +/// Lambert's $W$ function. +///////////////////////////////////////////////// +/// Serge Winitzki + +10 # LambertW(0) <-- 0; +10 # LambertW(Infinity) <-- Infinity; +10 # LambertW(Undefined) <-- Undefined; +10 # LambertW(-Infinity) <-- Infinity + I*Pi; +10 # LambertW(-Exp(-1)) <-- -1; +20 # LambertW(_x * Ln(_x)) <-- Ln(x); +20 # LambertW(Ln(_x) * _x) <-- Ln(x); + +30 # LambertW(x_IsConstant) _ InNumericMode() <-- Internal'LambertWNum(Eval(x)); + +/* {Internal'LambertWNum} computes a numeric approximation of Lambert's $W$ function +to the current precision. It uses a Halley iteration +$$ W'=W-(W-x*Exp(-W))/(W+1-(W+2)/(W+1)*(W-x*Exp(-W))/2) $$. +The function has real values for real $x >= -Exp(-1)$. (This point is a logarithmic branching point.) +*/ +10 # Internal'LambertWNum(x_IsNumber)_(x < -ExpN(-1)) <-- Undefined; +20 # Internal'LambertWNum(x_IsNumber) <-- +[ + Local(W); + NewtonNum( + `Hold( + { + {W}, + [ + Local(a); + a:=W- @x*ExpN(-W); + W-a/(W+1-(W+2)/(W+1)*a/2.); + ]}), + // initial approximation is the two-point global Pade: + If( + x<0, + x*ExpN(1) / (1+1 / (1 / SqrtN(2*(x*ExpN(1)+1)) - 1 / SqrtN(2) + 1/(ExpN(1)-1))), + Internal'LnNum(1+x)*(1-Internal'LnNum(1+Internal'LnNum(1+x))/(2+Internal'LnNum(1+x))) + ), + 10, // initial approximation is good to about 3 digits + 3 // 3rd order scheme + ); +]; + +%/mathpiper + + + +%mathpiper_docs,name="LambertW",categories="User Functions;Special Functions" +*CMD LambertW --- Lambert's $W$ function + +*STD +*CALL + LambertW(x) +*PARMS + +{x} -- expression, argument of the function + +*DESC + +Lambert's $W$ function is (a multiple-valued, complex function) defined for any (complex) $z$ by +$$ W(z) * Exp(W(z)) = z$$. +This function is sometimes useful to represent solutions of transcendental equations. For example, the equation $Ln(x)=3*x$ can be "solved" by writing $x= -3*W(-1/3)$. It is also possible to take a derivative or integrate this function "explicitly". + +For real arguments $x$, $W(x)$ is real if $x>= -Exp(-1)$. + +To compute the numeric value of the principal branch of Lambert's $W$ function for real arguments $x>= -Exp(-1)$ to current precision, one can call {N(LambertW(x))} (where the function {N} tries to approximate its argument with a real value). + +*E.G. +In> LambertW(0) +Result: 0; +In> N(LambertW(-0.24/Sqrt(3*Pi))) +Result: -0.0851224014; + +*SEE Exp +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/LnGamma.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/LnGamma.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/LnGamma.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/LnGamma.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper,def="LnGamma" + +///// Serge Winitzki + +10 # LnGamma(_n)_(IsInteger(n) And n<=0) <-- Infinity; + +20 # LnGamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- Ln((Round(2*n)/2-1)!); + +30 # LnGamma(x_IsConstant)_(InNumericMode()) <-- Internal'LnGammaNum(N(Eval(x))); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/om/om.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,28 @@ +%mathpiper,def="" + +// From code.mpi.def: +OMDef( "Gamma", "nums1", "gamma" ); +OMDef( "LnGamma" , mathpiper, "LnGamma" ); +OMDef( "Zeta" , mathpiper, "Zeta" ); +OMDef( "Bernoulli" , mathpiper, "Bernoulli" ); +OMDef( "ApproxInfSum" , mathpiper, "ApproxInfSum" ); +OMDef( "BesselJ" , mathpiper, "BesselJ" ); +OMDef( "BesselI" , mathpiper, "BesselI" ); +OMDef( "BesselY" , mathpiper, "BesselY" ); +OMDef( "Erf" , mathpiper, "Erf" ); +OMDef( "Erfc" , mathpiper, "Erfc" ); +OMDef( "Erfi" , mathpiper, "Erfi" ); +OMDef( "FresnelSin" , mathpiper, "FresnelSin" ); +OMDef( "FresnelCos" , mathpiper, "FresnelCos" ); +OMDef( "LambertW" , mathpiper, "LambertW" ); +OMDef( "Beta" , mathpiper, "Beta" ); +OMDef( "DirichletEta" , mathpiper, "DirichletEta" ); +OMDef( "DirichletLambda", mathpiper, "DirichletLambda" ); +OMDef( "DirichletBeta" , mathpiper, "DirichletBeta" ); +OMDef( "Sinc" , mathpiper, "Sinc" ); +OMDef( "PolyLog" , mathpiper, "PolyLog" ); +OMDef( "CatalanConstNum", mathpiper, "CatalanConstNum" ); +OMDef( "Digamma" , mathpiper, "Digamma" ); +OMDef( "DawsonIntegral" , mathpiper, "DawsonIntegral" ); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/PolyLog.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/PolyLog.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/PolyLog.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/PolyLog.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,86 @@ +%mathpiper,def="PolyLog" + +//Jonathan Leto + +////// Polylogarithm Function +/// coded by Jonathan Leto: PolyLog, Dirichlet*, Digamma, Bessel*, Erf*, Fresnel*, Beta, +/// CatalanConstNum, Sinc, Beta, DawsonIntegral +// Note: currently, the numerics are only working for x \in [-1,1] + +10 # PolyLog(_n,0) <-- 0; +// this is nicer than -Ln(1/2) +10 # PolyLog(1,1/2) <-- Ln(2); +10 # PolyLog(_n,1) <-- Zeta(n); +10 # PolyLog(_n,_m)_(m= -1) <-- DirichletEta(n); +10 # PolyLog(_n,_x)_(n< 0) <-- (1/((1-x)^(-n+1)))*Sum(i,0,-n,Eulerian(-n,i)*x^(-n-i) ); +//10 # PolyLog(_n,_x)_(n= -3) <-- x*(x^2 + 4*x + 1)/(x-1)^4; +//10 # PolyLog(_n,_x)_(n= -2) <-- x*(x+1)/(1-x)^3; +//10 # PolyLog(_n,_x)_(n= -1) <-- x/(1-x)^2; +10 # PolyLog(0,_x) <-- x/(1-x); +10 # PolyLog(1,_x) <-- -Ln(1-x); +// special values +10 # PolyLog(2,1/2) <-- (Pi^2 - 6*Ln(2)^2)/12; +10 # PolyLog(3,1/2) <-- (4*Ln(2)^3 - 2*Pi^2*Ln(2)+21*Zeta(3))/24; +10 # PolyLog(2,2) <-- Pi^2/4 - Pi*I*Ln(2); + +20 # PolyLog(_n,_x)_(InNumericMode() And x < -1 ) <-- [ + Local(prec,result); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(prec+5); + Echo("Warning: PolyLog is only currently accurate for x in [-1,1]"); + result:= (-1)^(n-1)*PolyLog(n,1/x) - ((Ln(-x))^n)/n! - + Sum(r,1,Round(n/2), + 2^(2*r-2)*Pi^(2*r)*Abs(Bernoulli(2*r))*Ln(-x)^(n-2*r)/( (2*r)! * (n - 2*r)! ) ); + BuiltinPrecisionSet(prec); + RoundTo(N(result),prec); +]; +20 # PolyLog(_n,_x)_(InNumericMode() And x>= -1 And x < 0 ) <-- [ + // this makes the domain [-1,0) into [0,1], + // so if the summation representation is used, it is monotone + Local(prec,result); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(prec+5); + + result:=PolyLog(n,x^2)/2^(n-1) - PolyLog(n,-x) ; + BuiltinPrecisionSet(prec); + RoundTo(N(result),prec); + +]; +/* this is very slow at high precision +20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x <= 1) <-- [ + Local(result,prec,term,k,eps); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(prec+5); + eps:=10^(-prec); + result:=0; + // Sorry Serge, I was only getting 2 digits of precision with this + // so why didn't you ask me? :) -- Serge + //terms:=Floor(10 + N(prec*Ln(10)/Ln(prec) - 1)); + //BuiltinPrecisionSet( prec + Floor(N(Ln(6*terms)/Ln(10))) ); + //result:=SumTaylorNum(x, {{k}, x^(k+1)/(k+1)^n }, terms ); + term:=1; + For(k:=1,Abs(term)>eps,k++)[ + term:=N(x^k/k^n); + result:=result+term; + ]; + BuiltinPrecisionSet(prec); + RoundTo(result,prec); +]; +*/ + +20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x < 1) <-- +[ // use Taylor series x^(k+1)/(k+1)^n, converges for -1Higher Transcendental Functions, vol. 1; +/// P. Borwein, An efficient algorithm for Riemann Zeta function (1995). + +/// Numerical computation of Zeta function using Borwein's "third" algorithm +/// The value of $n$ must be large enough to ensure required precision +/// Also $s$ must satisfy $Re(s)+n+1 > 0$ +Internal'ZetaNum(_s, n_IsInteger) <-- [ + Local(result, j, sign); + If (InVerboseMode(), Echo({"Internal'ZetaNum: Borwein's method, precision ", BuiltinPrecisionGet(), ", n = ", n})); + result := 0; + sign := 1; // flipping sign + For(j:=0, j<=2*n-1, j++) + [ // this is suboptimal b/c we can compute the coefficients a lot faster in this same loop, but ok for now + result := N(result + sign*Internal'ZetaNumCoeffEj(j,n)/(1+j)^s ); + sign := -sign; + ]; + N(result/(2^n)/(1-2^(1-s))); +]; + +/// direct method -- only good for large s +Internal'ZetaNum1(s, limit) := [ + Local(i, sum); + If (InVerboseMode(), Echo({"Internal'ZetaNum: direct method (sum), precision ", BuiltinPrecisionGet(), ", N = ", limit})); + sum := 0; + limit := Ceil(N(limit)); + For(i:=2, i<=limit, i++) sum := sum+N(1/PowerN(i, s)); +// sum := sum + ( N( 1/PowerN(limit, s-1)) + N(1/PowerN(limit+1, s-1)) )/2/(s-1); // these extra terms don't seem to help much + sum+1; // add small terms together and then add 1 +]; +/// direct method -- using infinite product. For internal math, Internal'ZetaNum2 is faster for Bernoulli numbers > 250 or so. +Internal'ZetaNum2(s, limit) := +[ + Local(i, prod); + If (InVerboseMode(), Echo({"Internal'ZetaNum: direct method (product), precision ", BuiltinPrecisionGet(), ", N = ", limit})); + prod := N( (1-1/PowerN(2, s))*(1-1/PowerN(3,s)) ); + limit := Ceil(N(limit)); + For(i:=5, i<=limit, i:= NextPrime(i)) + prod := prod*N(1-1/PowerN(i, s)); + 1/prod; +]; + +/// Compute coefficients e[j] (see Borwein -- excluding (-1)^j ) +Internal'ZetaNumCoeffEj(j,n) := [ + Local(k); + 2^n-If(j1-s identity, s=", s, ", precision ", prec})); + result := 2*Exp(Internal'LnGammaNum(1-s)-(1-s)*Ln(2*Internal'Pi()))*Sin(Internal'Pi()*s/2) * Internal'ZetaNum(1-s); + ], + // choose between methods + If (N(Re(s)) > N(1+(prec*Ln(10))/(Ln(prec)+0.1), 6), + [ // use direct summation + n:= N(10^(prec/(s-1)), 6)+2; // 2 guard terms + BuiltinPrecisionSet(prec+2); // 2 guard digits + result := Internal'ZetaNum1(s, n); + ], + [ // use Internal'ZetaNum(s, n) + n := Ceil( N( prec*Ln(10)/Ln(8) + 2, 6 ) ); // add 2 digits just in case + BuiltinPrecisionSet(prec+2); // 2 guard digits + result := Internal'ZetaNum(s, n); + ] + ) + ); + BuiltinPrecisionSet(prec); + result; +]; + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Zeta.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Zeta.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/specfunc/Zeta.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/specfunc/Zeta.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,57 @@ +%mathpiper,def="Zeta" + +///////////////////////////////////////////////// +/// Riemann's Zeta function +///////////////////////////////////////////////// +/// Serge Winitzki + +/// identities for exact values of Zeta + +10 # Zeta(1) <-- Infinity; +10 # Zeta(0) <-- -1/2; // let's save time +10 # Zeta(3)_InNumericMode() <-- Zeta3(); // special case +10 # Zeta(n_IsEven)_(n>0) <-- Pi^n*(2^(n-1)/n! *Abs(Bernoulli(n))); +10 # Zeta(n_IsInteger)_(n<0) <-- -Bernoulli(-n+1)/(-n+1); +11 # Zeta(n_IsInfinity) <-- 1; + +/// compute numeric value +20 # Zeta(s_IsConstant)_(InNumericMode()) <-- Internal'ZetaNum(N(Eval(s))); + +%/mathpiper + + + +%mathpiper_docs,name="Zeta",categories="User Functions;Special Functions" +*CMD Zeta --- Riemann's Zeta function + +*STD +*CALL + Zeta(x) + +*PARMS + +{x} -- expression + +{number} -- expression that can be evaluated to a number + +*DESC + +{Zeta(x)} is an interface to Riemann's Zeta function $zeta(s)$. It returns exact values on integer and half-integer arguments. {N(Zeta(x)} takes a numeric parameter and always returns a floating-point number in the current precision. + +*E.G. + +In> Precision(30) +Result: True; +In> Zeta(1) +Result: Infinity; +In> Zeta(1.3) +Result: Zeta(1.3); +In> N(Zeta(1.3)) +Result: 3.93194921180954422697490751058798; +In> Zeta(2) +Result: Pi^2/6; +In> N(Zeta(2)); +Result: 1.64493406684822643647241516664602; + +*SEE !, N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/BernoulliDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/BernoulliDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/BernoulliDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/BernoulliDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,30 @@ +%mathpiper,def="BernoulliDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +BernoulliDistribution(p_IsRationalOrNumber)_(p<0 Or p>1) <-- Undefined; + +%/mathpiper + + + +%mathpiper_docs,name="BernoulliDistribution",categories="User Functions;Statistics & Probability" +*CMD BernoulliDistribution --- Bernoulli distribution +*STD +*CALL + BernoulliDistribution(p) + +*PARMS + +{p} -- number, probability of an event in a single trial + +*DESC +A random variable has a Bernoulli distribution with probability {p} if +it can be interpreted as an indicator of an event, where {p} is the +probability to observe the event in a single trial. + +Numerical value of {p} must satisfy $01, False) + Or (IsConstant(n) And Not IsPositiveInteger(n)) ) + <-- Undefined; + +%/mathpiper + + + +%mathpiper_docs,name="BinomialDistribution",categories="User Functions;Statistics & Probability" +*CMD BinomialDistribution --- binomial distribution +*STD +*CALL + BinomialDistribution(p,n) + +*PARMS +{p} -- number, probability to observe an event in single trial + +{n} -- number of trials + +*DESC +Suppose we repeat a trial {n} times, the probability to observe an +event in a single trial is {p} and outcomes in all trials are mutually +independent. Then the number of trials when the event occurred +is distributed according to the binomial distribution. The probability +of that is {BinomialDistribution}{(p,n)}. + +Describes the number of successes for draws with replacement. + +Numerical value of {p} must satisfy $0=b) + <-- Undefined; + +%/mathpiper + + + + +%mathpiper_docs,name="ContinuousUniformDistribution",categories="User Functions;Statistics & Probability" +*CMD ContinuousUniformDistribution --- Discrete uniform distribution +*STD +*CALL + ContinuousUniformDistribution(a, b) + +*PARMS + +{a} -- number, lower range value +{b} -- number, upper range value + + +*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/DiscreteDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/DiscreteDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/DiscreteDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/DiscreteDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,26 @@ +%mathpiper,def="DiscreteDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +DiscreteDistribution( dom_IsRationalOrNumber , prob_IsRationalOrNumber) <-- Undefined; + +%/mathpiper + + + + +%mathpiper_docs,name="DiscreteDistribution",categories="User Functions;Statistics & Probability" +*CMD ContinuousUniformDistribution --- Discrete uniform distribution +*STD +*CALL + DiscreteDistribution(dom, prob) + +*PARMS + +{dom} -- list +{prob} -- list + + +*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/DiscreteUniformDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/DiscreteUniformDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/DiscreteUniformDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/DiscreteUniformDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,27 @@ +%mathpiper,def="DiscreteUniformDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +DiscreteUniformDistribution(a_IsRationalOrNumber, b_IsRationalOrNumber)_(a>=b) + <-- Undefined; + +%/mathpiper + + + + +%mathpiper_docs,name="DiscreteUniformDistribution",categories="User Functions;Statistics & Probability" +*CMD DiscreteUniformDistribution --- Discrete uniform distribution +*STD +*CALL + DiscreteUniformDistribution(a, b) + +*PARMS + +{a} -- number, lower range value +{b} -- number, upper range value + + +*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/ExponentialDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/ExponentialDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/ExponentialDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/ExponentialDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,25 @@ +%mathpiper,def="ExponentialDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +ExponentialDistribution(l_IsRationalOrNumber)_(l<0) <-- Undefined; + +%/mathpiper + + + + +%mathpiper_docs,name="ExponentialDistribution",categories="User Functions;Statistics & Probability" +*CMD ExponentialDistribution --- Exponential distribution +*STD +*CALL + ExponentialDistribution(lambda) + +*PARMS + +{lambda} -- number, the rate parameter + + +*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ContinuousUniformDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/FDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/FDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/FDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/FDistribution.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,22 @@ +%mathpiper,def="FDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +//Retract("FDistribution",*); +FDistribution(_n1, _n2) <-- Undefined; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="FDistribution",categories="User Functions;Statistics & Probability" +*CMD FDistribution --- the F distribution +*CALL + Not Implemented Yet + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/GeometricDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/GeometricDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/GeometricDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/GeometricDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,25 @@ +%mathpiper,def="GeometricDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +GeometricDistribution(p_IsRationalOrNumber)_(p<0 Or p>1) <-- Undefined; + +%/mathpiper + + + + +%mathpiper_docs,name="GeometricDistribution",categories="User Functions;Statistics & Probability" +*CMD GeometricDistribution --- Geometric distribution +*STD +*CALL + GeometricDistribution(p) + +*PARMS + +{p} -- number, probability of an event in a single trial + + +*SEE BinomialDistribution, BernoulliDistribution, DiscreteUniformDistribution, ChiSquareDistribution, ContinuousUniformDistribution, ExponentionalDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/HypergeometricDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/HypergeometricDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/HypergeometricDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/HypergeometricDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,63 @@ +%mathpiper,def="HypergeometricDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +HypergeometricDistribution(N_IsRationalOrNumber, M_IsRationalOrNumber, n_IsRationalOrNumber)_(M > N Or n > N) + <-- Undefined; + +%/mathpiper + + + + +%mathpiper_docs,name="HypergeometricDistribution",categories="User Functions;Statistics & Probability" +*CMD HypergeometricDistribution --- Hypergeometric distribution +*STD +*CALL + HypergeometricDistribution(N, M, n) + +*PARMS + +{N} -- number, a finite population +{M} -- number of items from N that fall into a class of interest +{n} -- number of items drawn from N + +*DESC + +A discrete probability distribution that describes the number of successes in a sequence of +draws from a finite population without replacement. The hypergeometric distribution is the +probability model which is used for selecting a random sample of n items without replacement +from a lot of N items, M of which are nonconforming or defective. + +*E.G. + +/%mathpiper,title="" + +PDF(HypergeometricDistribution(100,5,10),0); + +/%/mathpiper + + /%output,preserve="false" + Result: 0.5837523670 +. /%/output + + + +/%mathpiper,title="" + +CDF(HypergeometricDistribution(100,5,10),1); + +/%/mathpiper + + /%output,preserve="false" + Result: 0.9231432779 +. /%/output + +*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/NormalDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/NormalDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/NormalDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/NormalDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="NormalDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +NormalDistribution( _m , s2_IsRationalOrNumber)_(s2<=0) <-- Undefined; + +%/mathpiper + + + + +%mathpiper_docs,name="NormalDistribution",categories="User Functions;Statistics & Probability" +*CMD NormalDistribution --- The normal distribution. +*STD +*CALL + NormalDistribution(mean, sigma) + +*PARMS + +{mean} -- Number, the mean of the distribution +{sigma} -- Number, the standard deviation of the distribution + +*DESC +The normal distribution. + +*E.G. +In> N(CDF(NormalDistribution(60,5),64.3)) +Result: 0.8051055222 + +*SEE BinomialDistribution, BernoulliDistribution, ChiSquareDistribution, DiscreteUniformDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/PoissonDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/PoissonDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/PoissonDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/PoissonDistribution.mpw 2010-10-25 22:13:56.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="PoissonDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +PoissonDistribution(l_IsRationalOrNumber)_(l<=0) <-- Undefined; + +%/mathpiper + + + + + +%mathpiper_docs,name="PoissonDistribution",categories="User Functions;Statistics & Probability" +*CMD PoissonDistribution --- Poisson distribution +*STD +*CALL + PoissonDistribution(lambda) + +*PARMS +{lambda} -- number, the expected number of occurrences that occur during the given interval + +*DESC +The poisson distribution. + +*E.G. +In> N(PMF(PoissonDistribution(5), 7)) +Result: 0.1044448631 + +In> N(CDF(PoissonDistribution(5), 2)) +Result: 0.1246520197 + + +*SEE BinomialDistribution, BernoulliDistribution, DiscreteUniformDistribution, ChiSquareDistribution, ContinuousUniformDistribution, ExponentionalDistribution, GeometricDistribution, NormalDistribution, PoissonDistribution, tDistribution +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/tDistribution.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/tDistribution.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/distributions/tDistribution.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/distributions/tDistribution.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="tDistribution" + +/* Guard against distribution objects with senseless parameters + Anti-nominalism */ + +tDistribution(m_IsRationalOrNumber)_(Not IsPositiveInteger(m)) <-- Undefined; + +%/mathpiper + + + +%mathpiper_docs,name="tDistribution",categories="User Functions;Statistics & Probability" +*CMD tDistribution --- Student's $t$ distribution +*STD +*CALL + {tDistribution}(m) + +*PARMS +{m} -- integer, number of degrees of freedom + +*DESC + +*REM what does it do??? +The function {tDistribution} returns the ... + +Let $Y$ and $Z$ be independent random variables, $Y$ have the +NormalDistribution(0,1), {Z} have ChiSquareDistribution(m). Then +$Y/Sqrt(Z/m)$ has tDistribution(m). + +Numerical value of {m} must be positive integer. +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/GeometricMean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/GeometricMean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/GeometricMean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/GeometricMean.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="GeometricMean" + +GeometricMean(list) := +[ + Check(IsList(list), "Argument", "Argument must be a list."); + + Product(list)^(1/Length(list)); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="GeometricMean",categories="User Functions;Statistics & Probability" +*CMD GeometricMean --- calculates the mean of a list of values +*STD +*CALL + GeometricMean(list) + +*PARMS + +{list} -- list of values + +*DESC + +This function calculates the geometric mean of a list of values. + +*E.G. +In> Mean({73,94,80,37,56,94,40,21,7,24}) +Result: 263/5 + +In> N(Mean({73,94,80,37,56,94,40,21,7,24})) +Result: 52.6 + +*SEE Mean, WeightedMean, Median, Mode +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/hypothesystest/ChiSquareTest.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/hypothesystest/ChiSquareTest.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/hypothesystest/ChiSquareTest.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/hypothesystest/ChiSquareTest.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,136 @@ +%mathpiper,def="ChiSquareTest" + + +/* ChiSquare's CDF is computed as IncompleteGamma(x,dof/2)/Gamma(dof/2); */ + +Retract(ChiSquareTest,*); + + +10 # ChiSquareTest( observedFrequenciesMatrix_IsMatrix, expectedFrequenciesMatrix_IsMatrix) <-- +[ + + Local(observedFrequenciesList, expectedFrequenciesList); + + observedFrequenciesList := Flatten(observedFrequenciesMatrix,"List"); + + expectedFrequenciesList := Flatten(expectedFrequenciesMatrix,"List"); + + Check(Length(observedFrequenciesList) > 0, "Argument", "The first argument must be a nonempty matrix."); + + Check(Length(expectedFrequenciesList) > 0, "Argument", "The second argument must be a nonempty matrix."); + + Check(Length(expectedFrequenciesList) = Length(expectedFrequenciesList), "Argument", "The matrices must be of equal length."); + + Local( numerator, chi2, pValue, categoriesCount, degreesOfFreedom, resultList); + + resultList := {}; + + categoriesCount := Length(observedFrequenciesList); + + numerator := (observedFrequenciesList - expectedFrequenciesList)^2; //threading + + chi2 := Sum(i,1,categoriesCount,numerator[i]/(expectedFrequenciesList[i])); + + degreesOfFreedom := (Dimensions(observedFrequenciesMatrix)[1] - 1)*(Dimensions(observedFrequenciesMatrix)[2] - 1); + + pValue := 1-N(IncompleteGamma(degreesOfFreedom/2,chi2/2)/Gamma(degreesOfFreedom/2)); + + resultList["degreesOfFreedom"] := degreesOfFreedom; + + resultList["pValue"] := pValue; + + resultList["chiSquareScore"] := chi2; + + N(resultList); +]; + + + + +20 # ChiSquareTest( observedFrequenciesList_IsList, expectedFrequenciesList_IsList) <-- +[ + Check(Length(observedFrequenciesList) > 0, "Argument", "The first argument must be a nonempty list."); + + Check(Length(expectedFrequenciesList) > 0, "Argument", "The second argument must be a nonempty list."); + + Check(Length(expectedFrequenciesList) = Length(expectedFrequenciesList), "Argument", "The lists must be of equal length."); + + Local( numerator, chi2, pValue, categoriesCount, degreesOfFreedom, resultList); + + resultList := {}; + + categoriesCount := Length(observedFrequenciesList); + + numerator := (observedFrequenciesList - expectedFrequenciesList)^2; //threading + + chi2 := Sum(i,1,categoriesCount,numerator[i]/(expectedFrequenciesList[i])); + + degreesOfFreedom := categoriesCount - 1; + + pValue := 1-N(IncompleteGamma(degreesOfFreedom/2,chi2/2)/Gamma(degreesOfFreedom/2)); + + resultList["degreesOfFreedom"] := degreesOfFreedom; + + resultList["pValue"] := pValue; + + resultList["chiSquareScore"] := chi2; + + N(resultList); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="ChiSquareTest",categories="User Functions;Statistics & Probability" +*CMD ChiSquareTest --- Pearson's ChiSquare test +*STD + +*CALL + ChiSquareTest(observed,expected) + +*PARMS +{observed} -- list of observed frequencies + +{expected} -- list of expected frequencies + +*DESC +{ChiSquareTest} is intended to determine if a sample was drawn from a +given distribution or not. To find this out, one has to calculate +observed frequencies into certain intervals and expected ones. + +*E.G. +/%mathpiper,title="" + +observedList := {145,128,73,32,22}; + +expectedList := {160,120,80,20,20}; + +a := ChiSquareTest(observedList, expectedList); + +TableForm(a); + +/%/mathpiper + + /%output,preserve="false" + Result: True + + Side Effects: + {"chiSquareScore",9.952083333} + {"pValue",0.0412426135} + {"degreesOfFreedom",4} + +. /%/output + + +*SEE AlphaToChiSquareScore, ChiSquareScoreToAlpha +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/incompletegamma/IncompleteGamma.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/incompletegamma/IncompleteGamma.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/incompletegamma/IncompleteGamma.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/incompletegamma/IncompleteGamma.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,def="" + + + +/* IncompleteGamma function \int\limits_{0}^xt^{a-1}e^{-t}dt + + Calculation is based on series + IncompleteGamma(a,x)=x^a*Sum(k,0,infinity,(-1)^k*x^k/k!/(a+k) + (see D.S.Kouznetsov. Special functions. Vysshaia Shkola, Moscow, 1965) + for small x, and on asymptotic expansion + IncompleteGamma(a,x)=Gamma(x)-x^(a-1)*Exp(-x)*(1+(a-1)/z+(a-1)(a-2)/z^2+...) + (see O.E.Barndorf-Nielsen & D.R.Cox. Asymptotic techniques for Use + in Statistics.. Russian translation is also available) + for large x. +*/ + + +/* This function is commented out because IncompleteGamma(2.5,3.6) causes infinite looping. + +//Retract("IncompleteGamma",*); + +100 # IncompleteGamma(_a, _x)_(x<=a+1) <-- +[ + Local(prec,eps); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(Ceil(prec+1)); // this is a guess + eps:=5*10^(-prec); + + Local(term,result,k); + + term:=1/a; + k:=0; + result:=0; + While( Abs(term) >= eps )[ + k:=k+1; + result:=result+term; + term:= -x*(a+k-1)*term/k/(a+k); + //Echo({"term is ",term}); + ]; + result:= N(x^a*result); + BuiltinPrecisionSet(prec); + // This should not round, only truncate + // some outputs will be off by one in the last digit + RoundTo(result,prec); +]; + + +100 # IncompleteGamma(_a, _x)_(x>a+1) <-- +[ // Asymptotic expansion + Local(prec,eps); + prec:=BuiltinPrecisionGet(); + BuiltinPrecisionSet(Ceil(prec+1)); // this is a guess + eps:=5*10^(-prec); + + Local(term,result,k,expr); + + term:=1; + k:=0; + result:=0; + While( Abs(term) >= eps )[ + k:=k+1; + result:=result+term; + term:=term*(a-k)/x; + //Echo({"term is ",term}); + ]; + result:=N(Gamma(a)-x^(a-1)*Exp(-x)*result); + BuiltinPrecisionSet(prec); + // This should not round, only truncate + // some outputs will be off by one in the last digit + RoundTo(result,prec); +]; + +*/ + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/Mean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/Mean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/Mean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/Mean.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="Mean" + +Mean(list) := +[ + Check(IsList(list), "Argument", "Argument must be a list."); + + Sum(list)/Length(list); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Mean",categories="User Functions;Statistics & Probability" +*CMD Mean --- calculates the mean of a list of values +*STD +*CALL + Mean(list) + +*PARMS + +{list} -- list of values + +*DESC + +This function calculates the mean of a list of values. + +*E.G. +In> Mean({73,94,80,37,56,94,40,21,7,24}) +Result: 263/5 + +In> N(Mean({73,94,80,37,56,94,40,21,7,24})) +Result: 52.6 + +*SEE WeightedMean, Median, Mode, GeometricMean +%/mathpiper_docs + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/Median.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/Median.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/Median.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/Median.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,49 @@ +%mathpiper,def="Median" + +Median(list) := +[ + Check(IsList(list), "Argument", "Argument must be a list."); + + Local(sx,n,n2); // s[orted]x + + sx := HeapSort(list,"<"); + + n := Length(list); + + n2 := (n>>1); + + If(Modulo(n,2) = 1, sx[n2+1], (sx[n2]+sx[n2+1])/2); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper_docs,name="Median",categories="User Functions;Statistics & Probability" +*CMD Median --- calculates the median of a list of values +*STD +*CALL + Median(list) + +*PARMS + +{list} -- list of values + +*DESC + +This function calculates the median of a list of values. + +*E.G. +In> Median({73,94,80,37,57,94,40,21,7,26}) +Result: 97/2 + +In> N(Median({73,94,80,37,57,94,40,21,7,26})) +Result: 48.5 + +*SEE WeightedMean, Mean, Mode, GeometricMean +%/mathpiper_docs + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/randomtest.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/randomtest.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/randomtest.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/randomtest.mpw 2010-01-07 02:48:04.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="",scope="nobuild",subtype="manual_test" + +/* + Tests MathPiper's Randomnumber generator + Author Andrei Zorine, zoav1@uic.nnov.ru +*/ + +DefaultDerivtory("c:/src/ys/prob"); +LoadScript("incompletegamma.mpi"); +LoadScript("hypothesystest.mpi"); + + +Function("DoTest",{size}) +[ + Local(arr,o'f,e'f,i,j,m); +// size:=200; // sample size + arr := Table(Random(),i,1,size,1); + arr := HeapSort(arr,"<"); + o'f := {}; + e'f :={}; + m:=1; + For(i:=1, i<=10 And m<=size, i++) + [ + j:=0; + While(arr[m] StandardDeviation({73,94,80,37,57,94,40,21,7,26}) +Result: Sqrt(88009/90) + +In> N(StandardDeviation({73,94,80,37,57,94,40,21,7,26})) +Result: 31.271037366 + +*SEE Variance, UnbiasedVariance +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/UnbiasedVariance.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/UnbiasedVariance.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/UnbiasedVariance.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/UnbiasedVariance.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="UnbiasedVariance" + +UnbiasedVariance(list) := +[ + Check(IsList(list), "Argument", "Argument must be a list."); + + Sum((list - Mean(list))^2)/(Length(list)-1); +]; + +%/mathpiper + + + + + + +%mathpiper_docs,name="UnbiasedVariance",categories="User Functions;Statistics & Probability" +*CMD UnbiasedVariance --- calculates the unbiased variance of a list of values +*STD +*CALL + UnbiasedVariance(list) + +*PARMS + +{list} -- list of values + +*DESC + +This function calculates the unbiased variance of a list of values. + +*E.G. +In> UnbiasedVariance({73,94,80,37,57,94,40,21,7,26}) +Result: 88009/90 + +In> N(UnbiasedVariance({73,94,80,37,57,94,40,21,7,26})) +Result: 977.8777778 + +*SEE Variance, StandardDeviation +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/Variance.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/Variance.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/statistics/Variance.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/statistics/Variance.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="Variance" + +Variance(list) := +[ + Check(IsList(list), "Argument", "Argument must be a list."); + + Sum((list - Mean(list))^2)/Length(list); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="Variance",categories="User Functions;Statistics & Probability" +*CMD Variance --- calculates the variance of a list of values +*STD +*CALL + Variance(list) + +*PARMS + +{list} -- list of values + +*DESC + +This function calculates the variance of a list of values. + +*E.G. +In> Variance({73,94,80,37,57,94,40,21,7,26}) +Result: 88009/100 + +In> N(Variance({73,94,80,37,57,94,40,21,7,26})) +Result: 880.09 + +*SEE UnbiasedVariance, StandardDeviation +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stats/ExpressionDepth.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stats/ExpressionDepth.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stats/ExpressionDepth.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stats/ExpressionDepth.mpw 2010-01-06 01:59:24.000000000 +0000 @@ -0,0 +1,18 @@ +%mathpiper,def="ExpressionDepth" + +10 # ExpressionDepth(expression_IsFunction) <-- +[ + Local(result); + result:=0; + ForEach(item,Rest(FunctionToList(expression))) + [ + Local(newresult); + newresult:=ExpressionDepth(item); + result:=Maximum(result,newresult); + ]; + result+1; +]; +20 # ExpressionDepth(_expression) <-- 1; +UnFence("ExpressionDepth",1); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCosh.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCosh.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCosh.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCosh.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper,def="ArcCosh" + +10 # ArcCosh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln(x+Sqrt(x^2-1)) )); + +200 # ArcCosh(Infinity) <-- Infinity; +200 # ArcCosh(-Infinity) <-- Infinity+I*Pi/2; +200 # ArcCosh(Undefined) <-- Undefined; + +ArcCosh(xlist_IsList) <-- MapSingle("ArcCosh",xlist); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCos.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCos.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCos.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCos.mpw 2011-03-26 20:50:24.000000000 +0000 @@ -0,0 +1,76 @@ +%mathpiper,def="ArcCos" + +2 # ArcCos(x_IsNumber)_InNumericMode() <-- Internal'Pi()/2-ArcSin(x); + + /* TODO check! */ +200 # ArcCos(0) <-- Pi/2; +200 # ArcCos(1/2) <-- Pi/3; +200 # ArcCos(Sqrt(1/2)) <-- Pi/4; +200 # ArcCos(Sqrt(3/4)) <-- Pi/6; +200 # ArcCos(1) <-- 0; +200 # ArcCos(_n)_(n = -1) <-- Pi; +200 # ArcCos(_n)_(-n = Sqrt(3/4)) <-- 5/6*Pi; +200 # ArcCos(_n)_(-n = Sqrt(1/2)) <-- 3/4*Pi; +200 # ArcCos(_n)_(-n = 1/2) <-- 2/3*Pi; + +200 # ArcCos(Undefined) <-- Undefined; + +ArcCos(xlist_IsList) <-- MapSingle("ArcCos",xlist); + +110 # ArcCos(Complex(_r,_i)) <-- + (- I)*Ln(Complex(r,i) + (Complex(r,i)^2 - 1)^(1/2)); + +%/mathpiper + + + +%mathpiper_docs,name="ArcCos",categories="User Functions;Trigonometry (Symbolic)" + +*CMD ArcCos --- inverse trigonometric function arc-cosine +*STD +*CALL + ArcCos(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function represents the inverse trigonometric function arc-cosine. For +instance, the value of $ArcCos(x)$ is a number $y$ such that +$Cos(y)$ equals $x$. + +Note that the number $y$ is not unique. For instance, $Cos(Pi/2)$ and +$Cos(3*Pi/2)$ both equal 0, so what should $ArcCos(0)$ be? In MathPiper, +it is agreed that the value of $ArcCos(x)$ should be in the interval [0,$Pi$] . + +Usually, MathPiper leaves this function alone unless it is forced to do +a numerical evaluation by the {N} function. If the +argument is -1, 0, or 1 however, MathPiper will simplify the +expression. If the argument is complex, the expression will be +rewritten using the {Ln} function. + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + + +In> ArcCos(0) +Result: Pi/2 + +In> ArcCos(1/3) +Result: ArcCos(1/3) +In> Cos(ArcCos(1/3)) +Result: 1/3 + +In> x:=N(ArcCos(0.75)) +Result: 0.7227342478 +In> N(Cos(x)) +Result: 0.75 + + +*SEE Sin, Cos, Tan, N, Pi, Ln, ArcSin, ArcTan + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCoth.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCoth.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCoth.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCoth.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCot.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCot.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCot.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCot.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts yet. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCsch.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCsch.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCsch.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCsch.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCsc.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCsc.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcCsc.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcCsc.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts yet. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSech.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSech.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSech.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSech.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSec.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSec.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSec.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSec.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts yet. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSinh.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSinh.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSinh.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSinh.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper,def="ArcSinh" + +10 # ArcSinh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln(x+Sqrt(x^2+1)) )); + +200 # ArcSinh(Infinity) <-- Infinity; +200 # ArcSinh(-Infinity) <-- -Infinity; +200 # ArcSinh(Undefined) <-- Undefined; + +ArcSinh(xlist_IsList) <-- MapSingle("ArcSinh",xlist); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSin.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSin.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcSin.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcSin.mpw 2011-03-26 20:50:24.000000000 +0000 @@ -0,0 +1,77 @@ +%mathpiper,def="ArcSin" + +2 # ArcSin(x_IsNumber)_(InNumericMode() And Abs(x)<=1) <-- ArcSinNum(x); +/// complex ArcSin +3 # ArcSin(x_IsNumber)_InNumericMode() <-- Sign(x)*(Pi/2+I*ArcCosh(x)); + +110 # ArcSin(Complex(_r,_i)) <-- + (- I) * Ln((I*Complex(r,i)) + ((1-(Complex(r,i)^2))^(1/2))); + +150 # ArcSin(- _x)_(Not IsConstant(x)) <-- -ArcSin(x); +160 # (ArcSin(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcSin(-x); + +200 # ArcSin(0) <-- 0; +200 # ArcSin(1/2) <-- Pi/6; +200 # ArcSin(Sqrt(1/2)) <-- Pi/4; +200 # ArcSin(Sqrt(3/4)) <-- Pi/3; +200 # ArcSin(1) <-- Pi/2; +200 # ArcSin(_n)_(n = -1) <-- -Pi/2; +200 # ArcSin(_n)_(-n = Sqrt(3/4)) <-- -Pi/3; +200 # ArcSin(_n)_(-n = Sqrt(1/2)) <-- -Pi/4; +200 # ArcSin(_n)_(-n = 1/2) <-- -Pi/6; + +ArcSin(xlist_IsList) <-- MapSingle("ArcSin",xlist); + +200 # ArcSin(Undefined) <-- Undefined; + +%/mathpiper + + + +%mathpiper_docs,name="ArcSin",categories="User Functions;Trigonometry (Symbolic)" +*CMD ArcSin --- inverse trigonometric function arc-sine +*STD +*CALL + ArcSin(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function represents the inverse trigonometric function arcsine. For +instance, the value of $ArcSin(x)$ is a number $y$ such that +$Sin(y)$ equals $x$. + +Note that the number $y$ is not unique. For instance, $Sin(0)$ and +$Sin(Pi)$ both equal 0, so what should $ArcSin(0)$ be? In MathPiper, +it is agreed that the value of $ArcSin(x)$ should be in the interval +[-$Pi$/2,$Pi$/2]. + +Usually, MathPiper leaves this function alone unless it is forced to do +a numerical evaluation by the {N} function. If the +argument is -1, 0, or 1 however, MathPiper will simplify the +expression. If the argument is complex, the expression will be +rewritten using the {Ln} function. + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> ArcSin(1) +Result: Pi/2; + +In> ArcSin(1/3) +Result: ArcSin(1/3); +In> Sin(ArcSin(1/3)) +Result: 1/3; + +In> x:=N(ArcSin(0.75)) +Result: 0.848062; +In> N(Sin(x)) +Result: 0.7499999477; + +*SEE Sin, Cos, Tan, N, Pi, Ln, ArcCos, ArcTan +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcTanh.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcTanh.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcTanh.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcTanh.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,13 @@ +%mathpiper,def="ArcTanh" + +10 # ArcTanh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln((1+x)/(1-x))/2 )); + +200 # ArcTanh(Infinity) <-- Infinity+I*Pi/2; +200 # ArcTanh(-Infinity) <-- -Infinity-I*Pi/2; // this is a little silly b/c we don't support correct branch cuts yet +200 # ArcTanh(Undefined) <-- Undefined; + +ArcTanh(xlist_IsList) <-- MapSingle("ArcTanh",xlist); + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcTan.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcTan.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/ArcTan.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/ArcTan.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,77 @@ +%mathpiper,def="ArcTan" + +5 # (ArcTan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcTan(-x); + +//TODO fix! 4 # ArcTan(Tan(_x)) <-- x; +4 # ArcTan(-Tan(_x)) <-- -ArcTan(Tan(x)); +110 # ArcTan(Complex(_r,_i)) <-- + (- I*0.5)*Ln(Complex(1,Complex(r,i))/ Complex(1, - Complex(r,i))); + +150 # ArcTan(- _x)_(Not IsConstant(x)) <-- -ArcTan(x); +160 # (ArcTan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcTan(-x); + +200 # ArcTan(Sqrt(3)) <-- Pi/3; +200 # ArcTan(-Sqrt(3)) <-- -Pi/3; +200 # ArcTan(1) <-- Pi/4; +200 # ArcTan(0) <-- 0; +200 # ArcTan(_n)_(n = -1) <-- -Pi/4; + +200 # ArcTan(Infinity) <-- Pi/2; +200 # ArcTan(-Infinity) <-- -Pi/2; +200 # ArcTan(Undefined) <-- Undefined; + +ArcTan(xlist_IsList) <-- MapSingle("ArcTan",xlist); + +2 # ArcTan(x_IsNumber)_InNumericMode() <-- ArcTanNum(x); + + +%/mathpiper + + + +%mathpiper_docs,name="ArcTan",categories="User Functions;Trigonometry (Symbolic)" +*CMD ArcTan --- inverse trigonometric function arc-tangent +*STD +*CALL + ArcTan(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function represents the inverse trigonometric function arctangent. For +instance, the value of $ArcTan(x)$ is a number $y$ such that +$Tan(y)$ equals $x$. + +Note that the number $y$ is not unique. For instance, $Tan(0)$ and +$Tan(2*Pi)$ both equal 0, so what should $ArcTan(0)$ be? In MathPiper, +it is agreed that the value of $ArcTan(x)$ should be in the interval +[-$Pi$/2,$Pi$/2]. + +Usually, MathPiper leaves this function alone unless it is forced to do +a numerical evaluation by the {N} function. MathPiper will try to simplify +as much as possible while keeping the result exact. If the argument is +complex, the expression will be rewritten using the {Ln} function. + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> ArcTan(1) +Result: Pi/4 + +In> ArcTan(1/3) +Result: ArcTan(1/3) +In> Tan(ArcTan(1/3)) +Result: 1/3 + +In> x:=N(ArcTan(0.75)) +Result: 0.643501108793285592213351264945231378078460693359375 +In> N(Tan(x)) +Result: 0.75 + +*SEE Sin, Cos, Tan, N, Pi, Ln, ArcSin, ArcCos +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Cosh.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Cosh.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Cosh.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Cosh.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,26 @@ +%mathpiper,def="Cosh" + +5 # Cosh(- _x) <-- Cosh(x); + +// this is never activated + +//100 # Cosh(I*_x) <-- Cos(x); + +100 # Cosh(_x)*Sech(_x) <-- 1; + +200 # Cosh(0) <-- 1; +200 # Cosh(Infinity) <-- Infinity; +200 # Cosh(-Infinity) <-- Infinity; +200 # Cosh(ArcCosh(_x)) <-- x; +200 # Cosh(ArcSinh(_x)) <-- Sqrt(1+x^2); +200 # Cosh(ArcTanh(_x)) <-- 1/Sqrt(1-x^2); + +200 # Cosh(Undefined) <-- Undefined; + +Cosh(xlist_IsList) <-- MapSingle("Cosh",xlist); + +2 # Cosh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( (Exp(x)+Exp(-x))/2 )); + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Cos.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Cos.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Cos.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Cos.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,97 @@ +%mathpiper,def="Cos" + +1 # CosMap( _n )_(Not(IsRationalOrNumber(n))) <-- ListToFunction({ToAtom("Cos"),n*Pi}); +2 # CosMap( _n )_(n<0) <-- CosMap(-n); +2 # CosMap( _n )_(n>2) <-- CosMap(Modulo(n,2)); +3 # CosMap( _n )_(n>1) <-- CosMap(2-n); +4 # CosMap( _n )_(n>1/2) <-- -CosMap(1-n); + +5 # CosMap( 0 ) <-- 1; +5 # CosMap( 1/6 ) <-- Sqrt(3)/2; +5 # CosMap( 1/4 ) <-- Sqrt(2)/2; +5 # CosMap( 1/3 ) <-- 1/2; +5 # CosMap( 1/2 ) <-- 0; +5 # CosMap( 2/5 ) <-- (Sqrt(5)-1)/4; + +10 # CosMap(_n) <-- ListToFunction({ToAtom("Cos"),n*Pi}); + + + +2 # Cos(x_IsNumber)_InNumericMode() <-- CosNum(x); +4 # Cos(ArcCos(_x)) <-- x; +4 # Cos(ArcSin(_x)) <-- Sqrt(1-x^2); +4 # Cos(ArcTan(_x)) <-- 1/Sqrt(1+x^2); +5 # Cos(- _x)_(Not IsConstant(x)) <-- Cos(x); +6 # (Cos(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- Cos(-x); +// must prevent it from looping + +110 # Cos(Complex(_r,_i)) <-- + (Exp(I*Complex(r,i)) + Exp(- I*Complex(r,i))) / (2) ; + +6 # Cos(x_IsInfinity) <-- Undefined; +6 # Cos(Undefined) <-- Undefined; + +200 # Cos(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- + CosMap(Coef(v,Pi,1)); + +400 # Cos(x_IsRationalOrNumber) <-- + [ + Local(ll); + ll:= FloorN(N(Eval(x/Pi))); + If(IsEven(ll),x:=(x - Pi*ll),x:=(-x + Pi*(ll+1))); + ListToFunction({Cos,x}); + ]; + +400 # Cos(x_IsRationalOrNumber) <-- + [ + Local(ll); + ll:= FloorN(N(Eval(Abs(x)/Pi))); + If(IsEven(ll),x:=(Abs(x) - Pi*ll),x:=(-Abs(x) + Pi*(ll+1))); + ListToFunction({Cos,x}); + ]; + +100 # Cos(_x)*Tan(_x) <-- Sin(x); +100 # Cos(_x)/Sin(_x) <-- (1/Tan(x)); + +Cos(xlist_IsList) <-- MapSingle("Cos",xlist); + + +%/mathpiper + + + +%mathpiper_docs,name="Cos",categories="User Functions;Trigonometry (Symbolic)" +*CMD Cos --- trigonometric cosine function +*STD +*CALL + Cos(x) + +*PARMS + +{x} -- argument to the function, in radians + +*DESC + +This function represents the trigonometric function cosine. MathPiper leaves +expressions alone even if x is a number, trying to keep the result as +exact as possible. The floating point approximations of these functions +can be forced by using the {N} function. + +MathPiper knows some trigonometric identities, so it can simplify to exact +results even if {N} is not used. This is the case, for instance, +when the argument is a multiple of $Pi$/6 or $Pi$/4. + +These functions are threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Cos(1) +Result: Cos(1); +In> N(Cos(1),20) +Result: 0.5403023058681397174; +In> Cos(Pi/4) +Result: Sqrt(1/2); + +*SEE Sin, Tan, ArcSin, ArcCos, ArcTan, N, Pi +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Coth.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Coth.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Coth.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Coth.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,9 @@ +%mathpiper,def="Coth" + +100 # 1/Coth(_x) <-- Tanh(x); + +100 # Coth(_x) <-- 1/Tanh(x); + +100 # Coth(_x)*Sinh(_x) <-- Cosh(x); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Cot.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Cot.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Cot.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Cot.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Cot" + +100 # 1/Cot(_x) <-- Tan(x); + +100 # Cot(_x) <-- 1/Tan(x); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Csch.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Csch.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Csch.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Csch.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Csch" + +100 # 1/Csch(_x) <-- Sinh(x); + +100 # Csch(_x) <-- 1/Sinh(x); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Csc.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Csc.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Csc.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Csc.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Csc" + +100 # 1/Csc(_x) <-- Sin(x); + +100 # Csc(_x) <-- 1/Sin(x); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCoshN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCoshN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCoshN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCoshN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper + + + + + + +%mathpiper_docs,name="ArcCoshN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD ArcCoshN --- inverse hyperbolic cosine (arbitrary-precision math function) +*CALL + ArcCoshN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCosN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCosN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCosN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcCosN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="ArcCosN" + +ArcCosN(x) := +[ + FastArcCos(x); +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="ArcCosN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD ArcCosN --- inverse cosine (arbitrary-precision math function) +*CALL + ArcCosN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinhN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinhN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinhN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinhN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper + + + + + + +%mathpiper_docs,name="ArcSinhN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD ArcSinhN --- inverse hyperbolic sine (arbitrary-precision math function) +*STD +*CALL + ArcSinhN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcSinN.mpw 2010-12-20 19:47:24.000000000 +0000 @@ -0,0 +1,57 @@ +%mathpiper,def="ArcSinN" + + +Defun("ArcSinN",{int1}) +[ + Local(result,eps); + Bind(result,FastArcSin(int1)); + Local(x,q,s,c); + Bind(q,SubtractN(SinN(result),int1)); + Bind(eps,MathIntPower(10,MathNegate(BuiltinPrecisionGet()))); + While(IsGreaterThan(AbsN(q),eps)) + [ + Bind(s,SubtractN(int1,SinN(result))); + Bind(c,CosN(result)); + Bind(q,DivideN(s,c)); + Bind(result,AddN(result,q)); + ]; + result; +]; + +/* +ArcSinN(x) := +[ + FastArcSin(x); +];*/ + +%/mathpiper + + + + +%mathpiper_docs,name="ArcSinN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD ArcSinN --- inverse sine (arbitrary-precision math function) +*CALL + ArcSinN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. + +In> ArcSinN(.5) +Result> 0.5235987756 + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanhN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanhN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanhN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanhN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,35 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper + + + + + +%mathpiper_docs,name="ArcTanhN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD ArcTanhN --- inverse hyperbolic tangent (arbitrary-precision math function) +*CALL + ArcTanhN(x) () + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="ArcTanN" + +ArcTanN(x) := +[ + FastArcTan(x); +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="ArcTanN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD ArcTanN --- inverse tangent (arbitrary-precision math function) +*CALL + ArcTanN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN'Taylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN'Taylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN'Taylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ArcTanN'Taylor.mpw 2010-01-06 03:08:34.000000000 +0000 @@ -0,0 +1,23 @@ +%mathpiper,def="ArcTanN'Taylor" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// ArcTan(x), Taylor series for ArcTan(x)/x, use only with -1/2>1; + + // initialize u and u2 (u2==u^2). + u := 1 << l2; + u2 := u << l2; + + // Now for each lower bit: + While( l2 != 0 ) + [ + l2--; + // Get that bit in v, and v2 == v^2. + v := 1<must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Doubling.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Doubling.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Doubling.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Doubling.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,29 @@ +%mathpiper,def="CosN'Doubling" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Identity transformation, compute 1-Cos(x) from value=1-Cos(x/2^n) + +//Changed CosN'Doubling1 to CosN'Doubling. Note:tk. +CosN'Doubling(value, n) := +[ + Local(shift, result); + shift := n; + result := value; + While (shift>0) // lose 'shift' bits of precision here + [ + result := MultiplyN(MathMul2Exp(result, 1), 2 - result); + shift--; + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Taylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Taylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Taylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/CosN'Taylor.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="CosN'Taylor" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Cos(x), Taylor series +CosN'Taylor(x) := +[ + Local(num'terms, prec, Bx); + prec := QuotientN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) + Bx := -QuotientN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 + num'terms := QuotientN( QuotientN( prec-1, QuotientN( MathBitCount( prec-1)*1588, 2291)+Bx), 2)+1; + // (P*Ln(10)-1)/(Ln(P*Ln(10)-1)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) + SumTaylorNum(MultiplyN(x,x), 1, {{k}, -1/(2*k*(2*k-1))}, num'terms); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/DigitsToBits.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/DigitsToBits.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/DigitsToBits.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/DigitsToBits.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="DigitsToBits" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// BitsToDigits(n,base) and DigitsToBits(n,base). Enough to compute at low precision. +// this is now a call to the kernel functions, so leave as a reference implementation +DigitsToBits(n, base) := FloorN(0.51+n*N(Ln(base)/Ln(2),10)); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Doubling.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Doubling.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Doubling.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Doubling.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,44 @@ +%mathpiper,def="ExpN'Doubling" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Identity transformation, compute Exp(x)-1 from value=Exp(x/2^n)-1 + +ExpN'Doubling1(value, n) := +[ + Local(shift, result); + shift := n; + result := value; + While (shift>0) // lose 'shift' bits of precision here + [ + result := MathMul2Exp(result, 1) + MultiplyN(result, result); + shift--; + ]; + result; +]; + +/// Identity transformation, compute Exp(x) from value=Exp(x/2^n) +/* +ExpN'Doubling(value, n) := +[ + Local(shift, result); + shift := n; + result := value; + While (shift>0) // lose 'shift' bits of precision here + [ + result := MultiplyN(result, result); + shift--; + ]; + result; +]; +*/ + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Taylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Taylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Taylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/ExpN'Taylor.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,25 @@ +%mathpiper,def="ExpN'Taylor" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Compute Exp(x)-1 from the Taylor series for (Exp(x)-1)/x. +//Note:tk:changed name from ExpN'Taylor1 to ExpN'Taylor. +ExpN'Taylor(x) := +[ + Local(num'terms, prec, Bx); + prec := QuotientN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) + Bx := -QuotientN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 + num'terms := QuotientN( prec-1, QuotientN( MathBitCount( prec-1)*1588, 2291)+Bx)+1; + // (P*Ln(10)-1)/(Ln(P*Ln(10)-1)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) + x*SumTaylorNum(x, 1, {{k}, 1/(k+1)}, num'terms); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/GcdN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/GcdN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/GcdN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/GcdN.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="" + +/* +todo:tk:this function was accidently shadowed by a built in function when the names of all MathXXX functions +were changed to XXXN. However, I checked JYacas and GcdN was not used anyplace in the scripts anyway +so the shadowing did not seem to cause any harm. I am commenting this function out until a reason +can be found to uncomment it. +*/ +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + + +/// GcdN(x,y). Compute the GCD of two integers using the binary Euclidean algorithm. +5 # GcdN(x_IsNegativeInteger, y_IsInteger) <-- GcdN(-x, y); +5 # GcdN(y_IsNegativeInteger, x_IsNegativeInteger) <-- GcdN(x, -y); +6 # GcdN(0, _x) <-- 0; +6 # GcdN(_x, 0) <-- 0; + +10 # GcdN(x_IsInteger, y_IsInteger) <-- +[ + Local(z); + While(x!=y) + [ + While(x=1) + [ + nbits++; + value := MathMul2Exp(value, -1); + ]; + ]); + nbits; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Doubling.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Doubling.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Doubling.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Doubling.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,27 @@ +%mathpiper,def="MathLn'Doubling" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Compute Ln(x) from Ln(x^(2^(1/n))) +MathLn'Doubling(value, n) := +[ + Local(shift, result); + shift := n; + result := value; + While (shift>0) // lose 'shift' bits of precision here + [ + result := MultiplyN(result, result); + shift--; + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Taylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Taylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Taylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathLn'Taylor.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="MathLn'Taylor" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Ln(x), Taylor series for Ln(1+y)/y, use only with 1/2=curprec, k:=Quotient(k,order)+2) True; + If(k<5, curprec:=5, curprec:=k); + // Echo("initial precision", curprec); + // now k is the iteration counter + For(k:=0, curprec < prec, k := k+1) [ + // at this iteration we know the result to curprec digits + curprec := Minimum(prec, curprec * order-2); // 2 guard digits + BuiltinPrecisionSet(curprec+2); + // Echo("Iteration ", k, " setting precision to ", BuiltinPrecisionGet()); + // Echo("old result=", CosN(result)); + /*EchoTime()*/[ + delta := CosN(result); + ]; + /*EchoTime()*/[ + deltasq := MultiplyN(delta,delta); + ]; + result := /*EchoTime()*/result + delta*(1 + deltasq*(1/6 + deltasq*(3/40 + deltasq*(5/112 + deltasq*(35/1152 + (deltasq*63)/2816))))); + ]; + // Echo({"Method 3, using Pi/2 and order", order, ":", k, "iterations"}); + ]); + result*2; +]; + +%/mathpiper + + + + + + + +%mathpiper_docs,name="MathPi",categories="User Functions;Numeric",access="experimental" +*CMD MathPi --- The constant Pi. +*CALL + MathPi() + +*DESC + +The constant Pi. Using a simple method, solve Cos(x)=0. +iterate x := x + Cos(x) + 1/6 *Cos(x)^3 + ... to converge to x=Pi/2 + +It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) +The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + +If a better optimized version of this function is available through the kernel, +then the kernel version will automatically shadow this function. +This implementation is not necessarily the best optimized version. + + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathSqrtFloat.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathSqrtFloat.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathSqrtFloat.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/MathSqrtFloat.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,61 @@ +%mathpiper,def="MathSqrtFloat" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +// This function is *only* for float and positive A! +// The answer is only obtained at the current precision. +MathSqrtFloat(_A) <-- +[ + Local(bitshift, a0, x0, x0sq, targetbits, subtargetbits, gotbits, targetprec); + bitshift := ShiftRight(MathBitCount(A)-1,1); + // this is how many bits of precision we need + targetprec := BuiltinPrecisionGet(); + // argument reduction: a0 is between 1 and 4 and has the full target precision + a0 := MathMul2Exp(A, -bitshift*2); // this bit shift would be wrong for integer A + BuiltinPrecisionSet(10); // enough to compute at this point + // cannot get more target bits than 1 + (the bits in A) + // if this is less than the requested precision, the result will be silently less precise, but c'est la vie + targetbits := Minimum(DigitsToBits(targetprec, 10), 1+GetExactBitsN(A)); + // initial approximation + x0 := DivideN(14+22*a0, 31+5*a0); + // this approximation gives at least 7 bits (relative error < 0.005) of Sqrt(a0) for 1 <= a0 <= 4 + gotbits := 7; + // find the conditions for the last 2 iterations to be done in almost optimal precision + subtargetbits := QuotientN(targetbits+8, 9); + If(gotbits >= subtargetbits, subtargetbits := QuotientN(targetbits+2, 3)); + If(gotbits >= subtargetbits, subtargetbits := targetbits*4); +// Echo("debug: subtargetbits=", subtargetbits, "a0=", a0, "targetbits=", targetbits, "bitshift=", bitshift, "targetprec=", targetprec); + // now perform Halley iterations until we get at least subtargetbits, then start with subtargetbits and perform further Halley iterations + While(gotbits < targetbits) + [ + gotbits := 3*gotbits+1; // Halley iteration; get 3n+2 bits, allow 1 bit for roundoff + // check for suboptimal last iterations + If(gotbits >= subtargetbits, + [ // it could be very suboptimal to continue with our value of gotbits, so we curb precision for the last 2 iterations which dominate the calculation time at high precision + gotbits := subtargetbits; + subtargetbits := targetbits*4; // make sure that the above condition never becomes true again + ]); + BuiltinPrecisionSet(BitsToDigits(gotbits, 10)+2); // guard digits + x0 := SetExactBitsN(x0, gotbits+6); // avoid roundoff + x0sq := MultiplyN(x0, x0); +// this gives too much roundoff error x0 := MultiplyN(x0, DivideN(3*a0+x0sq, a0+3*x0sq)); +// rather use this equivalent formula: + x0 := AddN(x0, MultiplyN(x0*2, DivideN(a0-x0sq, a0+3*x0sq))); +// Echo("debug: ", gotbits, x0, GetExactBitsN(x0), BuiltinPrecisionGet()); + ]; + // avoid truncating a precise result in x0 by calling BuiltinPrecisionSet() too soon + x0 := SetExactBitsN(MathMul2Exp(x0, bitshift), gotbits); + BuiltinPrecisionSet(targetprec); +// Echo("debug: answer=", x0); + x0; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinhN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinhN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinhN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinhN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper + + + + + + +%mathpiper_docs,name="SinhN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD SinhN --- hyperbolic sine (arbitrary-precision math function) +*CALL + SinhN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Taylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Taylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Taylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Taylor.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="SinN'Taylor" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Compute Sin(x), Taylor series for Sin(x)/x +SinN'Taylor(x) := +[ + Local(num'terms, prec, Bx); + prec := QuotientN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) + Bx := -QuotientN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 + num'terms := QuotientN( QuotientN( prec+Bx, QuotientN( MathBitCount( prec+Bx)*1588, 2291)+Bx)+1, 2)+1; + // (P*Ln(10)-Ln(x)-2)/(Ln(P*Ln(10)-Ln(x)-2)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) + x*SumTaylorNum(MultiplyN(x,x), 1, {{k}, -1/(2*k*(2*k+1))}, num'terms); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Tripling.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Tripling.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Tripling.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SinN'Tripling.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,28 @@ +%mathpiper,def="SinN'Tripling" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// Identity transformation, compute Sin(x) from value=Sin(x/3^n) + +SinN'Tripling(value, n) := +[ + Local(shift, result); + shift := n; + result := value; + While (shift>0) // lose 'shift' bits of precision here + [ // Sin(x)*(3-4*Sin(x)^2) + result := MultiplyN(result, 3 - MathMul2Exp(MultiplyN(result,result), 2) ); + shift--; + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SqrtN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SqrtN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SqrtN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/SqrtN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,92 @@ +%mathpiper,def="SqrtN" + +/** This file contains routines for numerical evaluation of elementary functions: + * PowerN, ExpN, SinN etc. + * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) + * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. + * + * If a better optimized version of these functions is available through the kernel, + * then the kernel version will automatically shadow these functions. + * These implementations are not necessarily the best optimized versions. + */ + +/// SqrtN(x). +SqrtN(x) := MathSqrt1(x); // to have another function is easier for debugging + +/// Compute square root(x) with nonnegative x. FIXME: No precision tracking yet. +10 # MathSqrt1(0) <-- 0; +/// negative or non-numeric arguments give error message +100 # MathSqrt1(_x) <-- [ Echo("SqrtN: invalid argument: ", x); False;]; + +// this is too slow at the moment +30 # MathSqrt1(x_IsPositiveNumber) <-- x*NewtonNum({{r}, r+r*(1-x*r^2)/2}, FastPower(x,-0.5), 4, 2); + +30 # MathSqrt1(x_IsPositiveNumber) <-- MathSqrtFloat(x); + +// for integers, we need to compute Sqrt(x) to (the number of bits in x) + 1 bits to figure out whether Sqrt(x) is itself an integer. If Sqrt(x) for integer x is exactly equal to an integer, we should return the integer answer rather than the float answer. For this answer, the current precision might be insufficient, therefore we compute with potentially more digits. This is slower but we assume this is what the user wants when calling SqrtN() on an integer. +20 # MathSqrt1(x_IsInteger) _ (IsGreaterThan(x,0)) <-- +[ + Local(result); + If(ModuloN(x,4)<2 And ModuloN(x,3)<2 And ModuloN(x+1,5)<3, + // now the number x has a nonzero chance of being an exact square + [ + // check whether increased precision would be at all necessary +// Echo("checking integer case"); + GlobalPush(BuiltinPrecisionGet()); + If(MathBitCount(x)+3>DigitsToBits(BuiltinPrecisionGet(), 10), + BuiltinPrecisionSet(BitsToDigits(MathBitCount(x), 10)+1)); + // need one more digit to decide whether Sqrt(x) is integer + // otherwise the current precision is sufficient + + // convert x to float and use the float routine + result := MathSqrtFloat(x+0.); + // decide whether result is integer: decrease precision and compare + If(FloatIsInt(SetExactBitsN(result, GetExactBitsN(result)-3)), result:= Floor(result+0.5)); + BuiltinPrecisionSet(GlobalPop()); + ], + // now the number x cannot be an exact square; current precision is sufficient + result := MathSqrtFloat(x+0.) + ); + // need to set the correct precision on the result - will have no effect on integer answers + SetExactBitsN(result, DigitsToBits(BuiltinPrecisionGet(),10)); +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="SqrtN",categories="User Functions;Numeric" +*CMD SqrtN --- square root (x must be >= 0) (arbitrary-precision math function) +*CALL + SqrtN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> BuiltinPrecisionSet(10) +Result: True +In> Sqrt(10) +Result: Sqrt(10) +In> SqrtN(10) +Result: 3.16227766 +In> SqrtN(490000*2^150) +Result: 26445252304070013196697600 +In> SqrtN(490000*2^150+1) +Result: 0.264452523e26 + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/TanhN.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/TanhN.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/TanhN.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/elemfuncs/TanhN.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper + + + + + + +%mathpiper_docs,name="TanhN",categories="User Functions;Numeric;Trigonometry (Numeric)" +*CMD TanhN --- hyperbolic tangent (arbitrary-precision math function) +*CALL + TanhN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Exp.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Exp.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Exp.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Exp.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="Exp" + +2 # Exp(x_IsNumber)_InNumericMode() <-- ExpNum(x); +4 # Exp(Ln(_x)) <-- x; +110 # Exp(Complex(_r,_i)) <-- Exp(r)*(Cos(i) + I*Sin(i)); +200 # Exp(0) <-- 1; +200 # Exp(-Infinity) <-- 0; +200 # Exp(Infinity) <-- Infinity; +200 # Exp(Undefined) <-- Undefined; + +Exp(xlist_IsList) <-- MapSingle("Exp",xlist); + +%/mathpiper + + + +%mathpiper_docs,name="Exp",categories="User Functions;Calculus Related (Symbolic)" +*CMD Exp --- exponential function +*STD +*CALL + Exp(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function calculates $e$ raised to the power $x$, where $e$ is the +mathematic constant 2.71828... One can use {Exp(1)} +to represent $e$. + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Exp(0) +Result: 1; +In> Exp(I*Pi) +Result: -1; +In> N(Exp(1)) +Result: 2.7182818284; + +*SEE Ln, Sin, Cos, Tan, N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Ln.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Ln.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Ln.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Ln.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="Ln" + +2 # Ln(0) <-- -Infinity; +2 # Ln(1) <-- 0; +2 # Ln(Infinity) <-- Infinity; +2 # Ln(Undefined) <-- Undefined; + +/* 2 # Ln(-Infinity) <-- 0; */ +2 # Ln(x_IsNegativeNumber)_InNumericMode() <-- Complex(Ln(-x), Pi); +3 # Ln(x_IsNumber)_(InNumericMode() And x>=1) <-- Internal'LnNum(x); +4 # Ln(Exp(_x)) <-- x; + +3 # Ln(Complex(_r,_i)) <-- Complex(Ln(Abs(Complex(r,i))), Arg(Complex(r,i))); +4 # Ln(x_IsNegativeNumber) <-- Complex(Ln(-x), Pi); +5 # Ln(x_IsNumber)_(InNumericMode() And x<1) <-- - Internal'LnNum(DivideN(1, x)); + +Ln(xlist_IsList) <-- MapSingle("Ln",xlist); + +%/mathpiper + + + +%mathpiper_docs,name="Ln",categories="User Functions;Calculus Related (Symbolic)" +*CMD Ln --- natural logarithm +*STD +*CALL + Ln(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function calculates the natural logarithm of "x". This is the +inverse function of the exponential function, {Exp}, i.e. $Ln(x) = y$ implies that $Exp(y) = x$. For complex +arguments, the imaginary part of the logarithm is in the interval +(-$Pi$,$Pi$]. This is compatible with the branch cut of {Arg}. + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Ln(1) +Result: 0; +In> Ln(Exp(x)) +Result: x; +In> Differentiate(x) Ln(x) +Result: 1/x; + +*SEE Exp, Arg +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcSinNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcSinNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcSinNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcSinNum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="ArcSinNum" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +ArcSinNum(x) := +[ + // need to be careful when |x| close to 1 + If( + 239*Abs(x) >= 169, // 169/239 is a good enough approximation of 1/Sqrt(2) + // use trigonometric identity to avoid |x| close to 1 + Sign(x)*(Internal'Pi()/2-ArcSinN(Sqrt(1-x^2))), + ArcSinN(x) + ); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcTanNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcTanNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcTanNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/ArcTanNum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,91 @@ +%mathpiper,def="ArcTanNum" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +ArcTanNum(x) := +[ + // using trigonometric identities is faster for now + If( + Abs(x)>1, + Sign(x)*(Internal'Pi()/2-ArcSin(1/Sqrt(x^2+1))), + ArcSin(x/Sqrt(x^2+1)) + ); +]; + + + + + +/* old methods -- slower for now +/// numerical evaluation of ArcTan using continued fractions: top level +2 # ArcTan(x_IsNumber)_InNumericMode() <-- +Sign(x) * +// now we need to compute ArcTan of a nonnegative number Abs(x) +[ + Local(nterms, y); + y := Abs(x); + // use identities to improve convergence -- see essays book + If( + y>1, + y:=1/y // now y <= 1 + // we shall know that the first identity was used because Abs(x) > 1 still + ); + // use the second identity + y := y/(1+Sqrt(1+y^2)); // now y <= Sqrt(2)-1 + // find the required number of terms in the continued fraction + nterms := 1/y; // this needs to be calculated at full precision + // see essays book on the choice of the number of terms (added 2 "guard terms"). + // we need Hold() because otherwise, if InNumericMode() returns True, N(..., 5) will not avoid the full precision calculation of Ln(). + // the value of x should not be greater than 1 here! + nterms := 2 + Ceil( N(Hold(Ln(10)/(Ln(4)+2*Ln(nterms))), 5) * BuiltinPrecisionGet() ); + If( // call the actual routine + Abs(x)>1, + Pi/2-2*MyArcTan(y, nterms), // this is for |x|>1 + 2*MyArcTan(y, nterms) + // MyArcTan(x, nterms) + ); +]; +*/ + + + +/// numerical evaluation of ArcTan using continued fractions: low level + +// evaluation using recursion -- slightly faster but lose some digits to roundoff errors and needs large recursion depth +/* +10 # ContArcTan(_x,_n,_n) <-- (2*n-1); +20 # ContArcTan(_x,_n,_m) <-- +[ + (2*n-1) + (n*x)^2/ContArcTan(x,n+1,m); +]; + +MyArcTan(x,n) := +[ + x/ContArcTan(x,1,n); +]; +*/ +/* +/// evaluate n terms of the continued fraction for ArcTan(x) without recursion. +/// better control of roundoff errors +MyArcTan(x, n) := +[ + Local(i, p, q, t); + // initial numerator and denominator + p:=1; + q:=1; + // start evaluating from the last term upwards + For(i:=n, i>=1, i--) + [ + //{p,q} := {p + q*(i*x)^2/(4*i^2-1), p}; + // t := p*(2*i-1) + q*(i*x)^2; then have to start with p:=2*n+1 + t := p + q*(i*x)^2/(4*i^2-1); + q := p; + p := t; + ]; + // answer is x/(p/q) + x*q/p; +]; +*/ + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/BrentLn.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/BrentLn.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/BrentLn.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/BrentLn.mpw 2011-02-03 06:47:37.000000000 +0000 @@ -0,0 +1,58 @@ +%mathpiper,def="BrentLn" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +/* The BrentLn() algorithm is currently slower in internal math but should be asymptotically faster. */ + +CachedConstant(Ln2, Internal'LnNum(2)); // this is only useful for BrentLn + +// compute Ln(x_IsInteger) using the AGM sequence. See: Brent paper rpb028 (1975). +// this is currently faster than LogN(n) for precision > 40 digits +10 # BrentLn(x_IsInteger)_(BuiltinPrecisionGet()>40) <-- +[ + Local(y, n, k, eps); + n := BuiltinPrecisionGet(); // decimal digits + // initial power of x + k := 1 + Quotient(IntLog(4*10^n, x), 2); // now x^(2*k)>4*10^n + BuiltinPrecisionSet(n+5); // guard digits + eps := DivideN(1, 10^n); // precision + y := PowerN(x, k); // not yet divided by 4 + // this is Brent's AGM times y. This way we work around the MathPiper limitation of fixed precision, at cost of slightly slower initial iterations + y := DivideN(Internal'Pi()*y, (2*k)*ArithmeticGeometricMean(4, y, eps)); + BuiltinPrecisionSet(n); + RoundTo(y, n); // do not return a more precise number than we really have +]; + +15 # BrentLn(x_IsInteger) <-- LogN(x); + +/// calculation of Ln(x) using Brent's AGM sequence - use precomputed Pi and Ln2. +20 # BrentLn(_x)_(x<1) <-- -BrentLn(1/x); + +// this is currently faster than LogN() for precision > 85 digits and numbers >2 +30 # BrentLn(_x)_(BuiltinPrecisionGet()>85) <-- +[ + Local(y, n, n1, k, eps); + N([ + n := BuiltinPrecisionGet(); // decimal digits + // effective precision is n+Ln(n)/Ln(10) + n1 := n + IntLog(n,10); // Ln(2) < 7050/10171 + // initial power of 2 + k := 2 + Quotient(n1*28738, 2*8651) // Ln(10)/Ln(2) < 28738/8651; now 2^(2*k)>4*10^n1 + // find how many binary digits we already have in x, and multiply by a sufficiently large power of 2 so that y=x*2^k is larger than 2*10^(n1/2) + - IntLog(Floor(x), 2); + // now we need k*Ln(2)/Ln(10) additional digits to compensate for cancellation at the final subtraction + BuiltinPrecisionSet(n1+2+Quotient(k*3361, 11165)); // Ln(2)/Ln(10) < 3361/11165 + eps := DivideN(1, 10^(n1+1)); // precision + y := x*2^(k-2); // divided already by 4 + // initial values for AGM + // this is Brent's AGM times y. This way we work around the MathPiper limitation of fixed precision, at cost of slightly slower initial iterations + y:=Internal'Pi()*y/(2*ArithmeticGeometricMean(1,y,eps)) - k*Ln2(); + BuiltinPrecisionSet(n); + ]); + y; // do not return a more precise number than we really have +]; + +40 # BrentLn(x_IsNumber) <-- LogN(x); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/CosNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/CosNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/CosNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/CosNum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="CosNum" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +CosNum(x) := +[ + If(x<0 Or 113*x>710, x:=TruncRadian(x)); + CosN(x); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/ExpNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/ExpNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/ExpNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/ExpNum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,25 @@ +%mathpiper,def="ExpNum" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +// large positive x +10 # ExpNum(x_IsNumber) _ (x > MathExpThreshold()) <-- [ + Local(i, y); + i:=0; + For(i:=0, x > MathExpThreshold(), i++) + x := DivideN(x, 2.); + For(y:= ExpN(x), i>0, i--) + y := MultiplyN(y, y); + y; + +]; +// large negative x +20 # ExpNum(x_IsNumber) _ (2*x < -MathExpThreshold()) <-- DivideN(1, ExpNum(-x)); +// other values of x +30 # ExpNum(x_IsNumber) <-- ExpN(x); + + +//CachedConstant(Exp1, ExpN(1)); // Exp1 is useless so far + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/expthreshold.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/expthreshold.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/expthreshold.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/expthreshold.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,23 @@ +%mathpiper,def="MathExpThreshold;SetMathExpThreshold" + +/* def file definitions +MathExpThreshold +SetMathExpThreshold +*/ + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +////////////////////////////////////////////////// +/// Exponent +////////////////////////////////////////////////// + +LocalSymbols(mathExpThreshold) [ + // improve convergence of Exp(x) for large x + mathExpThreshold := If(Not IsBound(mathExpThreshold), 500); + + MathExpThreshold() := mathExpThreshold; + SetMathExpThreshold(threshold) := [mathExpThreshold:= threshold; ]; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/Internal'LnNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/Internal'LnNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/Internal'LnNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/Internal'LnNum.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,16 @@ +%mathpiper,def="Internal'LnNum" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +// natural logarithm: this should be called only for real x>1 +//Internal'LnNum(x) := LogN(x); +// right now the fastest algorithm is Halley's method for Exp(x)=a +// when internal math is fixed, we may want to use Brent's method (below) +// this method is using a cubically convergent Newton iteration for Exp(x/2)-a*Exp(-x/2)=0: +// x' := x - 2 * (Exp(x)-a) / (Exp(x)+a) = x-2+4*a/(Exp(x)+a) +Internal'LnNum(x_IsNumber)_(x>=1) <-- NewtonLn(x); + +Internal'LnNum(x_IsNumber)_(0 0 (arbitrary-precision math function) +*CALL + LogN(x) + +*DESC + +This command performs the calculation of an elementary mathematical +function. The arguments must be numbers. The reason for the +postfix {N} is that the library needs to define equivalent non-numerical +functions for symbolic computations, such as {Exp}, {Sin}, etc. + +Note that all xxxN functions accept integers as well as floating-point numbers. +The resulting values may be integers or floats. If the mathematical result is an +exact integer, then the integer is returned. For example, {Sqrt(25)} returns +the integer {5}, and {Power(2,3)} returns the integer {8}. In such cases, the +integer result is returned even if the calculation requires more digits than set by +{BuiltinPrecisionSet}. However, when the result is mathematically not an integer, +the functions return a floating-point result which is correct only to the current precision. + +*E.G. +In> +Result: + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/NewtonLn.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/NewtonLn.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/NewtonLn.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/NewtonLn.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,16 @@ +%mathpiper,def="NewtonLn" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +NewtonLn(x) := + LocalSymbols(y) +[ +// we need ExpN instead of Exp to avoid N() which is used in the definition of Exp. +// and we need ExpNum() instead of ExpN so that it is faster for large arguments and to avoid the error generated when core functions like ExpN are called on symbolic arguments. + NewtonNum({{y}, 4*x/(ExpNum(y)+x)-2+y}, + // initial guess is obtained as Ln(x^2)/Ln(2) * (Ln(2)/2) + DivideN(794*IntLog(Floor(x*x), 2), 2291), 10, 3); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/SinNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/SinNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/SinNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/SinNum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="SinNum" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +SinNum(x) := +[ + If(x<0 Or 113*x>710, x:=TruncRadian(x)); // 710/113 is close to 2*Pi + SinN(x); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/TanNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/TanNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/TanNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/TanNum.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,8 @@ +%mathpiper,def="TanNum" +TanNum(x) := +[ + If(x<0 Or 113*x>710, x:=TruncRadian(x)); + TanN(x); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/TruncRadian.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/TruncRadian.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/numerical/TruncRadian.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/numerical/TruncRadian.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="TruncRadian" + +/// low-level numerical calculations of elementary functions. +/// These are only called if InNumericMode() returns True + +/* TruncRadian truncates the radian r so it is between 0 and 2*Pi. + * It calculates r mod 2*Pi using the required precision. + */ +TruncRadian(_r) <-- +[ + Local(twopi); + // increase precision by the number of digits of r before decimal point; enough to evaluate Abs(r) with 1 digit of precision + N([ + r:=Eval(r); + twopi:=2*Internal'Pi(); + r:=r-FloorN(r/twopi)*twopi; + ], BuiltinPrecisionGet() + IntLog(Ceil(Abs(N(Eval(r), 1))), 10)); + r; +]; +HoldArgument("TruncRadian",r); + +%/mathpiper + + + +%mathpiper_docs,name="TruncRadian",categories="Programmer Functions;Numerical (Arbitrary Precision)" +*CMD TruncRadian --- remainder modulo $2*Pi$ +*STD +*CALL + TruncRadian(r) + +*PARMS + +{r} -- a number + +*DESC + +{TruncRadian} calculates $Modulo(r,2*Pi)$, returning a value between $0$ +and $2*Pi$. This function is used in the trigonometry functions, just +before doing a numerical calculation using a Taylor series. It greatly +speeds up the calculation if the value passed is a large number. + +The library uses the formula +$$TruncRadian(r) = r - Floor( r/(2*Pi) )*2*Pi$$, +where $r$ and $2*Pi$ are calculated with twice the precision used in the +environment to make sure there is no rounding error in the significant +digits. + +*E.G. + +In> 2*Internal'Pi() +Result: 6.283185307; +In> TruncRadian(6.28) +Result: 6.28; +In> TruncRadian(6.29) +Result: 0.0068146929; + +*SEE Sin, Cos, Tan + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/ArithmeticGeometricMean.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/ArithmeticGeometricMean.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/ArithmeticGeometricMean.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/ArithmeticGeometricMean.mpw 2011-02-03 07:34:31.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="ArithmeticGeometricMean" + +/// coded by Serge Winitzki. See essays documentation for algorithms. + +////////////////////////////////////////////////// +/// Numerical method: AGM sequence +////////////////////////////////////////////////// + +/// compute the AGM sequence up to a given precision +ArithmeticGeometricMean(a, b, eps) := +[ + Check(IsPositiveReal(a) And IsPositiveReal(b), "Argument", "The first two arguments must be positive real numbers."); + + Check(IsPositiveInteger(eps), "Argument", "The precision argument must be a positive integer."); + + a := N(a, eps); + + b := N(b, eps); + + Local(a1, b1); + + If(InVerboseMode(), Echo("ArithmeticGeometricMean: Info: at prec. ", BuiltinPrecisionGet())); + + // AGM main loop + While(Abs(a-b)>=eps) + [ + a1 := DivideN(a+b, 2); + b1 := SqrtN(MultiplyN(a, b)); // avoid Sqrt() which uses N() inside it + a := a1; + b := b1; + ]; + + DivideN(a+b, 2); +]; +//UnFence(ArithmeticGeometricMean, 3); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + +%mathpiper_docs,name="ArithmeticGeometricMean",categories="User Functions;Special Functions" +*CMD ArithmeticGeometricMean --- calculate the arithmetic geometric mean of two positive real numbers +*CALL + ArithmeticGeometricMean(a,b,precision) + +*PARMS +{a} -- a positive real number +{b} -- a positive real number +{precision} -- a positive integer which specifies the precision to use during the calculation + +*DESC +Computes the arithmetic geometric mean of two positive real numbers. + +*E.G. +In> ArithmeticGeometricMean(6,24,10) +Result: 13.5 + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/binsplit.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/binsplit.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/binsplit.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/binsplit.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,111 @@ +%mathpiper,def="BinSplitNum;BinSplitData;BinSplitFinal" + +/* +def file definitions +BinSplitNum +BinSplitData +BinSplitFinal +*/ + +/// coded by Serge Winitzki. See essays documentation for algorithms. + +////////////////////////////////////////////////// +/// Numerical method: binary splitting technique for simple series +////////////////////////////////////////////////// + +/// Binary splitting for series of the form +/// S(m,n) = Sum(k,m,n, a(k)/b(k)*(p(0)*...*p(k))/(q(0)*...*q(k))) + + +/// High-level interface routine +BinSplitNum(m,n,a,b,p,q) := BinSplitFinal(BinSplitData(m,n,a,b,p,q)); + +/// Low-level routine: compute the floating-point answer from P, Q, B, T data +BinSplitFinal({_P,_Q,_B,_T}) <-- DivideN(T, MultiplyN(B, Q)); + +/// Low-level routine: combine two binary-split intermediate results +BinSplitCombine({_P1, _Q1, _B1, _T1}, {_P2, _Q2, _B2, _T2}) <-- {P1*P2, Q1*Q2, B1*B2, B1*P1*T2+B2*Q2*T1}; + +/// Low-level routine: compute the list of four integers P, Q, B, T. (T=BQS) +/// Input: m, n and four functions a,b,p,q of one integer argument. + +// base of recursion +10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m>n) <-- {1,1,1,0}; + +10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m=n) <-- {p@m, q@m, b@m, (a@m)*(p@m)}; + +10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m+1=n) <-- {(p@m)*(p@n), (q@m)*(q@n), (b@m)*(b@n), (p@m)*((a@m)*(b@n)*(q@n)+(a@n)*(b@m)*(p@n))}; + +// could implement some more cases of recursion base, to improve speed + +// main recursion step +20 # BinSplitData(_m, _n, _a, _b, _p, _q) <-- +[ + BinSplitCombine(BinSplitData(m,(m+n)>>1, a,b,p,q), BinSplitData(1+((m+n)>>1),n, a,b,p,q)); +]; + + +%/mathpiper + + + +%mathpiper_docs,name="BinSplitNum;BinSplitData;BinSplitFinal",categories="User Functions;Series" +*CMD BinSplitNum --- computations of series by the binary splitting method +*CMD BinSplitData --- computations of series by the binary splitting method +*CMD BinSplitFinal --- computations of series by the binary splitting method +*STD +*CALL + BinSplitNum(n1, n2, a, b, c, d) + BinSplitData(n1,n2, a, b, c, d) + BinSplitFinal({P,Q,B,T}) + +*PARMS + +{n1}, {n2} -- integers, initial and final indices for summation + +{a}, {b}, {c}, {d} -- functions of one argument, coefficients of the series + +{P}, {Q}, {B}, {T} -- numbers, intermediate data as returned by {BinSplitData} + +*DESC + +The binary splitting method is an efficient way to evaluate many series when fast multiplication is available and when the series contains only rational numbers. +The function {BinSplitNum} evaluates a series of the form +$$ S(n[1],n[2])=Sum(k,n[1],n[2], a(k)/b(k)*(p(0)/q(0)) * ... * p(k)/q(k)) $$. +Most series for elementary and special functions at rational points are of this form when the functions $a(k)$, $b(k)$, $p(k)$, $q(k)$ are chosen appropriately. + +The last four arguments of {BinSplitNum} are functions of one argument that give the coefficients $a(k)$, $b(k)$, $p(k)$, $q(k)$. +In most cases these will be short integers that are simple to determine. +The binary splitting method will work also for non-integer coefficients, but the calculation will take much longer in that case. + +Note: the binary splitting method outperforms the straightforward summation only if the multiplication of integers is faster than quadratic in the number of digits. +See <*the algorithm documentation|mathpiperdoc://Algo/3/14/*> for more information. + +The two other functions are low-level functions that allow a finer control over the calculation. +The use of the low-level routines allows checkpointing or parallelization of a binary splitting calculation. + +The binary splitting method recursively reduces the calculation of $S(n[1],n[2])$ to the same calculation for the two halves of the interval [$n[1]$, $n[2]$]. +The intermediate results of a binary splitting calculation are returned by {BinSplitData} and consist of four integers $P$, $Q$, $B$, $T$. +These four integers are converted into the final answer $S$ by the routine {BinSplitFinal} using the relation +$$ S = T / (B*Q) $$. + +*E.G. + +Compute the series for $e=Exp(1)$ using binary splitting. +(We start from $n=1$ to simplify the coefficient functions.) +In> BuiltinPrecisionSet(21) +Result: True; +In> BinSplitNum(1,21, {{k},1}, + {{k},1},{{k},1},{{k},k}) +Result: 1.718281828459045235359; +In> N(Exp(1)-1) +Result: 1.71828182845904523536; +In> BinSplitData(1,21, {{k},1}, + {{k},1},{{k},1},{{k},k}) +Result: {1,51090942171709440000,1, + 87788637532500240022}; +In> BinSplitFinal(%) +Result: 1.718281828459045235359; + +*SEE SumTaylorNum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/IntPowerNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/IntPowerNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/IntPowerNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/IntPowerNum.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,def="IntPowerNum" + +/// coded by Serge Winitzki. See essays documentation for algorithms. + +////////////////////////////////////////////////// +/// Numerical method: integer powers by binary reduction +////////////////////////////////////////////////// + +/// generalized integer Power function using the classic binary method. +5 # IntPowerNum(_x, 0, _func, _unity) <-- unity; +10 # IntPowerNum(_x, n_IsInteger, _func, _unity) <-- +[ + // use binary method + Local(result); + // unity might be of non-scalar type, avoid assignment + While(n > 0) + [ + If( + (n&1) = 1, + If( + IsBound(result), // if result is already assigned + result := Apply(func, {result,x}), + result := x, // avoid multiplication + ) + ); + x := Apply(func, {x,x}); + n := n>>1; + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="IntPowerNum",categories="User Functions;Numbers (Operations)" +*CMD IntPowerNum --- optimized computation of integer powers +*STD +*CALL + IntPowerNum(x, n, mult, unity) + +*PARMS + +{x} -- a number or an expression + +{n} -- a non-negative integer (power to raise {x} to) + +{mult} -- a function that performs one multiplication + +{unity} -- value of the unity with respect to that multiplication + +*DESC + +{IntPowerNum} computes the power $x^n$ using the fast binary algorithm. +It can compute integer powers with $n>=0$ in any ring where multiplication with unity is defined. +The multiplication function and the unity element must be specified. +The number of multiplications is no more than $2*Ln(n)/Ln(2)$. + +Mathematically, this function is a generalization of {MathPower} to rings other than that of real numbers. + +In the current implementation, the {unity} argument is only used when the given power {n} is zero. + +*E.G. + +For efficient numerical calculations, the {MathMultiply} function can be passed: +In> IntPowerNum(3, 3, MathMultiply,1) +Result: 27; + +Otherwise, the usual {*} operator suffices: +In> IntPowerNum(3+4*I, 3, *,1) +Result: Complex(-117,44); +In> IntPowerNum(HilbertMatrix(2), 4, *, Identity(2)) +Result: {{289/144,29/27},{29/27,745/1296}}; + +Compute $Modulo(3^100,7)$: +In> IntPowerNum(3,100,{{x,y},Modulo(x*y,7)},1) +Result: 4; + +*SEE MultiplyNum, PowerN, MatrixPower +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/MultiplyNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/MultiplyNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/MultiplyNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/MultiplyNum.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,81 @@ +%mathpiper,def="MultiplyNum" + +/// coded by Serge Winitzki. See essays documentation for algorithms. + +////////////////////////////////////////////////// +/// Numerical method: multiply floats by rationals +////////////////////////////////////////////////// + +/// aux function: optimized numerical multiplication. Use MultiplyN() and DivideN(). +/// optimization consists of multiplying or dividing by integers if one of the arguments is a rational number. This is presumably always better than floating-point calculations, except if we use Rationalize() on everything. +/// note that currently this is not a big optimization b/c of slow arithmetic but it already helps for rational numbers under InNumericMode() returns True and it will help even more when faster math is done + +Function() MultiplyNum(x, y, ...); +Function() MultiplyNum(x); + +10 # MultiplyNum(x_IsList)_(Length(x)>1) <-- MultiplyNum(First(x), Rest(x)); + +10 # MultiplyNum(x_IsRational, y_IsRationalOrNumber) <-- +[ + If( + Type(y) = "/", // IsRational(y), changed by Nobbi before redefinition of IsRational + DivideN(Numerator(x)*Numerator(y), Denominator(x)*Denominator(y)), + // y is floating-point + // avoid multiplication or division by 1 + If( + Numerator(x)=1, + DivideN(y, Denominator(x)), + If( + Denominator(x)=1, + MultiplyN(y, Numerator(x)), + DivideN(MultiplyN(y, Numerator(x)), Denominator(x)) + ) + ) + ); +]; + +20 # MultiplyNum(x_IsNumber, y_IsRational) <-- MultiplyNum(y, x); + +25 # MultiplyNum(x_IsNumber, y_IsNumber) <-- MultiplyN(x,y); + +30 # MultiplyNum(Complex(r_IsNumber, i_IsNumber), y_IsRationalOrNumber) <-- Complex(MultiplyNum(r, y), MultiplyNum(i, y)); + +35 # MultiplyNum(y_IsNumber, Complex(r_IsNumber, i_IsRationalOrNumber)) <-- MultiplyNum(Complex(r, i), y); + +40 # MultiplyNum(Complex(r1_IsNumber, i1_IsNumber), Complex(r2_IsNumber, i2_IsNumber)) <-- Complex(MultiplyNum(r1,r2)-MultiplyNum(i1,i2), MultiplyNum(r1,i2)+MultiplyNum(i1,r2)); + +/// more than 2 operands +30 # MultiplyNum(x_IsRationalOrNumber, y_IsNumericList)_(Length(y)>1) <-- MultiplyNum(MultiplyNum(x, First(y)), Rest(y)); +40 # MultiplyNum(x_IsRationalOrNumber, y_IsNumericList)_(Length(y)=1) <-- MultiplyNum(x, First(y)); + +%/mathpiper + + + +%mathpiper_docs,name="MultiplyNum",categories="User Functions;Numbers (Operations)" +*CMD MultiplyNum --- optimized numerical multiplication +*STD +*CALL + MultiplyNum(x,y) + MultiplyNum(x,y,z,...) + MultiplyNum({x,y,z,...}) + +*PARMS + +{x}, {y}, {z} -- integer, rational or floating-point numbers to multiply + +*DESC +The function {MultiplyNum} is used to speed up multiplication of floating-point numbers with rational numbers. +Suppose we need to compute $(p/q)*x$ where $p$, $q$ are integers and $x$ is a floating-point number. +At high precision, it is faster to multiply $x$ by an integer $p$ and divide by an integer $q$ than to +compute $p/q$ to high precision and then multiply by $x$. The function {MultiplyNum} performs this optimization. + +The function accepts any number of arguments (not less than two) or a list of numbers. The result is always +a floating-point number (even if {InNumericMode()} returns False). + +*E.G. +In> MultiplyNum(1.2, 1/2) +Result: 0.6 + +*SEE MultiplyN +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/NewtonNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/NewtonNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/NewtonNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/NewtonNum.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,152 @@ +%mathpiper,def="NewtonNum" + +/// coded by Serge Winitzki. See essays documentation for algorithms. + +////////////////////////////////////////////////// +/// Numerical method: Newton-like superconvergent iteration +////////////////////////////////////////////////// + +// Newton's method, generalized, with precision control and diagnostics + +/// auxiliary utility: compute the number of common decimal digits of x and y (using relative precision) +Common'digits(x,y) := +[ + Local(diff); + diff := Abs(x-y); + If( + diff=0, + Infinity, + // use approximation Ln(2)/Ln(10) > 351/1166 + Quotient(IntLog(FloorN(DivideN(Maximum(Abs(x), Abs(y)), diff)), 2)*351, 1166) + ); // this many decimal digits in common +]; + +///interface +NewtonNum(_func, _x0) <-- NewtonNum(func, x0, 5); // default prec0 +NewtonNum(_func, _x0, _prec0) <-- NewtonNum(func, x0, prec0, 2); + +// func is the function to iterate, i.e. x' = func(x). +// prec0 is the initial precision necessary to get convergence started. +// order is the order of convergence of the given sequence (e.g. 2 or 3). +// x0 must be close enough so that x1 has a few common digits with x0 after at most 5 iterations. +NewtonNum(_func, _x'init, _prec0, _order) <-- +[ + Check(prec0>=4, "Argument", "NewtonNum: Error: initial precision must be at least 4"); + Check(IsInteger(order) And order>1, "Argument", "NewtonNum: Error: convergence order must be an integer and at least 2"); + Local(x0, x1, prec, exact'digits, int'part, initial'tries); + N([ + x0 := x'init; + prec := BuiltinPrecisionGet(); + int'part := IntLog(Ceil(Abs(x0)), 10); // how many extra digits for numbers like 100.2223 + // int'part must be set to 0 if we have true floating-point semantics of BuiltinPrecisionSet() + BuiltinPrecisionSet(2+prec0-int'part); // 2 guard digits + x1 := (func @ x0); // let's run one more iteration by hand + // first, we get prec0 exact digits + exact'digits := 0; + initial'tries := 5; // stop the loop the the initial value is not good + While(exact'digits*order < prec0 And initial'tries>0) + [ + initial'tries--; + x0 := x1; + x1 := (func @ x0); + exact'digits := Common'digits(x0, x1); + // If(InVerboseMode(), Echo("NewtonNum: Info: got", exact'digits, "exact digits at prec. ", BuiltinPrecisionGet())); + ]; + // need to check that the initial precision is achieved + If( + Assert("value", {"NewtonNum: Error: need a more accurate initial value than", x'init}) + exact'digits >= 1, + [ + exact'digits :=Minimum(exact'digits, prec0+2); + // run until get prec/order exact digits + int'part := IntLog(Ceil(Abs(x1)), 10); // how many extra digits for numbers like 100.2223 + While(exact'digits*order <= prec) + [ + exact'digits := exact'digits*order; + BuiltinPrecisionSet(2+Minimum(exact'digits, Quotient(prec,order)+1)-int'part); + x0 := x1; + x1 := (func @ x0); + // If(InVerboseMode(), Echo("NewtonNum: Info: got", Common'digits(x0, x1), "exact digits at prec. ", BuiltinPrecisionGet())); + ]; + // last iteration by hand + BuiltinPrecisionSet(2+prec); + x1 := RoundTo( (func @ x1), prec); + ], + // did not get a good initial value, so return what we were given + x1 := x'init + ); + BuiltinPrecisionSet(prec); + ]); + x1; +]; + + +/* +example: logarithm function using cubically convergent Newton iteration for +Exp(x/2)-a*Exp(-x/2)=0: + +x' := x - 2 * (Exp(x)-a) / (Exp(x)+a) + +LN(x_IsNumber)_(x>1 ) <-- + LocalSymbols(y) +[ +// initial guess is obtained as Ln(x^2)/Ln(2) * (Ln(2)/2) + NewtonNum({{y},4*x/(Exp(y)+x)-2+y}, N(794/2291*IntLog(Floor(x*x),2),5), 10, 3); +]; +*/ + +%/mathpiper + + + +%mathpiper_docs,name="NewtonNum",categories="User Functions;Solvers (Numeric) +*CMD NewtonNum --- low-level optimized Newton's iterations +*STD +*CALL + NewtonNum(func, x0, prec0, order) + NewtonNum(func, x0, prec0) + NewtonNum(func, x0) + +*PARMS + +{func} -- a function specifying the iteration sequence + +{x0} -- initial value (must be close enough to the root) + +{prec0} -- initial precision (at least 4, default 5) + +{order} -- convergence order (typically 2 or 3, default 2) + +*DESC + +This function is an optimized interface for computing Newton's +iteration sequences for numerical solution of equations in arbitrary precision. + +{NewtonNum} will iterate the given function starting from the initial +value, until the sequence converges within current precision. +Initially, up to 5 iterations at the initial precision {prec0} is +performed (the low precision is set for speed). The initial value {x0} +must be close enough to the root so that the initial iterations +converge. If the sequence does not produce even a single correct digit +of the root after these initial iterations, an error message is +printed. The default value of the initial precision is 5. + +The {order} parameter should give the convergence order of the scheme. +Normally, Newton iteration converges quadratically (so the default +value is {order}=2) but some schemes converge faster and you can speed +up this function by specifying the correct order. (Caution: if you give +{order}=3 but the sequence is actually quadratic, the result will be +silently incorrect. It is safe to use {order}=2.) + +*REM +The verbose option {V} can be used to monitor the convergence. The +achieved exact digits should roughly form a geometric progression. + +*E.G. +In> BuiltinPrecisionSet(20) +Result: True; +In> NewtonNum({{x}, x+Sin(x)}, 3, 5, 3) +Result: 3.14159265358979323846; + +*SEE Newton +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/SumTaylorNum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/SumTaylorNum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/nummethods/SumTaylorNum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/nummethods/SumTaylorNum.mpw 2011-02-02 08:25:04.000000000 +0000 @@ -0,0 +1,231 @@ +%mathpiper,def="SumTaylorNum" + +/// coded by Serge Winitzki. See essays documentation for algorithms. + +////////////////////////////////////////////////// +/// Numerical method: Taylor series, rectangular summation +////////////////////////////////////////////////// + +/// Fast summation of Taylor series using a rectangular scheme. +/// SumTaylorNum(x, nth'term'func, n'terms) = Sum(k, 0, n'terms, nth'term'func(k)*x^k) +/// Note that sufficient precision must be preset to avoid roundoff errors (these methods do not modify precision). +/// The only reason to try making these functions HoldArgument is to make sure that the closures nth'term'func and next'term'factor are passed intact. But it's probably not desired in most cases because a closure might contain parameters that should be evaluated. + +/// The short form is used when only the nth term is known but no simple relation between a term and the next term. +/// The long form is used when there is a simple relation between consecutive terms. In that case, the n'th term function is not needed, only the 0th term value. + +/// SumTaylorNum0 is summing the terms with direct methods (Horner's scheme or simple summation). SumTaylorNum1 is for the rectangular method. + +/// nth'term'func and next'term'func must be functions applicable to one argument. + +/// interface +SumTaylorNum0(_x, _nth'term'func, _n'terms) <-- SumTaylorNum0(x, nth'term'func, {}, n'terms); + +SumTaylorNum1(_x, _nth'term'func, _n'terms) <-- SumTaylorNum1(x, nth'term'func, {}, n'terms); + +/// interface +SumTaylorNum(_x, _nth'term'func, _n'terms) <-- +If( + n'terms >= 30, // threshold for calculation with next'term'factor + // use the rectangular algorithm for large enough number of terms + SumTaylorNum1(x, nth'term'func, n'terms), + SumTaylorNum0(x, nth'term'func, n'terms) +); + +SumTaylorNum(_x, _nth'term'func, _next'term'factor, _n'terms) <-- +If( + n'terms >= 5, // threshold for calculation with next'term'factor + SumTaylorNum1(x, nth'term'func, next'term'factor, n'terms), + SumTaylorNum0(x, nth'term'func, next'term'factor, n'terms) +); +//HoldArgumentNumber(SumTaylorNum, 3, 2); + +/// straightforward algorithms for a small number of terms +1# SumTaylorNum0(_x, _nth'term'func, {}, _n'terms) <-- +[ + Local(sum, k); + N([ + // use Horner scheme starting from the last term + x:=Eval(x); + sum := 0; + For(k:=n'terms, k>=0, k--) + sum := AddN(sum*x, nth'term'func @ k); + ]); + sum; +]; + +//HoldArgumentNumber(SumTaylorNum0, 3, 2); + +2# SumTaylorNum0(_x, _nth'term'func, _next'term'factor, _n'terms) <-- +[ + Local(sum, k, term, delta); + N([ + x:=Eval(x); // x must be floating-point + If (IsConstant(nth'term'func), + term := nth'term'func, + term := (nth'term'func @ {0}), + ); + sum := term; // sum must be floating-point + ]); + NonN([ + delta := 1; + For(k:=1, k<=n'terms And delta != 0, k++) + [ + term := MultiplyNum(term, next'term'factor @ {k}, x); // want to keep exact fractions here, but the result is floating-point + delta := sum; + sum := sum + term; // term must be floating-point + delta := Abs(sum-delta); // check for underflow + ]; + ]); + sum; +]; + +/// interface +SumTaylorNum0(_x, _nth'term'func, _n'terms) <-- SumTaylorNum0(x, nth'term'func, {}, n'terms); + +//HoldArgumentNumber(SumTaylorNum0, 4, 2); +//HoldArgumentNumber(SumTaylorNum0, 4, 3); + +/// this is to be used when a simple relation between a term and the next term is known. +/// next'term'factor must be a function applicable to one argument, so that if term = nth'term'func(k-1), then nth'term'func(k) = term / next'term'factor(k). (This is optimized for Taylor series of elementary functions.) In this case, nth'term'func is either a number, value of the 0th term, or a function. +/// A special case: when next'term'factor is an empty list; then we act as if there is no next'term'factor available. +/// In this case, nth'term'func must be a function applicable to one argument. +/// Need IntLog(n'terms, 10) + 1 guard digits due to accumulated roundoff error. +SumTaylorNum1(x, nth'term'func, next'term'factor, n'terms) := +[ + // need Sqrt(n'terms/2) units of storage (rows) and Sqrt(n'terms*2) columns. Let's underestimate the storage. + Local(sum, rows, cols, rows'tmp, last'power, i, j, x'power, term'tmp); + N([ // want to keep exact fractions + x:=Eval(x); // x must be floating-point + rows := IntNthRoot(n'terms+1, 2); + cols := Quotient(n'terms+rows, rows); // now: rows*cols >= n'terms+1 + Check(rows>1 And cols>1, "Argument", "SumTaylorNum1: Internal error: number of Taylor sum terms must be at least 4"); + rows'tmp := ArrayCreate(rows, 0); + x'power := x ^ rows; // do not use PowerN b/c x might be complex + // initialize partial sums (array rows'tmp) - the 0th column (i:=0) + // prepare term'tmp for the first element + // if we are using next'term'factor, then term'tmp is x^(rows*i)*a[rows*i] + // if we are not using it, then term'tmp is x^(rows*i) + If( + next'term'factor = {}, + term'tmp := 1, + // term'tmp := (nth'term'func @ 0) // floating-point + If (IsConstant(nth'term'func), + term'tmp := nth'term'func, + term'tmp := (nth'term'func @ {0}), + ) + ); + ]); + NonN([ // want to keep exact fractions below + // do horizontal summation using term'tmp to get the first element + For(i:=0, i0, j--) + sum := sum*x + rows'tmp[j]; + ]); + sum; +]; + +//HoldArgumentNumber(SumTaylorNum, 4, 2); +//HoldArgumentNumber(SumTaylorNum, 4, 3); + +/* +Examples: +In> SumTaylorNum(1,{{k}, 1/k!},{{k}, 1/k}, 10 ) +Result: 2.7182818006; +In> SumTaylorNum(1,{{k},1/k!}, 10 ) +Result: 2.7182818007; +*/ + +%/mathpiper + + + +%mathpiper_docs,name="SumTaylorNum",categories="User Functions;Series" +*CMD SumTaylorNum --- optimized numerical evaluation of Taylor series +*STD +*CALL + SumTaylorNum(x, NthTerm, order) + SumTaylorNum(x, NthTerm, TermFactor, order) + SumTaylorNum(x, ZerothTerm, TermFactor, order) + +*PARMS + +{NthTerm} -- a function specifying $n$-th coefficient of the series + +{ZerothTerm} -- value of the $0$-th coefficient of the series + +{x} -- number, value of the expansion variable + +{TermFactor} -- a function specifying the ratio of $n$-th term to the previous one + +{order} -- power of $x$ in the last term + +*DESC + +{SumTaylorNum} computes a Taylor series $Sum(k,0,n,a[k]*x^k)$ +numerically. This function allows very efficient computations of +functions given by Taylor series, although some tweaking of the +parameters is required for good results. + +The coefficients $a[k]$ of the Taylor series are given as functions of one integer variable ($k$). It is convenient to pass them to {SumTaylorNum} as closures. +For example, if a function {a(k)} is defined, then + SumTaylorNum(x, {{k}, a(k)}, n) +computes the series $Sum(k, 0, n, a(k)*x^k)$. + +Often a simple relation between successive coefficients $a[k-1]$, +$a[k]$ of the series is available; usually they are related by a +rational factor. In this case, the second form of {SumTaylorNum} should +be used because it will compute the series faster. The function +{TermFactor} applied to an integer $k>=1$ must return the ratio +$a[k]$/$a[k-1]$. (If possible, the function {TermFactor} should return +a rational number and not a floating-point number.) The function +{NthTerm} may also be given, but the current implementation only calls +{NthTerm(0)} and obtains all other coefficients by using {TermFactor}. +Instead of the function {NthTerm}, a number giving the $0$-th term can be given. + +The algorithm is described elsewhere in the documentation. +The number of terms {order}+1 +must be specified and a sufficiently high precision must be preset in +advance to achieve the desired accuracy. +(The function {SumTaylorNum} does not change the current precision.) + +*E.G. +To compute 20 digits of $Exp(1)$ using the Taylor series, one needs 21 +digits of working precision and 21 terms of the series. + +In> BuiltinPrecisionSet(21) +Result: True; +In> SumTaylorNum(1, {{k},1/k!}, 21) +Result: 2.718281828459045235351; +In> SumTaylorNum(1, 1, {{k},1/k}, 21) +Result: 2.71828182845904523535; +In> SumTaylorNum(1, {{k},1/k!}, {{k},1/k}, 21) +Result: 2.71828182845904523535; +In> RoundTo(N(Ln(%)),20) +Result: 1; + + +*SEE Taylor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/om/om.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,37 @@ +%mathpiper,def="" + +/// coded by Serge Winitzki. See essays documentation for algorithms. + +// From code.mpi.def: +OMDef( "ArcSin" , "transc1","arcsin" ); +OMDef( "ArcCos" , "transc1","arccos" ); +OMDef( "ArcTan" , "transc1","arctan" ); +OMDef( "ArcSec" , "transc1","arcsec" ); +OMDef( "ArcCsc" , "transc1","arccsc" ); +OMDef( "ArcCot" , "transc1","arccot" ); +OMDef( "ArcSinh", "transc1","arcsinh" ); +OMDef( "ArcCosh", "transc1","arccosh" ); +OMDef( "ArcTanh", "transc1","arctanh" ); +OMDef( "ArcSech", "transc1","arcsech" ); +OMDef( "ArcCsch", "transc1","arccsch" ); +OMDef( "ArcCoth", "transc1","arccoth" ); +OMDef( "Sin" , "transc1","sin" ); +OMDef( "Cos" , "transc1","cos" ); +OMDef( "Tan" , "transc1","tan" ); +OMDef( "Sec" , "transc1","sec" ); +OMDef( "Csc" , "transc1","csc" ); +OMDef( "Cot" , "transc1","cot" ); +OMDef( "Sinh" , "transc1","sinh" ); +OMDef( "Cosh" , "transc1","cosh" ); +OMDef( "Tanh" , "transc1","tanh" ); +OMDef( "Sech" , "transc1","sech" ); +OMDef( "Csch" , "transc1","csch" ); +OMDef( "Coth" , "transc1","coth" ); +OMDef( "Exp" , "transc1","exp" ); +OMDef( "Ln" , "transc1","ln" ); + +// Related OM symbols not yet defined in MathPiper: +// "log" , "transc1","log" + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sech.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sech.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sech.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sech.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,9 @@ +%mathpiper,def="Sech" + +100 # Sech(_x) <-- 1/Cosh(x); + +100 # 1/Sech(_x) <-- Cosh(x); + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sec.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sec.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sec.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sec.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Sec" + +100 # 1/Sec(_x) <-- Cos(x); +100 # Sec(_x) <-- 1/Cos(x); + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sinh.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sinh.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sinh.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sinh.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="Sinh" + +2 # Sinh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( (Exp(x)-Exp(-x))/2 )); +5 # Sinh(- _x) <-- -Sinh(x); + +5 # Sinh(- _x) <-- -Sinh(x); + +100 # Sinh(_x)^2-Cosh(_x)^2 <-- 1; +100 # Sinh(_x)+Cosh(_x) <-- Exp(x); +100 # Sinh(_x)-Cosh(_x) <-- Exp(-x); + +//100 # Sinh(I*_x) <-- I*Sin(x); + +100 # Sinh(_x)/Cosh(_x) <-- Tanh(x); +100 # Sinh(_x)*Csch(_x) <-- 1; + +200 # Sinh(0) <-- 0; +200 # Sinh(Infinity) <-- Infinity; +200 # Sinh(-Infinity) <-- -Infinity; +200 # Sinh(ArcSinh(_x)) <-- x; +200 # Sinh(ArcCosh(_x)) <-- Sqrt((x-1)/(x+1))*(x+1); +200 # Sinh(ArcTanh(_x)) <-- x/Sqrt(1-x^2); + +200 # Sinh(Undefined) <-- Undefined; + +/* Threading of standard analytic functions */ +Sinh(xlist_IsList) <-- MapSingle("Sinh",xlist); + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sin.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sin.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Sin.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Sin.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,84 @@ +%mathpiper,def="Sin" + + +1 # SinMap( _n )_(Not(IsRationalOrNumber(n))) <-- ListToFunction({ToAtom("Sin"),n*Pi}); +2 # SinMap( _n )_(n<0) <-- -SinMap(-n); +2 # SinMap( _n )_(n>2) <-- SinMap(Modulo(n,2)); +3 # SinMap( _n )_(n>1) <-- SinMap(n-2); +4 # SinMap( _n )_(n>1/2) <-- SinMap(1-n); + +5 # SinMap( n_IsInteger ) <-- 0; +5 # SinMap( 1/6 ) <-- 1/2; +5 # SinMap( 1/4 ) <-- Sqrt(2)/2; +5 # SinMap( 1/3 ) <-- Sqrt(3)/2; +5 # SinMap( 1/2 ) <-- 1; +5 # SinMap( 1/10) <-- (Sqrt(5)-1)/4; + +10 # SinMap(_n) <-- ListToFunction({ToAtom("Sin"),n*Pi}); + + + + +2 # Sin(x_IsNumber)_InNumericMode() <-- SinNum(x); +4 # Sin(ArcSin(_x)) <-- x; +4 # Sin(ArcCos(_x)) <-- Sqrt(1-x^2); +4 # Sin(ArcTan(_x)) <-- x/Sqrt(1+x^2); +5 # Sin(- _x)_(Not IsConstant(x)) <-- -Sin(x); +6 # (Sin(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -Sin(-x); + +// must prevent it from looping +6 # Sin(x_IsInfinity) <-- Undefined; +6 # Sin(Undefined) <-- Undefined; + +110 # Sin(Complex(_r,_i)) <-- + (Exp(I*Complex(r,i)) - Exp(- I*Complex(r,i))) / (I*2) ; + +200 # Sin(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- +[ + SinMap(Coef(v,Pi,1)); +]; + +100 # Sin(_x)/Tan(_x) <-- Cos(x); +100 # Sin(_x)/Cos(_x) <-- Tan(x); + +Sin(xlist_IsList) <-- MapSingle("Sin",xlist); + +%/mathpiper + + + +%mathpiper_docs,name="Sin",categories="User Functions;Trigonometry (Symbolic)" +*CMD Sin --- trigonometric sine function +*STD +*CALL + Sin(x) + +*PARMS + +{x} -- argument to the function, in radians + +*DESC + +This function represents the trigonometric function sine. MathPiper leaves +expressions alone even if x is a number, trying to keep the result as +exact as possible. The floating point approximations of these functions +can be forced by using the {N} function. + +MathPiper knows some trigonometric identities, so it can simplify to exact +results even if {N} is not used. This is the case, for instance, +when the argument is a multiple of $Pi$/6 or $Pi$/4. + +These functions are threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Sin(1) +Result: Sin(1); +In> N(Sin(1),20) +Result: 0.84147098480789650665; +In> Sin(Pi/4) +Result: Sqrt(2)/2; + +*SEE Cos, Tan, ArcSin, ArcCos, ArcTan, N, Pi +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Tanh.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Tanh.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Tanh.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Tanh.mpw 2009-12-29 04:47:50.000000000 +0000 @@ -0,0 +1,21 @@ +%mathpiper,def="Tanh" + +2 # Tanh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Sinh(x)/Cosh(x) )); + +100 # Tanh(_x)*Cosh(_x) <-- Sinh(x); + +200 # Tanh(0) <-- 0; +200 # Tanh(Infinity) <-- 1; +200 # Tanh(-Infinity) <-- -1; +200 # Tanh(ArcTanh(_x)) <-- x; +200 # Tanh(ArcSinh(_x)) <-- x/Sqrt(1+x^2); +200 # Tanh(ArcCosh(_x)) <-- Sqrt((x-1)/(x+1))*(x+1)/x; + +200 # Tanh(Undefined) <-- Undefined; + +/* Threading of standard analytic functions */ +Tanh(xlist_IsList) <-- MapSingle("Tanh",xlist); + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Tan.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Tan.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stdfuncs/Tan.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stdfuncs/Tan.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,78 @@ +%mathpiper,def="Tan" + +1 # TanMap( _n )_(Not(IsRationalOrNumber(n))) <-- ListToFunction({ToAtom("Tan"),n*Pi}); +2 # TanMap( _n )_(n<0) <-- -TanMap(-n); +2 # TanMap( _n )_(n>1) <-- TanMap(Modulo(n,1)); +4 # TanMap( _n )_(n>1/2) <-- -TanMap(1-n); + +5 # TanMap( 0 ) <-- 0; +5 # TanMap( 1/6 ) <-- 1/3*Sqrt(3); +5 # TanMap( 1/4 ) <-- 1; +5 # TanMap( 1/3 ) <-- Sqrt(3); +5 # TanMap( 1/2 ) <-- Infinity; + +10 # TanMap(_n) <-- ListToFunction({ToAtom("Tan"),n*Pi}); + + + + +2 # Tan(x_IsNumber)_InNumericMode() <-- TanNum(x); +4 # Tan(ArcTan(_x)) <-- x; +4 # Tan(ArcSin(_x)) <-- x/Sqrt(1-x^2); +4 # Tan(ArcCos(_x)) <-- Sqrt(1-x^2)/x; +5 # Tan(- _x)_(Not IsConstant(x)) <-- -Tan(x); +6 # (Tan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -Tan(-x); + +// must prevent it from looping +6 # Tan(Infinity) <-- Undefined; +6 # Tan(Undefined) <-- Undefined; + +110 # Tan(Complex(_r,_i)) <-- Sin(Complex(r,i))/Cos(Complex(r,i)); + +200 # Tan(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- + TanMap(Coef(v,Pi,1)); + +100 # Tan(_x)/Sin(_x) <-- (1/Cos(x)); +100 # Tan(_x)*Cos(_x) <-- Sin(x); + +Tan(xlist_IsList) <-- MapSingle("Tan",xlist); + +%/mathpiper + + + +%mathpiper_docs,name="Tan",categories="User Functions;Trigonometry (Symbolic)" +*CMD Tan --- trigonometric tangent function +*STD +*CALL + Tan(x) + +*PARMS + +{x} -- argument to the function, in radians + +*DESC + +This function represents the trigonometric function tangent. MathPiper leaves +expressions alone even if x is a number, trying to keep the result as +exact as possible. The floating point approximations of these functions +can be forced by using the {N} function. + +MathPiper knows some trigonometric identities, so it can simplify to exact +results even if {N} is not used. This is the case, for instance, +when the argument is a multiple of $Pi$/6 or $Pi$/4. + +These functions are threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Tan(1) +Result: Tan(1); +In> N(Tan(1),20) +Result: 1.5574077246549022305; +In> Tan(Pi/4) +Result: 1; + +*SEE Sin, Cos, ArcSin, ArcCos, ArcTan, N, Pi +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Abs.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Abs.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Abs.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Abs.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,58 @@ +%mathpiper,def="Abs" + +10 # Abs(Infinity) <-- Infinity; //Note:tk:moved here from stdfuncts. + +10 # Abs(n_IsNumber) <-- AbsN(n); +10 # Abs(n_IsPositiveNumber/m_IsPositiveNumber) <-- n/m; +10 # Abs(n_IsNegativeNumber/m_IsPositiveNumber) <-- (-n)/m; +10 # Abs(n_IsPositiveNumber/m_IsNegativeNumber) <-- n/(-m); +10 # Abs( Sqrt(_x)) <-- Sqrt(x); +10 # Abs(-Sqrt(_x)) <-- Sqrt(x); +10 # Abs(Complex(_r,_i)) <-- Sqrt(r^2 + i^2); +10 # Abs(n_IsInfinity) <-- Infinity; +10 # Abs(Undefined) <-- Undefined; +20 # Abs(n_IsList) <-- MapSingle("Abs",n); + +100 # Abs(_a^_n) <-- Abs(a)^n; + + + +%/mathpiper + + + +%mathpiper_docs,name="Abs",categories="User Functions;Calculus Related (Symbolic)" +*CMD Abs --- absolute value or modulus of complex number +*STD +*CALL + Abs(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function returns the absolute value (also called the modulus) of +"x". If "x" is positive, the absolute value is "x" itself; if +"x" is negative, the absolute value is "-x". For complex "x", +the modulus is the "r" in the polar decomposition +$x = r *Exp(I*phi)$. + +This function is connected to the {Sign} function by +the identity "Abs(x) * Sign(x) = x" for real "x". + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Abs(2); +Result: 2; +In> Abs(-1/2); +Result: 1/2; +In> Abs(3+4*I); +Result: 5; + +*SEE Sign, Arg +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/CanonicalAdd.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/CanonicalAdd.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/CanonicalAdd.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/CanonicalAdd.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,21 @@ +%mathpiper,def="CanonicalAdd" + +// Canonicalise an expression so its terms are grouped to the right +// ie a+(b+(c+d)) +// This doesn't preserve order of terms, when doing this would cause more +// subtractions and nested parentheses than necessary. +1 # CanonicalAdd((_a+_b)+_c) <-- CanonicalAdd(CanonicalAdd(a)+ + CanonicalAdd(CanonicalAdd(b)+ + CanonicalAdd(c))); +1 # CanonicalAdd((_a-_b)+_c) <-- CanonicalAdd(CanonicalAdd(a)+ + CanonicalAdd(CanonicalAdd(c)- + CanonicalAdd(b))); +1 # CanonicalAdd((_a+_b)-_c) <-- CanonicalAdd(CanonicalAdd(a)+ + CanonicalAdd(CanonicalAdd(b)- + CanonicalAdd(c))); +1 # CanonicalAdd((_a-_b)-_c) <-- CanonicalAdd(CanonicalAdd(a)- + CanonicalAdd(CanonicalAdd(b)+ + CanonicalAdd(c))); +2 # CanonicalAdd(_a) <-- a; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Ceil.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Ceil.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Ceil.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Ceil.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="Ceil" + +5 # Ceil(Infinity) <-- Infinity; +5 # Ceil(-Infinity) <-- -Infinity; +5 # Ceil(Undefined) <-- Undefined; + +10 # Ceil(x_IsRationalOrNumber) + <-- + [ + x:=N(x); + Local(prec,result,n); + Bind(prec,BuiltinPrecisionGet()); + If(IsZero(x),Bind(n,2), + If(x>0, + Bind(n,2+FloorN(N(FastLog(x)/FastLog(10)))), + Bind(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) + )); + If(n>prec,BuiltinPrecisionSet(n)); + Bind(result,CeilN(x)); + BuiltinPrecisionSet(prec); + result; + ]; +// CeilN (N(x)); + +%/mathpiper + + + +%mathpiper_docs,name="Ceil",categories="User Functions;Numbers (Operations)" +*CMD Ceil --- round a number upwards +*STD +*CALL + Ceil(x) + +*PARMS + +{x} -- a number + +*DESC + +This function returns $Ceil(x)$, the smallest integer larger than or equal to $x$. + +*E.G. + +In> Ceil(1.1) +Result: 2; +In> Ceil(-1.1) +Result: -1; + +*SEE Floor, Round +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/comparison_operators.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/comparison_operators.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/comparison_operators.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/comparison_operators.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,312 @@ +%mathpiper,def="<;>;<=;>=;!=" + +/* def file definitions += +< +> +<= +>= +!= + +*/ + +/* Comparison operators. They call the internal comparison routines when + * both arguments are numbers. The value Infinity is also understood. +*/ + +// Undefined is a very special case as we return False for everything +1 # Undefined < _x <-- False; +1 # Undefined <= _x <-- False; +1 # Undefined > _x <-- False; +1 # Undefined >= _x <-- False; +1 # _x < Undefined <-- False; +1 # _x <= Undefined <-- False; +1 # _x > Undefined <-- False; +1 # _x >= Undefined <-- False; + + +// If n and m are numbers, use the standard LessThan function immediately +5 # (n_IsNumber < m_IsNumber) <-- IsLessThan(n-m,0); + + +// If n and m are symbolic after a single evaluation, see if they can be coerced in to a real-valued number. +LocalSymbols(nNum,mNum) +[ + 10 # (_n < _m)_[nNum:=N(Eval(n)); mNum:=N(Eval(m));IsNumber(nNum) And IsNumber(mNum);] <-- IsLessThan(nNum-mNum,0); +]; + +// Deal with Infinity +20 # (Infinity < _n)_(Not(IsInfinity(n))) <-- False; +20 # (-Infinity < _n)_(Not(IsInfinity(n))) <-- True; +20 # (_n < Infinity)_(Not(IsInfinity(n))) <-- True; +20 # (_n < -Infinity)_(Not(IsInfinity(n))) <-- False; + +// Lots of known identities go here +30 # (_n1/_n2) < 0 <-- (n1 < 0) != (n2 < 0); +30 # (_n1*_n2) < 0 <-- (n1 < 0) != (n2 < 0); + +// This doesn't sadly cover the case where a and b have opposite signs +30 # ((_n1+_n2) < 0)_((n1 < 0) And (n2 < 0)) <-- True; +30 # ((_n1+_n2) < 0)_((n1 > 0) And (n2 > 0)) <-- False; +30 # _x^a_IsOdd < 0 <-- x < 0; +30 # _x^a_IsEven < 0 <-- False; // This is wrong for complex x + +// Add other functions here! Everything we can compare to 0 should be here. +40 # (Sqrt(_x))_(x > 0) < 0 <-- False; + +40 # (Sin(_x) < 0)_(Not(IsEven(N(x/Pi))) And IsEven(N(Floor(x/Pi)))) <-- False; +40 # (Sin(_x) < 0)_(Not(IsOdd (N(x/Pi))) And IsOdd (N(Floor(x/Pi)))) <-- True; + +40 # Cos(_x) < 0 <-- Sin(Pi/2-x) < 0; + +40 # (Tan(_x) < 0)_(Not(IsEven(N(2*x/Pi))) And IsEven(N(Floor(2*x/Pi)))) <-- False; +40 # (Tan(_x) < 0)_(Not(IsOdd (N(2*x/Pi))) And IsOdd (N(Floor(2*x/Pi)))) <-- True; + +// Functions that need special treatment with more than one of the comparison +// operators as they always return true or false. For these we must define +// both the `<' and `>=' operators. +40 # (Complex(_a,_b) < 0)_(b!=0) <-- False; +40 # (Complex(_a,_b) >= 0)_(b!=0) <-- False; +40 # (Sqrt(_x))_(x < 0) < 0 <-- False; +40 # (Sqrt(_x))_(x < 0) >= 0 <-- False; + +// Deal with negated terms +50 # -(_x) < 0 <-- Not((x<0) Or (x=0)); + +// Define each of {>,<=,>=} in terms of < +50 # _n > _m <-- m < n; +50 # _n <= _m <-- m >= n; +50 # _n >= _m <-- Not(n 2 < 5; +Result: True; +In> Cos(1) < 5; +Result: True; + +*SEE IsNumber, IsInfinity, N +%/mathpiper_docs + + + +%mathpiper_docs,name=">",categories="Operators" +*CMD > --- test for "greater than" +*STD +*CALL + e1 > e2 +Precedence: +*EVAL PrecedenceGet(">") + + +*PARMS + +{e1}, {e2} -- expressions to be compared + +*DESC + +The two expression are evaluated. If both results are numeric, they +are compared. If the first expression is larger than the second one, +the result is {True} and it is {False} otherwise. If either of the expression is not numeric, after +evaluation, the expression is returned with evaluated arguments. + +The word "numeric" in the previous paragraph has the following +meaning. An expression is numeric if it is either a number (i.e. {IsNumber} returns {True}), or the +quotient of two numbers, or an infinity (i.e. {IsInfinity} returns {True}). MathPiper will try to +coerce the arguments passed to this comparison operator to a real value before making the comparison. + +*E.G. + +In> 2 > 5; +Result: False; +In> Cos(1) > 5; +Result: False + +*SEE IsNumber, IsInfinity, N +%/mathpiper_docs + + + +%mathpiper_docs,name="<=",categories="Operators" +*CMD <= --- test for "less or equal" +*STD +*CALL + e1 <= e2 +Precedence: +*EVAL PrecedenceGet("<=") + + +*PARMS + +{e1}, {e2} -- expressions to be compared + +*DESC + +The two expression are evaluated. If both results are numeric, they +are compared. If the first expression is smaller than or equals the +second one, the result is {True} and it is {False} otherwise. If either of the expression is not +numeric, after evaluation, the expression is returned with evaluated +arguments. + +The word "numeric" in the previous paragraph has the following +meaning. An expression is numeric if it is either a number (i.e. {IsNumber} returns {True}), or the +quotient of two numbers, or an infinity (i.e. {IsInfinity} returns {True}). MathPiper will try to +coerce the arguments passed to this comparison operator to a real value before making the comparison. + +*E.G. + +In> 2 <= 5; +Result: True; +In> Cos(1) <= 5; +Result: True + +*SEE IsNumber, IsInfinity, N +%/mathpiper_docs + + + +%mathpiper_docs,name=">=",categories="Operators" +*CMD >= --- test for "greater or equal" +*STD +*CALL + e1 >= e2 +Precedence: +*EVAL PrecedenceGet(">=") + + +*PARMS + +{e1}, {e2} -- expressions to be compared + +*DESC + +The two expression are evaluated. If both results are numeric, they +are compared. If the first expression is larger than or equals the +second one, the result is {True} and it is {False} otherwise. If either of the expression is not +numeric, after evaluation, the expression is returned with evaluated +arguments. + +The word "numeric" in the previous paragraph has the following +meaning. An expression is numeric if it is either a number (i.e. {IsNumber} returns {True}), or the +quotient of two numbers, or an infinity (i.e. {IsInfinity} returns {True}). MathPiper will try to +coerce the arguments passed to this comparison operator to a real value before making the comparison. + +*E.G. + +In> 2 >= 5; +Result: False; +In> Cos(1) >= 5; +Result: False + +*SEE IsNumber, IsInfinity, N +%/mathpiper_docs + + + +%mathpiper_docs,name="!=",categories="Operators" +*CMD != --- test for "not equal" +*STD +*CALL + e1 != e2 +Precedence: +*EVAL PrecedenceGet("!=") + + +*PARMS + +{e1}, {e2} -- expressions to be compared + +*DESC + +Both expressions are evaluated and compared. If they turn out to be +equal, the result is {False}. Otherwise, the result +is {True}. + +The expression {e1 != e2} is equivalent to {Not(e1 = e2)}. + +*E.G. + +In> 1 != 2; +Result: True; +In> 1 != 1; +Result: False; + +*SEE = +%/mathpiper_docs + + + +%mathpiper_docs,name="=",categories="Operators" +*CMD = --- test for equality of expressions +*STD +*CALL + e1 = e2 +Precedence: +*EVAL PrecedenceGet("=") + + +*PARMS + +{e1}, {e2} -- expressions to be compared + +*DESC + +Both expressions are evaluated and compared. If they turn out to be equal, the +result is {True}. Otherwise, the result is {False}. The function {Equals} does +the same. + +Note that the test is on syntactic equality, not mathematical equality. Hence +even if the result is {False}, the expressions can still be +mathematically equal; see the examples below. Put otherwise, this +function tests whether the two expressions would be displayed in the same way +if they were printed. + +*E.G. + +In> e1 := (x+1) * (x-1); +Result: (x+1)*(x-1); +In> e2 := x^2 - 1; +Result: x^2-1; + +In> e1 = e2; +Result: False; +In> Expand(e1) = e2; +Result: True; + +*SEE !=, Equals +%/mathpiper_docs + + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Expand.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Expand.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Expand.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Expand.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,70 @@ +%mathpiper,def="Expand" + +/* Expand expands polynomials. + */ +10 # Expand(expr_CanBeUni) <-- NormalForm(MakeUni(expr)); +20 # Expand(_expr) <-- expr; + +10 # Expand(expr_CanBeUni(var),_var) <-- NormalForm(MakeUni(expr,var)); +20 # Expand(_expr,_var) <-- expr; + +%/mathpiper + + + +%mathpiper_docs,name="Expand",categories="User Functions;Polynomials (Operations)" +*CMD Expand --- transform a polynomial to an expanded form +*STD +*CALL + Expand(expr) + Expand(expr, var) + Expand(expr, varlist) + +*PARMS + +{expr} -- a polynomial expression + +{var} -- a variable + +{varlist} -- a list of variables + +*DESC + +This command brings a polynomial in expanded form, in which +polynomials are represented in the form +$c0 + c1*x + c2*x^2 + ... + c[n]*x^n$. In this form, it is easier to test whether a polynomial is +zero, namely by testing whether all coefficients are zero. + +If the polynomial "expr" contains only one variable, the first +calling sequence can be used. Otherwise, the second form should be +used which explicitly mentions that "expr" should be considered as a +polynomial in the variable "var". The third calling form can be used +for multivariate polynomials. Firstly, the polynomial "expr" is +expanded with respect to the first variable in "varlist". Then the +coefficients are all expanded with respect to the second variable, and +so on. + +*E.G. + +In> PrettyPrinterSet("PrettyForm"); + + True + +In> Expand((1+x)^5); + + 5 4 3 2 + x + 5 * x + 10 * x + 10 * x + 5 * x + 1 + +In> Expand((1+x-y)^2, x); + + 2 2 + x + 2 * ( 1 - y ) * x + ( 1 - y ) + +In> Expand((1+x-y)^2, {x,y}); + + 2 2 + x + ( -2 * y + 2 ) * x + y - 2 * y + 1 + + +*SEE ExpandBrackets +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Floor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Floor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Floor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Floor.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,69 @@ +%mathpiper,def="Floor" + +5 # Floor(Infinity) <-- Infinity; +5 # Floor(-Infinity) <-- -Infinity; +5 # Floor(Undefined) <-- Undefined; + + +10 # Floor(x_IsRationalOrNumber) + <-- + [ + x:=N(Eval(x)); +//Echo("x = ",x); + Local(prec,result,n); + Bind(prec,BuiltinPrecisionGet()); + If(IsZero(x), + Bind(n,2), + If(x>0, + Bind(n,2+FloorN(N(FastLog(x)/FastLog(10)))), + Bind(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) + )); + If(n>prec,BuiltinPrecisionSet(n)); +//Echo("Before"); + Bind(result,FloorN(x)); +//Echo("After"); + BuiltinPrecisionSet(prec); + result; + ]; + +// FloorN(N(x)); + + +//todo:tk:should this be removed because it is no longer needed? +/* Changed by Nobbi before redefinition of Rational +10 # Floor(x_IsNumber) <-- FloorN(x); +10 # Ceil (x_IsNumber) <-- CeilN (x); +10 # Round(x_IsNumber) <-- FloorN(x+0.5); + +20 # Floor(x_IsRational) _ (IsNumber(Numerator(x)) And IsNumber(Denominator(x))) <-- FloorN(N(x)); +20 # Ceil (x_IsRational) _ (IsNumber(Numerator(x)) And IsNumber(Denominator(x))) <-- CeilN (N(x)); +20 # Round(x_IsRational) _ (IsNumber(Numerator(x)) And IsNumber(Denominator(x))) <-- FloorN(N(x+0.5)); +*/ + +%/mathpiper + + + +%mathpiper_docs,name="Floor",categories="User Functions;Numbers (Operations)" +*CMD Floor --- round a number downwards +*STD +*CALL + Floor(x) + +*PARMS + +{x} -- a number + +*DESC + +This function returns $Floor(x)$, the largest integer smaller than or equal to $x$. + +*E.G. + +In> Floor(1.1) +Result: 1; +In> Floor(-1.1) +Result: -2; + +*SEE Ceil, Round +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Gcd.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Gcd.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Gcd.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Gcd.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,114 @@ +%mathpiper,def="Gcd" + +0 # Gcd(0,0) <-- 1; +1 # Gcd(0,_m) <-- Abs(m); +1 # Gcd(_n,0) <-- Abs(n); +1 # Gcd(_m,_m) <-- Abs(m); +2 # Gcd(_n,1) <-- 1; +2 # Gcd(1,_m) <-- 1; +2 # Gcd(n_IsInteger,m_IsInteger) <-- GcdN(n,m); +3 # Gcd(_n,_m)_(IsGaussianInteger(m) And IsGaussianInteger(n) )<-- GaussianGcd(n,m); + +4 # Gcd(-(_n), (_m)) <-- Gcd(n,m); +4 # Gcd( (_n),-(_m)) <-- Gcd(n,m); +4 # Gcd(Sqrt(n_IsInteger),Sqrt(m_IsInteger)) <-- Sqrt(Gcd(n,m)); +4 # Gcd(Sqrt(n_IsInteger),m_IsInteger) <-- Sqrt(Gcd(n,m^2)); +4 # Gcd(n_IsInteger,Sqrt(m_IsInteger)) <-- Sqrt(Gcd(n^2,m)); + +5 # Gcd(n_IsRational,m_IsRational) <-- +[ + Gcd(Numerator(n),Numerator(m))/Lcm(Denominator(n),Denominator(m)); +]; + + +10 # Gcd(list_IsList)_(Length(list)>2) <-- + [ + Local(first); + first:=Gcd(list[1],list[2]); + Gcd(first:Rest(Rest(list))); + ]; +14 # Gcd({0}) <-- 1; +15 # Gcd({_head}) <-- head; + +20 # Gcd(list_IsList)_(Length(list)=2) <-- Gcd(list[1],list[2]); + +30 # Gcd(n_CanBeUni,m_CanBeUni)_(Length(VarList(n*m))=1) <-- +[ + Local(vars); + vars:=VarList(n+m); + NormalForm(Gcd(MakeUni(n,vars),MakeUni(m,vars))); +]; + +100 # Gcd(n_IsConstant,m_IsConstant) <-- 1; +110 # Gcd(_m,_n) <-- +[ + Echo("Not simplified"); +]; + + +//Note:tk:moved here from univar.rep. +0 # Gcd(n_IsUniVar,m_IsUniVar)_ + (n[1] = m[1] And Degree(n) < Degree(m)) <-- Gcd(m,n); + +1 # Gcd(nn_IsUniVar,mm_IsUniVar)_ + (nn[1] = mm[1] And Degree(nn) >= Degree(mm)) <-- +[ + UniVariate(nn[1],0, + UniGcd(Concat(ZeroVector(nn[2]),nn[3]), + Concat(ZeroVector(mm[2]),mm[3]))); +]; + +%/mathpiper + + + +%mathpiper_docs,name="Gcd",categories="User Functions;Numbers (Operations)" +*CMD Gcd --- greatest common divisor +*STD +*CALL + Gcd(n,m) + Gcd(list) + +*PARMS + +{n}, {m} -- integers or Gaussian integers or univariate polynomials + +{list} -- a list of all integers or all univariate polynomials + +*DESC + +This function returns the greatest common divisor of "n" and "m". +The gcd is the largest number that divides "n" and "m". It is +also known as the highest common factor (hcf). The library code calls +{MathGcd}, which is an internal function. This +function implements the "binary Euclidean algorithm" for determining the +greatest common divisor: + +*HEAD Routine for calculating {Gcd(n,m)} + +* 1. if $n = m$ then return $n$ +* 2. if both $n$ and $m$ are even then return $2*Gcd(n/2,m/2)$ +* 3. if exactly one of $n$ or $m$ (say $n$) is even then return $Gcd(n/2,m)$ +* 4. if both $n$ and $m$ are odd and, say, $n>m$ then return $Gcd((n-m)/2,m)$ + +This is a rather fast algorithm on computers that can efficiently shift +integers. When factoring Gaussian integers, a slower recursive algorithm is used. + +If the second calling form is used, {Gcd} will +return the greatest common divisor of all the integers or polynomials +in "list". It uses the identity +$$Gcd(a,b,c) = Gcd(Gcd(a,b),c)$$. + +*E.G. + +In> Gcd(55,10) +Result: 5; +In> Gcd({60,24,120}) +Result: 12; +In> Gcd( 7300 + 12*I, 2700 + 100*I) +Result: Complex(-4,4); + + +*SEE Lcm +%/mathpiper_docs + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Lcm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Lcm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Lcm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Lcm.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,57 @@ +%mathpiper,def="Lcm" + +/* Least common multiple */ +5 # Lcm(a_IsInteger,b_IsInteger) <-- Quotient(a*b,Gcd(a,b)); + +10 # Lcm(list_IsList)_(Length(list)>2) <-- +[ + Local(first); + first:=Lcm(list[1],list[2]); + Lcm(first:Rest(Rest(list))); +]; + +10 # Lcm(list_IsList)_(Length(list)=2) <-- Lcm(list[1],list[2]); + +// We handle lists with just one element to avoid special-casing +// all the calls. +10 # Lcm(list_IsList)_(Length(list)=1) <-- Lcm(list[1],1); + +%/mathpiper + + + +%mathpiper_docs,name="Lcm",categories="User Functions;Numbers (Operations)" +*CMD Lcm --- least common multiple +*STD +*CALL + Lcm(n,m) + Lcm(list) + +*PARMS + +{n}, {m} -- integers or univariate polynomials +{list} -- list of integers + +*DESC + +This command returns the least common multiple of "n" and "m" or all of +the integers in the list {list}. +The least common multiple of two numbers "n" and "m" is the lowest +number which is an integer multiple of both "n" and "m". +It is calculated with the formula +$$Lcm(n,m) = Quotient(n*m,Gcd(n,m))$$. + +This means it also works on polynomials, since {Div}, {Gcd} and multiplication are also defined for +them. + +*E.G. + +In> Lcm(60,24) +Result: 120; +In> Lcm({3,5,7,9}) +Result: 315; + + +*SEE Gcd + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/LnCombine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/LnCombine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/LnCombine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/LnCombine.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,98 @@ +%mathpiper,def="LnCombine" + +////////////////////// Log rules stuff ////////////////////// + +// LnCombine is nice and simple now +LnCombine(_a) <-- DoLnCombine(CanonicalAdd(a)); + +// Combine single terms. This can always be done without a recursive call. +1 # DoLnCombine(Ln(_a)) <-- Ln(a); +1 # DoLnCombine(Ln(_a)*_b) <-- Ln(a^b); +1 # DoLnCombine(_b*Ln(_a)) <-- Ln(a^b); + +// Deal with the first two terms so they are both simple logs if at all +// possible. This involves converting a*Ln(b) to Ln(b^a) and moving log terms +// to the start of expressions. One of either of these operations always takes +// us to a strictly simpler form than we started in, so we can get away with +// calling DoLnCombine again with the partly simplified argument. + +// TODO: Make this deal with division everywhere it deals with multiplication + +// first term is a log multiplied by something +2 # DoLnCombine(Ln(_a)*_b+_c) <-- DoLnCombine(Ln(a^b)+c); +2 # DoLnCombine(Ln(_a)*_b-_c) <-- DoLnCombine(Ln(a^b)-c); +2 # DoLnCombine(_b*Ln(_a)+_c) <-- DoLnCombine(Ln(a^b)+c); +2 # DoLnCombine(_b*Ln(_a)-_c) <-- DoLnCombine(Ln(a^b)-c); + +// second term of a two-term expression is a log multiplied by something +2 # DoLnCombine(_a+(_c*Ln(_b))) <-- DoLnCombine(a+Ln(b^c)); +2 # DoLnCombine(_a-(_c*Ln(_b))) <-- DoLnCombine(a-Ln(b^c)); +2 # DoLnCombine(_a+(Ln(_b)*_c)) <-- DoLnCombine(a+Ln(b^c)); +2 # DoLnCombine(_a-(Ln(_b)*_c)) <-- DoLnCombine(a-Ln(b^c)); + +// second term of a three-term expression is a log multiplied by something +2 # DoLnCombine(_a+((Ln(_b)*_c)+_d)) <-- DoLnCombine(a+(Ln(b^c)+d)); +2 # DoLnCombine(_a+((Ln(_b)*_c)-_d)) <-- DoLnCombine(a+(Ln(b^c)-d)); +2 # DoLnCombine(_a-((Ln(_b)*_c)+_d)) <-- DoLnCombine(a-(Ln(b^c)+d)); +2 # DoLnCombine(_a-((Ln(_b)*_c)-_d)) <-- DoLnCombine(a-(Ln(b^c)-d)); + +2 # DoLnCombine(_a+((_c*Ln(_b))+_d)) <-- DoLnCombine(a+(Ln(b^c)+d)); +2 # DoLnCombine(_a+((_c*Ln(_b))-_d)) <-- DoLnCombine(a+(Ln(b^c)-d)); +2 # DoLnCombine(_a-((_c*Ln(_b))+_d)) <-- DoLnCombine(a-(Ln(b^c)+d)); +2 # DoLnCombine(_a-((_c*Ln(_b))-_d)) <-- DoLnCombine(a-(Ln(b^c)-d)); + +// Combine the first two terms if they are logs, otherwise move one or both to +// the front, then recurse on the remaining possibly-log-containing portion. +// (the code makes more sense than this comment) +3 # DoLnCombine(Ln(_a)+Ln(_b)) <-- Ln(a*b); +3 # DoLnCombine(Ln(_a)-Ln(_b)) <-- Ln(a/b); +3 # DoLnCombine(Ln(_a)+(Ln(_b)+_c)) <-- DoLnCombine(Ln(a*b)+c); +3 # DoLnCombine(Ln(_a)+(Ln(_b)-_c)) <-- DoLnCombine(Ln(a*b)-c); +3 # DoLnCombine(Ln(_a)-(Ln(_b)+_c)) <-- DoLnCombine(Ln(a/b)-c); +3 # DoLnCombine(Ln(_a)-(Ln(_b)-_c)) <-- DoLnCombine(Ln(a/b)+c); + +// We know that at least one of the first two terms isn't a log +4 # DoLnCombine(Ln(_a)+(_b+_c)) <-- b+DoLnCombine(Ln(a)+c); +4 # DoLnCombine(Ln(_a)+(_b-_c)) <-- b+DoLnCombine(Ln(a)-c); +4 # DoLnCombine(Ln(_a)-(_b+_c)) <-- DoLnCombine(Ln(a)-c)-b; +4 # DoLnCombine(Ln(_a)-(_b-_c)) <-- DoLnCombine(Ln(a)+c)-b; + +4 # DoLnCombine(_a+(Ln(_b)+_c)) <-- a+DoLnCombine(Ln(b)+c); +4 # DoLnCombine(_a+(Ln(_b)-_c)) <-- a+DoLnCombine(Ln(b)-c); +4 # DoLnCombine(_a-(Ln(_b)+_c)) <-- a-DoLnCombine(Ln(b)+c); +4 # DoLnCombine(_a-(Ln(_b)-_c)) <-- a-DoLnCombine(Ln(b)-c); + +// If we get here we know that neither of the first two terms is a log +5 # DoLnCombine(_a+(_b+_c)) <-- a+(b+DoLnCombine(c)); + +// Finished +6 # DoLnCombine(_a) <-- a; + + +%/mathpiper + + + +%mathpiper_docs,name="LnCombine",categories="User Functions;Expression Simplification" +*CMD LnCombine --- combine logarithmic expressions using standard logarithm rules +*STD +*CALL + LnCombine(expr) + +*PARMS + +{expr} -- an expression possibly containing multiple {Ln} terms to be combined + +*DESC + +{LnCombine} finds {Ln} terms in the expression it is given, and combines them +using logarithm rules. It is intended to be the exact converse of {LnExpand}. + +*E.G. +In> LnCombine(Ln(a)+Ln(b)*n) +Result: Ln(a*b^n) +In> LnCombine(2*Ln(2)+Ln(3)-Ln(5)) +Result: Ln(12/5) + +*SEE Ln, LnExpand +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/LnExpand.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/LnExpand.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/LnExpand.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/LnExpand.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="LnExpand" + +////////////////////// Log rules stuff ////////////////////// + +// LnExpand +1 # LnExpand(Ln(x_IsInteger)) + <-- Add(Map({{n,m},m*Ln(n)},Transpose(Factors(x)))); +1 # LnExpand(Ln(_a*_b)) <-- LnExpand(Ln(a))+LnExpand(Ln(b)); +1 # LnExpand(Ln(_a/_b)) <-- LnExpand(Ln(a))-LnExpand(Ln(b)); +1 # LnExpand(Ln(_a^_n)) <-- LnExpand(Ln(a))*n; +2 # LnExpand(_a) <-- a; + +%/mathpiper + + + +%mathpiper_docs,name="LnExpand",categories="User Functions;Expression Simplification" +*CMD LnExpand --- expand a logarithmic expression using standard logarithm rules +*STD +*CALL + LnExpand(expr) + +*PARMS + +{expr} -- the logarithm of an expression + +*DESC + +{LnExpand} takes an expression of the form $Ln(expr)$, and applies logarithm +rules to expand this into multiple {Ln} expressions where possible. An +expression like $Ln(a*b^n)$ would be expanded to $Ln(a)+n*Ln(b)$. + +If the logarithm of an integer is discovered, it is factorised using {Factors} +and expanded as though {LnExpand} had been given the factorised form. So +$Ln(18)$ goes to $Ln(x)+2*Ln(3)$. + +*E.G. +In> LnExpand(Ln(a*b^n)) +Result: Ln(a)+Ln(b)*n +In> LnExpand(Ln(a^m/b^n)) +Result: Ln(a)*m-Ln(b)*n +In> LnExpand(Ln(60)) +Result: 2*Ln(2)+Ln(3)+Ln(5) +In> LnExpand(Ln(60/25)) +Result: 2*Ln(2)+Ln(3)-Ln(5) + +*SEE Ln, LnCombine, Factors +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/minus_greaterthan_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/minus_greaterthan_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/minus_greaterthan_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/minus_greaterthan_operator.mpw 2010-03-14 06:56:53.000000000 +0000 @@ -0,0 +1,28 @@ +%mathpiper,def="->" + +Rulebase("->",{left,right}); + +HoldArgument("->",left); + +//HoldArgument("->",right); + +%/mathpiper + + + + +%mathpiper_docs,name="->",categories="Operators" +*CMD -> --- options operator +*CALL + option -> value + +*PARMS +{option} -- an option name + +{value} -- the value to associate with the option + +*DESC +The -> operator is used to create options. {option} and {value} +need to be placed in quotes if they are not meant to be evaluated. + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Modulo.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Modulo.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Modulo.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Modulo.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,112 @@ +%mathpiper,def="Modulo" + +//Retract("Modulo",*); + +0 # Modulo(_n,m_IsRationalOrNumber)_(m<0) <-- `Hold(Modulo(@n,@m)); + +1 # Modulo(n_IsNegativeInteger,m_IsPositiveInteger) <-- +[ + Local(result); + result := ModuloN(n,m); + If (result < 0,result := result + m); + result; +]; +1 # Modulo(n_IsPositiveInteger,m_IsPositiveInteger) <-- ModuloN(n,m); +2 # Modulo(0,_m) <-- 0; +2 # Modulo(n_IsPositiveInteger,Infinity) <-- n; +3 # Modulo(n_IsInteger,m_IsInteger) <-- ModuloN(n,m); +4 # Modulo(n_IsNumber,m_IsNumber) <-- NonN(Modulo(Rationalize(n),Rationalize(m))); + +5 # Modulo(n_IsRationalOrNumber,m_IsRationalOrNumber)/*_(n>0 And m>0)*/ <-- +[ + Local(n1,n2,m1,m2); + n1:=Numerator(n); + n2:=Denominator(n); + m1:=Numerator(m); + m2:=Denominator(m); + Modulo(n1*m2,m1*n2)/(n2*m2); +]; + +6 # Modulo(n_IsList,m_IsList) <-- Map("Modulo",{n,m}); +7 # Modulo(n_IsList,_m) <-- Map("Modulo",{n,FillList(m,Length(n))}); + + +30 # Modulo(n_CanBeUni,m_CanBeUni) <-- +[ + Local(vars); + vars:=VarList(n+m); + NormalForm(Modulo(MakeUni(n,vars),MakeUni(m,vars))); +]; + + +//Note:tk:moved here from univariate.rep. +0 # Modulo(n_IsUniVar,m_IsUniVar)_(Degree(n) < Degree(m)) <-- n; +1 # Modulo(n_IsUniVar,m_IsUniVar)_ + (n[1] = m[1] And Degree(n) >= Degree(m)) <-- +[ + UniVariate(n[1],0, + UniDivide(Concat(ZeroVector(n[2]),n[3]), + Concat(ZeroVector(m[2]),m[3]))[2]); +]; + +10 # Modulo(n_CanBeUni, m_CanBeUni, vars_IsList)_(Length(vars)=1) <-- +[ + NormalForm(Modulo(MakeUni(n,vars),MakeUni(m,vars))); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + +%mathpiper_docs,name="Modulo",categories="User Functions;Numbers (Operations)" +*CMD Modulo --- Determine remainder of two mathematical objects after dividing one by the other + +*STD +*CALL + Modulo(x,y) + Modulo(x,y,vars) + +*PARMS + +{x}, {y} -- integers or univariate polynomials +{vars} -- a list containing the name of the (single) variable appearing in both polynomials + +*DESC + +{Modulo} returns the remainder after division. {Modulo} is also defined for univariate polynomials. + +If {Quotient(x,y)} returns "a" and {Modulo(x,y)} equals "b", then these numbers satisfy $x =a*y + b$ and $0 <= b < y$. + +The second form of the function contains a third parameter, and is used in the special case where the +the "divisor" polynomial contains an unbound "variable" which is really just a parameter. +In that situation, MathPiper cannot distinguish the variable from the parameter, until you +specifically name the variable. See the example below. + +*E.G. + +In> Quotient(5,3) +Result: 1; +In> Modulo(5,3) +Result: 2; + +In> Modulo(x^2-5*x+2,x-1) +Result: -2 + +In> Modulo(x^2-5*x+2,x-k) +Result: x^2-5*x+2 + NOTE: answer is INCORRECT +In> Modulo(x^2-5*x+2,x-k,{x}) +Result: (k-5)*k+2 + NOTE: answer is now CORRECT + +*SEE Gcd, Lcm, Quotient +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Object.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Object.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Object.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Object.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="Object" + +Rulebase("Object",{pred,x}); +Rule("Object",2,0,Apply(pred,{x})=True) x; + +%/mathpiper + + + +%mathpiper_docs,name="Object",categories="User Functions;Variables" +*CMD Object --- create an incomplete type +*STD +*CALL + Object("pred", exp) + +*PARMS + +{pred} -- name of the predicate to apply + +{exp} -- expression on which "pred" should be applied + +*DESC + +This function returns "obj" as soon as "pred" returns {True} when applied on "obj". This is used to declare +so-called incomplete types. + +*E.G. + +In> a := Object("IsNumber", x); +Result: Object("IsNumber",x); +In> Eval(a); +Result: Object("IsNumber",x); +In> x := 5; +Result: 5; +In> Eval(a); +Result: 5; + +*SEE IsNonObject +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/om/om.mpw 2010-01-06 03:00:19.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="false" + +// From code.mpi.def: +OMDef( "Not", "logic1","not" ); +OMDef( "=" , "relation1","eq" ); +OMDef( ">=", "relation1","geq" ); +OMDef( ">" , "relation1","gt" ); +OMDef( "<=", "relation1","leq" ); +OMDef( "<" , "relation1","lt" ); +OMDef( "!=", "relation1","neq" ); +OMDef( "Gcd", "arith1","gcd" ); +OMDef( "Sqrt", "arith1","root", { $, _1, 2 }, $(_1)_(_2=2) | (_1^(1/_2)) ); +// Test [result: Sqrt(16)]: +// PipeFromString("162 ")OMRead() +// Test [result: IntNthRoot(16,3))]: +// PipeFromString("163 ")OMRead() +OMDef( "Abs", "arith1","abs" ); +OMDef( "Lcm", "arith1","lcm" ); + +OMDef( "Floor", "rounding1","floor" ); +OMDef( "Ceil" , "rounding1","ceiling" ); +OMDef( "Round", "rounding1","round" ); + +OMDef( "Quotient" , mathpiper,"div" ); +OMDef( "Modulo" , mathpiper,"mod" ); +OMDef( "Expand", mathpiper,"expand" ); +OMDef( "Object", mathpiper,"object" ); +OMDef( "Sign" , mathpiper,"sign" ); + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Quotient.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Quotient.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Quotient.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Quotient.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,66 @@ +%mathpiper,def="Quotient" + +/* Integer divisions */ +0 # Quotient(n_IsInteger,m_IsInteger) <-- QuotientN(n,m); +1 # Quotient(0 ,_m) <-- 0; +2 # Quotient(n_IsRationalOrNumber,m_IsRationalOrNumber) <-- +[ + Local(n1,n2,m1,m2,sgn1,sgn2); + n1:=Numerator(n); + n2:=Denominator(n); + m1:=Numerator(m); + m2:=Denominator(m); + sgn1 := Sign(n1*m2); + sgn2 := Sign(m1*n2); + sgn1*sgn2*Floor(DivideN(sgn1*n1*m2,sgn2*m1*n2)); +]; +30 # Quotient(n_CanBeUni,m_CanBeUni)_(Length(VarList(n*m))=1) <-- +[ + + Local(vars,nl,ml); + vars:=VarList(n*m); + nl := MakeUni(n,vars); + ml := MakeUni(m,vars); + NormalForm(Quotient(nl,ml)); +]; + + +//Note:tk:moved here from univariate.rep. +0 # Quotient(n_IsUniVar,m_IsUniVar)_(Degree(n) < Degree(m)) <-- 0; +1 # Quotient(n_IsUniVar,m_IsUniVar)_ + (n[1] = m[1] And Degree(n) >= Degree(m)) <-- +[ + UniVariate(n[1],0, + UniDivide(Concat(ZeroVector(n[2]),n[3]), + Concat(ZeroVector(m[2]),m[3]))[1]); +]; + +%/mathpiper + + +%mathpiper_docs,name="Quotient",categories="User Functions;Numbers (Operations)" +*CMD Quotient --- Determine quotient of two mathematical objects + +*STD +*CALL + Quotient(x,y) + +*PARMS + +{x}, {y} -- integers or univariate polynomials + +*DESC + +{Quotient} performs integer division. {Quotient} is also defined for polynomials. + +If {Quotient(x,y)} returns "a" and {Modulo(x,y)} equals "b", then these numbers satisfy $x =a*y + b$ and $0 <= b < y$. + +*E.G. + +In> Quotient(5,3) +Result: 1; +In> Modulo(5,3) +Result: 2; + +*SEE Gcd, Lcm, Modulo +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Rem.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Rem.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Rem.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Rem.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="Rem" + +//Note:tk:this was not listed in the def file. +0 # Rem(n_IsNumber,m_IsNumber) <-- n-m*Quotient(n,m); +30 # Rem(n_CanBeUni,m_CanBeUni) <-- Modulo(n,m); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Round.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Round.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Round.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Round.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="Round" + +5 # Round(Infinity) <-- Infinity; +5 # Round(-Infinity) <-- -Infinity; +5 # Round(Undefined) <-- Undefined; + +10 # Round(x_IsRationalOrNumber) <-- FloorN(N(x+0.5)); +10 # Round(x_IsList) <-- MapSingle("Round",x); + +20 # Round(x_IsComplex) _ (IsRationalOrNumber(Re(x)) And IsRationalOrNumber(Im(x)) ) + <-- FloorN(N(Re(x)+0.5)) + FloorN(N(Im(x)+0.5))*I; + +%/mathpiper + + + +%mathpiper_docs,name="Round",categories="User Functions;Numbers (Operations)" +*CMD Round --- round a number to the nearest integer +*STD +*CALL + Round(x) + +*PARMS + +{x} -- a number + +*DESC + +This function returns the integer closest to $x$. Half-integers +(i.e. numbers of the form $n + 0.5$, with $n$ an integer) are +rounded upwards. + +*E.G. + +In> Round(1.49) +Result: 1; +In> Round(1.51) +Result: 2; +In> Round(-1.49) +Result: -1; +In> Round(-1.51) +Result: -2; + +*SEE Floor, Ceil +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/shifting_operators.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/shifting_operators.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/shifting_operators.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/shifting_operators.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="<<;>>" + +/* def file definitions +<< +>> +*/ + +/* Shifting operators */ + +n_IsInteger << m_IsInteger <-- ShiftLeft(n,m); +n_IsInteger >> m_IsInteger <-- ShiftRight(n,m); + +%/mathpiper + + +%mathpiper_docs,name="<<;>>",categories="Operators" +*CMD << --- binary shift left operator +*CMD >> --- binary shift right operator +*STD +*CALL + n<>m + +*PARMS + +{n}, {m} -- integers + +*DESC + +These operators shift integers to the left or to the right. +They are similar to the C shift operators. These are sign-extended +shifts, so they act as multiplication or division by powers of 2. + +*E.G. + +In> 1 << 10 +Result: 1024; +In> -1024 >> 10 +Result: -1; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Sign.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Sign.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Sign.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Sign.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper,def="Sign" + +10 # Sign(n_IsPositiveNumber) <-- 1; +10 # Sign(n_IsZero) <-- 0; +20 # Sign(n_IsNumber) <-- -1; +15 # Sign(n_IsInfinity)_(n < 0) <-- -1; +15 # Sign(n_IsInfinity)_(n > 0) <-- 1; +15 # Sign(n_IsNumber/m_IsNumber) <-- Sign(n)*Sign(m); +20 # Sign(n_IsList) <-- MapSingle("Sign",n); + +100 # Sign(_a)^n_IsEven <-- 1; +100 # Sign(_a)^n_IsOdd <-- Sign(a); + +%/mathpiper + + + +%mathpiper_docs,name="Sign",categories="User Functions;Calculus Related (Symbolic)" +*CMD Sign --- sign of a number +*STD +*CALL + Sign(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function returns the sign of the real number $x$. It is "1" +for positive numbers and "-1" for negative numbers. Somewhat +arbitrarily, {Sign(0)} is defined to be 1. + +This function is connected to the {Abs} function by +the identity $Abs(x) * Sign(x) = x$ for real $x$. + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Sign(2) +Result: 1; +In> Sign(-3) +Result: -1; +In> Sign(0) +Result: 1; +In> Sign(-3) * Abs(-3) +Result: -3; + +*SEE Arg, Abs +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Sqrt.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Sqrt.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/stubs/Sqrt.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/stubs/Sqrt.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,64 @@ +%mathpiper,def="Sqrt" + +0 # Sqrt(0) <-- 0; +0 # Sqrt(Infinity) <-- Infinity; +0 # Sqrt(-Infinity) <-- Complex(0,Infinity); +0 # Sqrt(Undefined) <-- Undefined; +1 # Sqrt(x_IsPositiveInteger)_(IsInteger(SqrtN(x))) <-- SqrtN(x); +2 # Sqrt(x_IsPositiveNumber)_InNumericMode() <-- SqrtN(x); +2 # Sqrt(x_IsNegativeNumber) <-- Complex(0,Sqrt(-x)); +/* 3 # Sqrt(x_IsNumber/y_IsNumber) <-- Sqrt(x)/Sqrt(y); */ +3 # Sqrt(x_IsComplex)_InNumericMode() <-- x^(1/2); +/* Threading */ +Sqrt(xlist_IsList) <-- MapSingle("Sqrt",xlist); + +90 # (Sqrt(x_IsConstant))_(IsNegativeNumber(N(x))) <-- Complex(0,Sqrt(-x)); + +400 # x_IsRationalOrNumber * Sqrt(y_IsRationalOrNumber) <-- Sign(x)*Sqrt(x^2*y); +400 # Sqrt(y_IsRationalOrNumber) * x_IsRationalOrNumber <-- Sign(x)*Sqrt(x^2*y); +400 # x_IsRationalOrNumber / Sqrt(y_IsRationalOrNumber) <-- Sign(x)*Sqrt(x^2/y); +400 # Sqrt(y_IsRationalOrNumber) / x_IsRationalOrNumber <-- Sign(x)*Sqrt(y/(x^2)); +400 # Sqrt(y_IsRationalOrNumber) / Sqrt(x_IsRationalOrNumber) <-- Sqrt(y/x); +400 # Sqrt(y_IsRationalOrNumber) * Sqrt(x_IsRationalOrNumber) <-- Sqrt(y*x); +400 # Sqrt(x_IsInteger)_IsInteger(SqrtN(x)) <-- SqrtN(x); +400 # Sqrt(x_IsInteger/y_IsInteger)_(IsInteger(SqrtN(x)) And IsInteger(SqrtN(y))) <-- SqrtN(x)/SqrtN(y); + +%/mathpiper + + + +%mathpiper_docs,name="Sqrt",categories="User Functions;Calculus Related (Symbolic)" +*CMD Sqrt --- square root +*STD +*CALL + Sqrt(x) + +*PARMS + +{x} -- argument to the function + +*DESC + +This function calculates the square root of "x". If the result is +not rational, the call is returned unevaluated unless a numerical +approximation is forced with the {N} function. This +function can also handle negative and complex arguments. + +This function is threaded, meaning that if the argument {x} is a +list, the function is applied to all entries in the list. + +*E.G. + +In> Sqrt(16) +Result: 4; +In> Sqrt(15) +Result: Sqrt(15); +In> N(Sqrt(15)) +Result: 3.8729833462; +In> Sqrt(4/9) +Result: 2/3; +In> Sqrt(-1) +Result: Complex(0,1); + +*SEE Exp, ^, N +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/substitute/MacroSubstitute.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/substitute/MacroSubstitute.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/substitute/MacroSubstitute.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/substitute/MacroSubstitute.mpw 2011-02-05 04:04:44.000000000 +0000 @@ -0,0 +1,30 @@ +%mathpiper,def="MacroSubstitute" + +/*Extremely hacky workaround, MacroSubstitute is actually the same as Substitute, + but without re-evaluating its arguments. I could not just change Substitute, as + it changed behaviour such that tests started to break. + */ +Function("MacroSubstitute",{body,predicate,change}) +[ + `MacroSubstitute((Hold(@body))); +]; +HoldArgument("MacroSubstitute",predicate); +HoldArgument("MacroSubstitute",change); +UnFence("MacroSubstitute",3); +Rulebase("MacroSubstitute",{body}); +UnFence("MacroSubstitute",1); + +Rule("MacroSubstitute",1,1,`ApplyFast(predicate,{Hold(Hold(@body))}) = True) +[ + `ApplyFast(change,{Hold(Hold(@body))}); +]; +Rule("MacroSubstitute",1,2,`IsFunction(Hold(@body))) +[ + `ApplyFast("MacroMapArgs",{Hold(Hold(@body)),"MacroSubstitute"}); +]; +Rule("MacroSubstitute",1,3,True) +[ + `Hold(@body); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/substitute/Substitute.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/substitute/Substitute.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/substitute/Substitute.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/substitute/Substitute.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,23 @@ +%mathpiper,def="Substitute" + +Function("Substitute",{body,predicate,change}) +[ + Substitute(body); +]; +HoldArgument("Substitute",predicate); +HoldArgument("Substitute",change); +UnFence("Substitute",3); +Rulebase("Substitute",{body}); +UnFence("Substitute",1); + +Rule("Substitute",1,1,Apply(predicate,{body}) = True) +[ + Apply(change,{body}); +]; +Rule("Substitute",1,2,IsFunction(body)) +[ + Apply("MapArgs",{body,"Substitute"}); +]; +Rule("Substitute",1,3,True) body; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Add.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Add.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Add.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Add.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,45 @@ +%mathpiper,def="Add" + +Function() Add(val, ...); + +10 # Add({}) <-- 0; +20 # Add(values_IsList) <-- +[ + Local(i, sum); + sum:=0; + ForEach(i, values) [ sum := sum + i; ]; + sum; +]; + +// Add(1) should return 1 +30 # Add(_value) <-- value; + +%/mathpiper + + + +%mathpiper_docs,name="Add",categories="User Functions;Series",access="private" +*CMD Add --- find sum of a list of values +*STD +*CALL + Add(val1, val2, ...) + Add({list}) + +*PARMS + +{val1}, {val2} -- expressions + +{{list}} -- list of expressions to add + +*DESC + +This function adds all its arguments and returns their sum. It accepts any +number of arguments. The arguments can be also passed as a list. + +*E.G. + +In> Add(1,4,9); +Result: 14; +In> Add(1 .. 10); +Result: 55; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/asterisk_asterisk_asterisk_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/asterisk_asterisk_asterisk_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/asterisk_asterisk_asterisk_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/asterisk_asterisk_asterisk_operator.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,50 @@ +%mathpiper,def="***" + +/// partial factorial +n1_IsRationalOrNumber *** n2_IsRationalOrNumber <-- +[ + Check(n2-n1 <= 65535, "Argument", "Partial factorial: Error: the range " : ( PipeToString() Write(n2-n1) ) : " is too large, you may want to avoid exact calculation"); + If(n2-n1<0, + 1, + Factorial'partial(n1, n2) + ); +]; + +/// recursive routine to evaluate "partial factorial" a*(a+1)*...*b +// TODO lets document why the >>1 as used here is allowed (rounding down? What is the idea behind this algorithm?) +2# Factorial'partial(_a, _b) _ (b-a>=4) <-- Factorial'partial(a, a+((b-a)>>1)) * Factorial'partial(a+((b-a)>>1)+1, b); +3# Factorial'partial(_a, _b) _ (b-a>=3) <-- a*(a+1)*(a+2)*(a+3); +4# Factorial'partial(_a, _b) _ (b-a>=2) <-- a*(a+1)*(a+2); +5# Factorial'partial(_a, _b) _ (b-a>=1) <-- a*(a+1); +6# Factorial'partial(_a, _b) _ (b-a>=0) <-- a; +%/mathpiper + + + + +%mathpiper_docs,name="***",categories="Operators" +*CMD *** --- partial factorial operator + +*CALL + a *** b + +*PARMS +{a}, {b} -- numbers + +*DESC +The "partial factorial" function {a *** b} calculates the product $a*(a+1)*...$ +which is terminated at the least integer not greater than $b$. The arguments $a$ +and $b$ do not have to be integers; for integer arguments, {a *** b} = $b! / (a-1)!$. +This function is sometimes a lot faster than evaluating the two factorials, +especially if $a$ and $b$ are close together. If $a>b$ the function returns $1$. + +The factorial functions terminate and print an error message if the arguments are too large (currently the limit +is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably +not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision. + +*E.G. +In> 1/3 *** 10; +Result: 17041024000/59049; + +*SEE BinomialCoefficient, Product, Gamma, !, !!, Subfactorial +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Average.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Average.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Average.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Average.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not defined in scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/exclamationpoint_exclamationpoint_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/exclamationpoint_exclamationpoint_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/exclamationpoint_exclamationpoint_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/exclamationpoint_exclamationpoint_operator.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="!!" + +/// even/odd double factorial: product of even or odd integers up to n +1# (n_IsPositiveInteger)!! _ (n<=3) <-- n; +2# (n_IsPositiveInteger)!! <-- +[ + Check(n<=65535, "Argument", "Double factorial: Error: the argument " : ( PipeToString() Write(n) ) : " is too large, you may want to avoid exact calculation"); + Factorial'double(2+Modulo(n, 2), n); +]; +// special cases +3# (_n)!! _ (n= -1 Or n=0)<-- 1; + +// the purpose of this mess "Quotient(a+b,2)+1+Modulo(Quotient(a+b,2)+1-a, 2)" is to obtain the smallest integer which is >= Quotient(a+b,2)+1 and is also odd or even when a is odd or even; we need to add at most 1 to (Quotient(a+b,2)+1) +2# Factorial'double(_a, _b) _ (b-a>=6) <-- Factorial'double(a, Quotient(a+b,2)) * Factorial'double(Quotient(a+b,2)+1+Modulo(Quotient(a+b,2)+1-a, 2), b); +3# Factorial'double(_a, _b) _ (b-a>=4) <-- a*(a+2)*(a+4); +4# Factorial'double(_a, _b) _ (b-a>=2) <-- a*(a+2); +5# Factorial'double(_a, _b) <-- a; + +/// double factorial for lists is threaded +30 # (n_IsList)!! <-- MapSingle("!!",n); + +%/mathpiper + + + +%mathpiper_docs,name="!!",categories="Operators" +*CMD !! --- double factorial operator + +*CALL + n!! + +*PARMS +{n} -- integer, half-integer, or list + +*DESC +The "double factorial" function {n!!} calculates $n*(n-2)*(n-4)*...$. +This product terminates either with $1$ or with $2$ depending on +whether $n$ is odd or even. If $n=0$ the function returns $1$. + +The factorial functions are threaded, meaning that if the argument {n} is a +list, the function will be applied to each element of the list. + +The factorial functions terminate and print an error message if the arguments are too large (currently the limit +is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably +not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision. +*E.G. +In> 7!!; +Result: 105; + +*SEE BinomialCoefficient, Product, Gamma, !, ***, Subfactorial +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/exclamationpoint_operator.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/exclamationpoint_operator.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/exclamationpoint_operator.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/exclamationpoint_operator.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,85 @@ +%mathpiper,def="!" + +/* Factorials */ + +10 # 0! <-- 1; +10 # (Infinity)! <-- Infinity; +20 # ((n_IsPositiveInteger)!) <-- [ + Check(n <= 65535, "Argument", "Factorial: Error: the argument " : ( PipeToString() Write(n) ) : " is too large, you may want to avoid exact calculation"); + MathFac(n); +]; + +25 # ((x_IsConstant)!)_(FloatIsInt(x) And x>0) <-- (Round(x)!); + +30 # ((x_IsNumber)!)_InNumericMode() <-- Internal'GammaNum(x+1); + +40 # (n_IsList)! <-- MapSingle("!",n); + +/* formulae for half-integer factorials: + +(+(2*z+1)/2)! = Sqrt(Pi)*(2*z+1)! / (2^(2*z+1)*z!) for z >= 0 +(-(2*z+1)/2)! = Sqrt(Pi)*(-1)^z*z!*2^(2*z) / (2*z)! for z >= 0 + +Double factorials are more efficient: + (2*n-1)!! := 1*3*...*(2*n-1) = (2*n)! / (2^n*n!) + (2*n)!! := 2*4*...*(2*n) = 2^n*n! + +*/ +/* // old version - not using double factorials +HalfIntegerFactorial(n_IsOdd) _ (n>0) <-- + Sqrt(Pi) * ( n! / ( 2^n*((n-1)/2)! ) ); +HalfIntegerFactorial(n_IsOdd) _ (n<0) <-- + Sqrt(Pi) * ( (-1)^((-n-1)/2)*2^(-n-1)*((-n-1)/2)! / (-n-1)! ); +*/ +// new version using double factorials +HalfIntegerFactorial(n_IsOdd) _ (n>0) <-- + Sqrt(Pi) * ( n!! / 2^((n+1)/2) ); +HalfIntegerFactorial(n_IsOdd) _ (n<0) <-- + Sqrt(Pi) * ( (-1)^((-n-1)/2)*2^((-n-1)/2) / (-n-2)!! ); +//HalfIntegerFactorial(n_IsOdd) _ (n= -1) <-- Sqrt(Pi); + +/* Want to also compute (2.5)! */ +40 # (n_IsRationalOrNumber)! _(Denominator(Rationalize(n))=2) <-- HalfIntegerFactorial(Numerator(Rationalize(n))); + + +%/mathpiper + + + +%mathpiper_docs,name="!",categories="Operators" +*CMD ! --- factorial + +*CALL + n! + n!! + +*PARMS +{n} -- integer, half-integer, or list + +*DESC +The factorial function {n!} calculates the factorial of integer or half-integer numbers. For +nonnegative integers, $n! := n*(n-1)*(n-2)*...*1$. The factorial of +half-integers is defined via Euler's Gamma function, $z! := Gamma(z+1)$. If $n=0$ the function returns $1$. + +The factorial functions are threaded, meaning that if the argument {n} is a +list, the function will be applied to each element of the list. + +Note: For reasons of MathPiper syntax, the factorial sign {!} cannot precede other +non-letter symbols such as {+} or {*}. Therefore, you should enter a space +after {!} in expressions such as {x! +1}. + +The factorial functions terminate and print an error message if the arguments are too large (currently the limit +is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably +not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision. + +*E.G. + +In> 5! +Result: 120; +In> 1 * 2 * 3 * 4 * 5 +Result: 120; +In> (1/2)! +Result: Sqrt(Pi)/2; + +*SEE BinomialCoefficient, Product, Gamma, !!, ***, Subfactorial +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Maximum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Maximum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Maximum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Maximum.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,80 @@ +%mathpiper,def="Maximum" + +/* this is disabled because some functions seem to implicitly define Min / Max with a different number of args, and then MathPiper is confused if it hasn't loaded all the Function() declarations beforehand. +FIXME +/// Min, Max with many arguments +*/ + +//Retract("Maximum", 1); +//Retract("Maximum", 2); +//Retract("Maximum", 3); + +//Function() Maximum(list); + +//Function() Maximum(l1, l2); + +Function() Maximum(l1, l2, l3, ...); + + + +10 # Maximum(_l1, _l2, l3_IsList) <-- Maximum(Concat({l1, l2}, l3)); +20 # Maximum(_l1, _l2, _l3) <-- Maximum({l1, l2, l3}); +/**/ + +10 # Maximum(l1_IsList,l2_IsList) <-- Map("Maximum",{l1,l2}); + + +20 # Maximum(l1_IsRationalOrNumber,l2_IsRationalOrNumber) <-- If(l1>l2,l1,l2); + + +30 # Maximum(l1_IsConstant,l2_IsConstant) <-- If(N(Eval(l1-l2))>0,l1,l2); + +// Max on empty lists +10 # Maximum({}) <-- Undefined; + + +20 # Maximum(list_IsList) <-- +[ + Local(result); + result:= list[1]; + ForEach(item,Rest(list)) result:=Maximum(result,item); + result; +]; + + +30 # Maximum(_x) <-- x; + +%/mathpiper + + + +%mathpiper_docs,name="Maximum",categories="User Functions;Numbers (Operations)" +*CMD Maximum --- maximum of a number of values +*STD +*CALL + Maximum(x,y) + Maximum(list) + +*PARMS + +{x}, {y} -- pair of values to determine the maximum of + +{list} -- list of values from which the maximum is sought + +*DESC + +This function returns the maximum value of its argument(s). If the +first calling sequence is used, the larger of "x" and "y" is +returned. If one uses the second form, the largest of the entries in +"list" is returned. In both cases, this function can only be used +with numerical values and not with symbolic arguments. + +*E.G. + +In> Maximum(2,3); +Result: 3; +In> Maximum({5,8,4}); +Result: 8; + +*SEE Minimum, Sum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Minimum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Minimum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Minimum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Minimum.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,74 @@ +%mathpiper,def="Minimum" + +/* this is disabled because some functions seem to implicitly define Min / Max with a different number of args, +and then MathPiper is confused if it hasn't loaded all the Function() declarations beforehand. +FIXME +/// Min, Max with many arguments +*/ + +//Retract("Minimum", 1); +//Retract("Minimum", 2); +//Retract("Minimum", 3); + +//Function() Minimum(list); + +//Function() Minimum(l1, l2) + +Function() Minimum(l1, l2, l3, ...); + +10 # Minimum(_l1, _l2, l3_IsList) <-- Minimum(Concat({l1, l2}, l3)); +20 # Minimum(_l1, _l2, _l3) <-- Minimum({l1, l2, l3}); + +10 # Minimum(l1_IsList,l2_IsList) <-- Map("Minimum",{l1,l2}); + +20 # Minimum(l1_IsRationalOrNumber,l2_IsRationalOrNumber) <-- If(l1 Minimum(2,3); +Result: 2; +In> Minimum({5,8,4}); +Result: 4; + +*SEE Maximum, Sum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/om/om.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/om/om.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/om/om.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/om/om.mpw 2010-01-06 01:59:24.000000000 +0000 @@ -0,0 +1,30 @@ +%mathpiper,def="" + +// From code.mpi.def: +// [2005-12-28 matmota]: I have to implement some better solution for the +// MathPiper -> OM mapping for these symbols. +OMDef( "Minimum", "minmax1","min", + { "", "", + 1,2,3,4,5,6,7,8,9,10,11,12,13,14, + "", "" }, + ($):_1 ); +OMDef( "Maximum", "minmax1","max", + { "", "", + 1,2,3,4,5,6,7,8,9,10,11,12,13,14, + "", "" }, + ($):_1 ); +OMDef( "!", "integer1","factorial" ); +OMDef( "BinomialCoefficient", "combinat1","binomial" ); +OMDef( "!!", mathpiper,"double_factorial" ); +OMDef( "***", mathpiper,"partial_factorial" ); +OMDef( "Add", mathpiper,"Add" ); +OMDef( "Sum", "arith1","sum", // Same argument reordering as Integrate. + { $, _2 .. _3, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }, + { $, _{2,2,1}, _{1,1}, _{1,2}, _{2,3} } + ); +OMDef( "Product", mathpiper,"Product" ); +OMDef( "Taylor", mathpiper,"Taylor" ); +OMDef( "Subfactorial", mathpiper,"Subfactorial" ); + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Product.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Product.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Product.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Product.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,72 @@ +%mathpiper,def="Product" + +Function("Product",{sumvar,sumfrom,sumto,sumbody}) +[ + Local(sumi,sumsum); + sumsum:=1; + For(sumi:=sumfrom,sumi<=sumto And sumsum!=0,sumi++) + [ + MacroLocal(sumvar); + MacroBind(sumvar,sumi); + sumsum:=sumsum*Eval(sumbody); + ]; + sumsum; +]; +UnFence("Product",4); +HoldArgument("Product",sumvar); +HoldArgument("Product",sumbody); + +Product(sumlist_IsList) <-- +[ + Local(sumi,sumsum); + sumsum:=1; + ForEach(sumi,sumlist) + [ + sumsum:=sumsum*sumi; + ]; + sumsum; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Product",categories="User Functions;Series" +*CMD Product --- product of a list of values +*STD +*CALL + Product(list) + Product(var, from, to, body) + +*PARMS + +{list} -- list of values to multiply + +{var} -- variable to iterate over + +{from} -- integer value to iterate from + +{to} -- integer value to iterate up to + +{body} -- expression to evaluate for each iteration + +*DESC + +The first form of the {Product} command simply +multiplies all the entries in "list" and returns their product. + +If the second calling sequence is used, the expression "body" is +evaluated while the variable "var" ranges over all integers from +"from" up to "to", and the product of all the results is +returned. Obviously, "to" should be greater than or equal to +"from". + +*E.G. + +In> Product({1,2,3,4}); +Result: 24; +In> Product(i, 1, 4, i); +Result: 24; + +*SEE Sum, Apply +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Subfactorial.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Subfactorial.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Subfactorial.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Subfactorial.mpw 2010-08-10 03:10:33.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,def="Subfactorial" + +Function("Subfactorial",{n}) +[ + n! * Sum(k,0,n,(-1)^(k)/k!); +]; + +30 # Subfactorial(n_IsList) <-- MapSingle("Subfactorial",n); + +%/mathpiper + + + +%mathpiper_docs,name="Subfactorial",categories="User Functions;Combinatorics" +*CMD Subfactorial --- factorial and related functions +*CALL + Subfactorial(m) + +*PARMS +{m} -- integer + +*DESC +The {Subfactorial} function can be interpreted as the number of permutations of {m} objects in which no object +appears in its natural place, also called "derangements." + +The factorial functions terminate and print an error message if the arguments are too large (currently the limit +is $n < 65535$) because exact factorials of such large numbers are computationally expensive and most probably +not useful. One can call {Internal'LnGammaNum()} to evaluate logarithms of such factorials to desired precision. + +*E.G. +In> Subfactorial(10) +Result: 1334961; + +*SEE BinomialCoefficient, Product, Gamma, ,! !!, ***, +%/mathpiper_docs + + %output,preserve="false" + +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/SumFunc.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/SumFunc.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/SumFunc.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/SumFunc.mpw 2011-04-17 11:52:17.000000000 +0000 @@ -0,0 +1,92 @@ +%mathpiper,def="SumFunc" + +LocalSymbols(c,d,expr,from,to,summand,sum,predicate,n,r,var,x) [ + +// Attempt to Sum series + +Function() SumFunc(k,from,to,summand, sum, predicate ); +Function() SumFunc(k,from,to,summand, sum); +HoldArgument(SumFunc,predicate); +HoldArgument(SumFunc,sum); +HoldArgument(SumFunc,summand); + +// Difference code does not work +SumFunc(_sumvar,sumfrom_IsInteger,_sumto,_sumbody,_sum) <-- +[ + // Take the given answer and create 2 rules, one for an exact match + // for sumfrom, and one which will catch sums starting at a different + // index and subtract off the difference + + `(40 # Sum(@sumvar,@sumfrom,@sumto,@sumbody ) <-- Eval(@sum) ); + `(41 # Sum(@sumvar,p_IsInteger,@sumto,@sumbody)_(p > @sumfrom) + <-- + [ + Local(sub); + (sub := Eval(ListToFunction({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg}))); + Simplify(Eval(@sum) - sub ); + ]); +]; + +SumFunc(_sumvar,sumfrom_IsInteger,_sumto,_sumbody,_sum,_condition) <-- +[ + + `(40 # Sum(@sumvar,@sumfrom,@sumto,@sumbody)_(@condition) <-- Eval(@sum) ); + `(41 # Sum(@sumvar,p_IsInteger,@sumto,@sumbody )_(@condition And p > @sumfrom) + <-- + [ + Local(sub); + `(sub := Eval(ListToFunction({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg}))); + Simplify(Eval(@sum) - sub ); + ]); +]; + +// Some type of canonical form is needed so that these match when +// given in a different order, like x^k/k! vs. (1/k!)*x^k +// works ! +SumFunc(_k,1,_n,_c + _d, + Eval(ListToFunction({Sum,sumvar'arg,1,n,c})) + + Eval(ListToFunction({Sum,sumvar'arg,1,n,d})) +); +SumFunc(_k,1,_n,_c*_expr,Eval(c*ListToFunction({Sum,sumvar'arg,1,n,expr})), IsFreeOf(k,c) ); +SumFunc(_k,1,_n,_expr/_c,Eval(ListToFunction({Sum,sumvar'arg,1,n,expr})/c), IsFreeOf(k,c) ); + +// this only works when the index=1 +// If the limit of the general term is not zero, then the series diverges +// We need something like IsUndefined(term), because this croaks when limit return Undefined +//SumFunc(_k,1,Infinity,_expr,Infinity,Eval(Abs(ListToFunction({Limit,sumvar'arg,Infinity,expr})) > 0)); +SumFunc(_k,1,Infinity,1/_k,Infinity); + +SumFunc(_k,1,_n,_c,c*n,IsFreeOf(k,c) ); +SumFunc(_k,1,_n,_k, n*(n+1)/2 ); +//SumFunc(_k,1,_n,_k^2, n*(n+1)*(2*n+1)/6 ); +//SumFunc(_k,1,_n,_k^3, (n*(n+1))^2 / 4 ); +SumFunc(_k,1,_n,_k^_p,(Bernoulli(p+1,n+1) - Bernoulli(p+1))/(p+1), IsInteger(p) ); +SumFunc(_k,1,_n,2*_k-1, n^2 ); +SumFunc(_k,1,_n,HarmonicNumber(_k),(n+1)*HarmonicNumber(n) - n ); + +// Geometric series! The simplest of them all ;-) +SumFunc(_k,0,_n,(r_IsFreeOf(k))^(_k), (1-r^(n+1))/(1-r) ); + +// Infinite Series +// this allows Zeta a complex argument, which is not supported yet +SumFunc(_k,1,Infinity,1/(_k^_d), Zeta(d), IsFreeOf(k,d) ); +SumFunc(_k,1,Infinity,_k^(-_d), Zeta(d), IsFreeOf(k,d) ); + +SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1)!,Sinh(x) ); +SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k+1)/(2*_k+1)!,Sin(x) ); +SumFunc(_k,0,Infinity,_x^(2*_k)/(2*_k)!,Cosh(x) ); +SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k)/(2*_k)!,Cos(x) ); +SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1),ArcTanh(x) ); +SumFunc(_k,0,Infinity,1/(_k)!,Exp(1) ); +SumFunc(_k,0,Infinity,_x^_k/(_k)!,Exp(x) ); +40 # Sum(_var,_from,Infinity,_expr)_( `(Limit(@var,Infinity)(@expr)) = Infinity) <-- Infinity; + +SumFunc(_k,1,Infinity,1/BinomialCoefficient(2*_k,_k), (2*Pi*Sqrt(3)+9)/27 ); +SumFunc(_k,1,Infinity,1/(_k*BinomialCoefficient(2*_k,_k)), (Pi*Sqrt(3))/9 ); +SumFunc(_k,1,Infinity,1/(_k^2*BinomialCoefficient(2*_k,_k)), Zeta(2)/3 ); +SumFunc(_k,1,Infinity,1/(_k^3*BinomialCoefficient(2*_k,_k)), 17*Zeta(4)/36 ); +SumFunc(_k,1,Infinity,(-1)^(_k-1)/_k, Ln(2) ); + +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Sum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Sum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Sum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Sum.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,94 @@ +%mathpiper,def="Sum" + +/* Sums */ + + +Rulebase("Sum",{sumvar'arg,sumfrom'arg,sumto'arg,sumbody'arg}); + + + + +10 # Sum(_sumvar,sumfrom_IsNumber,sumto_IsNumber,_sumbody)_(sumfrom>sumto) <-- 0; + +20 # Sum(_sumvar,sumfrom_IsNumber,sumto_IsNumber,_sumbody)_(sumto Sum({1,2,3}) +Result> 6 + +In> Sum(1 .. 10); +Result: 55; + +In> Sum(i, 1, 3, i^2); +Result: 14; + +*SEE Product +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Taylor2.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Taylor2.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Taylor2.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Taylor2.mpw 2010-12-16 01:32:55.000000000 +0000 @@ -0,0 +1,803 @@ +%mathpiper,def="Taylor2" + +/* + * Taylor(x,a,n) y --- ENTRY POINT + * ~~~~~~~~~~~~~~~ + * The n-th degree Taylor polynomial of y around x=a + * + * This function is implemented by doing calculus on power series. For + * instance, the Taylor series of Sin(x)^2 around x=0 is computed as + * follows. First, we look up the series for Sin(x) + * Sin(x) = x - 1/6 x^3 + 1/120 x^5 - 1/5040 x^7 + ... + * and then we compute the square of this series + * Sin(x)^2 = x^2 - x^4/3 + 2/45 x^6 - 1/315 x^8 + ... + * + * An alternative method is to use the formula + * Taylor(x,a,n) y = \sum_{k=0}^n 1/k! a_k x^k, + * where a_k is the k-th order derivative of y with respect to x, + * evaluated at x=a. In fact, the old implementation of "Taylor", which + * is retained in obsolete.mpi, uses this method. However, we found out + * that the expressions for the derivatives often grow very large, which + * makes the computation too slow. + * + * The power series are implemented as lazy power series, which means + * that the coefficients are computed on demand. Lazy power series are + * encapsulated in expressions of the form + * Taylor'LPS(order, coeffs, var, expr). + * This represent the power series of "expr", seen as a function of + * "var". "coeffs" is list of coefficients that have been computed thus + * far. The integer "order" is the order of the first coefficient. + * + * For instance, the expression + * Taylor'LPS(1, {1,0,-1/6,0}, x, Sin(x)) + * contains the power series of Sin(x), viewed as a function of x, where + * the four coefficients corresponding to x, x^2, x^3, and x^4 have been + * computed. One can view this expression as x - 1/6 x^3 + O(x^5). + * + * "coeffs" is the empty list in the following special cases: + * 1) order = Infinity represents the zero power series + * 2) order = Undefined represents a power series of which no + * coefficients have yet been computed. + * 3) order = n represents a power series of order at least n, + * of which no coefficients have yet been computed. + * + * "expr" may contain subexpressions of the form + * Taylor'LPS'Add(lps1, lps2) = lps1)x) + lps2(x) + * Taylor'LPS'ScalarMult(a, lps) = a*lps(x) (a is scalar) + * Taylor'LPS'Multiply(lps1, lps2) = lps1(x) * lps2(x) + * Taylor'LPS'Inverse(lps) = 1/lps(x) + * Taylor'LPS'Power(lps, n) = lps(x)^n (n is natural number) + * Taylor'LPS'Compose(lps1, lps2) = lps1(lps2(x)) + * + * A well-formed LPS is an expression of the form + * Taylor'LPS(order, coeffs, var, expr) + * satisfying the following conditions: + * 1) order is an integer, Infinity, or Undefined; + * 2) coeffs is a list; + * 3) if order is Infinity or Undefined, then coeffs is {}; + * 4) if order is an integer, then coeffs is empty + * or its first entry is nonzero; + * 5) var does not appear in coeffs; + * 6) expr is normalized with Taylor'LPS'NormalizeExpr. + * + */ + +/* For the moment, the function is called Taylor2. */ + +/* HELP: Is this the correct mechanism to signal incorrect input? */ +/*COMMENT FROM AYAL: Formally, I would do it the other way around, although this is more efficient. This + scheme says: all following rules hold if n>=0. Ideally you'd have a rule "this transformation rule holds + if n>=0". But then you would end up checking that n>=0 for each transformation rule, making things a little + bit slower (but more correct, more elegant). + */ +10 # (Taylor2(_x, _a, _n) _y) + _ (Not(IsPositiveInteger(n) Or IsZero(n))) + <-- Check(False, "Argument", "Third argument to Taylor should be a nonnegative integer"); + +20 # (Taylor2(_x, 0, _n) _y) <-- +[ + Local(res); + res := Taylor'LPS'PowerSeries(Taylor'LPS'Construct(x, y), n, x); + If (ClearError("singularity"), + Echo(y, "has a singularity at", x, "= 0.")); + If (ClearError("dunno"), + Echo("Cannot determine power series of", y)); + res; +]; + +30 # (Taylor2(_x, _a, _n) _y) + <-- Subst(x,x-a) Taylor2(x,0,n) Subst(x,x+a) y; + +/********************************************************************** + * + * Parameters + * ~~~~~~~~~~ + * The number of coefficients to be computed before concluding that a + * given power series is zero */ + + + +/*TODO COMMENT FROM AYAL: This parameter, 15, seems to be a bit arbitrary. This implies that there is an input + with more than 15 zeroes, and then a non-zero coefficient, that this would fail on. Correct? Is there not + a more accurate estimation of this parameter? + */ +Taylor'LPS'Param1() := 15; + +/********************************************************************** + * + * Taylor'LPS'Construct(var, expr) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * construct a LPS + * PRE: var is a name + * POST: returns a well-formed LPS + */ + +10 # Taylor'LPS'Construct(_var, _expr) + <-- Taylor'LPS(Undefined, {}, var, + Taylor'LPS'NormalizeExpr(var, expr)); + +/********************************************************************** + * + * Taylor'LPS'Coeffs(lps, n1, n2) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * List of coefficients of order n1 up to n2 + * PRE: lps is a well-formed LPS, n1 in Z, n2 in Z, n2 >= n1 + * POST: returns list of length n2-n1+1, + * or raises "dunno", "div-by-zero", or "maybe-div-by-zero" + * lps may be changed, but it's still a well-formed LPS + */ + +Taylor'LPS'Coeffs(_lps, _n1, _n2) <-- +[ + Local(res, finished, order, j, k, n, tmp, c1, c2); + finished := False; + + /* Case 1: Zero power series */ + + If (lps[1] = Infinity, + [ + res := FillList(0, n2-n1+1); + finished := True; + ]); + + /* Case 2: Coefficients are already computed */ + + If (Not finished And lps[1] != Undefined And n2 < lps[1]+Length(lps[2]), + [ + If (n1 >= lps[1], + res := Take(lps[2], {n1-lps[1]+1, n2-lps[1]+1}), + If (n2 >= lps[1], + res := Concat(FillList(0, lps[1]-n1), + Take(lps[2], n2-lps[1]+1)), + res := FillList(0, n2-n1+1))); + finished := True; + ]); + + /* Case 3: We need to compute the coefficients */ + + If (Not finished, + [ + /* Subcase 3a: Expression is recognized by Taylor'LPS'CompOrder */ + + order := Taylor'LPS'CompOrder(lps[3], lps[4]); + If (Not ClearError("dunno"), + [ + If (lps[1] = Undefined, + [ + lps[1] := order; + If (order <= n2, + [ + lps[2] := Table(Taylor'LPS'CompCoeff(lps[3], lps[4], n), + n, order, n2, 1); + ]); + ],[ + tmp := Table(Taylor'LPS'CompCoeff(lps[3], lps[4], n), + n, lps[1]+Length(lps[2]), n2, 1); + lps[2] := Concat(lps[2], tmp); + ]); + finished := True; + ]); + + /* Subcase 3b: Addition */ + + If (Not finished And lps[4][0] = Taylor'LPS'Add, + [ + lps[1] := Minimum(Taylor'LPS'GetOrder(lps[4][1])[1], + Taylor'LPS'GetOrder(lps[4][2])[1], n2); + If (IsError("dunno"), + [ + ClearError("dunno"); + ClearError("dunno"); + ],[ + If (lps[1] <= n2, + [ + c1 := Taylor'LPS'Coeffs(lps[4][1], lps[1] + Length(lps[2]), n2); + c2 := Taylor'LPS'Coeffs(lps[4][2], lps[1] + Length(lps[2]), n2); + lps[2] := Concat(lps[2], c1 + c2); + ]); + finished := True; + ]); + ]); + + /* Subcase 3c: Scalar multiplication */ + + If (Not finished And lps[4][0] = Taylor'LPS'ScalarMult, + [ + lps[1] := Minimum(Taylor'LPS'GetOrder(lps[4][2])[1], n2); + If (Not ClearError("dunno"), + [ + If (lps[1] <= n2, + [ + tmp := Taylor'LPS'Coeffs(lps[4][2], + lps[1] + Length(lps[2]), n2); + tmp := lps[4][1] * tmp; + lps[2] := Concat(lps[2], tmp); + ]); + finished := True; + ]); + ]); + + /* Subcase 3d: Multiplication */ + + If (Not finished And lps[4][0] = Taylor'LPS'Multiply, + [ + lps[1] := Taylor'LPS'GetOrder(lps[4][1])[1] + + Taylor'LPS'GetOrder(lps[4][2])[1]; + If (IsError("dunno"), + [ + ClearError("dunno"); + ClearError("dunno"); + ],[ + If (lps[1] <= n2, + [ + c1 := Taylor'LPS'Coeffs(lps[4][1], lps[4][1][1], + n2 - lps[4][2][1]); + c2 := Taylor'LPS'Coeffs(lps[4][2], lps[4][2][1], + n2 - lps[4][1][1]); + tmp := lps[2]; + ForEach(k, (Length(lps[2])+1) .. Length(c1)) + tmp := Append(tmp, Sum(j, 1, k, c1[j]*c2[k+1-j])); + lps[2] := tmp; + ]); + finished := True; + ]); + ]); + + /* Subcase 3e: Inversion */ + + If (Not finished And lps[4][0] = Taylor'LPS'Inverse, + [ + If (lps[4][1][1] = Infinity, + [ + Assert("div-by-zero") False; + finished := True; + ]); + If (Not finished And lps[2] = {}, + [ + order := Taylor'LPS'GetOrder(lps[4][1])[1]; + n := order; + c1 := Taylor'LPS'Coeffs(lps[4][1], n, n)[1]; + While (c1 = 0 And n < order + Taylor'LPS'Param1()) + [ + n := n + 1; + c1 := Taylor'LPS'Coeffs(lps[4][1], n, n)[1]; + ]; + If (c1 = 0, + [ + Assert("maybe-div-by-zero") False; + finished := True; + ]); + ]); + If (Not finished, + [ + lps[1] := -lps[4][1][1]; + c1 := Taylor'LPS'Coeffs(lps[4][1], lps[4][1][1], + lps[4][1][1]+n2-lps[1]); + tmp := lps[2]; + If (tmp = {}, tmp := {1/c1[1]}); + If (Length(c1)>1, + [ + ForEach(k, (Length(tmp)+1) .. Length(c1)) + [ + n := -Sum(j, 1, k-1, c1[k+1-j]*tmp[j]) / c1[1]; + tmp := Append(tmp, n); + ]; + ]); + lps[2] := tmp; + finished := True; + ]); + ]); + + /* Subcase 3f: Composition */ + + If (Not finished And lps[4][0] = Taylor'LPS'Compose, + [ + j := Taylor'LPS'GetOrder(lps[4][1])[1]; + Check(j >= 0, "Math", "Expansion of f(g(x)) where f has a" + : "singularity is not implemented"); + k := Taylor'LPS'GetOrder(lps[4][2])[1]; + c1 := {j, Taylor'LPS'Coeffs(lps[4][1], j, n2)}; + c2 := {k, Taylor'LPS'Coeffs(lps[4][2], k, n2)}; + c1 := Taylor'TPS'Compose(c1, c2); + lps[1] := c1[1]; + lps[2] := c1[2]; + finished := True; + ]); + + /* Case 3: The end */ + + If (finished, + [ + /* normalization: remove initial zeros from lps[2] */ + + While (lps[2] != {} And lps[2][1] = 0) + [ + lps[1] := lps[1] + 1; + lps[2] := Rest(lps[2]); + ]; + + /* get result */ + + If (Not IsError("dunno") And Not IsError("div-by-zero") + And Not IsError("maybe-div-by-zero"), + [ + If (lps[1] <= n1, + res := Take(lps[2], {n1-lps[1]+1, n2-lps[1]+1}), + If (lps[1] <= n2, + res := Concat(FillList(0, lps[1]-n1), lps[2]), + res := FillList(0, n2-n1+1))); + ]); + ],[ + Assert("dunno") False; + res := False; + ]); + ]); + + /* Return res */ + + res; +]; + + +/********************************************************************** + * + * Truncated power series + * ~~~~~~~~~~~~~~~~~~~~~~ + * Here is the start of an implementation of truncated power series. + * This should be cleaned up. + * + * {n, {a0,a1,a2,a3,...}} represents + * a0 x^n + a1 x^(n+1) + a2 x^(n+2) + a3 x^(n+3) + ... + * + * The function Taylor'TPS'Add(tps1, tps2) adds two of such beasts, + * and returns the sum in the same truncated power series form. + * Similar for the other functions. + */ + +10 # Taylor'TPS'GetCoeff({_n,_c}, _k) _ (k < n) <-- 0; +10 # Taylor'TPS'GetCoeff({_n,_c}, _k) _ (k >= n+Length(c)) <-- Undefined; +20 # Taylor'TPS'GetCoeff({_n,_c}, _k) <-- c[k-n+1]; + + +10 # Taylor'TPS'Add({_n1,_c1}, {_n2,_c2}) <-- +[ + Local(n, len, c1b, c2b); + n := Minimum(n1,n2); + len := Minimum(n1+Length(c1), n2+Length(c2)) - n; + c1b := Take(Concat(FillList(0, n1-n), c1), len); + c2b := Take(Concat(FillList(0, n2-n), c2), len); + {n, c1b+c2b}; +]; + +10 # Taylor'TPS'ScalarMult(_a, {_n2,_c2}) <-- {n2, a*c2}; + +10 # Taylor'TPS'Multiply({_n1,_c1}, {_n2,_c2}) <-- +[ + Local(j,k,c); + c := {}; + For (k:=1, k<=Minimum(Length(c1), Length(c2)), k++) + [ + c := c : Sum(j, 1, k, c1[j]*c2[k+1-j]); + ]; + {n1+n2, c}; +]; + +10 # Taylor'TPS'Compose({_n1,_c1}, {_n2,_c2}) <-- +[ + Local(res, tps, tps2, k, n); + n := Minimum(n1+Length(c1)-1, n2+Length(c2)-1); + tps := {0, 1 : FillList(0, n)}; // tps = {n2,c2} ^ k + res := Taylor'TPS'ScalarMult(Taylor'TPS'GetCoeff({n1,c1}, 0), tps); + For (k:=1, k<=n, k++) + [ + tps := Taylor'TPS'Multiply(tps, {n2,c2}); + tps2 := Taylor'TPS'ScalarMult(Taylor'TPS'GetCoeff({n1,c1}, k), tps); + res := Taylor'TPS'Add(res, tps2); + ]; + res; +]; + + + +/********************************************************************** + * + * Taylor'LPS'NormalizeExpr(var, expr) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Return expr, with "+" replaced by Taylor'LPS'Add, etc. + * PRE: var is a name + */ + +5 # Taylor'LPS'NormalizeExpr(_var, _e1) + _ [Taylor'LPS'CompOrder(var,e1); Not ClearError("dunno");] + <-- e1; + +10 # Taylor'LPS'NormalizeExpr(_var, _e1 + _e2) + <-- Taylor'LPS'Add(Taylor'LPS'Construct(var, e1), + Taylor'LPS'Construct(var, e2)); + +10 # Taylor'LPS'NormalizeExpr(_var, - _e1) + <-- Taylor'LPS'ScalarMult(-1, Taylor'LPS'Construct(var, e1)); + +10 # Taylor'LPS'NormalizeExpr(_var, _e1 - _e2) + <-- (Taylor'LPS'Add(Taylor'LPS'Construct(var, e1), + Taylor'LPS'Construct(var, e3)) + Where e3 == Taylor'LPS'ScalarMult(-1, Taylor'LPS'Construct(var, e2))); + +10 # Taylor'LPS'NormalizeExpr(_var, e1_IsFreeOf(var) * _e2) + <-- Taylor'LPS'ScalarMult(e1, Taylor'LPS'Construct(var, e2)); + +10 # Taylor'LPS'NormalizeExpr(_var, _e1 * e2_IsFreeOf(var)) + <-- Taylor'LPS'ScalarMult(e2, Taylor'LPS'Construct(var, e1)); + +20 # Taylor'LPS'NormalizeExpr(_var, _e1 * _e2) + <-- Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), + Taylor'LPS'Construct(var, e2)); + +10 # Taylor'LPS'NormalizeExpr(_var, _e1 / e2_IsFreeOf(var)) + <-- Taylor'LPS'ScalarMult(1/e2, Taylor'LPS'Construct(var, e1)); + +20 # Taylor'LPS'NormalizeExpr(_var, 1 / _e1) + <-- Taylor'LPS'Inverse(Taylor'LPS'Construct(var, e1)); + +30 # Taylor'LPS'NormalizeExpr(_var, _e1 / _e2) + <-- (Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), + Taylor'LPS'Construct(var, e3)) + Where e3 == Taylor'LPS'Inverse(Taylor'LPS'Construct(var, e2))); + +/* Implement powers as repeated multiplication, + * which is seriously inefficient. + */ +10 # Taylor'LPS'NormalizeExpr(_var, _e1 ^ (n_IsPositiveInteger)) + _ (e1 != var) + <-- Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), + Taylor'LPS'Construct(var, e1^(n-1))); + +10 # Taylor'LPS'NormalizeExpr(_var, Tan(_x)) + <-- (Taylor'LPS'Multiply(Taylor'LPS'Construct(var, Sin(x)), + Taylor'LPS'Construct(var, e3)) + Where e3 == Taylor'LPS'Inverse(Taylor'LPS'Construct(var, Cos(x)))); + +LocalSymbols(res) +[ +50 # Taylor'LPS'NormalizeExpr(_var, _e1) +_[ + Local(c, lps1, lps2, lps3, success); + success := True; + If (IsAtom(e1), success := False); + If (success And Length(e1) != 1, success := False); + If (success And IsAtom(e1[1]), success := False); + If (success And CanBeUni(var, e1[1]) And Degree(e1[1], var) = 1, + [ + success := False; + ]); + If (success, + [ + lps2 := Taylor'LPS'Construct(var, e1[1]); + c := Taylor'LPS'Coeffs(lps2, 0, 0)[1]; + If (IsError(), + [ + ClearErrors(); + success := False; + ]); + If (success And Taylor'LPS'GetOrder(lps2)[1] < 0, + [ + success := False; + ],[ + If (c = 0, + [ + lps1 := Taylor'LPS'Construct(var, Apply(e1[0], {var})); + res := Taylor'LPS'Compose(lps1, lps2); + ],[ + lps1 := Taylor'LPS'Construct(var, Apply(e1[0], {var+c})); + lps3 := Taylor'LPS'Construct(var, -c); + lps2 := Taylor'LPS'Construct(var, Taylor'LPS'Add(lps2, lps3)); + res := Taylor'LPS'Compose(lps1, lps2); + ]); + ]); + ]); + success; + ] <-- res; +]; + +60000 # Taylor'LPS'NormalizeExpr(_var, _e1) <-- e1; + + +/********************************************************************** + * + * Taylor'LPS'CompOrder(var, expr) --- HOOK + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Compute order of expr as a power series in var + * PRE: var is a name + * POST: returns an integer, or raises "dunno" + * + * Taylor'LPS'CompCoeff(var, expr, n) --- HOOK + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Compute n-th coefficient of expr as a power series in var + * PRE: var is a name, n is an integer, + * Taylor'LPS'CompOrder(var, expr) does not raise "dunno" + * POST: returns an expression not containing var + */ + +5 # Taylor'LPS'CompCoeff(_var, _expr, _n) + _ (n < Taylor'LPS'CompOrder(var, expr)) + <-- 0; + +/* Zero */ + +10 # Taylor'LPS'CompOrder(_x, 0) <-- Infinity; + +/* Constant */ + +20 # Taylor'LPS'CompOrder(_x, e_IsFreeOf(x)) <-- 0; +20 # Taylor'LPS'CompCoeff(_x, e_IsFreeOf(x), 0) <-- e; +21 # Taylor'LPS'CompCoeff(_x, e_IsFreeOf(x), _n) <-- 0; + +/* Identity */ + +30 # Taylor'LPS'CompOrder(_x, _x) <-- 1; +30 # Taylor'LPS'CompCoeff(_x, _x, 1) <-- 1; +31 # Taylor'LPS'CompCoeff(_x, _x, _n) <-- 0; + +/* Powers */ + +40 # Taylor'LPS'CompOrder(_x, _x^(k_IsPositiveInteger)) <-- k; +40 # Taylor'LPS'CompCoeff(_x, _x^(k_IsPositiveInteger), _k) <-- 1; +41 # Taylor'LPS'CompCoeff(_x, _x^(k_IsPositiveInteger), _n) <-- 0; + +/* Sqrt */ + +50 # Taylor'LPS'CompOrder(_x, Sqrt(_y)) + _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) + <-- 0; + +50 # Taylor'LPS'CompCoeff(_x, Sqrt(_y), 0) + _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) + <-- Sqrt(Coef(y,x,0)); + +51 # Taylor'LPS'CompCoeff(_x, Sqrt(_y), _n) + _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) <-- +[ + Local(j); + Coef(y,x,0)^(1/2-n) * Product(j,0,n-1,1/2-j) * Coef(y,x,1)^n/n!; +]; + +/* Exp */ + +60 # Taylor'LPS'CompOrder(_x, Exp(_x)) <-- 0; +60 # Taylor'LPS'CompCoeff(_x, Exp(_x), _n) <-- 1/n!; + +70 # Taylor'LPS'CompOrder(_x, Exp(_y))_(CanBeUni(x,y) And Degree(y,x) = 1) + <-- 0; + +70 # Taylor'LPS'CompCoeff(_x, Exp(_y), _n)_(CanBeUni(x,y) And Degree(y,x) = 1) + <-- Exp(Coef(y,x,0)) * Coef(y,x,1)^n / n!; + +/* Ln */ + +80 # Taylor'LPS'CompOrder(_x, Ln(_x+1)) <-- 1; +80 # Taylor'LPS'CompCoeff(_x, Ln(_x+1), _n) <-- (-1)^(n+1)/n; + +/* Sin */ + +90 # Taylor'LPS'CompOrder(_x, Sin(_x)) <-- 1; +90 # Taylor'LPS'CompCoeff(_x, Sin(_x), n_IsOdd) <-- (-1)^((n-1)/2) / n!; +90 # Taylor'LPS'CompCoeff(_x, Sin(_x), n_IsEven) <-- 0; + +/* Cos */ + +100 # Taylor'LPS'CompOrder(_x, Cos(_x)) <-- 0; +100 # Taylor'LPS'CompCoeff(_x, Cos(_x), n_IsOdd) <-- 0; +100 # Taylor'LPS'CompCoeff(_x, Cos(_x), n_IsEven) <-- (-1)^(n/2) / n!; + +/* Inverse (not needed but speeds things up) */ + +110 # Taylor'LPS'CompOrder(_x, 1/_x) <-- -1; +110 # Taylor'LPS'CompCoeff(_x, 1/_x, -1) <-- 1; +111 # Taylor'LPS'CompCoeff(_x, 1/_x, _n) <-- 0; + + +/*COMMENT FROM AYAL: Jitse, what do you think, fall-through defaulting to calculating the coefficient + the hard way? Worst-case, if people define a taylor series in this module it is faster, otherwise it uses + the old scheme that does explicit derivatives, which is slower, but still better than not returning a result + at all? With this change the new taylor code is at least as good as the old code? + + The ugly part is obvious: instead of having a rule here that says "I work for the following input" I had to + find out empirically what the "exclude list" is, eg. the input it will not work on. This because the system + as it works currently yields "dunno", at which moment some other routine picks up. + + I think we can refactor this. + */ + + + + +Taylor'LPS'AcceptDeriv(_expr) <-- + (Contains({"ArcTan"},Type(expr))); +/* + ( Type(Deriv(x)(expr)) != "Deriv" + And Not Contains({ + "/","+","*","^","-","Sin","Cos","Sqrt","Ln","Exp","Tan" + },Type(expr))); +*/ + +200 # Taylor'LPS'CompOrder(_x, (_expr))_(Taylor'LPS'AcceptDeriv(expr)) + <-- + [ +//Echo("CompOrder for ",expr); +// 0; //generic case, assume zeroeth coefficient is non-zero. + Local(n); + n:=0; + While ((Limit(x,0)expr) = 0 And n=0 ) <-- + [ + // This routine is written out for debugging purposes + Local(result); + result:=(Limit(x,0)(Deriv(x,n)expr))/(n!); +Echo(expr," ",n," ",result); + result; + ]; + +/* Default */ + +60000 # Taylor'LPS'CompOrder(_var, _expr) + <-- Assert("dunno") False; + +60000 # Taylor'LPS'CompCoeff(_var, _expr, _n) + <-- Check(False, "Argument", "Taylor'LPS'CompCoeff'FallThrough" + : PipeToString() Write({var,expr,n})); + +/********************************************************************** + * + * Taylor'LPS'GetOrder(lps) + * ~~~~~~~~~~~~~~~~~~~~~~~~ + * Returns a pair {n,flag}. If flag is True, then n is the order of + * the LPS. If flag is False, then n is a lower bound on the order. + * PRE: lps is a well-formed LPS + * POST: returns a pair {n,flag}, where n is an integer or Infinity, + * and flag is True or False, or raises "dunno"; + * may update lps. + */ + +20 # Taylor'LPS'GetOrder(Taylor'LPS(_order, _coeffs, _var, _expr)) + _ (order != Undefined) + <-- {order, coeffs != {}}; + +40 # Taylor'LPS'GetOrder(_lps) <-- +[ + Local(res, computed, exact, res1, res2); + computed := False; + + res := Taylor'LPS'CompOrder(lps[3], lps[4]); + If (Not ClearError("dunno"), + [ + res := {res, True}; + computed := True; + ]); + + If (Not computed And lps[4][0] = Taylor'LPS'Add, + [ + res1 := Taylor'LPS'GetOrder(lps[4][1]); + If (Not ClearError("dunno"), + [ + res2 := Taylor'LPS'GetOrder(lps[4][2]); + If (Not ClearError("dunno"), + [ + res := {Minimum(res1[1],res2[1]), False}; + /* flag = False, since terms may cancel */ + computed := True; + ]); + ]); + ]); + + If (Not computed And lps[4][0] = Taylor'LPS'ScalarMult, + [ + res := Taylor'LPS'GetOrder(lps[4][2]); + If (Not ClearError("dunno"), computed := True); + ]); + + If (Not computed And lps[4][0] = Taylor'LPS'Multiply, + [ + res1 := Taylor'LPS'GetOrder(lps[4][1]); + If (Not ClearError("dunno"), + [ + res2 := Taylor'LPS'GetOrder(lps[4][2]); + If (Not ClearError("dunno"), + [ + res := {res1[1]+res2[1], res1[1] And res2[1]}; + computed := True; + ]); + ]); + ]); + + If (Not computed And lps[4][0] = Taylor'LPS'Inverse, + [ + res := Taylor'LPS'GetOrder(lps[4][1]); + If (Not ClearError("dunno"), + [ + If (res[1] = Infinity, + [ + res[1] = Undefined; + Assert("div-by-zero") False; + computed := True; + ]); + If (Not computed And res[2] = False, + [ + Local(c, n); + n := res[1]; + c := Taylor'LPS'Coeffs(lps[4][1], res[1], res[1])[1]; + While (c = 0 And res[1] < n + Taylor'LPS'Param1()) + [ + res[1] := res[1] + 1; + c := Taylor'LPS'Coeffs(lps[4][1], res[1], res[1])[1]; + ]; + If (c = 0, + [ + res[1] := Undefined; + Assert("maybe-div-by-zero") False; + computed := True; + ]); + ]); + If (Not computed, + [ + res := {-res[1], True}; + computed := True; + ]); + ]); + ]); + + If (Not computed And lps[4][0] = Taylor'LPS'Compose, + [ + res1 := Taylor'LPS'GetOrder(lps[4][1]); + If (Not ClearError("dunno"), + [ + res2 := Taylor'LPS'GetOrder(lps[4][2]); + If (Not ClearError("dunno"), + [ + res := {res1[1]*res2[1], res1[1] And res2[1]}; + computed := True; + ]); + ]); + ]); + + If (computed, lps[1] := res[1]); + Assert("dunno") computed; + res; +]; + +/********************************************************************** + * + * Taylor'LPS'PowerSeries(lps, n, var) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Convert the LPS in a power series in var up to order n + * PRE: lps is a well-formed LPS, n is a natural number + * POST: returns an expression, or raises "singularity" or "dunno" + */ + +10 # Taylor'LPS'PowerSeries(_lps, _n, _var) <-- +[ + Local(ord, k, coeffs); + coeffs := Taylor'LPS'Coeffs(lps, 0, n); + If (IsError("dunno"), + [ + False; + ],[ + If (lps[1] < 0, + [ + Assert("singularity") False; + Undefined; + ],[ + Sum(k, 0, n, coeffs[k+1]*var^k); + ]); + ]); +]; + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Taylor3.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Taylor3.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Taylor3.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Taylor3.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,198 @@ +%mathpiper,def="Taylor3" + + + +/* Taylor3, implementation of Taylor series expansion by doing calculation on series directly. + */ + +Defun("Taylor3'MultiplyCoefs",{coefs1,coefs2,degree}) +[ + Local(result,i,j,jset,ilimit,jlimit); + Bind(result, ArrayCreate(AddN(degree,1),0)); + Bind(i,1); + Bind(ilimit,AddN(degree,2)); + While (Not IsEqual(i,ilimit)) + [ +//Echo(coefs1,coefs2); + Bind(j,1); + Bind(jlimit,AddN(degree,SubtractN(3,i))); + While (Not IsEqual(j,jlimit)) + [ + Bind(jset,AddN(i,SubtractN(j,1))); +//Echo("index = ",i+j-1); + ArraySet(result,jset,ArrayGet(result,jset) + ArrayGet(coefs1,i)*ArrayGet(coefs2,j)); + Bind(j,AddN(j,1)); + ]; + Bind(i,AddN(i,1)); + ]; + result; +]; + + +Bodied("Taylor3'TaylorCoefs",0); +10 # (Taylor3'TaylorCoefs(_var,_degree)(_var)) <-- +[ + Local(result); + Bind(result,ArrayCreate(degree+1,0)); + ArraySet(result,2, 1); + result; +//Echo("degree = ",degree); +// BaseVector(2,degree+1); +]; +20 # (Taylor3'TaylorCoefs(_var,_degree)(_atom))_(IsFreeOf(var,atom)) + <-- + [ + Local(result); + Bind(result,ArrayCreate(degree+1,0)); + ArraySet(result,1, atom); + result; +// atom*BaseVector(1,degree+1); + ]; +30 # (Taylor3'TaylorCoefs(_var,_degree)(_X + _Y)) + <-- + [ + Local(result,add,i); + Bind(result,Taylor3'TaylorCoefs(var,degree)(X)); + Bind(add, Taylor3'TaylorCoefs(var,degree)(Y)); + For(i:=1,i<=degree+1,i++) + [ + ArraySet(result,i,ArrayGet(result,i)+ArrayGet(add,i)); + ]; + result; + ]; + +30 # (Taylor3'TaylorCoefs(_var,_degree)(_X - _Y)) + <-- + [ + Local(result,add,i); + Bind(result,Taylor3'TaylorCoefs(var,degree)(X)); + Bind(add, Taylor3'TaylorCoefs(var,degree)(Y)); + For(i:=1,i<=degree+1,i++) + [ + ArraySet(result,i,ArrayGet(result,i)-ArrayGet(add,i)); + ]; + result; + ]; + +30 # (Taylor3'TaylorCoefs(_var,_degree)( - _Y)) + <-- + [ + Local(result,add,i); + Bind(result,Taylor3'TaylorCoefs(var,degree)(Y)); + For(i:=1,i<=degree+1,i++) + [ + ArraySet(result,i,-ArrayGet(result,i)); + ]; + result; + ]; + +30 # (Taylor3'TaylorCoefs(_var,_degree)(_X * _Y)) + <-- Taylor3'MultiplyCoefs( + Taylor3'TaylorCoefs(var,degree)(X), + Taylor3'TaylorCoefs(var,degree)(Y), + degree); + +30 # (Taylor3'TaylorCoefs(_var,_degree)((_X) ^ N_IsPositiveInteger)) + <-- +[ + Local(result,factor); + factor:=Taylor3'TaylorCoefs(var,degree)(X); + result:=ArrayCreate(degree+1,0); + result[1] := 1; + //TODO@@@ optimize + While(N>0) + [ + result:=Taylor3'MultiplyCoefs(result,factor,degree); + N--; + ]; + result; +]; + +60 # Taylor3'UniFunction("Exp") <-- True; +60 # Taylor3'CompCoeff("Exp", _n) <-- 1/n!; + +80 # Taylor3'UniFunction("Ln") <-- False; // False because this rule is only applicable for Ln(x+1) +80 # Taylor3'CompCoeff("Ln", 0) <-- 0; +81 # Taylor3'CompCoeff("Ln", _n) <-- (-1)^(n+1)/n; + +90 # Taylor3'UniFunction("Sin") <-- True; +90 # Taylor3'CompCoeff("Sin", n_IsOdd) <-- (-1)^((n-1)/2) / n!; +90 # Taylor3'CompCoeff("Sin", n_IsEven) <-- 0; + +100 # Taylor3'UniFunction("Cos") <-- True; +100 # Taylor3'CompCoeff("Cos", n_IsOdd) <-- 0; +100 # Taylor3'CompCoeff("Cos", n_IsEven) <-- (-1)^(n/2) / n!; + + +210 # Taylor3'UniFunction(_any)_ + ( + [ + Local(result); + result:= Deriv(var)ListToFunction({ToAtom(any),var}); + Type(result) != "Deriv"; + ] + ) <-- + [ + True; + ]; +210 # Taylor3'CompCoeff(_any, n_IsInteger) + <-- + [ + Limit(var,0)(Deriv(var,n)(ListToFunction({ToAtom(any),var}))/n!); + ]; + + + +60000 # Taylor3'UniFunction(_any) <-- False; + + +Taylor3'FuncCoefs(_fname,_degree) <-- +[ + Local(sins,i); + Bind(sins, ArrayCreate(degree+1,0)); + For (i:=0,i<=degree,Bind(i,i+1)) + [ + ArraySet(sins,i+1, Taylor3'CompCoeff(fname,i)); + ]; + sins; +]; + + +100 # (Taylor3'TaylorCoefs(_var,_degree)(Ln(_f)))_(Simplify(f-1) = var) <-- Taylor3'FuncCoefs("Ln",degree); + + +110 # (Taylor3'TaylorCoefs(_var,_degree)(f_IsFunction))_(ArgumentsCount(f) = 1 And (Taylor3'UniFunction(Type(f)))) <-- +[ + Local(sins,i,j,result,xx,expr,sinfact); + expr := f[1]; + sins:=Taylor3'FuncCoefs(Type(f),degree); +//Echo("sins = ",sins); + expr:=Taylor3'TaylorCoefs(var,degree)expr; + result:=ArrayCreate(degree+1,0); + ArraySet(result,1, ArrayGet(sins,1)); + xx:=expr; +//Echo("8...",sins,expr); + For (i:=2,i<=degree+1,i++) + [ + Bind(sinfact,sins[i]); +//Echo("8.1..",i," ",j); + For (j:=1,j<=degree+1,j++) + [ + ArraySet(result,j,ArrayGet(result,j) + (ArrayGet(xx,j) * sinfact)); + ]; +//Echo("8.2.."); + Bind(xx,Taylor3'MultiplyCoefs(xx,expr,degree)); +//Echo("8.3.."); + ]; + result; +]; + + +(Taylor3(_var,_degree)(_expr)) <-- Add((Taylor3'TaylorCoefs(var,degree)(expr))[1 .. degree+1]*var^(0 .. degree)); +10 # (Taylor3(_x, 0, _n) _y) <-- Taylor3(x,n) y; +20 # (Taylor3(_x, _a, _n) _y) <-- Subst(x,x-a) Taylor3(x,n) Subst(x,x+a) y; + + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Taylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Taylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/sums/Taylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/sums/Taylor.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,102 @@ +%mathpiper,def="Taylor" + +/*COMMENT FROM AYAL: Jitse, I added some code to make Taylor2 work in the most general case too I believe. + Could you check to see if you agree with my changes? If that is correct, perhaps we can start calling Taylor2 + by default in stead of Taylor1. + */ +Function("Taylor",{taylorvariable,taylorat,taylororder,taylorfunction}) + Taylor1(taylorvariable,taylorat,taylororder)(taylorfunction); + +/*COMMENT FROM AYAL: this is the old slow but working version of Taylor series expansion. Jitse wrote a + * faster version which resides in taylor.mpi, and uses lazy power series. This slow but correct version is still + * useful for tests (the old and the new routine should yield identical results). + */ +Function("Taylor1",{taylorvariable,taylorat,taylororder,taylorfunction}) +[ + Local(n,result,dif,polf); + [ + MacroLocal(taylorvariable); + [ + MacroLocal(taylorvariable); + MacroBind(taylorvariable, taylorat); + result:=Eval(taylorfunction); + ]; + If(result=Undefined, + [ + result:=Apply("Limit",{taylorvariable,taylorat,taylorfunction}); + ]); +/* + MacroBind(taylorvariable,taylorat); + result:=Eval(taylorfunction); +*/ + ]; + dif:=taylorfunction; + polf:=(taylorvariable-taylorat); + For(n:=1,result != Undefined And n<=taylororder,n++) + [ + dif:= Deriv(taylorvariable) dif; + Local(term); + MacroLocal(taylorvariable); + [ + MacroLocal(taylorvariable); + MacroBind(taylorvariable, taylorat); + term:=Eval(dif); + ]; + If(term=Undefined, + [ + term:=Apply("Limit",{taylorvariable,taylorat,dif}); + ]); + + result:=result+(term/(n!))*(polf^n); +/* result:=result+Apply("Limit",{taylorvariable,taylorat,(dif/(n!))})*(polf^n); */ +/* + MacroBind(taylorvariable,taylorat); + result:=result+(Eval(dif)/(n!))*(polf^n); +*/ + ]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Taylor",categories="User Functions;Series" +*CMD Taylor --- univariate Taylor series expansion +*STD +*CALL + Taylor(var, at, order) expr + +*PARMS + +{var} -- variable + +{at} -- point to get Taylor series around + +{order} -- order of approximation + +{expr} -- expression to get Taylor series for + +*DESC + +This function returns the Taylor series expansion of the expression +"expr" with respect to the variable "var" around "at" up to order +"order". This is a polynomial which agrees with "expr" at the +point "var = at", and furthermore the first "order" derivatives of +the polynomial at this point agree with "expr". Taylor expansions +around removable singularities are correctly handled by taking the +limit as "var" approaches "at". + +*E.G. + +In> PrettyForm(Taylor(x,0,9) Sin(x)) + + 3 5 7 9 + x x x x + x - -- + --- - ---- + ------ + 6 120 5040 362880 + +Result: True; + +*SEE D, InverseTaylor, ReversePoly, BigOh +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/ApplyDelta.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/ApplyDelta.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/ApplyDelta.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/ApplyDelta.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,19 @@ +%mathpiper,def="ApplyDelta" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +10 # ApplyDelta(_result,Delta(_i,_j)) <-- + DestructiveInsert(result,1,Delta(i,j)); +20 # ApplyDelta(_result,(_x) ^ (n_IsInteger))_(n>0) <-- + [ + Local(i); + For(i:=1,i<=n,i++) + [ + ApplyDelta(result,x); + ]; + ]; +100 # ApplyDelta(_result,_term) <-- + DestructiveAppend(result,term); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/Delta.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/Delta.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/Delta.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/Delta.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="Delta" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +/* functions internal to tensors */ +Rulebase("Delta",{ind1,ind2}); + +//Not defined in the scripts. todo:tk. + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/MoveDeltas.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/MoveDeltas.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/MoveDeltas.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/MoveDeltas.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,23 @@ +%mathpiper,def="MoveDeltas" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +/* Move the delta factors to the front, so they can be simplified + away. It uses ApplyDelta to move a factor either to the front + or to the back of the list. Input is a list of factors, as + returned by Flatten(expressions,"*") + */ +MoveDeltas(_list) <-- +[ + Local(result,i,nr); + result:={}; + nr:=Length(list); + For(i:=1,i<=nr,i++) + [ + ApplyDelta(result,list[i]); + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TD.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TD.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TD.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TD.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,19 @@ +%mathpiper,def="TD" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +Rulebase("TD",{ind}); + +/* And the simplificaiton rules for X, addition, subtraction + and multiplication */ +10 # (TD(_i)X(_j)) <-- Delta(i,j); +10 # (TD(_i) ( (_f) + (_g) ) ) <-- (TD(i)f) + (TD(i)g); +10 # (TD(_i) ( (_f) - (_g) ) ) <-- (TD(i)f) - (TD(i)g); +10 # (TD(_i) ( - (_g) ) ) <-- - TD(i)g; +10 # (TD(_i) ( (_f) * (_g) ) ) <-- (TD(i)f)*g + f*(TD(i)g); +10 # (TD(_i) ( (_f) ^ (n_IsPositiveInteger) ) ) <-- n*(TD(i)f)*f^(n-1); +10 # (TD(_i)Delta(_j,_k)) <-- 0; +10 # (TD(_i)f_IsNumber) <-- 0; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TExplicitSum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TExplicitSum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TExplicitSum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TExplicitSum.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="TExplicitSum" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +/* TExplicitSum sets the dimension of the space under consideration, + so summation can proceed */ +(TExplicitSum(Ndim_IsInteger)(_body)) <-- Eval(body); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TList.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="TList" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +Rulebase("TList",{head,tail}); + +//Not defined in the scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSimplify.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSimplify.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSimplify.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSimplify.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,47 @@ +%mathpiper,def="TSimplify" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +/* TSimplify : expand brackets, and send the expression of addition + of terms to TSimplifyAux */ +TSimplify(TSum(_indices)(_f)) <-- +[ + TSimplifyAux(TSum(indices)ExpandBrackets(f)); +]; + + +/* TSimplifyAux : simplify each term independently */ +10 # TSimplifyAux(TSum(_indices)((_f) + (_g))) <-- + TSimplifyAux(TSum(FlatCopy(indices))(f)) + + TSimplifyAux(TSum(FlatCopy(indices))(g)); +10 # TSimplifyAux(TSum(_indices)((_f) - (_g))) <-- + TSimplifyAux(TSum(FlatCopy(indices))(f)) - + TSimplifyAux(TSum(FlatCopy(indices))(g)); +10 # TSimplifyAux(TSum(_indices)( - (_g))) <-- + - TSimplifyAux(TSum(indices)(g)); + +40 # TSimplifyAux(TSum(_indices)_body) <-- +[ + Local(flat); + + /* Convert expressions of the form (a*b*c) to {a,b,c} */ + flat:=Flatten(body,"*"); + + /* Move the deltas to the front. */ + flat:=MoveDeltas(flat); + + /* Simplify the deltas away (removing the required indices) */ + flat:=TSumRest(flat); + + /* Determine if there are indices the summand still depends on */ + Local(varlist,independ,nrdims); + varlist:=VarList(flat); + independ:=Intersection(indices,varlist); + nrdims:=Length(indices)-Length(independ); + + /* Return result, still summing over the indices not removed by deltas */ + Ndim^nrdims*TSum(independ)flat; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSum.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSum.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSum.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSum.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,31 @@ +%mathpiper,def="TSum" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +Rulebase("TSum",{indices,body}); + +/* The only TSum summation simplification: summing over no indices + means no summation. */ +10 # (TSum({})(_body)) <-- body; + +/* Explicit summation when Ndim is defined. This summation will + be invoked when using TExplicitSum. */ +20 # (TSum(_indices)(_body))_(IsInteger(Ndim)) <-- + LocalSymbols(index,i,sum) + [ + Local(index,i,sum); + index:=indices[1]; + sum:=0; + MacroLocal(index); + For(i:=1,i<=Ndim,i++) + [ + MacroBind(index,i); + sum:=sum+Eval(TSum(Rest(indices))body); + ]; + sum; + ]; + +UnFence("TSum",2); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSumRest.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSumRest.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSumRest.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSumRest.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,14 @@ +%mathpiper,def="TSumRest" + +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +10 # TSumRest({}) <-- 1; +20 # TSumRest(_list) <-- +[ + TSumSimplify(TList(First(list),Rest(list))); +]; + +UnFence("TSumRest",1); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSumSimplify.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSumSimplify.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/TSumSimplify.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/TSumSimplify.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,46 @@ +%mathpiper,def="TSumSimplify" + +/* Terminating condition for the tensorial simplification */ + +10 # TSumSimplify(TList(Delta(_ind,_ind),_list))_Contains(indices,ind) <-- + +[ + /* Remove the index from the list of indices to sum over, since + it is now implicitly summed over by simplifying the delta */ + DestructiveDelete(indices,Find(indices,ind)); + +/* Return result simplified for this delta */ + Ndim*TSumRest(list); +]; + +11 # TSumSimplify(TList(Delta(_ind1,_ind2),_list))_ + Contains(indices,ind2) <-- +[ + /* Remove the index from the list of indices to sum over, since + it is now implicitly summed over by simplifying the delta */ + DestructiveDelete(indices,Find(indices,ind2)); + + /* Return result simplified for this delta */ + TSumRest( Subst(ind2,ind1)list ); +]; +11 # TSumSimplify(TList(Delta(_ind1,_ind2),_list))_ + Contains(indices,ind1) <-- +[ + /* Remove the index from the list of indices to sum over, since + it is now implicitly summed over by simplifying the delta */ + DestructiveDelete(indices,Find(indices,ind1)); + + /* Return result simplified for this delta */ + TSumRest( Subst(ind1,ind2)list ); +]; + + + +1010 # TSumSimplify(TList(_term,_list)) <-- +[ + term*TSumRest(list); +]; + +UnFence("TSumSimplify",1); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/X.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/X.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/tensor/X.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/tensor/X.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,10 @@ +%mathpiper,def="" +//todo:tk:this conflicts with "linalg.rep/code.mpi" when published as a def file. +/* Tensor package. This code intends to simplify tensorial expressions. + */ + +Rulebase("X",{ind}); + +//Not implemented in the scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/BenchCall.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/BenchCall.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/BenchCall.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/BenchCall.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,13 @@ +%mathpiper,def="BenchCall" + +Function("BenchCall",{expr}) +[ + Echo("In> ",expr); + WriteString(""); + Eval(expr); + WriteString(""); + True; +]; +HoldArgument("BenchCall",expr); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/BenchShow.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/BenchShow.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/BenchShow.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/BenchShow.mpw 2010-03-21 06:00:19.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="BenchShow" + +Function("BenchShow",{expr}) +[ + Echo("In> ",expr); + WriteString(" "); + Echo("Out> ",Eval(expr),""); + True; +]; +HoldArgument("BenchShow",expr); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/EqualAsSets.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/EqualAsSets.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/EqualAsSets.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/EqualAsSets.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="EqualAsSets" + +//Retract("EqualAsSets",*); + +10 # EqualAsSets( A_IsList, B_IsList )_(Length(A)=Length(B)) <-- +[ + Local(Acopy,b,nba,result); + Acopy := FlatCopy(A); + result := True; + ForEach(b,B) + [ + nba := Find(Acopy,b); + If( nba < 0, [ result := False; Break(); ] ); + DestructiveDelete(Acopy,nba); + ]; + If( Not result, result := Length(Acopy)=0 ); + result; +]; + +20 # EqualAsSets( _A, _B ) <-- False; + +%/mathpiper + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/KnownFailure.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/KnownFailure.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/KnownFailure.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/KnownFailure.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="KnownFailure" + +Function("KnownFailure",{expr}) +[ + Local(rfail); + Echo("Known failure: ", expr); + Bind(rfail,Eval(expr)); + If(rfail,Echo({"Failure resolved!"})); +]; +HoldArgument("KnownFailure",expr); + +%/mathpiper + + + + +%mathpiper_docs,name="KnownFailure",categories="Programmer Functions;Testing" +*CMD KnownFailure --- Mark a test as a known failure +*STD +*CALL + KnownFailure(test) + +*PARMS + +{test} -- expression that should return {False} on failure + +*DESC + +The command {KnownFailure} marks a test as known to fail +by displaying a message to that effect on screen. + +This might be used by developers when they have no time +to fix the defect, but do not wish to alarm users who download +MathPiper and type {make test}. + +*E.G. + +In> KnownFailure(Verify(1,2)) + Known failure: + ****************** + 1 evaluates to 1 which differs from 2 + ****************** +Result: False; +In> KnownFailure(Verify(1,1)) + Known failure: + Failure resolved! +Result: True; + +*SEE Verify, TestMathPiper, LogicVerify, LogicTest + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/LogicTest.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/LogicTest.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/LogicTest.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/LogicTest.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,63 @@ +%mathpiper,def="LogicTest" + +/* LogicTest compares the truth tables of two expressions. */ +LocalSymbols(TrueFalse) +[ + MacroRulebase(TrueFalse,{var,expr}); + 10 # TrueFalse(var_IsAtom,_expr) <-- `{(@expr) Where (@var)==False,(@expr) Where (@var)==True}; + 20 # TrueFalse({},_expr) <-- `(@expr); + 30 # TrueFalse(var_IsList,_expr) <-- + `[ + Local(t,h); + Bind(h,First(@var)); + Bind(t,Rest(@var)); + TrueFalse(h,TrueFalse(t,@expr)); + ]; + + Macro(LogicTest,{vars,expr1,expr2}) Verify(TrueFalse((@vars),(@expr1)), TrueFalse((@vars),(@expr2))); +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="LogicTest",categories="Programmer Functions;Testing" +*CMD LogicTest --- verifying equivalence of two expressions +*STD +*CALL + LogicTest(variables,expr1,expr2) + +*PARMS + +{variables} -- list of variables + +{exprN} -- Some boolean expression + +*DESC + +The command {LogicTest} can be used to verify that an +expression is equivalent to a correct answer after evaluation. +It returns {True} or {False}. + + +*E.G. + +In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or B) +Result: True +In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or C) + ****************** + CommandLine: 1 + + $TrueFalse4({A,B,C},Not(Not A And Not B)) + evaluates to + {{{False,False},{True,True}},{{True,True},{True,True}}} + which differs from + {{{False,True},{False,True}},{{True,True},{True,True}}} + ****************** +Result: False + +*SEE Simplify, CanProve, KnownFailure, Verify, TestMathPiper, LogicVerify + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/LogicVerify.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/LogicVerify.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/LogicVerify.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/LogicVerify.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="LogicVerify" + +Function("LogicVerify",{aLeft,aRight}) +[ + If(aLeft != aRight, + Verify(CanProve(aLeft => aRight),True) + ); +]; + +%/mathpiper + + + +%mathpiper_docs,name="LogicVerify",categories="Programmer Functions;Testing" +*CMD LogicVerify --- verifying equivalence of two expressions +*STD +*CALL + LogicVerify(question,answer) + +*PARMS + +{question} -- expression to check for + +{answer} -- expected result after evaluation + + +*DESC + +The command {LogicVerify} can be used to verify that an +expression is equivalent to a correct answer after evaluation. +It returns {True} or {False} + +*E.G. +In> LogicVerify(a And c Or b And Not c,a Or b) +Result: True; +In> LogicVerify(a And c Or b And Not c,b Or a) +Result: True; + +*SEE Simplify, CanProve, KnownFailure, Verify, TestMathPiper, LogicTest + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/NextTest.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/NextTest.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/NextTest.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/NextTest.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="NextTest" + +Function("NextTest",{aLeft}) +[ +// curline++; +WriteString(" +Test suite for ":aLeft:" : " + ); + NewLine(); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/NumericEqual.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/NumericEqual.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/NumericEqual.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/NumericEqual.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,83 @@ +%mathpiper,def="NumericEqual" + +//Retract("NumericEqual",*); + +10 # NumericEqual(left_IsDecimal, right_IsDecimal, precision_IsPositiveInteger) <-- +[ + If(InVerboseMode(),Tell("NumericEqual",{left,right})); + Local(repL,repR,precL,precR,newL,newR,plo,phi,replo,rephi); + Local(newhi,newrepL,newlo,newrepR,ans); + repL := NumberToRep(left); + repR := NumberToRep(right); + precL := repL[2]; + precR := repR[2]; + If(InVerboseMode(),Tell(" ",{precL,precR,precision})); + newL := RoundToPrecision(left, precision ); + newR := RoundToPrecision(right, precision ); + If(InVerboseMode(),Tell(" ",{newL,newR})); + newrepL := NumberToRep( newL ); + newrepR := NumberToRep( newR ); + If(InVerboseMode(),Tell(" ",{newrepL,newrepR})); + ans := Verify( newrepL[1] - newrepR[1], 0 ); + If(InVerboseMode(),Tell(" ",ans)); + ans; +]; + + +15 # NumericEqual(left_IsInteger, right_IsInteger, precision_IsPositiveInteger) <-- +[ + If(InVerboseMode(),Tell("NumericEqualInt",{left,right})); + left = right; +]; + + +20 # NumericEqual(left_IsNumber, right_IsNumber, precision_IsPositiveInteger) <-- +[ + If(InVerboseMode(),Tell("NumericEqualNum",{left,right})); + Local(nI,nD,repI,repD,precI,precD,intAsDec,newDec,newrepI,newrepD,ans); + If( IsInteger(left), [nI:=left; nD:=right;], [nI:=right; nD:=left;]); + // the integer can be converted to the equivalent decimal at any precision + repI := NumberToRep(nI); + repD := NumberToRep(nD); + precI := repI[2]; + precD := repD[2]; + intAsDec := RoundToPrecision(1.0*nI,precision); + newDec := RoundToPrecision( nD, precision ); + newrepI := NumberToRep( intAsDec ); + newrepD := NumberToRep( newDec ); + If(InVerboseMode(), + [ + Tell(" ",{nI,nD}); + Tell(" ",{repI,repD}); + Tell(" ",{precI,precD}); + Tell(" ",{intAsDec,newDec}); + Tell(" ",{newrepI,newrepD}); + ] + ); + ans := Verify( newrepI[1] - newrepD[1], 0 ); + If(InVerboseMode(),Tell(" ",ans)); + ans; +]; + + +25 # NumericEqual(left_IsComplex, right_IsComplex, precision_IsPositiveInteger) <-- +[ + If(InVerboseMode(),Tell("NumericEqualC",{left,right})); + Local(rrL,iiL,rrR,iiR,ans); + rrL := Re(left); + iiL := Im(left); + rrR := Re(right); + iiR := Im(right); + If(InVerboseMode(), + [ + Tell(" ",{left,right}); + Tell(" ",{rrL,rrR}); + Tell(" ",{iiL,iiR}); + ] + ); + ans := (NumericEqual(rrL,rrR,precision) And NumericEqual(iiL,iiR,precision)); +]; + +%/mathpiper + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/RandVerifyArithmetic.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/RandVerifyArithmetic.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/RandVerifyArithmetic.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/RandVerifyArithmetic.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="RandVerifyArithmetic" + +RandVerifyArithmetic(_n)<-- +[ + While(n>0) + [ + n--; + VerifyArithmetic(FloorN(300*Random()),FloorN(80*Random()),FloorN(90*Random())); + ]; +]; + +%/mathpiper + + + + +%mathpiper_docs,name="RandVerifyArithmetic",categories="Programmer Functions;Testing" +*CMD RandVerifyArithmetic --- Special purpose arithmetic verifiers +*STD +*CALL + RandVerifyArithmetic(n) + +*PARMS + +{n} -- integer arguments + +*DESC + +{RandVerifyArithmetic(n)} calls {VerifyArithmetic} with +random values, {n} times. + +*E.G. + +In> RandVerifyArithmetic(4) +Result: True; + +*SEE Verify, VerifyArithmetic, RandVerifyArithmetic, VerifyDiv, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/RoundTo.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/RoundTo.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/RoundTo.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/RoundTo.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,78 @@ +%mathpiper,def="RoundTo" + +/* Functions that aid in testing */ + +/* Round to specified number of digits */ +10 # RoundTo(x_IsNumber, precision_IsPositiveInteger) <-- +[ + Local(oldPrec,result); + + oldPrec:=BuiltinPrecisionGet(); + + BuiltinPrecisionSet(precision); + + Bind(result,DivideN( Round( MultiplyN(x, 10^precision) ), 10^precision )); + + BuiltinPrecisionSet(oldPrec); + + result; +]; + + + +// complex numbers too +10 # RoundTo(Complex(r_IsNumber, i_IsNumber), precision_IsPositiveInteger) <-- Complex(RoundTo(r, precision), RoundTo(i, precision)); + + + + +// Infinities, rounding does not apply. +20 # RoundTo( Infinity,precision_IsPositiveInteger) <-- Infinity; + +20 # RoundTo(-Infinity,precision_IsPositiveInteger) <-- -Infinity; + + + +/* ------ moved to separate file (already present but empty!) --- + +Macro(NumericEqual,{left,right,precision}) +[ + Verify(RoundTo((@left)-(@right),@precision),0); +]; + +*/ + +%/mathpiper + + + + + +%mathpiper_docs,name="RoundTo",categories="Programmer Functions;Testing" +*CMD RoundTo --- Round a real-valued result to a set number of digits +*STD +*CALL + RoundTo(number,precision) + +*PARMS + +{number} -- number to round off + +{precision} -- precision to use for round-off + +*DESC + +The function {RoundTo} rounds a floating point number to a +specified precision, allowing for testing for correctness +using the {Verify} command. + +*E.G. + +In> N(RoundTo(Exp(1),30),30) +Result: 2.71828182110230114951959786552; +In> N(RoundTo(Exp(1),20),20) +Result: 2.71828182796964237096; + +*SEE Verify, VerifyArithmetic, VerifyDiv + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/ShowLine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/ShowLine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/ShowLine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/ShowLine.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,6 @@ +%mathpiper,def="ShowLine" + +// print current file and line +ShowLine() := [Echo(CurrentFile(),": ",CurrentLine());]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/TestEquivalent.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/TestEquivalent.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/TestEquivalent.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/TestEquivalent.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,104 @@ +%mathpiper,def="TestEquivalent" + +//Retract("TestEquivalent",*); +//Retract("TestTwoLists",*); + +Macro("TestEquivalent",{left,right}) +[ + Local(leftEval,rightEval,diff,vars,isEquiv); + If(InVerboseMode(),[Tell(TestEquivalent,{left,right});]); + leftEval := @left; + rightEval := @right; + If(InVerboseMode(), + [ NewLine(); Tell(" ",leftEval); Tell(" ",rightEval); ]); + If( IsList(leftEval), + [ + If( IsList(rightEval), + [ + // both are lists + If(InVerboseMode(),Tell(" both are lists ")); + isEquiv := TestTwoLists(leftEval,rightEval); + ], + isEquiv := False + ); + ], + [ + If( IsList(rightEval), + isEquiv := False, + [ + // neither is a list, so check equality of diff + If(InVerboseMode(),Tell(" neither is list ")); + If(IsEquation(leftEval), + [ + If(IsEquation(rightEval), + [ + If(InVerboseMode(),Tell(" both are equations")); + Local(dLHs,dRHS); + dLHS := Simplify(EquationLeft(leftEval) - EquationLeft(rightEval)); + dRHS := Simplify(EquationRight(leftEval) - EquationRight(rightEval)); + If(InVerboseMode(),Tell(" ",{dLHS,dRHS})); + isEquiv := dLHS=0 And dRHS=0; + ], + isEquiv := False + ); + ], + [ + If(IsEquation(rightEval), + isEquiv := False, + [ + If(InVerboseMode(),Tell(" neither is equation")); + diff := Simplify(leftEval - rightEval); + vars := VarList(diff); + If(InVerboseMode(), + [ + Tell(" ",{leftEval,rightEval}); + Tell(" ",vars); + Tell(" ",diff); + ] + ); + isEquiv := ( IsZero(diff) Or IsZeroVector(diff) ); + ] + ); + ] + ); + ] + ); + ] + ); + If(InVerboseMode(),Tell(" Equivalence = ",isEquiv)); + If ( Not isEquiv, + [ + WriteString("******************"); NewLine(); + WriteString("L.H.S. evaluates to: "); + Write(leftEval); NewLine(); + WriteString("which differs from "); + Write(rightEval); NewLine(); + WriteString(" by "); + Write(diff); NewLine(); + WriteString("******************"); NewLine(); + ] + ); + isEquiv; +]; + + +10 # TestTwoLists( L1_IsList, L2_IsList ) <-- +[ + If(InVerboseMode(),[Tell(" TestTwoLists");Tell(" ",L1);Tell(" ",L2);]); + If(Length(L1)=1 And Length(L2)=1, + [ + TestEquivalent(L1[1],L2[1]); + ], + [ + EqualAsSets(L1,L2); + ] + ); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/Testing.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/Testing.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/Testing.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/Testing.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,9 @@ +%mathpiper,def="Testing" + +Function("Testing",{aLeft}) +[ + WriteString("--"); + WriteString(aLeft); NewLine(); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/TestMathPiper.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/TestMathPiper.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/TestMathPiper.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/TestMathPiper.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,107 @@ +%mathpiper,def="TestMathPiper" + +/* Testing MathPiper functionality by checking expressions against correct + answer. + Use with algebraic expressions only, since we need Simplify() for that to work. + */ + +/* +Macro ("TestMathPiper", {expr, ans}) +[ + Local(diff,exprEval, ansEval); + exprEval:= @expr; + ansEval:= @ans; + + diff := Simplify(exprEval - ansEval); + If (Simplify(diff)=0, True, + [ + WriteString("******************"); + NewLine(); + ShowLine(); + Write(Hold(@expr)); + WriteString(" evaluates to "); + NewLine(); + Write(exprEval); + NewLine(); + WriteString(" which differs from "); + NewLine(); + Write(ansEval); + NewLine(); + WriteString(" by "); + NewLine(); + Write(diff); + NewLine(); + WriteString("******************"); + NewLine(); + False; + ] + ); +]; +*/ + + + +Function ("TestMathPiper", {expr, ans}) +[ + Local(diff); + diff := Simplify(Eval(expr)-Eval(ans)); + If (Simplify(diff)=0, True, + [ + WriteString("******************"); + NewLine(); + ShowLine(); + Write(expr); + WriteString(" evaluates to "); + NewLine(); + Write(Eval(expr)); + NewLine(); + WriteString(" which differs from "); + NewLine(); + Write(Eval(ans)); + NewLine(); + WriteString(" by "); + NewLine(); + Write(diff); + NewLine(); + WriteString("******************"); + NewLine(); + False; + ] + ); +]; + +HoldArgument("TestMathPiper", expr); +HoldArgument("TestMathPiper", ans); + + +%/mathpiper + + + + +%mathpiper_docs,name="TestMathPiper",categories="Programmer Functions;Testing" +*CMD TestMathPiper --- verifying equivalence of two expressions +*STD +*CALL + TestMathPiper(question,answer) + +*PARMS + +{question} -- expression to check for + +{answer} -- expected result after evaluation + +*DESC + +The command {TestMathPiper} can be used to verify that an +expression is equivalent to a correct answer after evaluation. +It returns {True} or {False}. + +*E.G. +In> TestMathPiper(x*(1+x),x^2+x) +Result: True; + + +*SEE Simplify, CanProve, KnownFailure, Verify, LogicVerify, LogicTest + +%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/VerifyArithmetic.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/VerifyArithmetic.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/VerifyArithmetic.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/VerifyArithmetic.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,53 @@ +%mathpiper,def="VerifyArithmetic" + +LocalSymbols(f1,f2) +[ + // f1 and f2 are used inside VerifyArithmetic + f1(x,n,m):=(x^n-1)*(x^m-1); + f2(x,n,m):=x^(n+m)-(x^n)-(x^m)+1; + + VerifyArithmetic(x,n,m):= + [ + Verify(f1(x,n,m),f2(x,n,m)); + ]; +]; + +%/mathpiper + + + + +%mathpiper_docs,name="VerifyArithmetic",categories="Programmer Functions;Testing" +*CMD VerifyArithmetic --- Special purpose arithmetic verifiers +*STD +*CALL + VerifyArithmetic(x,n,m) + +*PARMS + +{x}, {n}, {m} -- integer arguments + +*DESC + +The command {VerifyArithmetic} tests a +mathematic equality which should hold, testing that the +result returned by the system is mathematically correct +according to a mathematically provable theorem. + +{VerifyArithmetic} verifies for an arbitrary set of numbers +$ x $, $ n $ and $ m $ that +$$ (x^n-1)*(x^m-1) = x^(n+m)-(x^n)-(x^m)+1 $$. + +The left and right side represent two ways to arrive at the +same result, and so an arithmetic module actually doing the +calculation does the calculation in two different ways. +The results should be exactly equal. + +*E.G. + +In> VerifyArithmetic(100,50,60) +Result: True; + +*SEE Verify, VerifyArithmetic, RandVerifyArithmetic, VerifyDiv, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/VerifyDiv.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/VerifyDiv.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/VerifyDiv.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/VerifyDiv.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,42 @@ +%mathpiper,def="VerifyDiv" + +VerifyDiv(_u,_v) <-- +[ + Local(q,r); + q:=Quotient(u,v); + r:=Rem(u,v); + + Verify(Expand(u),Expand(q*v+r)); +]; + +%/mathpiper + + + + +%mathpiper_docs,name="VerifyDiv",categories="Programmer Functions;Testing" +*CMD VerifyDiv --- Special purpose arithmetic verifiers +*STD +*CALL + VerifyDiv(u,v) + +*PARMS + +{u}, {v} -- integer arguments + +*DESC + +{VerifyDiv(u,v)} checks that +$$ u = v*Quotient(u,v) + Modulo(u,v) $$. + + +*E.G. + +In> VerifyDiv(x^2+2*x+3,x+1) +Result: True; +In> VerifyDiv(3,2) +Result: True; + +*SEE Verify, VerifyArithmetic, RandVerifyArithmetic, VerifyDiv, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/Verify.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/Verify.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/Verify.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/Verify.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,169 @@ +%mathpiper,def="Verify" + +/* +Macro("Verify",{aLeft,aRight}) +[ + + Local(result); + result := @aLeft; // to save time + If (Not(IsEqual(result,@aRight)), + [ + WriteString("******************"); + NewLine(); + ShowLine(); + NewLine(); + Write(Hold(@aLeft)); + NewLine(); + WriteString(" evaluates to "); + NewLine(); + Write(result); + WriteString(" which differs from "); + NewLine(); + Write(Hold(@aRight)); + NewLine(); + WriteString("******************"); + NewLine(); + False; + ], + True + ); +]; +*/ + + +Function("Verify",{aLeft,aRight}) +[ + + Local(result); + result := Eval(aLeft); // to save time + If (Not(IsEqual(result,aRight)), + [ + WriteString("******************"); + NewLine(); + ShowLine(); + NewLine(); + Write(aLeft); + NewLine(); + WriteString(" evaluates to "); + NewLine(); + Write(result); + NewLine(); + WriteString(" which differs from "); + NewLine(); + Write(aRight); + NewLine(); + WriteString("******************"); + NewLine(); + False; + ], + True + ); +]; +HoldArgument("Verify",aLeft); +UnFence("Verify",2); +/* +HoldArgument("Verify",aRight); +*/ + +Macro("Verify", {a,b,message}) +[ + Echo("test ", @message); + Verify(@a, @b); +]; + + +%/mathpiper + + + + + + +%mathpiper_docs,name="Verify",categories="Programmer Functions;Testing" +*CMD Verify --- verifying equivalence of two expressions +*STD +*CALL + Verify(question,answer) + +*PARMS + +{question} -- expression to check for + +{answer} -- expected result after evaluation + + +*DESC + +The command {Verify} can be used to verify that an +expression is equivalent to a correct answer after evaluation. +It returns {True} or {False}. + +For some calculations, the demand that two expressions +are identical syntactically is too stringent. The +MathPiper system might change at various places in the future, +but $ 1+x $ would still be equivalent, from a mathematical +point of view, to $ x+1 $. + +The general problem of deciding that two expressions $ a $ and $ b $ +are equivalent, which is the same as saying that $ a-b=0 $ , +is generally hard to decide on. The following commands solve +this problem by having domain-specific comparisons. + +The comparison commands do the following comparison types: + +* {Verify} -- verify for literal equality. +This is the fastest and simplest comparison, and can be +used, for example, to test that an expression evaluates to $ 2 $. +* {TestMathPiper} -- compare two expressions after simplification as +multivariate polynomials. If the two arguments are equivalent +multivariate polynomials, this test succeeds. {TestMathPiper} uses {Simplify}. Note: {TestMathPiper} currently should not be used to test equality of lists. +* {LogicVerify} -- Perform a test by using {CanProve} to verify that from +{question} the expression {answer} follows. This test command is +used for testing the logic theorem prover in MathPiper. +* {LogicTest} -- Generate a truth table for the two expressions and compare these two tables. They should be the same if the two expressions are logically the same. + +*E.G. +In> Verify(1+2,3) +Result: True; + +In> Verify(x*(1+x),x^2+x) + ****************** + x*(x+1) evaluates to x*(x+1) which differs + from x^2+x + ****************** +Result: False; + +In> TestMathPiper(x*(1+x),x^2+x) +Result: True; + +In> Verify(a And c Or b And Not c,a Or b) + ****************** + a And c Or b And Not c evaluates to a And c + Or b And Not c which differs from a Or b + ****************** +Result: False; + +In> LogicVerify(a And c Or b And Not c,a Or b) +Result: True; + +In> LogicVerify(a And c Or b And Not c,b Or a) +Result: True; + +In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or B) +Result: True + +In> LogicTest({A,B,C},Not((Not A) And (Not B)),A Or C) + ****************** + CommandLine: 1 + + TrueFalse4({A,B,C},Not(Not A And Not B)) + evaluates to + {{{False,False},{True,True}},{{True,True},{True,True}}} + which differs from + {{{False,True},{False,True}},{{True,True},{True,True}}} + ****************** +Result: False + +*SEE Simplify, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/VerifySolve.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/VerifySolve.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/testers/VerifySolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/testers/VerifySolve.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,131 @@ +%mathpiper,def="VerifySolve" + +//Retract("VerifySolve",*); +//Retract("VerifySolve'Equal",*); + +VerifySolve(_e1, _e2) <-- +If (VerifySolve'Equal(Eval(e1), Eval(e2)), + True, + [ + WriteString("******************"); NewLine(); + ShowLine(); NewLine(); + Write(e1); NewLine(); + WriteString(" evaluates to "); NewLine(); + Write(Eval(e1)); NewLine(); + WriteString(" which differs from "); NewLine(); + Write(e2); NewLine(); + WriteString("******************"); NewLine(); + False; + ]); +HoldArgumentNumber("VerifySolve", 2, 1); + +10 # VerifySolve'Equal({}, {}) <-- True; + +20 # VerifySolve'Equal({}, e2_IsList) <-- False; + +30 # VerifySolve'Equal(e1_IsList, e2_IsList) <-- +[ + Local(i, found); + found := False; + i := 0; + While(i < Length(e2) And Not found) [ + i++; + found := VerifySolve'Equal(First(e1), e2[i]); + ]; + If (found, VerifySolve'Equal(Rest(e1), Delete(e2, i)), False); +]; + +40 # VerifySolve'Equal(_l1 == _r1, _l2 == _r2) +<-- IsEqual(l1,l2) And Simplify(r1-r2)=0; + +50 # VerifySolve'Equal(_e1, _e2) <-- Simplify(e1-e2) = 0; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper_docs,name="VerifySolve",categories="Programmer Functions;Testing" +*CMD VerifySolve --- verifies that one expression is mathematically equivalent to another +*STD +*CALL + VerifySolve(expression,answer) + +*PARMS + +{expression} -- expression to be checked + +{answer} -- expected result + + +*DESC + +VerifySolve(expression, answer) tests whether 'expression' evaluates to +something "equal" to 'answer', and complains explicitly if it doesn't. + + Here, "equal" means: + o for lists: having the same entries, possibly in a different order; + o for equations: having the same right-hand sides, possibly after 'Simplify'; + o in all other cases: equality, possible after 'Simplify'. + Hence, { a == 1, a == x+1 } is "equal" to { a == 1+x, a == 1 }. + +The command {VerifySolve} is usually employed to verify that an equation or +set of equations has been solved correctly. + +But it also has a wider applicability. + +NOTE: + This function used to be defined in the test file solve.mpt, where it was +used extensively. However, by defining it in that file, it was unavailable for +use as a general tool. Now it has been made available. + +*E.G. + +In> VerifySolve(Solve(a+x*y==z,x),{x==(z-a)/y}); +Result: True + +In> VerifySolve(Solve(a+x*y==z,x),{x==(a-z)/y}); +Result: False +Side Effects: +****************** +none: -1 +Solve(a+x*y==z,x) + evaluates to +{x==-(a-z)/y} + which differs from +{x==(a-z)/y} +****************** + +In> Verify(x*(1+x),x+x^2) +Result: False +Side Effects: +****************** +none: -1 +x*(1+x) + evaluates to +x*(x+1) + which differs from +x+x^2 +****************** + +In> VerifySolve(x*(1+x),x+x^2) +Result: True + +NOTE: Verify cannot see past the syntactical dissimilarity; + VerifySolve can see the mathematical identity. + +*SEE Verify, Simplify, CanProve, KnownFailure, TestMathPiper, LogicVerify, LogicTest + +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/transforms/laplace/LaplaceTransform.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/transforms/laplace/LaplaceTransform.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/transforms/laplace/LaplaceTransform.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/transforms/laplace/LaplaceTransform.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,109 @@ +%mathpiper,def="LaplaceTransform" + +10 # LaplaceTransform(_var1,_var2, _expr ) <-- LapTran(var1,var2,expr); + +// Linearity properties +10 # LapTran(_var1,_var2,_x + _y) <-- LapTran(var1,var2,x) + LapTran(var1,var2,y); +10 # LapTran(_var1,_var2,_x - _y) <-- LapTran(var1,var2,x) - LapTran(var1,var2,y); +10 # LapTran(_var1,_var2, - _y) <-- LapTran(var1,var2,y); +10 # LapTran(_var1,_var2, c_IsConstant*_y) <-- c*LapTran(var1,var2,y); +10 # LapTran(_var1,_var2, _y*c_IsConstant) <-- c*LapTran(var1,var2,y); +10 # LapTran(_var1,_var2, _y/c_IsConstant) <-- LapTran(var1,var2,y)/c; + +// Shift properties +10 # LapTran(_var1,_var2, Exp(c_IsConstant*_var1)*_expr ) <-- LapTran(var1,var2-c,expr); +10 # LapTran(_var1,_var2, Exp(-c_IsConstant*_var1)*_expr ) <-- LapTran(var1,var2+c,expr); +10 # LapTran(_var1,_var2, _expr*Exp(c_IsConstant*_var1) ) <-- LapTran(var1,var2-c,expr); +10 # LapTran(_var1,_var2, _expr*Exp(-c_IsConstant*_var1) ) <-- LapTran(var1,var2+c,expr); + +// Other operational properties +10 # LapTran(_var1,_var2, _expr/_var1 ) <-- Integrate(var2,var2,Infinity) LapTran(var1,var2,expr) ; +10 # LapTran(_var1,_var2, _var1*_expr ) <-- - Deriv(var2) LapTran(var1,var2,expr); +10 # LapTran(_var1,_var2, _var1^(n_IsInteger)*_expr ) <-- (-1)^n * Deriv(var2,n) LapTran(var1,var2,expr); +10 # LapTran(_var1,_var2, _expr*_var1 ) <-- - Deriv(var2) LapTran(var1,var2,expr); +10 # LapTran(_var1,_var2, _expr*_var1^(n_IsInteger) ) <-- (-1)^n * Deriv(var2,n) LapTran(var1,var2,expr); + +// didn't match, return unevaled +100 # LapTran(_var1,_var2, _expr ) <-- `Hold(LaplaceTransform(@var1,@var2,@expr)); + +LapTranDef(_in,_out) <-- +[ + Local(i,o); + + //Echo("50 # LapTran(_t,_s,",in,") <-- ",out,";"); + `(50 # LapTran(_t,_s,@in) <-- @out ); + + i:=Subst(_t,c_IsPositiveInteger*_t) in; + o:=Subst(s,s/c) out; + + //Echo("50 # LapTran(_t,_s,",i,") <-- ",o/c,";"); + `(50 # LapTran(_t,_s,@i ) <-- @o/c ); + + i:=Subst(_t,_t/c_IsPositiveInteger) in; + o:=Subst(s,s*c) out; + + //Echo("50 # LapTran(_t,_s,",i,") <-- ",o/c,";"); + `(50 # LapTran(_t,_s,@i ) <-- @o*c ); + +]; + +// transforms of specific functions +LapTranDef( (_t)^(n_IsConstant), Gamma(n+1)/s^(n+1) ); +LapTranDef( _t, 1/s^2 ); +LapTranDef( Sqrt(_t), Sqrt(Pi)/(2*s^(3/2)) ); +LapTranDef( c_IsFreeOf({t,s}), c/s ); +LapTranDef( Sin(_t), 1/(s^2+1) ); +LapTranDef( Cos(_t), s/(s^2+1) ); +LapTranDef( Sinh(_t), c/(s^2-1) ); +LapTranDef( Cosh(_t), s/(s^2-1) ); +LapTranDef( Exp(_t), 1/(s-1) ); +LapTranDef( BesselJ(n_IsConstant,_t), (Sqrt(s^2+1)-s)^n /Sqrt(s^2+1) ); +LapTranDef( BesselI(n_IsConstant,_t), (s-Sqrt(s^2+1))^n /Sqrt(s^2-1) ); +LapTranDef( Ln(_t), -(gamma+Ln(s))/s); +LapTranDef( Ln(_t)^2, Pi^2/(6*s)+(gamma+Ln(s))/s ); +LapTranDef( Erf(_t), Exp(s^2/4)*Erfc(s/2)/s ); +LapTranDef( Erf(Sqrt(_t)), 1/(Sqrt(s+1)*s) ); + + +%/mathpiper + + + +%mathpiper_docs,name="LaplaceTransform",categories="User Functions;Transforms" +*CMD LaplaceTransform --- Laplace Transform +*STD +*CALL + LaplaceTransform(t,s,func) +*PARMS + +{t} -- independent variable that is being transformed + +{s} -- independent variable that is being transformed into + +{f} -- function + +*DESC + +This function attempts to take the function {f(t)} and find the Laplace transform +of it,{F(s)}, which is defined as {Integrate(t,0,Infinity) Exp(-s*t)*f}. This is +also sometimes referred to the "unilateral" Laplace tranform. {LaplaceTransform} +can transform most elementary functions that do not require a convolution integral, +as well as any polynomial times an elementary function. If a transform cannot +be found then {LaplaceTransform} will return unevaluated. This can happen +for function which are not of "exponential order", which means that they grow +faster than exponential functions. + + +*E.G. + +In> LaplaceTransform(t,s,2*t^5+ t^2/2 ) +Result: 240/s^6+2/(2*s^3); +In> LaplaceTransform(t,s,t*Sin(2*t)*Exp(-3*t) ) +Result: (2*(s+3))/(2*(2*(((s+3)/2)^2+1))^2); +In> LaplaceTransform(t,s, BesselJ(3,2*t) ) +Result: (Sqrt((s/2)^2+1)-s/2)^3/(2*Sqrt((s/2)^2+1)); +In> LaplaceTransform(t,s,Exp(t^2)); // not of exponential order +Result: LaplaceTransform(t,s,Exp(t^2)); +In> LaplaceTransform(p,q,Ln(p)) +Result: -(gamma+Ln(q))/q; +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/trigsimp/TrigSimpCombine.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/trigsimp/TrigSimpCombine.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/trigsimp/TrigSimpCombine.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/trigsimp/TrigSimpCombine.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,513 @@ +%mathpiper,def="TrigSimpCombine" + + +/* This file defines TrigSimpCombine. TrigSimpCombine is designed to + simplify expressions like Cos(a)*Sin(b) to additions + only (in effect, removing multiplications between + trigonometric functions). + + The accepted expressions allow additions and multiplications + between trig. functions, and raising trig. functions to an + integer power. + + You can invoke it by calling TrigSimpCombine(f). Examples: + TrigSimpCombine(Cos(a)*Sin(a^2+b)^2) + TrigSimpCombine(Cos(a)*Sin(a)^2) + TrigSimpCombine(Cos(a)^3*Sin(a)^2) + TrigSimpCombine(d*Cos(a)^3*Sin(a)^2) + TrigSimpCombine(Cos(a)^3*Sin(a)^2) + TrigSimpCombine(Cos(a)*Sin(a)) + TrigSimpCombine(Cos(a)*Sin(b)*Cos(c)) + + */ + + +/* FSin, FCos and :*: are used for the internal representation + of the expression to work on: + - a*b -> a:*:b this is used because we want to expand powers, + without the standard engine collapsing them back again. + - a*Sin(b) -> FSin(a,b) and a*Cos(b) -> FCos(a,b). This makes + adding and multiplying expressions with trig. functions, non-trig. + functions, constants, etc. a lot easier. +*/ +Rulebase("FSin",{f,x}); +Rulebase("FCos",{f,x}); +Rulebase(":*:",{x,y}); +Infix(":*:",3); + + +IsTrig(f) := (Type(f) = "Sin" Or Type(f) = "Cos"); +IsFTrig(f) := (Type(f) = "FSin" Or Type(f) = "FCos"); +IsMul(f) := (Type(f) = "*"); +IsMulF(f) := (Type(f) = ":*:"); + +IsPow(f):= + (Type(f) = "^" And + IsInteger(f[2]) And + f[2] > 1 + ); + + +/* Convert Sin/Cos to FSin/FCos */ +Rulebase("TrigChange",{f}); +Rule("TrigChange",1,1,Type(f)="Cos") FCos(1,f[1]); +Rule("TrigChange",1,1,Type(f)="Sin") FSin(1,f[1]); + +Rulebase("TrigUnChange",{f}); +Rule("TrigUnChange",1,1,Type(f)="FCos") Cos(f[2]); +Rule("TrigUnChange",1,1,Type(f)="FSin") Sin(f[2]); + + +/* Do a full replacement to internal format on a term. */ +Rulebase("FReplace",{f}); +UnFence("FReplace",1); +Rule("FReplace",1,1,IsMul(f)) Substitute(f[1]) :*: Substitute(f[2]); +Rule("FReplace",1,2,IsPow(f)) (Substitute(f[1]) :*: Substitute(f[1])) :*: Substitute(f[1]^(f[2]-2)); +/* +Rule("FReplace",1,2,IsPow(f)) +[ + Local(trm,i,res,n); + Bind(trm,Substitute(f[1])); + Bind(n,f[2]); + Bind(res,trm); + For(i:=2,i<=n,i++) + [ + Bind(res,res :*: trm); + ]; + res; +]; +*/ + +Rule("FReplace",1,3,IsTrig(f)) TrigChange(f); +FTest(f):=(IsMul(f) Or IsPow(f) Or IsTrig(f)); + +/* Central function that converts to internal format */ +FToInternal(f):=Substitute(f,"FTest","FReplace"); + +FReplaceBack(f):=(Substitute(f[1])*Substitute(f[2])); +UnFence("FReplaceBack",1); +FFromInternal(f):=Substitute(f,"IsMulF","FReplaceBack"); + + +/* FLog(s,f):=[WriteString(s:" ");Write(f);NewLine();]; */ + FLog(s,f):=[]; + + +/* FSimpTerm simplifies the current term, wrt. trigonometric functions. */ +Rulebase("FSimpTerm",{f,rlist}); +UnFence("FSimpTerm",2); + +/* Addition: add all the subterms */ +Rule("FSimpTerm",2,1,Type(f) = "+") +[ + Local(result,lst); + lst:=Flatten(f,"+"); + + result:={{},{}}; +FLog("simpadd",lst); + + ForEach(tt,lst) + [ + Local(new); + new:=FSimpTerm(tt,{{},{}}); + result:={Concat(result[1],new[1]),Concat(result[2],new[2])}; + ]; + result; +]; + + +TrigNegate(f):= +[ + ListToFunction({f[0],-(f[1]),f[2]}); +]; + + +FUnTrig(result) := Substitute(result,"IsFTrig","TrigUnChange"); + +Rule("FSimpTerm",2,1,Type(f) = "-" And ArgumentsCount(f)=1) +[ + Local(result); + result:=FSimpTerm(f[1],{{},{}}); + Substitute(result,"IsFTrig","TrigNegate"); +]; +Rule("FSimpTerm",2,1,Type(f) = "-" And ArgumentsCount(f)=2) +[ + Local(result1,result2); + result1:=FSimpTerm(f[1],{{},{}}); + result2:=FSimpTerm(-(f[2]),{{},{}}); + {Concat(result1[1],result2[1]),Concat(result1[2],result2[2])}; +]; + +Rule("FSimpTerm",2,2,Type(f) = ":*:") +[ + FSimpFactor({Flatten(f,":*:")}); +]; +Rule("FSimpTerm",2,3,Type(f) = "FSin") +[ + {rlist[1],f:(rlist[2])}; +]; +Rule("FSimpTerm",2,3,Type(f) = "FCos") +[ + {f:(rlist[1]),rlist[2]}; +]; + +Rule("FSimpTerm",2,4,True) +[ + {(FCos(f,0)):(rlist[1]),rlist[2]}; +]; + +/* FSimpFactor does the difficult part. it gets a list, representing + factors, a*b*c -> {{a,b,c}}, and has to add terms from it. + Special cases to deal with: + - (a+b)*c -> a*c+b*c -> {{a,c},{b,c}} + - {a,b,c} where one of them is not a trig function or an addition: + replace with FCos(b,0), which is b*Cos(0) = b + - otherwise, combine two factors and make them into an addition. + - the lists should get shorter, but the number of lists should + get longer, until there are only single terms to be added. + */ +FSimpFactor(flist):= +[ + Local(rlist); + rlist:={{},{}}; + /* Loop over each term */ + While(flist != {}) + [ + Local(term); +FLog("simpfact",flist); + term:=First(flist); + flist:=Rest(flist); + FProcessTerm(term); + ]; +FLog("simpfact",flist); + +FLog("rlist",rlist); + rlist; +]; +UnFence("FSimpFactor",1); + + +Rulebase("FProcessTerm",{t}); +UnFence("FProcessTerm",1); + +/* Deal with (a+b)*c -> a*c+b*c */ +Rule("FProcessTerm",1,1,Type(t[1]) = "+") +[ + Local(split,term1,term2); + split:=t[1]; + term1:=FlatCopy(t); + term2:=FlatCopy(t); + term1[1]:=split[1]; + term2[1]:=split[2]; + DestructiveInsert(flist,1,term1); + DestructiveInsert(flist,1,term2); +]; +Rule("FProcessTerm",1,1,Type(t[1]) = "-" And ArgumentsCount(t[1]) = 2) +[ + Local(split,term1,term2); + split:=t[1]; + term1:=FlatCopy(t); + term2:=FlatCopy(t); + term1[1]:=split[1]; + term2[1]:=split[2]; + DestructiveInsert(term2,1,FCos(-1,0)); + DestructiveInsert(flist,1,term1); + DestructiveInsert(flist,1,term2); +]; + +Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "-" And ArgumentsCount(t[2]) = 2) +[ + Local(split,term1,term2); + split:=t[2]; + term1:=FlatCopy(t); + term2:=FlatCopy(t); + term1[2]:=split[1]; + term2[2]:=split[2]; + DestructiveInsert(term2,1,FCos(-1,0)); + DestructiveInsert(flist,1,term1); + DestructiveInsert(flist,1,term2); +]; + +Rule("FProcessTerm",1,1,Type(t[1]) = ":*:") +[ + Local(split,term); + split:=t[1]; + term:=FlatCopy(t); + term[1]:=split[1]; + DestructiveInsert(term,1,split[2]); + DestructiveInsert(flist,1,term); +]; + +Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = ":*:") +[ + Local(split,term); + split:=t[2]; + term:=FlatCopy(t); + term[2]:=split[1]; + DestructiveInsert(term,1,split[2]); + DestructiveInsert(flist,1,term); +]; + +Rule("FProcessTerm",1,1,Type(t[1]) = "-" And ArgumentsCount(t[1]) = 1) +[ + Local(split,term); + split:=t[1]; + term:=FlatCopy(t); + term[1]:=split[1]; + DestructiveInsert(term,1,FCos(-1,0)); + DestructiveInsert(flist,1,term); +]; +Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "-" And ArgumentsCount(t[2]) = 1) +[ + Local(split,term); + split:=t[2]; + term:=FlatCopy(t); + term[2]:=split[1]; + DestructiveInsert(term,1,FCos(-1,0)); + DestructiveInsert(flist,1,term); +]; + + +/* Deal with (a*(b+c) -> a*b+a*c */ +Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "+") +[ + Local(split,term1,term2); + split:=t[2]; + term1:=FlatCopy(t); + term2:=FlatCopy(t); + term1[2]:=split[1]; + term2[2]:=split[2]; + DestructiveInsert(flist,1,term1); + DestructiveInsert(flist,1,term2); +]; + + + +/* Deal with a*FCos(1,b) ->FCos(a,0)*FCos(1,b) */ +Rule("FProcessTerm",1,2,Not(IsFTrig(t[1])) ) +[ + t[1]:=FCos(t[1],0); + DestructiveInsert(flist,1,t); +]; +Rule("FProcessTerm",1,2,Length(t)>1 And Not(IsFTrig(t[2])) ) +[ + t[2]:=FCos(t[2],0); + DestructiveInsert(flist,1,t); +]; + + +Rule("FProcessTerm",1,4,Length(t)=1 And Type(t[1]) = "FCos") +[ + DestructiveInsert(rlist[1],1,t[1]); +]; +Rule("FProcessTerm",1,4,Length(t)=1 And Type(t[1]) = "FSin") +[ + DestructiveInsert(rlist[2],1,t[1]); +]; + +/* Now deal with the real meat: FSin*FCos etc. Reduce the multiplication + of the first two terms to an addition, adding two new terms to + the pipe line. + */ +Rule("FProcessTerm",1,5,Length(t)>1) +[ + Local(x,y,term1,term2,news); + x:=t[1]; + y:=t[2]; + news:=TrigSimpCombineB(x,y); + /* Drop one term */ + t:=Rest(t); + term1:=FlatCopy(t); + term2:=FlatCopy(t); + term1[1]:=news[1]; + term2[1]:=news[2]; + DestructiveInsert(flist,1,term1); + DestructiveInsert(flist,1,term2); +]; + +/* TrigSimpCombineB : take two FSin/FCos factors, and write them out into two terms */ +Rulebase("TrigSimpCombineB",{x,y}); +Rule("TrigSimpCombineB",2,1,Type(x) = "FCos" And Type(y) = "FCos") + { FCos((x[1]*y[1])/2,x[2]+y[2]) , FCos((x[1]*y[1])/2,x[2]-y[2]) }; +Rule("TrigSimpCombineB",2,1,Type(x) = "FSin" And Type(y) = "FSin") + { FCos(-(x[1]*y[1])/2,x[2]+y[2]) , FCos((x[1]*y[1])/2,x[2]-y[2]) }; +Rule("TrigSimpCombineB",2,1,Type(x) = "FSin" And Type(y) = "FCos") + { FSin((x[1]*y[1])/2,x[2]+y[2]) , FSin( (x[1]*y[1])/2,x[2]-y[2]) }; +Rule("TrigSimpCombineB",2,1,Type(x) = "FCos" And Type(y) = "FSin") + { FSin((x[1]*y[1])/2,x[2]+y[2]) , FSin(-(x[1]*y[1])/2,x[2]-y[2]) }; + + +Rulebase("TrigSimpCombine",{f}); +Rule("TrigSimpCombine",1,1,IsList(f)) + Map("TrigSimpCombine",{f}); + +Rule("TrigSimpCombine",1,10,True) +[ + Local(new,varlist); + new:=f; + + /* varlist is used for normalizing the trig. arguments */ + varlist:=VarList(f); + +/* Convert to internal format. */ + new:=FToInternal(new); +FLog("Internal",new); + + /* terms will contain FSin/FCos entries, the final result */ + + /* rlist gathers the true final result */ + Local(terms); + terms:=FSimpTerm(new,{{},{}}); + /* terms now contains two lists: terms[1] is the list of cosines, + and terms[2] the list of sines. + */ +FLog("terms",terms); + + /* cassoc and sassoc will contain the assoc lists with the cos/sin + arguments as key. + */ + Local(cassoc,sassoc); + cassoc:={}; + sassoc:={}; + ForEach(item,terms[1]) + [ + CosAdd(item); + ]; + ForEach(item,terms[2]) + [ + SinAdd(item); + ]; +FLog("cassoc",cassoc); +FLog("sassoc",sassoc); + + /* Now rebuild the normal form */ + Local(result); + result:=0; + +//Echo({cassoc}); +//Echo({sassoc}); + ForEach(item,cassoc) + [ +Log("item",item); + result:=result+Expand(FUnTrig(FFromInternal(item[2])))*Cos(item[1]); + ]; + ForEach(item,sassoc) + [ +Log("item",item); + result:=result+Expand(FUnTrig(FFromInternal(item[2])))*Sin(item[1]); + ]; + + result; +]; + + + +CosAdd(t):= +[ + Local(look,arg); + arg:=Expand(t[2],varlist); + look:=Assoc(arg,cassoc); + If(look = Empty, + [ + arg:=Expand(-arg,varlist); + look:=Assoc(arg,cassoc); + If(look = Empty, + DestructiveInsert(cassoc,1,{arg,t[1]}), + look[2]:=look[2]+t[1] + ); + ] + , + look[2]:=look[2]+t[1] + ); +]; +UnFence("CosAdd",1); + +SinAdd(t):= +[ + Local(look,arg); + arg:=Expand(t[2],varlist); + look:=Assoc(arg,sassoc); + If(look = Empty, + [ + arg:=Expand(-arg,varlist); + look:=Assoc(arg,sassoc); + If(look = Empty, + DestructiveInsert(sassoc,1,{arg,-(t[1])}), + look[2]:=look[2]-(t[1]) + ); + ] + , + look[2]:=look[2]+t[1] + ); +]; +UnFence("SinAdd",1); + + +/* +In( 4 ) = Exp(I*a)*Exp(I*a) +Out( 4 ) = Complex(Cos(a)^2-Sin(a)^2,Cos(a)*Sin(a)+Sin(a)*Cos(a)); +In( 5 ) = Exp(I*a)*Exp(-I*a) +Out( 5 ) = Complex(Cos(a)^2+Sin(a)^2,Sin(a)*Cos(a)-Cos(a)*Sin(a)); + +In( 5 ) = Exp(I*a)*Exp(I*b) +Out( 5 ) = Complex(Cos(a)*Cos(b)-Sin(a)*Sin(b),Cos(a)*Sin(b)+Sin(a)*Cos(b)); +In( 6 ) = Exp(I*a)*Exp(-I*b) +Out( 6 ) = Complex(Cos(a)*Cos(b)+Sin(a)*Sin(b),Sin(a)*Cos(b)-Cos(a)*Sin(b)); + + +*/ + + + +%/mathpiper + + + +%mathpiper_docs,name="TrigSimpCombine",categories="User Functions;Expression Simplification" +*CMD TrigSimpCombine --- combine products of trigonometric functions +*STD +*CALL + TrigSimpCombine(expr) + +*PARMS + +{expr} -- expression to simplify + +*DESC + +This function applies the product rules of trigonometry, e.g. +$Cos(u)*Sin(v) = (1/2)*(Sin(v-u) + Sin(v+u))$. As a +result, all products of the trigonometric functions {Cos} and {Sin} disappear. The function also tries to simplify the resulting expression as much as +possible by combining all similar terms. + +This function is used in for instance {Integrate}, +to bring down the expression into a simpler form that hopefully can be +integrated easily. + +*E.G. + +In> PrettyPrinterSet("PrettyForm"); + + True + +In> TrigSimpCombine(Cos(a)^2+Sin(a)^2) + + 1 + +In> TrigSimpCombine(Cos(a)^2-Sin(a)^2) + + Cos( -2 * a ) + +Result: +In> TrigSimpCombine(Cos(a)^2*Sin(b)) + + Sin( b ) Sin( -2 * a + b ) + -------- + ----------------- + 2 4 + + Sin( -2 * a - b ) + - ----------------- + 4 + +*SEE Simplify, Integrate, Expand, Sin, Cos, Tan +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/BigOh.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/BigOh.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/BigOh.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/BigOh.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="BigOh" + +10 # BigOh(UniVariate(_var,_first,_coefs),_var,_degree) <-- + [ + While(first+Length(coefs)>=(degree+1) And Length(coefs)>0) DestructiveDelete(coefs,Length(coefs)); + UniVariate(var,first,coefs); + ]; +20 # BigOh(_uv,_var,_degree)_CanBeUni(uv,var) <-- NormalForm(BigOh(MakeUni(uv,var),var,degree)); + +%/mathpiper + + + +%mathpiper_docs,name="BigOh",categories="User Functions;Series" +*CMD BigOh --- drop all terms of a certain order in a polynomial +*STD +*CALL + BigOh(poly, var, degree) + +*PARMS + +{poly} -- a univariate polynomial + +{var} -- a free variable + +{degree} -- positive integer + +*DESC + +This function drops all terms of order "degree" or higher in +"poly", which is a polynomial in the variable "var". + +*E.G. + +In> BigOh(1+x+x^2+x^3,x,2) +Result: x+1; + +*SEE Taylor, InverseTaylor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/CanBeUni.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/CanBeUni.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/CanBeUni.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/CanBeUni.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,36 @@ +%mathpiper,def="CanBeUni" + +/* CanBeUni returns whether the function can be converted to a + * univariate, with respect to a variable. + */ +Function("CanBeUni",{expression}) CanBeUni(UniVarList(expression),expression); + + +/* Accepting an expression as being convertable to univariate */ + +/* Dealing wiht a list of variables. The poly should be expandable + * to each of these variables (smells like tail recursion) + */ +10 # CanBeUni({},_expression) <-- True; +20 # CanBeUni(var_IsList,_expression) <-- + CanBeUni(First(var),expression) And CanBeUni(Rest(var),expression); + +/* Atom can always be a polynom to any variable */ +30 # CanBeUni(_var,expression_IsAtom) <-- True; +35 # CanBeUni(_var,expression_IsFreeOf(var)) <-- True; + +/* Other patterns supported. */ +40 # CanBeUni(_var,_x + _y) <-- CanBeUni(var,x) And CanBeUni(var,y); +40 # CanBeUni(_var,_x - _y) <-- CanBeUni(var,x) And CanBeUni(var,y); +40 # CanBeUni(_var, + _y) <-- CanBeUni(var,y); +40 # CanBeUni(_var, - _y) <-- CanBeUni(var,y); +40 # CanBeUni(_var,_x * _y) <-- CanBeUni(var,x) And CanBeUni(var,y); +40 # CanBeUni(_var,_x / _y) <-- CanBeUni(var,x) And IsFreeOf(var,y); +/* Special case again: raising powers */ +40 # CanBeUni(_var,_x ^ y_IsInteger)_(y >= 0 And CanBeUni(var,x)) <-- True; +41 # CanBeUni(_var,(x_IsFreeOf(var)) ^ (y_IsFreeOf(var))) <-- True; +50 # CanBeUni(_var,UniVariate(_var,_first,_coefs)) <-- True; +1000 # CanBeUni(_var,_f)_(Not(IsFreeOf(var,f))) <-- False; +1001 # CanBeUni(_var,_f) <-- True; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Coef.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Coef.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Coef.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Coef.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper,def="Coef" + +5 # Coef(uv_IsUniVar,order_IsList) <-- +[ + Local(result); + result:={}; + ForEach(item,order) + [ + DestructiveAppend(result,Coef(uv,item)); + ]; + result; +]; + +10 # Coef(uv_IsUniVar,order_IsInteger)_(order=uv[2]+Length(uv[3])) <-- 0; +20 # Coef(uv_IsUniVar,order_IsInteger) <-- uv[3][(order-uv[2])+1]; +30 # Coef(uv_CanBeUni,_order)_(IsInteger(order) Or IsList(order)) <-- Coef(MakeUni(uv),order); + +Function("Coef",{expression,var,order}) + NormalForm(Coef(MakeUni(expression,var),order)); + + + +%/mathpiper + + + +%mathpiper_docs,name="Coef",categories="User Functions;Polynomials (Operations)" +*CMD Coef --- coefficient of a polynomial +*STD +*CALL + Coef(expr, var, order) + +*PARMS + +{expr} -- a polynomial + +{var} -- a variable occurring in "expr" + +{order} -- integer or list of integers + +*DESC + +This command returns the coefficient of "var" to the power "order" +in the polynomial "expr". The parameter "order" can also be a list +of integers, in which case this function returns a list of +coefficients. + +*E.G. + +In> e := Expand((a+x)^4,x) +Result: x^4+4*a*x^3+(a^2+(2*a)^2+a^2)*x^2+ + (a^2*2*a+2*a^3)*x+a^4; +In> Coef(e,a,2) +Result: 6*x^2; +In> Coef(e,a,0 .. 4) +Result: {x^4,4*x^3,6*x^2,4*x,1}; + +*SEE Expand, Degree, LeadingCoef +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/CollectOn.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/CollectOn.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/CollectOn.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/CollectOn.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,62 @@ +%mathpiper,def="CollectOn" + +//::: Collect terms of a polynomial-like expression on powers of var, +// starting with power 0. + +//Retract("CollectOn",*); + +10 # CollectOn(_var,_expr)_(CanBeUni(var,expr)) <-- +[ + If(InVerboseMode(),Echo("<< Collect on: ",var," in expression ",expr)); + + Local(u,a); + u := MakeUni(expr,var); + If( u[2] > 0, + [ a := FillList(0,u[2]); u[3] := Concat(a,u[3]); u[2] := 0; ] + ); + u[3]; +]; + +%/mathpiper + + + + + +%mathpiper_docs,name="CollectOn",categories="User Functions;Polynomials (Operations)" +*CMD CollectOn -- Collect terms of a polynomial-like expression on powers of {var}, starting with power 0. + +*CALL +CollectOn( var, expr ) +*PARMS +{var} -- The variable on which to collect +{expr} -- a polynomial-like expression containing one or more terms in variable {var} +*DESC +This function collects the terms of {expr} into a list according to the power of +variable {var}. The list always begins with the zeroth power in {var} and +contains {n+1} elements, where {n} is the highest power of {var} present in {expr}. + + +*E.G. +In> CollectOn(x,2*x-2*y-a*x+x*y) +Result: {-2*y,2-a+y} + NOTE 1: This result indicates that the given expression could be rewritten in + the form -2*y+(2-a+y)*x. + NOTE 2: If P is the list output by a call to CollectOn, this rewriting could + be done by evaluating Dot(P,FillList(var,Length(P))^(0 .. Length(P)-1)). + +In> CollectOn(y,2*x-2*y-a*x+x*y) +Result: {2*x-a*x,x-2} + NOTE 1: This result indicates that the given expression could be rewritten in + the form (2*x-a*x)+(x-2)*y. + NOTE 2: The collection is ONLY made on the given variable; any other variable + is not collected further. + +*SEE +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Content.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Content.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Content.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Content.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,39 @@ +%mathpiper,def="Content" + +10 # Content(UniVariate(_var,_first,_coefs)) <-- Gcd(coefs)*var^first; +20 # Content(poly_CanBeUni) <-- NormalForm(Content(MakeUni(poly))); + +%/mathpiper + + + +%mathpiper_docs,name="Content",categories="User Functions;Polynomials (Operations)" +*CMD Content --- content of a univariate polynomial +*STD +*CALL + Content(expr) + +*PARMS + +{expr} -- univariate polynomial + +*DESC + +This command determines the content of a univariate polynomial. The +content is the greatest common divisor of all the terms in the +polynomial. Every polynomial can be written as the product of the +content with the primitive part. + +*E.G. + +In> poly := 2*x^2 + 4*x; +Result: 2*x^2+4*x; +In> c := Content(poly); +Result: 2*x; +In> pp := PrimitivePart(poly); +Result: x+2; +In> Expand(pp*c); +Result: 2*x^2+4*x; + +*SEE PrimitivePart, Gcd +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/cyclotomic/Cyclotomic.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/cyclotomic/Cyclotomic.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/cyclotomic/Cyclotomic.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/cyclotomic/Cyclotomic.mpw 2010-01-07 02:48:04.000000000 +0000 @@ -0,0 +1,226 @@ +%mathpiper,def="Cyclotomic" + +// Cyclotomic(n,x): +// Returns the cyclotomic polinomial in the variable x +// (which is the minimal polynomial of the n-th primitive +// roots of the unit). +// Autor: Pablo De Napoli + +LoadScriptOnce("univar.rep/code.mpi"); + +// Auxiliar function for Cyclotomic: returns the internal representation of +// x^q+a as an univarate polinomial (like MakeUni(x^q+a) but more efficient) + +Function ("UniVariateBinomial",{x,q,a}) +[ +Local(L,i); +L := {a}; +For (i:=1,i0,i--) + [ + Local(term); + exponent := first+i-1; + c:= coefs[i]; + nc := If(IsEven(exponent),c,-c); + term:=NormalForm(nc*var^(exponent*k)); + result:=result+term; + ]; + result; +]; + +// Returns a list of elements of the form {d1,d2,m} +// where +// 1) d1,d2 runs through the square free divisors of n +// 2) d1 divides d2 and d2/d1 is a prime factor of n +// 3) m=Moebius(d1) +// Addapted form: MoebiusDivisorsList + +CyclotomicDivisorsList(n_IsPositiveInteger) <-- +[ + Local(nFactors,f,result,oldresult,x); + nFactors:= Factors(n); + result := {{1,nFactors[1][1],1}}; + nFactors := Rest(nFactors); + ForEach (f,nFactors) + [ + oldresult := result; + ForEach (x,oldresult) + result:=Append(result,{x[1]*f[1],x[2]*f[1],-x[3]}); + ]; + result; +]; + +// CyclotomicFactor(x,a,b): Auxiliary function that constructs the term list of +// the polynomial +// Quotient(x^a-1,x^b-1) = +// x^(b*(p-1)) + x^(b^*(p-2)) + ... + x^(b) + 1 +// p= a/b, b should divide a + + +CyclotomicFactor(_a,_b) <-- +[ + Local(coef,p,i,j,result); p := a/b; result:= {{b*(p-1),1}}; For (i:= + p-2,i>=0,i--) + DestructiveAppend(result,{b*i,1}); + result; +]; + + + +// This new implementation makes use of the internal representations of univariate +// polynomials as SparseUniVar(var,termlist). + + +// For n even, we write n= m*k, where k is a Power of 2 +// and m is odd, and redce it to the case m even since: +// +// Cyclotomic(n,x) = Cyclotomic(m,-x^{k/2}) +// +// If m=1, n is a power of 2, and Cyclotomic(n,x)= x^k+1 */ + + +10 # InternalCyclotomic(n_IsEven,_x) <-- + [ + Local(k,m,result,p,t); + k := 1; + m := n; + While(IsEven(m)) + [ + k := k*2; + m := m/2; + ]; + k := k/2 ; + If(m>1, [ + p:= InternalCyclotomic(m,x)[2]; + // Substitute x by -x^k + result:={}; + ForEach(t,p) + DestructiveAppend(result, {t[1]*k,If(IsEven(t[1]),t[2],-t[2])}); + ], + result := {{k,1},{0,1}} // x^k+1 + ); + SparseUniVar(x,result); + ]; + + +// For n odd, the algoritm is based on the formula +// +// Cyclotomic(n,x) := Prod (x^(n/d)-1)^Moebius(d) +// +// where d runs through the divisors of n. + +// We compute in poly1 the product +// of (x^(n/d)-1) with Moebius(d)=1 , and in poly2 the product of these polynomials +// with Moebius(d)=-1. Finally we compute the quotient poly1/poly2 + +// In order to compute this in a efficient way, we use the functions +// CyclotomicDivisorsList and CyclotomicFactors (in order to avoid +// unnecesary polynomial divisions) + + +20 # InternalCyclotomic(n_IsOdd,_x)_(n>1) <-- +[ + Local(divisors,poly1,poly2,q,d,f,coef,i,j,result); + divisors := CyclotomicDivisorsList(n); + poly1 := {{0,1}}; + poly2 := {{0,1}}; + ForEach (d,divisors) + [ + If(InVerboseMode(),Echo("d=",d)); + f:= CyclotomicFactor(n/d[1],n/d[2]); + If (d[3]=1,poly1:=MultiplyTerms(poly1,f),poly2:=MultiplyTerms(poly2,f)); + If(InVerboseMode(), + [ + Echo("poly1=",poly1); + Echo("poly2=",poly2); + ]); + ]; + If(InVerboseMode(),Echo("End ForEach")); + result := If(poly2={{0,1}},poly1,DivTermList(poly1,poly2)); + SparseUniVar(x,result); +]; + + +10 # Cyclotomic(1,_x) <-- x-1; +20 # Cyclotomic(n_IsInteger,_x) <-- ExpandSparseUniVar(InternalCyclotomic(n,x)); + + + +%/mathpiper + + + +%mathpiper_docs,name="Cyclotomic",categories="User Functions;Number Theory" +*CMD Cyclotomic --- construct the cyclotomic polynomial +*STD +*CALL + Cyclotomic(n,x) + +*PARMS + +{n} -- positive integer + +{x} -- variable + +*DESC + +Returns the cyclotomic polynomial in the variable {x} +(which is the minimal polynomial of the $n$-th primitive +roots of the unit, over the field of rational numbers). + +For $n$ even, we write $n= m*k$, where $k$ is a power of $2$ +and $m$ is odd, and reduce it to the case of even $m$ since +$$ Cyclotomic(n,x) = Cyclotomic(m,-x^(k/2)) $$. + +If $m=1$, $n$ is a power of $2$, and $Cyclotomic(n,x)= x^k+1$. + +For $n$ odd, the algorithm is based on the formula +$$ Cyclotomic(n,x) := Prod((x^(n/d)-1)^mu(d)) $$, +where $d$ runs through the divisors of $n$. +In order to compute this in a efficient way, we use the function +{MoebiusDivisorsList}. Then we compute in {poly1} the product +of $x^(n/d)-1$ with $mu(d)=1$ , and in {poly2} the product of these polynomials +with $mu(d)= -1$. Finally we compute the quotient {poly1}/{poly2}. + +*SEE RamanujanSum +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/cyclotomic/OldCyclotomic.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/cyclotomic/OldCyclotomic.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/cyclotomic/OldCyclotomic.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/cyclotomic/OldCyclotomic.mpw 2010-01-06 02:51:37.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="OldCyclotomic" + +// OldInternalCyclotomic(n,x,WantNormalForm) is the internal implementation +// WantNormalForm is a boolean parameter. If it is true, returns the normal +// form, if it is false returns the UniVariate representation. + +// This (old) implementation makes use of the internal representations of univariate +// polynomials as UniVariate(var,begining,coefficients). +// There is also a version UniVariateCyclotomic(n,x) that returns the +// cyclotomic polynomial in the UniVariate representation. + + +10 # OldInternalCyclotomic(n_IsEven,_x,WantNormalForm_IsBoolean) <-- + [ + Local(k,m,p); + k := 1; + m := n; + While(IsEven(m)) + [ + k := k*2; + m := m/2; + ]; + k := k/2 ; + If(m>1, [ + p := OldInternalCyclotomic(m,x,False); + If (WantNormalForm, SubstituteAndExpandInUniVar(p,k),SubstituteInUniVar(p,k)); + ], + If (WantNormalForm, x^k+1, UniVariateBinomial(x,k,1)) + ); + ]; + +20 # OldInternalCyclotomic(n_IsOdd,_x,WantNormalForm_IsBoolean)_(n>1) <-- +[ + Local(divisors,poly1,poly2,q,d,f,result); + divisors := MoebiusDivisorsList(n); + poly1 :=1 ; + poly2 := 1; + ForEach (d,divisors) + [ + q:=n/d[1]; + f:=UniVariateBinomial(x,q,-1); + If (d[2]=1,poly1:=poly1*f,poly2:=poly2*f); + ]; + result := Quotient(poly1,poly2); + If(WantNormalForm,NormalForm(result),result); +]; + +10 # OldCyclotomic(1,_x) <-- _x-1; +20 # OldCyclotomic(n_IsInteger,_x) <-- OldInternalCyclotomic(n,x,True); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/cyclotomic/UniVariateCyclotomic.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/cyclotomic/UniVariateCyclotomic.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/cyclotomic/UniVariateCyclotomic.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/cyclotomic/UniVariateCyclotomic.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,9 @@ +%mathpiper,def="UniVariateCyclotomic" + +// This function returns the Cyclotomic polynomial, but in the univariate +// representation + +10 # UniVariateCyclotomic(1,_x) <-- UniVariate(x,0,{-1,1}); +20 # UniVariateCyclotomic(n_IsInteger,_x) <-- OldInternalCyclotomic(n,x,False); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Degree.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Degree.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Degree.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Degree.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,97 @@ +%mathpiper,def="Degree" + +//Retract("Degree",*); + +Rulebase("Degree",{expr}); +Rule("Degree",1,0, IsUniVar(expr)) +[ + + Local(i,min,max); + min:=expr[2]; + max:=min+Length(expr[3]); + i:=max; + While(i >= min And IsZero(Coef(expr,i))) i--; + i; +]; + +10 # Degree(poly_CanBeUni) <-- Degree(MakeUni(poly)); + +10 # Degree(_poly,_var)_(CanBeUni(var,poly)) <-- Degree(MakeUni(poly,var)); + +20 # Degree(_poly,_var)_(Type(poly)="Sqrt") <-- Degree(poly^2,var)/2; + +20 # Degree(_poly,_var)_(FunctionToList(poly)[1]= ^) <-- +[ + Local(ex,pwr,deg); + ex := FunctionToList(poly)[3]; + pwr := 1/ex; + //Tell(" ",{ex,pwr}); + deg := Degree(poly^pwr,var); + //Tell(" ",deg); + deg*ex; +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + +%mathpiper_docs,name="Degree",categories="User Functions;Polynomials (Operations)" +*CMD Degree --- degree of a polynomial +*STD +*CALL + Degree(expr) + Degree(expr, var) + +*PARMS + +{expr} -- a polynomial + +{var} -- a variable occurring in "expr" + +*DESC + +This command returns the degree of the polynomial "expr" with +respect to the variable "var". The degree is the highest power of +"var" occurring in the polynomial. If only one variable occurs in +"expr", the first calling sequence can be used. Otherwise the user +should use the second form in which the variable is explicitly +mentioned. + +If {expr} is not a polynomial in the accepted sense of the word, +this command will return unevaluated. In particular, if {expr} +contains negative powers of the variable, it is not a polynomial. + +However, if {expr} is a simple root of a polynomial -- i.e., of +the form poly^(1/n), and {poly} is of degree n in {var}, then the +call {Degree(expr,var)} will correctly identify the "degree" of +this non-polynomial. + +*E.G. +In> Degree(x^5+x-1) +Result: 5 + +In> Degree(a+b*x^3, a) +Result: 1 + +In> Degree(a+b*x^3, x) +Result: 3 + +In> Degree(x^-2+x-1) +Result: Degree(x^(-2)+x-1) + +In> Degree( (Sqrt(2)*x^2*(x+3))^(1/3),x) +Result: 1 + +*SEE Expand, Coef +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/DivPoly.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/DivPoly.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/DivPoly.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/DivPoly.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,33 @@ +%mathpiper,def="DivPoly" + +DivPoly(_A,_B,_var,_deg) <-- +[ + Local(a,b,c,i,j,denom); + b:=MakeUni(B,var); + denom:=Coef(b,0); + + if (denom = 0) + [ + Local(f); + f:=Content(b); + b:=PrimitivePart(b); + A:=Simplify(A/f); + denom:=Coef(b,0); + ]; + a:=MakeUni(A,var); + + c:=FillList(0,deg+1); + For(i:=0,i<=deg,i++) + [ + Local(sum,j); + sum:=0; + For(j:=0,j0,i--) + [ + Local(term); + term:=NormalForm(coefs[i])*var^(first+i-1); + result:=result+term; + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/FactorUniVar.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/FactorUniVar.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/FactorUniVar.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/FactorUniVar.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Horner.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Horner.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Horner.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Horner.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,59 @@ +%mathpiper,def="Horner" + +Horner(_e,_v) <-- +[ + Local(uni,coefs,result); + uni := MakeUni(e,v); + coefs:=DestructiveReverse(uni[3]); + result:=0; + + While(coefs != {}) + [ + result := result*v; + result := result+First(coefs); + coefs := Rest(coefs); + ]; + result:=result*v^uni[2]; + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="Horner",categories="User Functions;Polynomials (Operations)" +*CMD Horner --- convert a polynomial into the Horner form +*STD +*CALL + Horner(expr, var) + +*PARMS + +{expr} -- a polynomial in "var" + +{var} -- a variable + +*DESC + +This command turns the polynomial "expr", considered as a univariate +polynomial in "var", into Horner form. A polynomial in normal form +is an expression such as +$$c[0] + c[1]*x + ... + c[n]*x^n$$. + +If one converts this polynomial into Horner form, one gets the +equivalent expression +$$(...( c[n] * x + c[n-1] ) * x + ... + c[1] ) * x + c[0]$$. + +Both expression are equal, but the latter form gives a more +efficient way to evaluate the polynomial as the powers have +disappeared. + +*E.G. + +In> expr1:=Expand((1+x)^4) +Result: x^4+4*x^3+6*x^2+4*x+1; +In> Horner(expr1,x) +Result: (((x+4)*x+6)*x+4)*x+1; + +*SEE Expand, ExpandBrackets, EvaluateHornerScheme +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/IsUniVar.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/IsUniVar.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/IsUniVar.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/IsUniVar.mpw 2010-01-06 01:59:24.000000000 +0000 @@ -0,0 +1,75 @@ +%mathpiper,def="IsUniVar" + +10 # IsUniVar(UniVariate(_var,_first,_coefs)) <-- True; +20 # IsUniVar(_anything) <-- False; + +200 # aLeft_IsUniVar ^ aRight_IsPositiveInteger <-- + RepeatedSquaresMultiply(aLeft,aRight); + + +200 # aLeft_IsUniVar - aRight_IsUniVar <-- +[ + Local(from,result); + Local(curl,curr,left,right); + + curl:=aLeft[2]; + curr:=aRight[2]; + left:=aLeft[3]; + right:=aRight[3]; + result:={}; + from:=Minimum(curl,curr); + + While(curl poly := 2*x^2 + 4*x; +Result: 2*x^2+4*x; +In> lc := LeadingCoef(poly); +Result: 2; +In> m := Monic(poly); +Result: x^2+2*x; +In> Expand(lc*m); +Result: 2*x^2+4*x; + +In> LeadingCoef(2*a^2 + 3*a*b^2 + 5, a); +Result: 2; +In> LeadingCoef(2*a^2 + 3*a*b^2 + 5, b); +Result: 3*a; + +*SEE Coef, Monic + +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/MakeUni.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/MakeUni.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/MakeUni.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/MakeUni.mpw 2010-01-07 03:14:36.000000000 +0000 @@ -0,0 +1,51 @@ +%mathpiper,def="MakeUni" + +Function("MakeUni",{expression}) MakeUni(expression,UniVarList(expression)); + +/* Convert normal form to univariate expression */ +Rulebase("MakeUni",{expression,var}); + +5 # MakeUni(_expr,{}) <-- UniVariate(dummyvar,0,{expression}); +6 # MakeUni(_expr,var_IsList) <-- +[ + Local(result,item); + result:=expression; + ForEach(item,var) + [ + result:=MakeUni(result,item); + ]; + result; +]; + +10 # MakeUni(UniVariate(_var,_first,_coefs),_var) <-- + UniVariate(var,first,coefs); + +20 # MakeUni(UniVariate(_v,_first,_coefs),_var) <-- +[ + Local(reslist,item); + reslist:={}; + ForEach(item,expression[3]) + [ + If(IsFreeOf(var,item), + DestructiveAppend(reslist,item), + DestructiveAppend(reslist,MakeUni(item,var)) + ); + ]; + UniVariate(expression[1],expression[2],reslist); +]; + + +LocalSymbols(a,b,var,expression) +[ + 20 # MakeUni(expression_IsFreeOf(var),_var) + <-- UniVariate(var,0,{expression}); + 30 # MakeUni(_var,_var) <-- UniVariate(var,1,{1}); + 30 # MakeUni(_a + _b,_var) <-- MakeUni(a,var) + MakeUni(b,var); + 30 # MakeUni(_a - _b,_var) <-- MakeUni(a,var) - MakeUni(b,var); + 30 # MakeUni( - _b,_var) <-- - MakeUni(b,var); + 30 # MakeUni(_a * _b,_var) <-- MakeUni(a,var) * MakeUni(b,var); + 1 # MakeUni(_a ^ n_IsInteger,_var) <-- MakeUni(a,var) ^ n; + 30 # MakeUni(_a / (b_IsFreeOf(var)),_var) <-- MakeUni(a,var) * (1/b); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Monic.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Monic.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/Monic.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/Monic.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,56 @@ +%mathpiper,def="Monic" + +10 # Monic(UniVariate(_var,_first,_coefs)) <-- +[ + DropEndZeroes(coefs); + UniVariate(var,first,coefs/coefs[Length(coefs)]); +]; +20 # Monic(poly_CanBeUni) <-- NormalForm(Monic(MakeUni(poly))); + +30 # Monic(_poly,_var)_CanBeUni(poly,var) <-- NormalForm(Monic(MakeUni(poly,var))); + +%/mathpiper + + + +%mathpiper_docs,name="Monic",categories="User Functions;Polynomials (Operations)" +*CMD Monic --- monic part of a polynomial +*STD +*CALL + Monic(poly) + Monic(poly, var) + +*PARMS + +{poly} -- a polynomial + +{var} -- a variable + +*DESC + +This function returns the monic part of "poly", regarded as a +polynomial in the variable "var". The monic part of a polynomial is +the quotient of this polynomial by its leading coefficient. So the +leading coefficient of the monic part is always one. If only one +variable appears in the expression "poly", it is obvious that it +should be regarded as a polynomial in this variable and the first +calling sequence may be used. + +*E.G. + +In> poly := 2*x^2 + 4*x; +Result: 2*x^2+4*x; +In> lc := LeadingCoef(poly); +Result: 2; +In> m := Monic(poly); +Result: x^2+2*x; +In> Expand(lc*m); +Result: 2*x^2+4*x; + +In> Monic(2*a^2 + 3*a*b^2 + 5, a); +Result: a^2+(a*3*b^2)/2+5/2; +In> Monic(2*a^2 + 3*a*b^2 + 5, b); +Result: b^2+(2*a^2+5)/(3*a); + +*SEE LeadingCoef +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/NormalForm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/NormalForm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/NormalForm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/NormalForm.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,12 @@ +%mathpiper,def="" + +/* +Note:tk:since this version of NormalForm is only used in univariate functions, and since + the standard version of NormalForm is published as a def in standard.mpw, +I am not publishing it as a def here. +*/ + +0 # NormalForm(UniVariate(_var,_first,_coefs)) <-- + ExpandUniVariate(var,first,coefs); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/PrimitivePart.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/PrimitivePart.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/PrimitivePart.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/PrimitivePart.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="PrimitivePart" + +10 # PrimitivePart(UniVariate(_var,_first,_coefs)) <-- + UniVariate(var,0,coefs/Gcd(coefs)); +20 # PrimitivePart(poly_CanBeUni) <-- NormalForm(PrimitivePart(MakeUni(poly))); + +%/mathpiper + + + +%mathpiper_docs,name="PrimitivePart",categories="User Functions;Polynomials (Operations)" +*CMD PrimitivePart --- primitive part of a univariate polynomial +*STD +*CALL + PrimitivePart(expr) + +*PARMS + +{expr} -- univariate polynomial + +*DESC + +This command determines the primitive part of a univariate +polynomial. The primitive part is what remains after the content (the +greatest common divisor of all the terms) is divided out. So the +product of the content and the primitive part equals the original +polynomial. + +*E.G. + +In> poly := 2*x^2 + 4*x; +Result: 2*x^2+4*x; +In> c := Content(poly); +Result: 2*x; +In> pp := PrimitivePart(poly); +Result: x+2; +In> Expand(pp*c); +Result: 2*x^2+4*x; + +*SEE Content +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/RepeatedSquaresMultiply.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/RepeatedSquaresMultiply.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/RepeatedSquaresMultiply.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/RepeatedSquaresMultiply.mpw 2010-05-10 07:37:46.000000000 +0000 @@ -0,0 +1,26 @@ +%mathpiper,def="RepeatedSquaresMultiply" + +/* Repeated squares multiplication + TODO put somewhere else!!! + */ +10 # RepeatedSquaresMultiply(_a,- (n_IsInteger)) <-- 1/RepeatedSquaresMultiply(a,n); + +15 # RepeatedSquaresMultiply(UniVariate(_var,_first,{_coef}),(n_IsInteger)) <-- + UniVariate(var,first*n,{coef^n}); +20 # RepeatedSquaresMultiply(_a,n_IsInteger) <-- +[ + Local(m,b); + Bind(m,1); + Bind(b,1); + While(m<=n) Bind(m,(ShiftLeft(m,1))); + Bind(m, ShiftRight(m,1)); + While(m>0) + [ + Bind(b,b*b); + If (Not(IsEqual(BitAnd(m,n), 0)),Bind(b,b*a)); + Bind(m, ShiftRight(m,1)); + ]; + b; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/SetOrder.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/SetOrder.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/SetOrder.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/SetOrder.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,5 @@ +%mathpiper,def="" + +//Not implemented in scripts. todo:tk. + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/AddTerm.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/AddTerm.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/AddTerm.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/AddTerm.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,41 @@ +%mathpiper,def="AddTerm" + +/* +Note:tk:I am publishing this function as a def because +but it seems like it was meant to be a published function. +*/ + +// Add a term into a termlist: this function assumes that +// 1) the list of terms is sorted in decreasing order of exponents +// 2) there are not two terms with the same exponent. +// 3) There is no term with cero coefficient +// This assumptions are preserved. + +// The parameter begining tell us where to begin the search +// (it is used for increasing the efficency of the algorithms!) +// The function returns the position at which the new term is added plus 1. +// (to be used as begining for sucesive AddTerm calls + +Function("AddTerm",{termlist,term,begining}) +[ + Local(l,i); + l := Length(termlist); + If(term[2]!=0, + [ + i:=begining; +// Fix-me: search by using binary search ? + If (l>=1, While ((i<=l) And (term[1]l, [DestructiveAppend(termlist,term);i++;], + If (term[1]=termlist[i][1], + [ Local(nc); + nc:=termlist[i][2]+term[2]; + If(nc!=0,DestructiveReplace(termlist,i,{term[1],nc}), + [DestructiveDelete(termlist,i);i--;]); + ], DestructiveInsert(termlist,i,term)) + ); + ] + ); + i+1; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/AddTerms.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/AddTerms.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/AddTerms.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/AddTerms.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,17 @@ +%mathpiper,def="AddTerms" + +/* +Note:tk:I am publishing this function as a def because +but it seems like it was meant to be a published function. +*/ + +Function("AddTerms",{terms1,terms2}) +[ + Local(result,begining,t); + begining :=1; + ForEach (t,terms2) + begining :=AddTerm(terms1,t,begining); + terms1; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/DivTermList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/DivTermList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/DivTermList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/DivTermList.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="DivTermList" + +// Implements the division of polynomials! + +Function("DivTermList",{a,b}) +[ + Local(q,nq,t,c,begining); + q := {}; + // a[1][1] is the degree of a, b[1][1] is the degree of b + While ((a!={}) And a[1][1]>=b[1][1]) + [ + begining := 1; + If(InVerboseMode(),Echo("degree=",a[1][1])); + nq := {a[1][1]-b[1][1],a[1][2]/b[1][2]}; // a new term of the quotient + DestructiveAppend(q,nq); + // We compute a:= a - nq* b + ForEach (t,b) + begining := AddTerm(a,{t[1]+nq[1],-t[2]*nq[2]},begining); + ]; + // a is the rest at the end + q; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/ExpandSparseUniVar.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/ExpandSparseUniVar.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/ExpandSparseUniVar.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/ExpandSparseUniVar.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,18 @@ +%mathpiper,def="ExpandSparseUniVar" + +Function("ExpandSparseUniVar",{s}) +[ + Local(result,t,var,termlist); + result :=0; + var := s[1]; + termlist := s[2]; + ForEach (t,termlist) + [ + Local(term); + term := NormalForm(t[2]*var^t[1]); + result := result + term; + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/MakeSparseUniVar.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/MakeSparseUniVar.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sparse/MakeSparseUniVar.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sparse/MakeSparseUniVar.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,29 @@ +%mathpiper,def="MakeSparseUniVar" + +//Retract("MakeSparseUniVar",*); + +10 # MakeSparseUniVar(poly_CanBeUni,var_IsAtom) <-- +[ + If(InVerboseMode(),Tell("MakeSparseUniVar",{var,poly})); + Local(uni,first,coeffs,n,c,lc,termlist,term); + uni := MakeUni(poly,var); + If(InVerboseMode(),Tell(" ",uni)); + first := uni[2]; + coeffs := (uni[3]); + If(InVerboseMode(),[Tell(" ",first); Tell(" ",coeffs);]); + termlist := {}; + lc := Length(coeffs); + For(n:=0,n0 And Contains(vlcc,var), zeroRoot:=True,zeroRoot:=False); + p:=SquareFree(Rationalize(pp)); + If(iDebug,Tell(" after sqf",p)); + minb := MinimumBound(p); + maxb := MaximumBound(p); + If(iDebug,Tell(" ",{minb,maxb})); + rr := FindRealRoots(p,minb,maxb); + If(zeroRoot,DestructiveAppend(rr,0)); + rr; +]; + + +FindRealRoots(_p,_Mmin,_Mmax) <-- +[ + If(iDebug,Tell(" FindRealRoots3",{p,Mmin,Mmax})); + Local(bounds,result,i,prec,requiredPrec); + bounds := BoundRealRoots(p,Mmin,Mmax); + If(iDebug,Tell(" ",{bounds,Length(bounds)})); + result:=FillList(0,Length(bounds)); + requiredPrec := BuiltinPrecisionGet(); + BuiltinPrecisionSet(BuiltinPrecisionGet()+4); + prec:=10^-(requiredPrec+1); + + For(i:=1,i<=Length(bounds),i++) + [ + If(iDebug,Tell(i)); + Local(a,b,c,r); + {a,b} := bounds[i]; + c:=N(Eval((a+b)/2)); + If(iDebug,Tell(" ",{a,b,c})); + r := Fail; + If(iDebug,Tell(" newt1",`Hold(Newton(@p,x,@c,@prec,@a,@b)))); + if (a != b) [r := `Newton(@p,x,@c,prec,a,b);]; + If(iDebug,Tell(" newt2",r)); + if (r = Fail) + [ + Local(c,cold,pa,pb,pc); + pa:=(p Where x==a); + pb:=(p Where x==b); + c:=((a+b)/2); + cold := a; + While (Abs(cold-c)>prec) + [ + pc:=(p Where x==c); + If(iDebug,Tell(" ",{a,b,c})); + if (Abs(pc) < prec) + [ a:=c; b:=c; ] + else if (pa*pc < 0) + [ b:=c; pb:=pc; ] + else + [ a:=c; pa:=pc; ]; + cold:=c; + c:=((a+b)/2); + ]; + r:=c; + ]; + result[i] := N(Eval((r/10)*(10)),requiredPrec); + ]; + BuiltinPrecisionSet(requiredPrec); + result; +]; + +%/mathpiper + + + +%mathpiper_docs,name="FindRealRoots",categories="User Functions;Solvers (Numeric)" +*CMD FindRealRoots --- find the real roots of a polynomial +*STD +*CALL + FindRealRoots(p) + +*PARMS + +{p} - a polynomial in {x} + +*DESC + +Return a list with the real roots of $ p $. It tries to find the real-valued +roots, and thus requires numeric floating point calculations. The precision +of the result can be improved by increasing the calculation precision. + +*E.G. notest + +In> p:=Expand((x+3.1)^5*(x-6.23)) +Result: x^6+9.27*x^5-0.465*x^4-300.793*x^3- + 1394.2188*x^2-2590.476405*x-1783.5961073; +In> FindRealRoots(p) +Result: {-3.1,6.23}; + +*SEE SquareFree, RealRootsCount, MinimumBound, MaximumBound, Factor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/MaximumBound.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/MaximumBound.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/MaximumBound.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/MaximumBound.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper,def="MaximumBound" + +/** Maximum bound on the absolute value of the roots of a + polynomial p in variable x, according to Knuth: + + Maximum( Abs(a[n-1]/a[n]) , Abs(a[n-2]/a[n])^(1/2), ... , Abs(a[0]/a[n])^(1/n) ) + + As described in Davenport. + */ + 5 # MaximumBound(_p)_(IsZero(p Where x==0)) <-- MaximumBound(Simplify(p/x)); +10 # MaximumBound(_p)_(Degree(p)>0) <-- +[ + Local(an); + an:=Coef(p,(Degree(p)-1) .. 0)/Coef(p,Degree(p)); + an := N(Eval(Abs(an)^(1/(1 .. Degree(p))))); + Rationalize(2*Maximum(an)); +]; + +20 # MaximumBound(_p) <-- Infinity; + +%/mathpiper + + + +%mathpiper_docs,name="MaximumBound",categories="User Functions;Solvers (Numeric)" +*CMD MaximumBound --- return upper bounds on the absolute values of real roots of a polynomial +*STD +*CALL + MaximumBound(p) + +*PARMS + +{p} - a polynomial in $x$ + +*DESC + +Return maximum bounds for the absolute values of the real +roots of a polynomial {p}. The polynomial has to be converted to one with +rational coefficients first, and be made square-free. +The polynomial must use the variable {x}. + +*E.G. + +In> p:=SquareFree(Rationalize((x-3.1)*(x+6.23))) +Result: (-40000*x^2-125200*x+772520)/870489; +In> MaximumBound(p) +Result: 10986639613/1250000000; +In> N(%) +Result: 8.7893116904; + +*SEE MinimumBound, SquareFree, RealRootsCount, FindRealRoots, Factor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/MinimumBound.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/MinimumBound.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/MinimumBound.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/MinimumBound.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,49 @@ +%mathpiper,def="MinimumBound" + +10 # MinimumBound(_p)_(IsZero(p Where x==0)) <-- 0; + +20 # MinimumBound(_p)_(Degree(p)>0) <-- +[ + Local(an,result); + an:=Coef(p,1 .. (Degree(p)))/Coef(p,0); + an := N(Eval(Abs(an)^(1/(1 .. Degree(p))))); + + result:=0; + an:=2*Maximum(an); + if(Not IsZero(an)) [result := 1/an;]; + Simplify(Rationalize(result)); +]; +30 # MinimumBound(_p) <-- -Infinity; + +%/mathpiper + + + +%mathpiper_docs,name="MinimumBound",categories="User Functions;Solvers (Numeric) +*CMD MinimumBound --- return lower bounds on the absolute values of real roots of a polynomial +*STD +*CALL + MinimumBound(p) + +*PARMS + +{p} - a polynomial in $x$ + +*DESC + +Return minimum bounds for the absolute values of the real +roots of a polynomial {p}. The polynomial has to be converted to one with +rational coefficients first, and be made square-free. +The polynomial must use the variable {x}. + +*E.G. + +In> p:=SquareFree(Rationalize((x-3.1)*(x+6.23))) +Result: (-40000*x^2-125200*x+772520)/870489; +In> MinimumBound(p) +Result: 5000000000/2275491039; +In> N(%) +Result: 2.1973279236; + +*SEE MaximumBound, SquareFree, RealRootsCount, FindRealRoots, Factor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/RealRootsCount.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/RealRootsCount.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/RealRootsCount.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/RealRootsCount.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,38 @@ +%mathpiper,def="RealRootsCount" + +RealRootsCount(_p) <-- +[ + Local(S); + p:=SquareFree(Rationalize(p)); + S:=SturmSequence(p); + SturmVariations(S,-Infinity)-SturmVariations(S,Infinity); +]; + +%/mathpiper + + + +%mathpiper_docs,name="RealRootsCount",categories="User Functions;Solvers (Numeric)" +*CMD RealRootsCount --- return the number of real roots of a polynomial +*STD +*CALL + RealRootsCount(p) + +*PARMS + +{p} - a polynomial in {x} + +*DESC + +Returns the number of real roots of a polynomial $ p $. +The polynomial must use the variable {x} and no other variables. + +*E.G. + +In> RealRootsCount(x^2-1) +Result: 2; +In> RealRootsCount(x^2+1) +Result: 0; + +*SEE FindRealRoots, SquareFree, MinimumBound, MaximumBound, Factor +%/mathpiper_docs \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/SquareFree.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/SquareFree.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/SquareFree.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/SquareFree.mpw 2011-02-05 07:50:02.000000000 +0000 @@ -0,0 +1,75 @@ +%mathpiper,def="SquareFree" + +//Retract("SquareFree",*); + + +10 # SquareFree(_p)_(Length(VarList(p))!=1) <-- Check(False,"Argument","Input must be Univariate"); + +12 # SquareFree(_p) <-- SquareFree(p,VarList(p)[1]); + +14 # SquareFree(_p,_var)_(Not IsPolynomial(p,var)) <-- Check(False,"Argument","Input must be Univariate Polynomial"); + +16 # SquareFree(_p,_var) <-- +[ + /* + Local(dp,gcd); + dp:=MakeMultiNomial(`(Differentiate(var)(@p)),{var}); + + p:=MakeMultiNomial(p,{var}); + gcd:=MultiGcd(p,dp); + NormalForm(MultiDivide(p,{gcd})[1][1]); + */ + Quotient(p,Gcd(p,(`(Differentiate(@var)(@p))))); +]; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + + + +%mathpiper_docs,name="SquareFree",categories="User Functions;Polynomials (Operations)" +*CMD SquareFree --- return the square-free part of a univariate polynomial +*STD +*CALL + SquareFree(p) + +*PARMS + +{p} - a univariate polynomial + +*DESC + +Given a polynomial +$$ p = p[1]^n[1]* ... * p[m]^n[m] $$ +with irreducible polynomials $ p[i] $, +return the square-free version part (with all the factors having +multiplicity 1): +$$ p[1]* ... * p[m] $$ + +Throws "argument" exception if input is not a univariate polynomial. + +*E.G. + +In> Expand((x+1)^5) +Result: x^5+5*x^4+10*x^3+10*x^2+5*x+1; +In> SquareFree(%) +Result: (x+1)/5; +In> Monic(%) +Result: x+1; + +*SEE FindRealRoots, RealRootsCount, MinimumBound, MaximumBound, Factor +%/mathpiper_docs + + %output,preserve="false" + +. %/output + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/SturmSequence.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/SturmSequence.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/SturmSequence.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/SturmSequence.mpw 2011-01-24 07:22:16.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="SturmSequence" + +//Retract("SturmSequence",*); + +/** SturmSequence(p) : generate a Sturm sequence for a univariate polynomial + */ + +10 # SturmSequence(_p,_var) <-- +[ + Local(result,i,deg,nt); + If(InVerboseMode(),Tell(10)); + result := {p,`Differentiate(@var)(@p)}; + deg := Degree(p,var); + For(i:=3,i<=deg+1,i++) + [ + nt := -NormalForm(MultiDivide(MM(result[i-2],{var}),{MM(result[i-1],{var})})[2]);//?? + DestructiveAppend(result,nt); + ]; + result; +]; + +20 # SturmSequence(_p)_(Length(VarList(p))=1) <-- SturmSequence(p,VarList(p)[1]); + +30 # SturmSequence(_p) <-- Check(Length(VarList(p))=1,"Argument","Input must be Univariate Polynomial. "); + + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/SturmVariations.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/SturmVariations.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/sturm/SturmVariations.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/sturm/SturmVariations.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,48 @@ +%mathpiper,def="SturmVariations" + +10 # SturmVariations(_S,Infinity) <-- +[ + Local(i,s); + s:=FillList(0,Length(S)); + For(i:=1,i<=Length(S),i++) + [ + s[i] := LeadingCoef(S[i]); + ]; + SturmVariations(s); +]; + +10 # SturmVariations(_S,-Infinity) <-- +[ + Local(i,s); + s:=FillList(0,Length(S)); + For(i:=1,i<=Length(S),i++) + [ + s[i] := ((-1)^Degree(S[i]))*LeadingCoef(S[i]); + ]; + SturmVariations(s); +]; + +20 # SturmVariations(_S,_x) <-- SturmVariations(Eval(S)); +SturmVariations(_S) <-- +[ + Local(result,prev); +//Echo("S = ",S); + result:=0; + While(Length(S)>0 And IsZero(S[1])) S:=Rest(S); +//Echo("S = ",S); + if (Length(S)>0) + [ + prev:=S[1]; + ForEach(item,Rest(S)) + [ + if(Not IsZero(item)) + [ + if (prev*item < 0) [result++;]; + prev:=item; + ]; + ]; + ]; + result; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniDivide.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniDivide.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniDivide.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniDivide.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,32 @@ +%mathpiper,def="UniDivide" + +/* division algo: (for zero-base univariates:) */ +Function("UniDivide",{u,v}) +[ + Local(m,n,q,r,k,j); + m := Length(u)-1; + n := Length(v)-1; + While (m>0 And IsZero(u[m+1])) m--; + While (n>0 And IsZero(v[n+1])) n--; + q := ZeroVector(m-n+1); + r := FlatCopy(u); /* (m should be >= n) */ + For(k:=m-n,k>=0,k--) + [ + q[k+1] := r[n+k+1]/v[n+1]; + For (j:=n+k-1,j>=k,j--) + [ + r[j+1] := r[j+1] - q[k+1]*v[j-k+1]; + ]; + ]; + Local(end); + end:=Length(r); + While (end>n) + [ + DestructiveDelete(r,end); + end:=end-1; + ]; + + {q,r}; +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniGCD.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniGCD.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniGCD.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniGCD.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,43 @@ +%mathpiper,def="UniGcd" + +Function("UniGcd",{u,v}) +[ + Local(l,div,mod,m); + + DropEndZeroes(u); + DropEndZeroes(v); +/* + If(Length(v)>Length(u), + [ + Locap(swap); + swap:=u; + u:=v; + v:=swap; + ] ); + If(Length(u)=Length(v) And v[Length(v)] > u[Length(u)], + [ + Locap(swap); + swap:=u; + u:=v; + v:=swap; + ] ); + */ + + + l:=UniDivide(u,v); + + div:=l[1]; + mod:=l[2]; + + DropEndZeroes(mod); + m := Length(mod); + +/* Echo({"v,mod = ",v,mod}); */ +/* If(m <= 1, */ + If(m = 0, + v, +/* v/v[Length(v)], */ + UniGcd(v,mod)); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniTaylor.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniTaylor.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniTaylor.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniTaylor.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,24 @@ +%mathpiper,def="UniTaylor" + +Function("UniTaylor",{taylorfunction,taylorvariable,taylorat,taylororder}) +[ + Local(n,result,dif,polf); + result:={}; + [ + MacroLocal(taylorvariable); + MacroBind(taylorvariable,taylorat); + DestructiveAppend(result,Eval(taylorfunction)); + ]; + dif:=taylorfunction; + polf:=(taylorvariable-taylorat); + For(n:=1,n<=taylororder,n++) + [ + dif:= Deriv(taylorvariable) dif; + MacroLocal(taylorvariable); + MacroBind(taylorvariable,taylorat); + DestructiveAppend(result,(Eval(dif)/n!)); + ]; + UniVariate(taylorvariable,0,result); +]; + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniVariate.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniVariate.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniVariate.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniVariate.mpw 2010-01-31 04:25:54.000000000 +0000 @@ -0,0 +1,113 @@ +%mathpiper,def="UniVariate" + +//Auxiliary function. +ShiftUniVar(UniVariate(_var,_first,_coefs),_fact,_shift) + <-- + [ +//Echo("fact, coefs = ",fact,coefs); + UniVariate(var,first+shift,fact*coefs); + ]; + + + +Rulebase("UniVariate",{var,first,coefs}); + +Rule("UniVariate",3,10,Length(coefs)>0 And coefs[1]=0) + UniVariate(var,first+1,Rest(coefs)); +Rule("UniVariate",3,1000,IsComplex(var) Or IsList(var)) + ExpandUniVariate(var,first,coefs); + +500 # UniVariate(_var,_f1,_c1) + UniVariate(_var,_f2,_c2) <-- +[ + Local(from,result); + Local(curl,curr,left,right); + + Bind(curl, f1); + Bind(curr, f2); + Bind(left, c1); + Bind(right, c2); + Bind(result, {}); + Bind(from, Minimum(curl,curr)); + + While(And(IsLessThan(curl,curr),left != {})) + [ + DestructiveAppend(result,First(left)); + Bind(left,Rest(left)); + Bind(curl,AddN(curl,1)); + ]; + While(IsLessThan(curl,curr)) + [ + DestructiveAppend(result,0); + Bind(curl,AddN(curl,1)); + ]; + While(And(IsLessThan(curr,curl), right != {})) + [ + DestructiveAppend(result,First(right)); + Bind(right,Rest(right)); + Bind(curr,AddN(curr,1)); + ]; + While(IsLessThan(curr,curl)) + [ + DestructiveAppend(result,0); + Bind(curr,AddN(curr,1)); + ]; + While(And(left != {}, right != {})) + [ + DestructiveAppend(result,First(left)+First(right)); + Bind(left, Rest(left)); + Bind(right, Rest(right)); + ]; + While(left != {}) + [ + DestructiveAppend(result,First(left)); + Bind(left, Rest(left)); + ]; + While(right != {}) + [ + DestructiveAppend(result,First(right)); + Bind(right, Rest(right)); + ]; + + UniVariate(var,from,result); +]; + + +200 # UniVariate(_var,_first,_coefs) + a_IsNumber <-- + UniVariate(var,first,coefs) + UniVariate(var,0,{a}); +200 # a_IsNumber + UniVariate(_var,_first,_coefs) <-- + UniVariate(var,first,coefs) + UniVariate(var,0,{a}); + + +200 # - UniVariate(_var,_first,_coefs) <-- UniVariate(var,first,-coefs); + + +200 # (_factor * UniVariate(_var,_first,_coefs))_((IsFreeOf(var,factor))) <-- + UniVariate(var,first,coefs*factor); + +200 # (UniVariate(_var,_first,_coefs)/_factor)_((IsFreeOf(var,factor))) <-- + UniVariate(var,first,coefs/factor); + + + +200 # UniVariate(_var,_f1,_c1) * UniVariate(_var,_f2,_c2) <-- +[ + Local(i,j,n,shifted,result); + Bind(result,MakeUni(0,var)); +//Echo("c1 = ",var,f1,c1); +//Echo("c2 = ",var,f2,c2); + Bind(n,Length(c1)); + For(i:=1,i<=n,i++) + [ +//Echo("before = ",result); +//Echo("parms = ",var,c1,c2,f1,f2,f1+i-1); + Bind(result,result+ShiftUniVar(UniVariate(var,f2,c2),MathNth(c1,i),f1+i-1)); +//Echo("after = ",result); + ]; +//Echo("result = ",result); + result; +]; + + + + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniVarList.mpw mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniVarList.mpw --- mathpiper-0.0.svn2556/src/org/mathpiper/scripts4/univar/UniVarList.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/scripts4/univar/UniVarList.mpw 2009-12-29 06:58:01.000000000 +0000 @@ -0,0 +1,7 @@ +%mathpiper,def="UniVarList" + +//Note:tk:since this is used in more than one univariate function, I am publishing it as a def. + +UniVarList(expr) := VarList(expr); + +%/mathpiper \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/Build.java mathpiper-0.81f+dfsg1/src/org/mathpiper/test/Build.java --- mathpiper-0.0.svn2556/src/org/mathpiper/test/Build.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/Build.java 2010-07-16 16:38:31.000000000 +0000 @@ -25,7 +25,6 @@ import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; -import java.io.IOException; import java.io.InputStreamReader; import java.io.Writer; import java.util.ArrayList; @@ -46,13 +45,15 @@ private java.io.FileWriter packagesFile; private String sourceScriptsDirectory = null; private String outputScriptsDirectory = null; - private String outputDocsDirectory = null; + private String outputDirectory = null; private String sourceDirectory = null; private java.io.DataOutputStream documentationFile; private java.io.FileWriter documentationIndexFile; private long documentationOffset = 0; private java.io.FileWriter functionCategoriesFile; private List functionCategoriesList = new ArrayList(); + private int documentedFunctionsCount = 0; + private int undocumentedMPWFileCount = 0; public Build() { @@ -65,14 +66,15 @@ }//end constructor. - public Build(String sourceScriptsDirectory, String outputScriptsDirectory, String outputDocsDirectory) throws Exception { + public Build(String sourceScriptsDirectory, String outputScriptsDirectory, String outputDirectory) throws Exception { this(sourceScriptsDirectory, outputScriptsDirectory); - this.outputDocsDirectory = outputDocsDirectory; + this.outputDirectory = outputDirectory; - documentationFile = new DataOutputStream(new java.io.FileOutputStream(outputDocsDirectory + "documentation.txt")); - documentationIndexFile = new java.io.FileWriter(outputDocsDirectory + "documentation_index.txt"); - functionCategoriesFile = new java.io.FileWriter(outputDocsDirectory + "function_categories.txt"); + + documentationFile = new DataOutputStream(new java.io.FileOutputStream(outputDirectory + "org/mathpiper/ui/gui/help/data/documentation.txt")); + documentationIndexFile = new java.io.FileWriter(outputDirectory + "org/mathpiper/ui/gui/help/data/documentation_index.txt"); + functionCategoriesFile = new java.io.FileWriter(outputDirectory + "org/mathpiper/ui/gui/help/data/function_categories.txt"); @@ -89,18 +91,17 @@ }//end method. - public void setOutputDocsDirectory(String outputDocsDirectory) throws Exception { - this.outputDocsDirectory = outputDocsDirectory; + public void setOutputDirectory(String outputDirectory) throws Exception { + this.outputDirectory = outputDirectory; - documentationFile = new DataOutputStream(new java.io.FileOutputStream(outputDocsDirectory + "documentation.txt")); - documentationIndexFile = new java.io.FileWriter(outputDocsDirectory + "documentation_index.txt"); - functionCategoriesFile = new java.io.FileWriter(outputDocsDirectory + "function_categories.txt"); + documentationFile = new DataOutputStream(new java.io.FileOutputStream(outputDirectory + "org/mathpiper/ui/gui/help/data/documentation.txt")); + documentationIndexFile = new java.io.FileWriter(outputDirectory + "org/mathpiper/ui/gui/help/data/documentation_index.txt"); + functionCategoriesFile = new java.io.FileWriter(outputDirectory + "org/mathpiper/ui/gui/help/data/function_categories.txt"); }//end method. - public void setBaseDirectory(String baseDirectory) { this.sourceDirectory = baseDirectory + "src/"; }//end method. @@ -108,12 +109,6 @@ public void compileScripts() throws Exception { - StringBuilder mainScriptsClassBuffer = new StringBuilder(); - - - mainScriptsClassBuffer.append("static{\n"); - - //System.out.println("XXXXX " + outputDirectory); packagesFile = new java.io.FileWriter(outputScriptsDirectory + "initialization.rep/packages.mpi"); @@ -152,7 +147,7 @@ String newPackageName = dirNameRep + ".rep"; String newPackagePath = outputScriptsDirectory + newPackageName; File newPackageFile = new File(newPackagePath); - Boolean directoryCreated = newPackageFile.mkdir(); + Boolean directoryCreated = newPackageFile.mkdirs(); //mpi file. BufferedWriter mpiFileOut = null; @@ -160,7 +155,7 @@ newMPIFile.createNewFile(); mpiFileOut = new BufferedWriter(new FileWriter(newMPIFile)); - packagesFile.write("\"org/mathpiper/assembledscripts/" + newPackageName + "/code.mpi\",\n"); + packagesFile.write("\"" + newPackageName + "/code.mpi\",\n"); //mpi.def file BufferedWriter mpiDefFileOut = null; @@ -187,21 +182,28 @@ Arrays.sort(packageDirectoryContentsArray); - // }//note:tk:remove. - String classNameUpper = null; - for (int x2 = 0; x2 < packageDirectoryContentsArray.length; x2++) { //Process each script or subdirectory in a .rep directory.*********************************************************************************** File scriptFileOrSubdirectoy = packageDirectoryContentsArray[x2]; - System.out.println(" " + scriptFileOrSubdirectoy.getName()); - if (scriptFileOrSubdirectoy.getName().endsWith(".mrw")) { - //Process a .mrw files that is in a top-level package. ************************************************************************ + if (scriptFileOrSubdirectoy.getName().toLowerCase().endsWith(".mrw")) { + throw new Exception("The .mrw file extension has been deprecated ( " + scriptFileOrSubdirectoy.getName() +" )."); + } + + if (scriptFileOrSubdirectoy.getName().toLowerCase().endsWith(".mpw")) { + //Process a .mpw files that is in a top-level package. ************************************************************************ + + System.out.print(" " + scriptFileOrSubdirectoy.getName() +" -> "); - processMRWFile(scriptFileOrSubdirectoy, mpiDefFileOut, mpiFileOut); + documentedFunctionsCount++; + + processMPWFile(scriptFileOrSubdirectoy, mpiDefFileOut, mpiFileOut); } else { //Process a subdirectory.*********************************************************************************************** + + System.out.println(" " + scriptFileOrSubdirectoy.getName()); + java.io.File[] packageSubDirectoryContentsArray = scriptFileOrSubdirectoy.listFiles(new java.io.FilenameFilter() { public boolean accept(java.io.File file, String name) { @@ -222,7 +224,7 @@ newMPISubDirectoyFile.createNewFile(); mpiSubDirectoyFileOut = new BufferedWriter(new FileWriter(newMPISubDirectoyFile)); - packagesFile.write("\"org/mathpiper/assembledscripts/" + newPackageName + "/" + scriptFileOrSubdirectoy.getName() + ".mpi" + "\",\n"); + packagesFile.write("\"" + newPackageName + "/" + scriptFileOrSubdirectoy.getName() + ".mpi" + "\",\n"); //mpi.def file BufferedWriter mpiSubDirectoyDefFileOut = null; @@ -233,9 +235,9 @@ for (int x3 = 0; x3 < packageSubDirectoryContentsArray.length; x3++) { //Process each script in a package subdirectlry directory. File scriptFile2 = packageSubDirectoryContentsArray[x3]; - System.out.println(" " + scriptFile2.getName()); + System.out.print(" " + scriptFile2.getName() + " -> "); - processMRWFile(scriptFile2, mpiSubDirectoyDefFileOut, mpiSubDirectoyFileOut); + processMPWFile(scriptFile2, mpiSubDirectoyDefFileOut, mpiSubDirectoyFileOut); //mpi file. @@ -253,8 +255,6 @@ }//end package for. - - }//end if. if (mpiFileOut != null) { @@ -266,7 +266,12 @@ }//end for. if (documentationFile != null) { - processBuiltinDocs(); + + processBuiltinDocs(sourceDirectory, outputDirectory, "org/mathpiper/builtin/functions/core"); + + processBuiltinDocs(sourceDirectory, outputDirectory, "org/mathpiper/builtin/functions/optional"); + + processBuiltinDocs(sourceDirectory, outputDirectory, "org/mathpiper/builtin/functions/plugins/jfreechart"); } Collections.sort(functionCategoriesList); @@ -290,6 +295,9 @@ } + System.out.println("\nDocumented functions: " + this.documentedFunctionsCount + "\n"); + + System.out.println("Undocumented .mpw files: " + this.undocumentedMPWFileCount + "\n"); }//end method. @@ -302,7 +310,7 @@ //Uncomment for debugging. /* - if (fileName.equals("Factors.mrw")) { + if (fileName.equals("Factors.mpw")) { int xxx = 1; }//end if.*/ @@ -409,14 +417,14 @@ }//end inner class. - private void processMRWFile(File mrwFile, Writer mpiDefFileOut, Writer mpiFileOut) throws Exception { + private void processMPWFile(File mpwFile, Writer mpiDefFileOut, Writer mpiFileOut) throws Exception { - List folds = scanSourceFile(mrwFile); + List folds = scanSourceFile(mpwFile); boolean hasDocs = false; String scopeAttribute = "public"; - String scope = "public"; + //String scope = "public"; for (Fold fold : folds) { @@ -446,14 +454,17 @@ }//end if. }//end if. - scope = scopeAttribute; + //scope = scopeAttribute; }//end if. } else if (foldType.equalsIgnoreCase("%mathpiper_docs")) { //System.out.println(" **** Contains docs *****"); hasDocs = true; - processMathPiperDocsFold(fold, scope); + + String mpwFilePath = mpwFile.getPath(); + + processMathPiperDocsFold(fold, mpwFilePath); }//end if. @@ -461,20 +472,27 @@ }//end subpackage for. if (!hasDocs) { - System.out.println(" ^^^^ Does not contain docs ^^^^"); + System.out.println("**** Does not contain docs ****"); + this.undocumentedMPWFileCount++; + } + else + { + System.out.println(); } }//end method. - private void processMathPiperDocsFold(Fold fold, String scope) throws IOException { + private void processMathPiperDocsFold(Fold fold, String mpwFilePath) throws Exception { if (documentationFile != null) { + + mpwFilePath = mpwFilePath.substring(mpwFilePath.indexOf(File.separator + "org" + File.separator + "mathpiper" + File.separator)); //"/org/mathpiper/"; String functionNamesString = ""; if (fold.getAttributes().containsKey("name")) { functionNamesString = (String) fold.getAttributes().get("name"); //Uncomment to debug the documentation for a given function.. - /*if(functionNamesString.equals("Factors")) + /*if(functionNamesString.equals("RepToNumber")) { int xxx = 1; }*/ @@ -486,7 +504,7 @@ //DataOutputStream individualDocumentationFile = null; /* try{ - individualDocumentationFile = new DataOutputStream(new java.io.FileOutputStream(outputDocsDirectory + functionName)); + individualDocumentationFile = new DataOutputStream(new java.io.FileOutputStream(outputDirectory + functionName)); }catch(Exception ex) { ex.printStackTrace(); @@ -496,6 +514,9 @@ documentationIndexFile.write(documentationOffset + ","); String contents = fold.getContents(); + + contents = contents + "\n*SOURCE " + mpwFilePath; + byte[] contentsBytes = contents.getBytes(); documentationFile.write(contentsBytes, 0, contentsBytes.length); //individualDocumentationFile.write(contentsBytes, 0, contentsBytes.length); @@ -509,14 +530,27 @@ documentationOffset = documentationOffset + separator.length; + String access = "public"; + if (fold.getAttributes().containsKey("categories")) { int commandIndex = contents.indexOf("*CMD"); + if(commandIndex == -1) + { + throw new Exception("Missing *CMD tag."); + } String descriptionLine = contents.substring(commandIndex, contents.indexOf("\n", commandIndex)); String description = descriptionLine.substring(descriptionLine.lastIndexOf("--") + 2); description = description.trim(); + if(description.contains(",")) + { + description = "\"" + description + "\""; + } + + System.out.print(functionName + ": " + description + ", "); + String functionCategories = (String) fold.getAttributes().get("categories"); String[] categoryNames = functionCategories.split(";"); String categories = ""; @@ -548,13 +582,22 @@ } //functionCategoriesFile.write("\n"); if (functionCategoryName.equalsIgnoreCase("")) { - functionCategoryName = "Uncategorized"; + functionCategoryName = "Uncategorized"; //todo:tk:perhaps we should throw an exception here. + } + + if (fold.getAttributes().containsKey("access")) { + access = (String) fold.getAttributes().get("access"); } - CategoryEntry categoryEntry = new CategoryEntry(functionCategoryName, functionName, scope, description, categories); + + CategoryEntry categoryEntry = new CategoryEntry(functionCategoryName, functionName, access, description, categories); functionCategoriesList.add(categoryEntry); - }//end if. + } + else + { + System.out.print(functionName + ": **** Uncategorized ****, "); + } }//end for. }//end if. @@ -578,15 +621,15 @@ private String categoryName; private String functionName; - private String scope; + private String access; private String description; private String categories; - public CategoryEntry(String categoryName, String functionName, String scope, String description, String categories) { + public CategoryEntry(String categoryName, String functionName, String access, String description, String categories) { this.categoryName = categoryName; this.functionName = functionName; - this.scope = scope; + this.access = access; this.description = description; this.categories = categories; } @@ -604,18 +647,28 @@ public String toString() { - return categoryName + "," + functionName + "," + scope + "," + description + "," + categories; + return categoryName + "," + functionName + "," + access + "," + description + "," + categories; }//end method. }//end class. - private void processBuiltinDocs() throws Exception { + private void processBuiltinDocs(String sourceDirectoryPath, String outputDirectoryPath, String pluginFilePath) throws Exception { // try { - System.out.println("***** Processing built in docs..."); + System.out.println("\n***** Processing built in docs *****"); + + File builtinFunctionsSourceDir = new java.io.File(sourceDirectoryPath + pluginFilePath ); + + String directoryPath = builtinFunctionsSourceDir.getPath(); + + + java.io.FileWriter pluginsListFile = null; + if(!directoryPath.endsWith("core")) + { + pluginsListFile = new java.io.FileWriter(outputDirectoryPath + "/" + pluginFilePath + "/plugins_list.txt"); + } - File builtinFunctionsSourceDir = new java.io.File(sourceDirectory + "org/mathpiper/builtin/functions/core"); if (builtinFunctionsSourceDir.exists()) { java.io.File[] javaFilesDirectory = builtinFunctionsSourceDir.listFiles(new java.io.FilenameFilter() { @@ -634,11 +687,19 @@ Arrays.sort(javaFilesDirectory); for (int x = 0; x < javaFilesDirectory.length; x++) { + File javaFile = javaFilesDirectory[x]; String javaFileName = javaFile.getName(); + if(pluginsListFile != null) + { + pluginsListFile.append( javaFileName.substring(0,javaFileName.length() - 4) + "class" + "\n"); + } + + + System.out.print(javaFileName + " -> "); - System.out.println(javaFileName); + this.documentedFunctionsCount++; List folds = scanSourceFile(javaFile); @@ -652,14 +713,19 @@ hasDocs = true; - processMathPiperDocsFold(fold, "public"); + processMathPiperDocsFold(fold, javaFile.getPath()); }//end if. }//end for if (!hasDocs) { - System.out.println(" ^^^^ Does not contain docs ^^^^ ");// + javaFileName); + System.out.println("**** Does not contain docs ****");// + javaFileName); + this.undocumentedMPWFileCount++; + } + else + { + System.out.println(); } @@ -667,6 +733,11 @@ }//end for + if(pluginsListFile != null) + { + pluginsListFile.close(); + } + }//end if. /* } catch (java.io.IOException e) { @@ -684,26 +755,34 @@ if (args.length > 0) { sourceScriptsDirectory = args[0]; } else { - sourceScriptsDirectory = "/home/tkosan/NetBeansProjects/mathpiper/src/org/mathpiper/scripts3/"; + sourceScriptsDirectory = "/home/tkosan/NetBeansProjects/mathpiper/src/org/mathpiper/scripts4/"; } String outputScriptsDirectory = "/home/tkosan/NetBeansProjects/scripts/"; File newScriptsDirectory = new File(outputScriptsDirectory); - Boolean directoryCreated = newScriptsDirectory.mkdir(); + Boolean directoryCreated = newScriptsDirectory.mkdirs(); + + File newInitializationDirectory = new File(outputScriptsDirectory + "initialization.rep/"); - newInitializationDirectory.mkdir(); + newInitializationDirectory.mkdirs(); + + File outputDocsDirectory = new File(outputScriptsDirectory + "documentation/org/mathpiper/ui/gui/help/data/"); + outputDocsDirectory.mkdirs(); + + File pluginsDirectory = new File(outputScriptsDirectory + "documentation/org/mathpiper/builtin/functions/optional/"); + pluginsDirectory.mkdirs(); - File outputDocsDirectory = new File(outputScriptsDirectory + "documentation/"); - outputDocsDirectory.mkdir(); + pluginsDirectory = new File(outputScriptsDirectory + "documentation/org/mathpiper/builtin/functions/plugins/jfreechart/"); + pluginsDirectory.mkdirs(); //String outputDirectory = "/home/tkosan/temp/mathpiper/org/mathpiper/assembledscripts/"; try { - Build scripts = new Build(sourceScriptsDirectory, outputScriptsDirectory, outputDocsDirectory.getPath() + "/"); + Build scripts = new Build(sourceScriptsDirectory, outputScriptsDirectory, outputScriptsDirectory + "documentation/"); scripts.setBaseDirectory("/home/tkosan/NetBeansProjects/mathpiper/"); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/InterpreterTest.java mathpiper-0.81f+dfsg1/src/org/mathpiper/test/InterpreterTest.java --- mathpiper-0.0.svn2556/src/org/mathpiper/test/InterpreterTest.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/InterpreterTest.java 2010-07-26 03:29:39.000000000 +0000 @@ -28,18 +28,33 @@ public InterpreterTest() { - Interpreter interpreter; + EvaluationResponse response; - interpreter = Interpreters.getSynchronousInterpreter(); + final Interpreter interpreter = Interpreters.getSynchronousInterpreter(); + + /* + final Timer timer = new Timer(); + + timer.schedule(new TimerTask() { + public void run() { + interpreter.haltEvaluation(); + timer.cancel(); + } + + }, 1000); //Time out after one second. + */ // response = interpreter.evaluate("Tell(a);"); // System.out.println("Straight: " + "Result: " + response.getResult() + " Side Effects: " + response.getSideEffects() + " Errors: " + response.getExceptionMessage()); //Load("/home/tkosan/NetBeansProjects/mathpiper/src/org/mathpiper/test/test.mpi"); - response = interpreter.evaluate("Load(\"/home/tkosan/NetBeansProjects/mathpiper/src/org/mathpiper/test/test.mpi\");"); - System.out.println("Load test: " + "Result: " + response.getResult() + " Side Effects: " + response.getSideEffects() + " Errors: " + response.getExceptionMessage()); + response = interpreter.evaluate("LoadScript(\"/home/tkosan/NetBeansProjects/mathpiper/src/org/mathpiper/test/test.mpi\");"); + + //timer.cancel(); + + System.out.println("Load test: " + "Result: " + response.getResult() + " Side Effects: " + response.getSideEffects() + " Errors: " + response.getExceptionMessage() + " File: " + response.getSourceFileName() + " Line number: " + response.getLineNumber()); /* response = interpreter.evaluate("3+3;"); System.out.println("Straight: " + "Result: " + response.getResult() + " Side Effects: " + response.getSideEffects() + " Errors: " + response.getExceptionMessage()); @@ -70,11 +85,42 @@ /* JFrame frame = new JFrame(); Container contentPane = frame.getContentPane(); - JButton haltButton = org.mathpiper.ui.gui.controlpanel.HaltButton.getInstance(); - contentPane.add(haltButton); - frame.setBounds ( 10 , 10 , 200 , 90 ); + + geogebra.GeoGebraPanel ggbPanel = new geogebra.GeoGebraPanel(); + ggbPanel.setShowAlgebraInput(true); + ggbPanel.setShowAlgebraView(false); + ggbPanel.setMaxIconSize(24); + ggbPanel.setShowMenubar(true); + ggbPanel.setShowToolbar(true); + ggbPanel.buildGUI(); + contentPane.add(ggbPanel); + frame.setBounds ( 10 , 10 , 700 , 700 ); frame.setVisible(true); - */ - } + geogebra.plugin.GgbAPI ggbAPI = ggbPanel.getGeoGebraAPI(); + + + //Wait until the frame is shown. + try + { + Thread.sleep(3000); + } + catch(InterruptedException ie) + { + + } + + + ggbAPI.setRepaintingActive(false); + + + + //Plot 1000 points to the drawing pad. + for(double x = -5; x < 5; x = x + .01) + { + ggbAPI.evalCommand("(" + x + "," + x + ")"); + }//end for. + */ + + }//end main. } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/AlgebraicFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/AlgebraicFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/AlgebraicFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/AlgebraicFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,2019 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Algebraic Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*(c (a + b x)^n)^m Powers of powers of linear binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Reciprocal rule for integration*) + + +(* ::Item:: *) +(*Basis: D[(a*f[x]^n)^m/f[x]^(m*n),x] == 0*) + + +Int[(c_.*(a_.+b_.*x_)^n_.)^m_,x_Symbol] := + (a+b*x)*(c*(a+b*x)^n)^m*Log[a+b*x]/b /; +FreeQ[{a,b,c,m,n},x] && ZeroQ[m*n+1] + + +(* ::Item::Closed:: *) +(*Derivation: Power rule for integration*) + + +(* ::Item:: *) +(*Basis: D[(a*f[x]^n)^m/f[x]^(m*n),x] == 0*) + + +Int[(c_.*(a_.+b_.*x_)^n_)^m_,x_Symbol] := + (a+b*x)*(c*(a+b*x)^n)^m/(b*(m*n+1)) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[m*n+1] + + +(* ::Subsection::Closed:: *) +(*u (a v^m w^n ...)^p Distribute powers over powers and products*) + + +(* Note: The generalization of these rules when m*p is rational is in GeneralIntegrationRules.m *) + + +(* ::Item:: *) +(*Basis: D[(a*f[x]^n)^m/f[x]^(m*n),x] == 0*) + + +Int[u_.*(a_.*v_^m_)^p_, x_Symbol] := + Module[{q=FractionalPart[p]}, + a^(p-q)*(a*v^m)^q/v^(m*q)*Int[u*v^(m*p),x]] /; +FreeQ[{a,m,p},x] && IntegerQ[m*p] + + +(* ::Item:: *) +(*Basis: D[(a*f[x]^m*g[x]^n)^p/(f[x]^(m*p)*g[x]^(n*p)),x] == 0*) + + +Int[u_.*(a_.*v_^m_.*w_^n_.)^p_, x_Symbol] := + Module[{q=FractionalPart[p]}, + a^(p-q)*(a*v^m*w^n)^q/(v^(m*q)*w^(n*q))*Int[u*v^(m*p)*w^(n*p),x]] /; +FreeQ[{a,m,n,p},x] && IntegerQ[m*p] && IntegerQ[n*p] + + +(* ::Subsection::Closed:: *) +(*a x^m + b x^n + \[CenterEllipsis] Integrands involving sums of monomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a*z^m+b*z^n == z^m*(a+b*z^(n-m))*) + + +(* ::Item:: *) +(*Note : Way kool rule! If m*(p+1)-n+1=0, then rule for x^(n-1)*(a+b*x^n)^p will fire.*) + + +Int[(a_.*x_^m_.+b_.*x_^n_.)^p_,x_Symbol] := + Int[x^(m*p)*(a+b*x^(n-m))^p,x] /; +FreeQ[{a,b,m,n},x] && IntegerQ[p] && ZeroQ[m*(p+1)-n+1] && Not[IntegerQ[{m,n}]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a*z^m+b*z^n == z^m*(a+b*z^(n-m))*) + + +(* ::Item:: *) +(*Note : Way kool rule! If m*(p+1)-n+1=0, then rule for x^(n-1)*(a+b*x^n)^p will fire.*) + + +Int[(a_.*x_^m_.+b_.*x_^n_.)^p_,x_Symbol] := + Int[(x^m*(a+b*x^(n-m)))^p,x] /; +FreeQ[{a,b,m,n},x] && FractionQ[p] && ZeroQ[m*(p+1)-n+1] + + +(* Int[(a_.*x_^m_.+b_.*x_^n_.)^p_,x_Symbol] := + Int[(x^m*(a+b*x^(n-m)))^p,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m<=n && HalfIntegerQ[p] && ZeroQ[m*(p+1)-n+1] *) + + +(* Int[(a_.*x_^m_.+b_.*x_^n_.)^p_,x_Symbol] := + Int[(x^m*(a+b*x^(n-m)))^p,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m<=n && HalfIntegerQ[p] && Not[2*m==n==2] *) + + +Int[(a_.*x_^m_.+b_.*x_^n_.+c_.*x_^q_.)^p_,x_Symbol] := + Int[(x^m*(a+b*x^(n-m)+c*x^(q-m)))^p,x] /; +FreeQ[{a,b,c},x] && IntegerQ[{m,n,q}] && FractionQ[p] && m<=n<=q + + +Int[u_.*x_^m_./(a_.*x_^n_.+b_.*x_^p_),x_Symbol] := + Int[u*x^(m-n)/(a+b*x^(p-n)),x] /; +FreeQ[{a,b},x] && FractionQ[{m,n,p}] && 0 Int[x^m*u+x^m*v+\[CenterEllipsis],x] *) + + +If[ShowSteps, +Int[x_^m_.*u_,x_Symbol] := + ShowStep["","Int[x^m*(u+v+\[CenterEllipsis]),x]","Int[x^m*u+x^m*v+\[CenterEllipsis],x]",Hold[ + Int[Map[Function[x^m*#],u],x]]] /; +SimplifyFlag && FreeQ[m,x] && SumQ[u], + +Int[x_^m_.*u_,x_Symbol] := + Int[Map[Function[x^m*#],u],x] /; +FreeQ[m,x] && SumQ[u]] + + +(* ::Subsection::Closed:: *) +(*(a+b x^n)^p / x Quotients of powers of binomials by integation variable*) + + +(* ::Item:: *) +(*Reference: CRC 276b*) + + +Int[1/(x_*Sqrt[a_+b_.*x_^n_.]),x_Symbol] := + -2*ArcTanh[Sqrt[a+b*x^n]/Rt[a,2]]/(n*Rt[a,2]) /; +FreeQ[{a,b,n},x] && PosQ[a] + + +(* ::Item:: *) +(*Reference: CRC 277*) + + +Int[1/(x_*Sqrt[a_+b_.*x_^n_.]),x_Symbol] := + 2*ArcTan[Sqrt[a+b*x^n]/Rt[-a,2]]/(n*Rt[-a,2]) /; +FreeQ[{a,b,n},x] && NegQ[a] + + +(* ::Item:: *) +(*Reference: G&R 2.110.1, CRC 88b*) + + +Int[(a_+b_.*x_^n_.)^p_/x_,x_Symbol] := + (a+b*x^n)^p/(n*p) + + Dist[a,Int[(a+b*x^n)^(p-1)/x,x]] /; +FreeQ[{a,b,n},x] && FractionQ[p] && p>0 + + +(* ::Item:: *) +(*Reference: G&R 2.110.2, CRC 88d*) + + +Int[(a_+b_.*x_^n_.)^p_/x_,x_Symbol] := + -(a+b*x^n)^(p+1)/(a*n*(p+1)) + + Dist[1/a,Int[(a+b*x^n)^(p+1)/x,x]] /; +FreeQ[{a,b,n},x] && FractionQ[p] && p<-1 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[x^n]/x == (f[x^n]/x^n)*D[x^n,x]/n*) + + +(* Int[(a_+b_.*x_^n_)^p_/x_,x_Symbol] := + Subst[Int[(a+b*x)^p/x,x],x,x^n]/n /; +FreeQ[{a,b,n},x] && FractionQ[p] && -1=0, (a+z)^m*(c-z)^m == (a*c-(a-c)*z-z^2)^m*) + + +Int[u_.*(a_+b_.*x_)^m_*(c_+d_.*x_)^m_,x_Symbol] := + Int[u*(a*c+(a*d+b*c)*x+b*d*x^2)^m,x] /; +FreeQ[{a,b,c,d},x] && FractionQ[m] && ZeroQ[b+d] && PositiveQ[a+c] + + +(* ::Subsubsection::Closed:: *) +(*1 / ((a+b x) Sqrt[c+d x]) Reciprocals of products of linears and square-roots of linears*) + + +(* ::Item:: *) +(*Reference: G&R 2.246.1', CRC 147a', A&S 3.3.30'*) + + +Int[1/((a_.+b_.*x_)*Sqrt[c_.+d_.*x_]),x_Symbol] := + -2*ArcTanh[Sqrt[c+d*x]/Rt[(b*c-a*d)/b,2]]/(b*Rt[(b*c-a*d)/b,2]) /; +FreeQ[{a,b,c,d},x] && PosQ[(b*c-a*d)/b] + + +(* ::Item:: *) +(*Reference: G&R 2.246.2, CRC 148, A&S 3.3.29*) + + +Int[1/((a_.+b_.*x_)*Sqrt[c_.+d_.*x_]),x_Symbol] := + 2*ArcTan[Sqrt[c+d*x]/Rt[(a*d-b*c)/b,2]]/(b*Rt[(a*d-b*c)/b,2]) /; +FreeQ[{a,b,c,d},x] && NegQ[(b*c-a*d)/b] + + +(* ::Subsubsection::Closed:: *) +(*1 / (Sqrt[a+b x] Sqrt[c+d x]) Reciprocal of products of square-roots of linears*) + + +Int[1/(Sqrt[a_+b_.*x_]*Sqrt[c_+b_.*x_]),x_Symbol] := + ArcCosh[b*x/a]/b /; +FreeQ[{a,b,c},x] && ZeroQ[a+c] && PositiveQ[a] + + +Int[1/(Sqrt[a_.+b_.*x_]*Sqrt[c_.+d_.*x_]),x_Symbol] := + 2*Rt[b/d,2]*ArcSinh[Sqrt[a+b*x]/Rt[b/d,2]]/b /; +FreeQ[{a,b,c,d},x] && PosQ[b/d] && ZeroQ[a*d-b*c+b] + + +Int[1/(Sqrt[a_.+b_.*x_]*Sqrt[c_.+d_.*x_]),x_Symbol] := + 2*Rt[-b/d,2]*ArcSin[Sqrt[a+b*x]/Rt[-b/d,2]]/b /; +FreeQ[{a,b,c,d},x] && NegQ[b/d] && ZeroQ[a*d-b*c+b] + + +Int[1/(Sqrt[a_.+b_.*x_]*Sqrt[c_.+d_.*x_]),x_Symbol] := + 2*Rt[b/d,2]*ArcSinh[Rt[b/(a*d-b*c),2]*Sqrt[c+d*x]]/b /; +FreeQ[{a,b,c,d},x] && PosQ[b/d] && PositiveQ[(a*d-b*c)/d] + + +Int[1/(Sqrt[a_.+b_.*x_]*Sqrt[c_.+d_.*x_]),x_Symbol] := + -2*Rt[-b/d,2]*ArcSin[Rt[b/(b*c-a*d),2]*Sqrt[c+d*x]]/b /; +FreeQ[{a,b,c,d},x] && NegQ[b/d] && PositiveQ[(a*d-b*c)/d] + + +Int[1/(Sqrt[a_.+b_.*x_]*Sqrt[c_.+d_.*x_]),x_Symbol] := + 2*Rt[d/b,2]*ArcTanh[Rt[d/b,2]*Sqrt[a+b*x]/Sqrt[c+d*x]]/d /; +FreeQ[{a,b,c,d},x] && PosQ[d/b] && NonzeroQ[a*d-b*c] + + +Int[1/(Sqrt[a_.+b_.*x_]*Sqrt[c_.+d_.*x_]),x_Symbol] := + -2*Rt[-d/b,2]*ArcTan[Rt[-d/b,2]*Sqrt[a+b*x]/Sqrt[c+d*x]]/d /; +FreeQ[{a,b,c,d},x] && NegQ[d/b] && NonzeroQ[a*d-b*c] + + +(* ::Subsubsection::Closed:: *) +(*(a+b x)^m (c+d x)^n Products of powers of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If b*c-a*d=0 and n is an integer, (a+b*x)^m*(c+d*x)^n == (d/b)^n*(a+b*x)^(m+n)*) + + +Int[(a_.+b_.*x_)^m_.*(c_.+d_.*x_)^n_.,x_Symbol] := + Dist[(d/b)^n,Int[(a+b*x)^(m+n),x]] /; +FreeQ[{a,b,c,d,m},x] && IntegerQ[n] && ZeroQ[b*c-a*d] && Not[IntegerQ[m]] + + +Int[(a_.+b_.*x_)^m_*(c_.+d_.*x_)^n_,x_Symbol] := + (a+b*x)^(m+1)*(c+d*x)^n*Log[a+b*x]/b /; +FreeQ[{a,b,c,d,m,n},x] && Not[IntegerQ[m]] && Not[IntegerQ[n]] && ZeroQ[b*c-a*d] && ZeroQ[m+n+1] && +(LeafCount[a+b*x]0 + + +(* ::Item:: *) +(*Reference: G&R 2.151, CRC 59b*) + + +(* Note: Experimental!!! *) +Int[(a_.+b_.*x_)^m_*(c_.+d_.*x_),x_Symbol] := + (a+b*x)^(m+1)*(c+d*x)/(b*(m+2)) + + Dist[(b*c-a*d)/(b*(m+2)),Int[(a+b*x)^m,x]] /; +FreeQ[{a,b,c,d,m},x] && Not[IntegerQ[m]] && NonzeroQ[b*c-a*d] + + +(* ::Item:: *) +(* Reference: G&R 2.151, CRC 59b*) + + +Int[(a_.+b_.*x_)^m_*(c_.+d_.*x_)^n_,x_Symbol] := + (a+b*x)^(m+1)*(c+d*x)^n/(b*(m+n+1)) + + Dist[n/(m+n+1)*(b*c-a*d)/b,Int[(a+b*x)^m*(c+d*x)^(n-1),x]] /; +FreeQ[{a,b,c,d,m},x] && NonzeroQ[b*c-a*d] && NonzeroQ[m+n+1] && RationalQ[n] && n>0 && +Not[IntegerQ[m]] && (IntegerQ[n] || FractionQ[m] && (n<=m || -1<=m<0)) + + +(* ::Item:: *) +(*Reference: G&R 2.155, CRC 59a*) + + +Int[(a_.+b_.*x_)^m_.*(c_.+d_.*x_)^n_,x_Symbol] := + -(a+b*x)^(m+1)*(c+d*x)^(n+1)/((n+1)*(b*c-a*d)) + + Dist[(m+n+2)/(n+1)*b/(b*c-a*d),Int[(a+b*x)^m*(c+d*x)^(n+1),x]] /; +FreeQ[{a,b,c,d,m},x] && NonzeroQ[b*c-a*d] && RationalQ[n] && n<-1 && Not[IntegerQ[{m,n}]] && +(Not[RationalQ[m]] || n>=m || -1<=m<0 (* || n+2<=2*(m+n+2)<0 *)) + + +(* ::Item:: *) +(*Reference: G&R 2.155, CRC 59a*) + + +Int[(a_.+b_.*x_)^m_.*(c_.+d_.*x_)^n_,x_Symbol] := + -(a+b*x)^(m+1)*(c+d*x)^(n+1)/((n+1)*(b*c-a*d)) + + Dist[(m+n+2)/(n+1)*b/(b*c-a*d),Int[(a+b*x)^m*(c+d*x)^(n+1),x]] /; +FreeQ[{a,b,c,d,m,n},x] && NonzeroQ[b*c-a*d] && NonzeroQ[n+1] && Not[RationalQ[n]] && +RationalQ[m+n] && Simplify[m+n]<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.153.3, CRC 59c*) + + +Int[(a_.+b_.*x_)*(c_.+d_.*x_)^n_,x_Symbol] := + (a+b*x)*(c+d*x)^(n+1)/(d*(n+1)) - + Dist[b/(d*(n+1)),Int[(c+d*x)^(n+1),x]] /; +FreeQ[{a,b,c,d,n},x] && Not[IntegerQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.153.3, CRC 59c*) + + +Int[(a_.+b_.*x_)^m_*(c_.+d_.*x_)^n_,x_Symbol] := + (a+b*x)^m*(c+d*x)^(n+1)/(d*(n+1)) - + Dist[m/(n+1)*b/d,Int[(a+b*x)^(m-1)*(c+d*x)^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[{m,n}] && Not[IntegerQ[{m,n}]] && m>0 && n<-1 + + +Int[(a_.+b_.*x_)^m_/(c_+d_.*x_),x_Symbol] := + Module[{p=Denominator[m]}, + Dist[p,Subst[Int[x^(m*p+p-1)/(b*c-a*d+d*x^p),x],x,(a+b*x)^(1/p)]]] /; +FreeQ[{a,b,c,d},x] && FractionQ[m] && -10 && ZeroQ[a*d+b*c] + + +Int[(a_+b_.*x_)^n_*(c_+d_.*x_)^n_/x_,x_Symbol] := + (a+b*x)^n*(c+d*x)^n/(2*n) + + Dist[(a*d+b*c)/2,Int[(a+b*x)^(n-1)*(c+d*x)^(n-1),x]] + + Dist[a*c,Int[(a+b*x)^(n-1)*(c+d*x)^(n-1)/x,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>0 && NonzeroQ[a*d+b*c] + + +(* ::Item:: *) +(*Reference: G&R 2.268b, CRC 122*) + + +Int[(a_+b_.*x_)^n_*(c_+d_.*x_)^n_/x_,x_Symbol] := + -(a+b*x)^(n+1)*(c+d*x)^(n+1)/(2*a*c*(n+1)) + + Dist[1/(a*c),Int[(a+b*x)^(n+1)*(c+d*x)^(n+1)/x,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n<-1 && ZeroQ[a*d+b*c] + + +Int[(a_+b_.*x_)^n_*(c_+d_.*x_)^n_/x_,x_Symbol] := + -(a+b*x)^(n+1)*(c+d*x)^(n+1)/(2*a*c*(n+1)) - + Dist[(a*d+b*c)/(2*a*c),Int[(a+b*x)^n*(c+d*x)^n,x]] + + Dist[1/(a*c),Int[(a+b*x)^(n+1)*(c+d*x)^(n+1)/x,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n<-1 && NonzeroQ[a*d+b*c] + + +(* ::Item:: *) +(*Reference: G&R 2.174.2*) + + +Int[x_^m_*(a_.+b_.*x_)^n_*(c_.+d_.*x_)^n_,x_Symbol] := + x^(m-1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(2*b*d*(n+1)) + + Dist[1/(b*d),Int[x^(m-2)*(a+b*x)^(n+1)*(c+d*x)^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && RationalQ[m] && m+2*n+1==0 && m>1 && ZeroQ[a*d+b*c] + + +Int[x_^m_*(a_.+b_.*x_)^n_*(c_.+d_.*x_)^n_,x_Symbol] := + x^(m-1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(2*b*d*(n+1)) - + Dist[(a*d+b*c)/(2*b*d),Int[x^(m-1)*(a+b*x)^n*(c+d*x)^n,x]] + + Dist[1/(b*d),Int[x^(m-2)*(a+b*x)^(n+1)*(c+d*x)^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && RationalQ[m] && m+2*n+1==0 && m>1 && NonzeroQ[a*d+b*c] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[x_*(a_.+b_.*x_)^n_*(c_.+d_.*x_)^n_,x_Symbol] := + (a+b*x)^(n+1)*(c+d*x)^(n+1)/(2*b*d*(n+1)) /; +FreeQ[{a,b,c,d,n},x] && NonzeroQ[n+1] && ZeroQ[a*d+b*c] + + +Int[x_*(a_.+b_.*x_)^n_*(c_.+d_.*x_)^n_,x_Symbol] := + (a+b*x)^(n+1)*(c+d*x)^(n+1)/(2*b*d*(n+1)) - + Dist[(a*d+b*c)/(2*b*d),Int[(a+b*x)^n*(c+d*x)^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] + + +Int[x_^m_*(a_.+b_.*x_)^n_*(c_.+d_.*x_)^n_,x_Symbol] := + x^(m-1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(b*d*(m+2*n+1)) - + Dist[a*c*(m-1)/(b*d*(m+2*n+1)),Int[x^(m-2)*(a+b*x)^n*(c+d*x)^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && RationalQ[m] && NonzeroQ[m+2*n+1] && m>1 && (ZeroQ[m+n] || ZeroQ[a*d+b*c]) + + +Int[x_^m_*(a_.+b_.*x_)^n_*(c_.+d_.*x_)^n_,x_Symbol] := + x^(m-1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(b*d*(m+2*n+1)) - + Dist[(m+n)*(a*d+b*c)/(b*d*(m+2*n+1)),Int[x^(m-1)*(a+b*x)^n*(c+d*x)^n,x]] - + Dist[a*c*(m-1)/(b*d*(m+2*n+1)),Int[x^(m-2)*(a+b*x)^n*(c+d*x)^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && RationalQ[m] && NonzeroQ[m+2*n+1] && m>1 + + +(* ::Item:: *) +(*Reference: G&R 2.176, CRC 123*) + + +Int[x_^m_*(a_+b_.*x_)^n_*(c_+d_.*x_)^n_,x_Symbol] := + x^(m+1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(a*c*(m+1)) /; +FreeQ[{a,b,c,d,n},x] && NonzeroQ[m+1] && ZeroQ[m+2*n+3] && ZeroQ[a*d+b*c] + + +Int[x_^m_*(a_+b_.*x_)^n_*(c_+d_.*x_)^n_,x_Symbol] := + x^(m+1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(a*c*(m+1)) - + Dist[(m+n+2)/(m+1)*((a*d+b*c)/(a*c)),Int[x^(m+1)*(a+b*x)^n*(c+d*x)^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && RationalQ[m] && m<-1 && ZeroQ[m+2*n+3] + + +Int[x_^m_*(a_+b_.*x_)^n_*(c_+d_.*x_)^n_,x_Symbol] := + x^(m+1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(a*c*(m+1)) - + Dist[(m+2*n+3)/(m+1)*(b*d/(a*c)),Int[x^(m+2)*(a+b*x)^n*(c+d*x)^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && RationalQ[m] && m<-1 && (ZeroQ[m+n+2] || ZeroQ[a*d+b*c]) + + +Int[x_^m_*(a_+b_.*x_)^n_*(c_+d_.*x_)^n_,x_Symbol] := + x^(m+1)*(a+b*x)^(n+1)*(c+d*x)^(n+1)/(a*c*(m+1)) - + Dist[(m+n+2)/(m+1)*((a*d+b*c)/(a*c)),Int[x^(m+1)*(a+b*x)^n*(c+d*x)^n,x]] - + Dist[(m+2*n+3)/(m+1)*(b*d/(a*c)),Int[x^(m+2)*(a+b*x)^n*(c+d*x)^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && RationalQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x)^n (c+d x)^p Products of monomials and different powers of two linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: (a+b*x)^n/x == b*(a+b*x)^(n-1) + a*(a+b*x)^(n-1)/x*) + + +Int[(a_+b_.*x_)^n_*(c_+d_.*x_)^p_/x_,x_Symbol] := + Dist[b,Int[(a+b*x)^(n-1)*(c+d*x)^p,x]] + + Dist[a,Int[(a+b*x)^(n-1)*(c+d*x)^p/x,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[{n,p}] && n>0 && IntegerQ[n-p] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: (a+b*x)^n/x == (a+b*x)^(n+1)/(a*x) - b/a*(a+b*x)^n*) + + +Int[(a_+b_.*x_)^n_*(c_+d_.*x_)^p_/x_,x_Symbol] := + Dist[1/a,Int[(a+b*x)^(n+1)*(c+d*x)^p/x,x]] - + Dist[b/a,Int[(a+b*x)^n*(c+d*x)^p,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[{n,p}] && n<-1 && IntegerQ[n-p] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: x^m*(a+b*x)^n == x^(m-1)*(a+b*x)^(n+1)/b - a*x^(m-1)*(a+b*x)^n/b*) + + +(* ::Item:: *) +(*Basis: If m>=0 is an integer, x^m == 1/b^m*Sum[(-a)^(m-k)*Binomial[m,m-k]*(a+b*x)^k, {k,0,m}]*) + + +Int[x_^m_.*(a_+b_.*x_)^n_*(c_.+d_.*x_)^p_.,x_Symbol] := + Sum[Dist[(-a)^(m-k)/b^m*Binomial[m,m-k],Int[(a+b*x)^(n+k)*(c+d*x)^p,x]],{k,0,m}] /; +FreeQ[{a,b,c,d,n,p},x] && IntegerQ[{m,p-n}] && m>0 && Not[IntegerQ[n]] && p-n<0 && +(m>3 || n=!=-1/2) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: x^m*(a+b*x)^n == x^(m-1)*(a+b*x)^(n+1)/b - a*x^(m-1)*(a+b*x)^n/b*) + + +(* ::Item:: *) +(*Basis: If m and p-n are integers and 00 and p-n>0 are integers, (a+b*x)^n*(c+d*x)^p/x^m == *) +(* (-b)^m*Sum[1/a^(m+k)*Binomial[k+m-1,m-1]*(a+b*x)^(n+k)*(c+d*x)^p, {k,0,p-n-1}] + *) +(* 1/a^(p-n)*Sum[(-b/a)^k*Binomial[p-n+k-1,p-n-1]*(a+b*x)^p*(c+d*x)^p/x^(m-k), {k,0,m-1}]*) + + +Int[x_^m_.*(a_+b_.*x_)^n_*(c_.+d_.*x_)^p_,x_Symbol] := + Sum[Dist[a^(m-k)/(-b)^m*Binomial[k-m-1,-m-1],Int[(a+b*x)^(n+k)*(c+d*x)^p,x]], {k,0,p-n-1}] + + Sum[Dist[(-b/a)^k/a^(p-n)*Binomial[p-n+k-1,p-n-1],Int[x^(m+k)*(a+b*x)^p*(c+d*x)^p,x]], {k,0,-m-1}] /; +FreeQ[{a,b,c,d,n,p},x] && IntegerQ[{m,p-n}] && m<0 && p-n>0 && Not[IntegerQ[n]] + + +(* ::Subsubsection::Closed:: *) +(*x^m (e (a+b x)^p+f (c+d x)^q)^n Products of expn and powers of sums of square-roots of linears*) + + +(* ::Item:: *) +(*Basis: r^p*(v*r^q + w) == v*r^(p+q) + w*r^p*) + + +(* Int[u_.*r_^p_*(v_.*r_^q_+w_),x_Symbol] := + Int[u*v*r^(p+q),x] + Int[u*w*r^p,x] /; +HalfIntegerQ[{p,q}] *) + + +(* Int[u_.*(a_*r_^p_+s_.)*(b_*r_^q_+t_.),x_Symbol] := + Dist[a*b,Int[u*r^(p+q),x]] + Int[u*(a*t*r^p+b*s*r^q+s*t),x] /; +FreeQ[{a,b},x] && HalfIntegerQ[{p,q}] *) + + +(* Int[(e_.*(a_.+b_.*x_)^p_+f_.*(c_.+d_.*x_)^q_)^n_,x_Symbol] := + Int[Expand[(e*(a+b*x)^p+f*(c+d*x)^q)^n],x] /; +FreeQ[{a,b,c,d,e,f},x] && IntegerQ[n] && n>0 && HalfIntegerQ[{p,q}] *) + + +(* Int[x_^m_.*(e_.*(a_.+b_.*x_)^p_+f_.*(c_.+d_.*x_)^q_)^n_,x_Symbol] := + Int[Expand[x^m*(e*(a+b*x)^p+f*(c+d*x)^q)^n],x] /; +FreeQ[{a,b,c,d,e,f,m},x] && IntegerQ[n] && n>0 && HalfIntegerQ[{p,q}] *) + + +(* ::Subsection::Closed:: *) +(*(a + b x^n)^p Powers of binomials*) + + +(* ::Subsubsection::Closed:: *) +(*1 / (a+b x^n) Reciprocals of binomials*) + + +Int[1/(a_+b_.*(x_^m_)^n_),x_Symbol] := + Rt[b/a,2]*x*ArcTan[Rt[b/a,2]*(x^m)^(1/m)]/(b*(x^m)^(1/m)) /; +FreeQ[{a,b,m,n},x] && m*n===2 && PosQ[a/b] + + +Int[1/(a_+b_.*(x_^m_)^n_),x_Symbol] := + -Rt[-b/a,2]*x*ArcTanh[Rt[-b/a,2]*(x^m)^(1/m)]/(b*(x^m)^(1/m)) /; +FreeQ[{a,b,m,n},x] && m*n===2 && NegQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*z^n) == 1/a - b/(a*(b+a/z^n))*) + + +Int[1/(a_+b_.*x_^n_),x_Symbol] := + x/a - Dist[b/a,Int[1/(b+a*x^(-n)),x]] /; +FreeQ[{a,b},x] && FractionQ[n] && n<0 + + +(* ::Subsubsection::Closed:: *) +(*1 / Sqrt[a+b x^n] Reciprocals of square-root of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 278*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: ArcSinh'[z] == 1/Sqrt[1+z^2]*) + + +Int[1/Sqrt[a_+b_.*x_^2],x_Symbol] := + ArcSinh[Rt[b,2]*x/Sqrt[a]]/Rt[b,2] /; +FreeQ[{a,b},x] && PositiveQ[a] && PosQ[b] + + +(* ::Item::Closed:: *) +(*Reference: CRC 279, A&S 3.3.44*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: ArcSin'[z] == 1/Sqrt[1-z^2]*) + + +Int[1/Sqrt[a_+b_.*x_^2],x_Symbol] := + ArcSin[Rt[-b,2]*x/Sqrt[a]]/Rt[-b,2] /; +FreeQ[{a,b},x] && PositiveQ[a] && NegQ[b] + + +(* ::Item:: *) +(*Reference: CRC 278'*) + + +Int[1/Sqrt[a_+b_.*x_^2],x_Symbol] := + ArcTanh[Sqrt[a+b*x^2]/(Rt[b,2]*x)]/Rt[b,2] /; +FreeQ[{a,b},x] && Not[PositiveQ[a]] && PosQ[b] + + +(* ::Item:: *) +(*Reference: CRC 279'*) + + +Int[1/Sqrt[a_+b_.*x_^2],x_Symbol] := + -ArcTan[Sqrt[a+b*x^2]/(Rt[-b,2]*x)]/Rt[-b,2] /; +FreeQ[{a,b},x] && Not[PositiveQ[a]] && NegQ[b] + + +Int[1/Sqrt[a_+b_.*x_^4],x_Symbol] := + EllipticF[ArcSin[Rt[-b/a,4]*x],-1]/(Rt[-b/a,4]*Sqrt[a]) /; +FreeQ[{a,b},x] && PositiveQ[a] + + +Int[1/Sqrt[a_+b_.*x_^4],x_Symbol] := + Sqrt[(a+b*x^4)/a]*EllipticF[ArcSin[Rt[-b/a,4]*x],-1]/(Rt[-b/a,4]*Sqrt[a+b*x^4]) /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*(a+b x^n)^p Powers of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Sqrt[a+b/z^2] == -Sqrt[a+b*(1/z)^2]/(1/z)^2*D[1/z,z]*) + + +Int[Sqrt[a_.+b_./x_^2],x_Symbol] := + -Subst[Int[Sqrt[a+b*x^2]/x^2,x],x,1/x] /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Reference: G&R 2.110.2', CRC 88d'*) + + +Int[(a_+b_.*x_^n_)^p_,x_Symbol] := + x*(a+b*x^n)^(p+1)/a /; +FreeQ[{a,b,n,p},x] && ZeroQ[n*(p+1)+1] + + +(* ::Item:: *) +(*Reference: G&R 2.110.1, CRC 88b*) + + +Int[(a_+b_.*x_^n_)^p_,x_Symbol] := + x*(a+b*x^n)^p/(n*p+1) + + Dist[n*p*a/(n*p+1),Int[(a+b*x^n)^(p-1),x]] /; +FreeQ[{a,b,n},x] && FractionQ[p] && p>0 && NonzeroQ[n*p+1] + + +(* ::Item:: *) +(*Reference: G&R 2.110.2, CRC 88d*) + + +Int[(a_+b_.*x_^n_)^p_,x_Symbol] := + -x*(a+b*x^n)^(p+1)/(n*(p+1)*a) + + Dist[(n*(p+1)+1)/(n*(p+1)*a),Int[(a+b*x^n)^(p+1),x]] /; +FreeQ[{a,b,n},x] && FractionQ[p] && p<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.110.6, CRC 88c*) + + +Int[(a_+b_./x_)^p_,x_Symbol] := + x*(a+b/x)^(p+1)/a + + Dist[b*p/a,Int[(a+b/x)^p/x,x]] /; +FreeQ[{a,b,p},x] && Not[IntegerQ[p]] +(* Transforms fractional power p of binomial into an integer *) + + +Int[(a_+b_.*x_^n_)^p_,x_Symbol] := + Module[{q=Denominator[p]}, + Dist[q*a^(p+1/n)/n, + Subst[Int[x^(q/n-1)/(1-b*x^q)^(p+1/n+1),x],x,x^(n/q)/(a+b*x^n)^(1/q)]]] /; +FreeQ[{a,b},x] && RationalQ[{p,n}] && -11 is integer*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n/(m+1) is an integer, x^n == (x^(m+1))^(n/(m+1))*) + + +Int[x_^m_.*(a_.+b_.*x_^n_)^p_.,x_Symbol] := + Dist[1/(m+1),Subst[Int[(a+b*x^(n/(m+1)))^p,x],x,x^(m+1)]] /; +FreeQ[{a,b,m,n,p},x] && NonzeroQ[m+1] && IntegerQ[n/(m+1)] && n/(m+1)>1 && Not[IntegerQ[{m,n,p}]] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x^n)^p Products of monomials and powers of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If p is an integer, (a+b*x^n)^p == x^(n*p)*(b+a/x^n)^p*) + + +Int[x_^m_.*(a_+b_.*x_^n_)^p_,x_Symbol] := + Int[x^(m+n*p)*(b+a/x^n)^p,x] /; +FreeQ[{a,b,m},x] && FractionQ[n] && n<0 && IntegerQ[p] && p<0 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.3*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*(a_+b_.*x_^n_)^p_,x_Symbol] := + x^(m+1)*(a+b*x^n)^p/(m+1) - + Dist[b*n*p/(m+1),Int[x^(m+n)*(a+b*x^n)^(p-1),x]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && FractionQ[p] && p>0 && (n>0 && m<-1 || 0<-n<=m+1) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.4*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m*(a+b*x^n)^p == x^(m-n+1)*((a+b*x^n)^p*x^(n-1))*) + + +Int[x_^m_.*(a_+b_.*x_^n_)^p_,x_Symbol] := + x^(m-n+1)*(a+b*x^n)^(p+1)/(b*n*(p+1)) - + Dist[(m-n+1)/(b*n*(p+1)),Int[x^(m-n)*(a+b*x^n)^(p+1),x]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && FractionQ[p] && (00 && +Not[IntegerQ[(m+1)/n] && (m+1)/n>0] + + +(* ::Item:: *) +(*Reference: G&R 2.110.2, CRC 88d*) + + +Int[x_^m_.*(a_+b_.*x_^n_)^p_,x_Symbol] := + -x^(m+1)*(a+b*x^n)^(p+1)/(a*n*(p+1)) + + Dist[(m+n*(p+1)+1)/(a*n*(p+1)),Int[x^m*(a+b*x^n)^(p+1),x]] /; +FreeQ[{a,b,m,n},x] && FractionQ[p] && p<-1 && NonzeroQ[m+n*(p+1)+1] && NonzeroQ[m-n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.110.5, CRC 88a*) + + +Int[x_^m_.*(a_+b_.*x_^n_.)^p_,x_Symbol] := + x^(m-n+1)*(a+b*x^n)^(p+1)/(b*(m+n*p+1)) - + Dist[a*(m-n+1)/(b*(m+n*p+1)),Int[x^(m-n)*(a+b*x^n)^p,x]] /; +FreeQ[{a,b,m,n,p},x] && NonzeroQ[m+n*p+1] && NonzeroQ[m-n+1] && NonzeroQ[m+1] && +Not[IntegerQ[{m,n,p}]] && + (IntegerQ[{m,n}] && (0=1]) + + +(* ::Item:: *) +(*Reference: G&R 2.110.6, CRC 88c*) + + +Int[x_^m_.*(a_+b_.*x_^n_.)^p_,x_Symbol] := + x^(m+1)*(a+b*x^n)^(p+1)/(a*(m+1)) - + Dist[b*(m+n*(p+1)+1)/(a*(m+1)),Int[x^(m+n)*(a+b*x^n)^p,x]] /; +FreeQ[{a,b,m,n,p},x] && NonzeroQ[m+1] && (* NonzeroQ[m+n*(p+1)+1] && *) Not[IntegerQ[{m,n,p}]] && + (IntegerQ[{m,n}] && (n>0 && m<-1 || 0<-n<=m+1) || + Not[RationalQ[m]] && RationalQ[m+n] || + RationalQ[n] && MatchQ[m,u_+q_ /; RationalQ[q] && (n>0 && q<0 || 0<-n<=q)] || + MatchQ[m,u_+q_*n /; RationalQ[q] && q<0]) +(* Transforms fractional power p of binomial into an integer *) + + +Int[x_^m_.*(a_+b_.*x_^n_)^p_,x_Symbol] := + Module[{q=Denominator[p]}, + q*a^(p+(m+1)/n)/n* + Subst[Int[x^(q*(m+1)/n-1)/(1-b*x^q)^(p+(m+1)/n+1),x],x,x^(n/q)/(a+b*x^n)^(1/q)]] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && -10 && q<=-1 && ZeroQ[a*d-b*c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: (a+b*z^n)/(c+d*z^n) == b/d + (a*d-b*c)/(d*(c+d*z^n))*) + + +Int[(a_.+b_.*x_^n_)^p_*(c_.+d_.*x_^n_)^q_.,x_Symbol] := + Dist[(a*d-b*c)/d,Int[(a+b*x^n)^(p-1)*(c+d*x^n)^q,x]] + + Dist[b/d,Int[(a+b*x^n)^(p-1)*(c+d*x^n)^(q+1),x]] /; +FreeQ[{a,b,c,d,n},x] && RationalQ[{p,q}] && p>0 && q<=-1 && NonzeroQ[a*d-b*c] && +IntegerQ[n] && n>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/((a+b*z^n)*(c+d*z^n)) == b/((b*c-a*d)*(a+b*z^n)) - d/((b*c-a*d)*(c+d*z^n))*) + + +Int[(a_.+b_.*x_^n_)^p_.*(c_.+d_.*x_^n_)^q_.,x_Symbol] := + Dist[b/(b*c-a*d),Int[(a+b*x^n)^p*(c+d*x^n)^(q+1),x]] - + Dist[d/(b*c-a*d),Int[(a+b*x^n)^(p+1)*(c+d*x^n)^q,x]] /; +FreeQ[{a,b,c,d,n},x] && RationalQ[{p,q}] && p<-1 && q<=-1 && NonzeroQ[b*c-a*d] && +IntegerQ[n] && n>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If b*c-a*d==0, (a+b*z^n)*(c+d*z^n) == d/b*(a+b*z^n)^2*) + + +(* Int[u_.*(a_+b_.*x_^n_.)^p_*(c_+d_.*x_^n_.)^q_,x_Symbol] := + Dist[(d/b)^q,Int[u*(a+b*x^n)^(p+q),x]] /; +FreeQ[{a,b,c,d,n,p},x] && IntegerQ[q] && ZeroQ[b*c-a*d] *) + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x^2)^n (c+d x^2)^p Products of monomials and powers of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: z/Sqrt[a+b*z] == Sqrt[a+b*z]/b - a/(b*Sqrt[a+b*z])*) + + +Int[x_^2/(Sqrt[a_+b_.*x_^2]*Sqrt[c_+d_.*x_^2]),x_Symbol] := + Dist[1/b,Int[Sqrt[a+b*x^2]/Sqrt[c+d*x^2],x]] - + Dist[a/b,Int[1/(Sqrt[a+b*x^2]*Sqrt[c+d*x^2]),x]] /; +FreeQ[{a,b,c,d},x] + + +Int[x_^2*Sqrt[a_+b_.*x_^2]/Sqrt[c_+d_.*x_^2],x_Symbol] := + x*Sqrt[a+b*x^2]*Sqrt[c+d*x^2]/(3*d) - + Dist[1/(3*d),Int[(a*c+(2*b*c-a*d)*x^2)/(Sqrt[a+b*x^2]*Sqrt[c+d*x^2]),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x^n) / (c+d x^p) Products of monomials and quotients of binomials*) + + +Int[(a_.+b_.*x_^n_.)/(x_*(c_+d_.*x_^p_.)),x_Symbol] := + a*Log[x]/c+ + Dist[1/c,Int[x^(n-1)*(b*c-a*d*x^(p-n))/(c+d*x^p),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[{n,p}] && 00. *) + + +Int[1/Sqrt[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + ArcSinh[(b+2*c*x)/(Sqrt[4*a-b^2/c]*Rt[c,2])]/Rt[c,2] /; +FreeQ[{a,b,c},x] && PositiveQ[4*a-b^2/c] && PosQ[c] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.261.3', CRC 238', A&S 3.3.36'*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[ArcSin[x],x] == 1/Sqrt[1-x^2] *) + + +(* Note: Unlike in the references,this formulation of the rule is valid even if not c>0. *) +Int[1/Sqrt[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + -ArcSin[(b+2*c*x)/(Sqrt[4*a-b^2/c]*Rt[-c,2])]/Rt[-c,2] /; +FreeQ[{a,b,c},x] && PositiveQ[4*a-b^2/c] && NegQ[c] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.261.1, CRC 237a, A&S 3.3.33*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +Int[1/Sqrt[a_.+b_.*x_+c_.*x_^2],x_Symbol] := +(* ArcTanh[(b+2*c*x)/(2*Rt[c,2]*Sqrt[a+b*x+c*x^2])]/Rt[c,2] /; *) + ArcTanh[(2*Rt[c,2]*Sqrt[a+b*x+c*x^2])/(b+2*c*x)]/Rt[c,2] /; +FreeQ[{a,b,c},x] && PosQ[c] && NonzeroQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Reference: CRC 238'*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +Int[1/Sqrt[a_.+b_.*x_+c_.*x_^2],x_Symbol] := +(* -ArcTan[(b+2*c*x)/(2*Rt[-c,2]*Sqrt[a+b*x+c*x^2])]/Rt[-c,2] /; *) + ArcTan[(2*Rt[-c,2]*Sqrt[a+b*x+c*x^2])/(b+2*c*x)]/Rt[-c,2] /; +FreeQ[{a,b,c},x] && NegQ[c] && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*1 / ((d+e x) Sqrt[a+b x+c x^2]) Reciprocals of products of linears and square-roots of quadratic trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.266.7, CRC 260*) +(* Note: Unnecessary because this is a special case of the rule for when m+2*(n+1) is zero! *) + + +(* Int[1/((d_.+e_.*x_)*Sqrt[a_.+c_.*x_^2]),x_Symbol] := + Module[{q=c*d^2+a*e^2}, +(* e*Sqrt[a+c*x^2]/(c*d*(d+e*x)) /; *) + (-d+e*x)/(d*e*Sqrt[a+c*x^2]) /; + ZeroQ[q]] /; +FreeQ[{a,c,d,e},x] *) + + +(* ::Item:: *) +(*Reference: G&R 2.266.1', CRC 258'*) + + +Int[1/((d_.+e_.*x_)*Sqrt[a_.+c_.*x_^2]),x_Symbol] := + Module[{q=c*d^2+a*e^2}, +(* -ArcTanh[(a*e-c*d*x)/(Rt[q,2]*Sqrt[a+c*x^2])]/Rt[q,2] /; *) + -ArcTanh[(Rt[q,2]*Sqrt[a+c*x^2])/(a*e-c*d*x)]/Rt[q,2] /; + PosQ[q]] /; +FreeQ[{a,c,d,e},x] + + +(* ::Item:: *) +(*Reference: G&R 2.266.3, CRC 259*) + + +Int[1/((d_.+e_.*x_)*Sqrt[a_.+c_.*x_^2]),x_Symbol] := + Module[{q=c*d^2+a*e^2}, +(* ArcTan[(a*e-c*d*x)/(Rt[-q,2]*Sqrt[a+c*x^2])]/Rt[-q,2] /; *) + -ArcTan[(Rt[-q,2]*Sqrt[a+c*x^2])/(a*e-c*d*x)]/Rt[-q,2] /; + NegQ[q]] /; +FreeQ[{a,c,d,e},x] + + +(* ::Item:: *) +(*Reference: G&R 2.266.7, CRC 260*) + + +Int[1/((d_.+e_.*x_)*Sqrt[a_.+b_.*x_+c_.*x_^2]),x_Symbol] := + -2*e*Sqrt[a+b*x+c*x^2]/((b*e-2*c*d)*(d+e*x)) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[c*d^2-b*d*e+a*e^2] + + +(* ::Item:: *) +(*Reference: G&R 2.266.1', CRC 258'*) + + +Int[1/((d_.+e_.*x_)*Sqrt[a_.+b_.*x_+c_.*x_^2]),x_Symbol] := + Module[{q=c*d^2-b*d*e+a*e^2}, + -ArcTanh[(2*Rt[q,2]*Sqrt[a+b*x+c*x^2])/(2*a*e-b*d+(b*e-2*c*d)*x)]/Rt[q,2] /; + PosQ[q]] /; +FreeQ[{a,b,c,d,e},x] + + +(* ::Item:: *) +(*Reference: G&R 2.266.3, CRC 259*) + + +Int[1/((d_.+e_.*x_)*Sqrt[a_.+b_.*x_+c_.*x_^2]),x_Symbol] := + Module[{q=c*d^2-b*d*e+a*e^2}, + -ArcTan[(2*Rt[-q,2]*Sqrt[a+b*x+c*x^2])/(2*a*e-b*d+(b*e-2*c*d)*x)]/Rt[-q,2] /; + NegQ[q]] /; +FreeQ[{a,b,c,d,e},x] + + +(* ::Subsubsection::Closed:: *) +(*(a+b x+c x^2)^n Powers of quadratic trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.260.2, CRC 245, A&S 3.3.37*) + + +Int[(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + (b+2*c*x)*(a+b*x+c*x^2)^n/(2*c*(2*n+1)) - + Dist[n*(b^2-4*a*c)/(2*c*(2*n+1)),Int[(a+b*x+c*x^2)^(n-1),x]] /; +FreeQ[{a,b,c},x] && FractionQ[n] && n>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m / (a+b x+c x^2) Quotients of monomials by quadratic trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[x_^m_/(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + x^(m-1)/(c*(m-1))- + Dist[1/c,Int[x^(m-2)*(a+b*x)/(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c},x] && FractionQ[m] && m>1 + + +(* ::Item:: *) +(*Reference: G&R 2.265c*) + + +Int[x_^m_/(b_.*x_+c_.*x_^2),x_Symbol] := + x^m/(b*m)- + Dist[c/b,Int[x^(m+1)/(b*x+c*x^2),x]] /; +FreeQ[{b,c},x] && FractionQ[m] && m<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.176, CRC 123*) + + +Int[x_^m_/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + x^(m+1)/(a*(m+1))- + Dist[1/a,Int[x^(m+1)*(b+c*x)/(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c},x] && FractionQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m (d+e x) / (a+b x+c x^2) Products of monomials and quotients of linears by quadratic trinomials*) + + +Int[x_^m_.*(d_+e_.*x_)/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + e*x^m/(c*m)- + Dist[1/c,Int[x^(m-1)*(a*e+(b*e-c*d)*x)/(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[m] && m>0 + + +Int[x_^m_.*(d_+e_.*x_)/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + d*x^(m+1)/(a*(m+1))- + Dist[1/a,Int[x^(m+1)*(b*d-a*e+c*d*x)/(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b x+c x^2)^n / (d+e x) Quotients of powers of quadratic trinomials by linears*) + + +(* ::Item:: *) +(*Reference: G&R 2.265b*) + + +Int[(a_.+b_.*x_+c_.*x_^2)^n_/(d_.+e_.*x_),x_Symbol] := + (a+b*x+c*x^2)^n/(2*e*n) + + Dist[(b*e-2*c*d)/(2*e^2), Int[(a+b*x+c*x^2)^(n-1),x]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[n] && n>0 && ZeroQ[c*d^2-b*d*e+a*e^2] + + +(* ::Item:: *) +(*Reference: G&R 2.265b*) + + +Int[(a_.+b_.*x_+c_.*x_^2)^n_/(d_.+e_.*x_),x_Symbol] := + (a+b*x+c*x^2)^n/(2*e*n) + + Dist[(c*d^2-b*d*e+a*e^2)/e^2, Int[(a+b*x+c*x^2)^(n-1)/(d+e*x),x]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[n] && n>0 && ZeroQ[b*e-2*c*d] + + +(* ::Item:: *) +(*Reference: G&R 2.265b*) + + +Int[(a_.+b_.*x_+c_.*x_^2)^n_/(d_.+e_.*x_),x_Symbol] := + (a+b*x+c*x^2)^n/(2*e*n) + + Dist[(b*e-2*c*d)/(2*e^2), Int[(a+b*x+c*x^2)^(n-1),x]] + + Dist[(c*d^2-b*d*e+a*e^2)/e^2, Int[(a+b*x+c*x^2)^(n-1)/(d+e*x),x]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[n] && n>0 + + +(* ::Item:: *) +(*Reference: G&R 2.268b, CRC 122*) + + +Int[(a_.+b_.*x_+c_.*x_^2)^n_/(d_.+e_.*x_),x_Symbol] := + -e*(a+b*x+c*x^2)^(n+1)/(2*(n+1)*(c*d^2-b*d*e+a*e^2)) + + Dist[e^2/(c*d^2-b*d*e+a*e^2), Int[(a+b*x+c*x^2)^(n+1)/(d+e*x),x]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[n] && n<-1 && NonzeroQ[c*d^2-b*d*e+a*e^2] && ZeroQ[2*c*d-b*e] + + +(* ::Item:: *) +(*Reference: G&R 2.268b, CRC 122*) + + +Int[(a_.+b_.*x_+c_.*x_^2)^n_/(d_.+e_.*x_),x_Symbol] := + -e*(a+b*x+c*x^2)^(n+1)/(2*(n+1)*(c*d^2-b*d*e+a*e^2)) + + Dist[(2*c*d-b*e)/(2*(c*d^2-b*d*e+a*e^2)), Int[(a+b*x+c*x^2)^n,x]] + + Dist[e^2/(c*d^2-b*d*e+a*e^2), Int[(a+b*x+c*x^2)^(n+1)/(d+e*x),x]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[n] && n<-1 && NonzeroQ[c*d^2-b*d*e+a*e^2] + + +(* ::Subsection::Closed:: *) +(*a + b x^2 + c x^4 Integrands involving symmetric quartic trinomials*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4*a*c], then a+b*x^2+c*x^4 == a*(1+2*c*x^2/(b-q))*(1+2*c*x^2/(b+q))*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4*a*c], then D[Sqrt[1+2*c*x^2/(b-q)]*Sqrt[1+2*c*x^2/(b+q)]/Sqrt[a+b*x^2+c*x^4], x] == 0*) + + +Int[1/Sqrt[a_+b_.*x_^2+c_.*x_^4],x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Sqrt[1+2*c*x^2/(b-q)]*Sqrt[1+2*c*x^2/(b+q)]/Sqrt[a+b*x^2+c*x^4]*Int[1/(Sqrt[1+2*c*x^2/(b-q)]*Sqrt[1+2*c*x^2/(b+q)]),x]] /; +FreeQ[{a,b,c},x] && NonzeroQ[b^2-4*a*c] + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4*a*c], then a+b*x^2+c*x^4 == a*(1+2*c*x^2/(b-q))*(1+2*c*x^2/(b+q))*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4*a*c], then D[Sqrt[1+2*c*x^2/(b-q)]*Sqrt[1+2*c*x^2/(b+q)]/Sqrt[a+b*x^2+c*x^4], x] == 0*) + + +Int[x_^2/Sqrt[a_+b_.*x_^2+c_.*x_^4],x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Sqrt[1+2*c*x^2/(b-q)]*Sqrt[1+2*c*x^2/(b+q)]/Sqrt[a+b*x^2+c*x^4]*Int[x^2/(Sqrt[1+2*c*x^2/(b-q)]*Sqrt[1+2*c*x^2/(b+q)]),x]] /; +FreeQ[{a,b,c},x] && NonzeroQ[b^2-4*a*c] + + +(* ::Subsection::Closed:: *) +(*a + b x^k + c x^(2k) Integrands involving symmetric trinomials*) + + +(* ::Subsubsection::Closed:: *) +(*(a + b x^2)/(c + d x^2 + e x^4) Quotients of binomials by quartic trinomials*) + + +(* ::ItemParagraph:: *) +(*Previously undiscovered rules ??? *) + + +Int[(a_+b_.*x_^k_)/(c_+d_.*x_^2+e_.*x_^k_+f_.*x_^j_), x_Symbol] := + a/Rt[c*d,2]*ArcTan[(k-1)*a*Rt[c*d,2]*x/(c*((k-1)*a-b*x^k))] /; +FreeQ[{a,b,c,d,e,f,j,k},x] && Not[IntegerQ[k]] && j===2*k && ZeroQ[(k-1)^2*a^2*f-b^2*c] && ZeroQ[b*e+2*(k-1)*a*f] && +PosQ[c*d] + + +Int[(a_+b_.*x_^k_)/(c_+d_.*x_^2+e_.*x_^k_+f_.*x_^j_), x_Symbol] := + a/Rt[-c*d,2]*ArcTanh[(k-1)*a*Rt[-c*d,2]*x/(c*((k-1)*a-b*x^k))] /; +FreeQ[{a,b,c,d,e,f,j,k},x] && Not[IntegerQ[k]] && j===2*k && ZeroQ[(k-1)^2*a^2*f-b^2*c] && ZeroQ[b*e+2*(k-1)*a*f] && +NegQ[c*d] + + +Int[x_^m_.*(a_+b_.*x_^n_.)/(c_+d_.*x_^k_.+e_.*x_^n_.+f_.*x_^j_), x_Symbol] := + a*ArcTan[(m-n+1)*a*Rt[c*d,2]*x^(m+1)/(c*((m-n+1)*a+(m+1)*b*x^n))]/((m+1)*Rt[c*d,2]) /; +FreeQ[{a,b,c,d,e,f,j,k,m,n},x] && ZeroQ[k-2*(m+1)] && ZeroQ[j-2*n] && +ZeroQ[(m-n+1)^2*a^2*f-(m+1)^2*b^2*c] && ZeroQ[(m+1)*b*e-2*(m-n+1)*a*f] && PosQ[c*d] + + +Int[x_^m_.*(a_+b_.*x_^n_.)/(c_+d_.*x_^k_.+e_.*x_^n_.+f_.*x_^j_), x_Symbol] := + a*ArcTanh[(m-n+1)*a*Rt[-c*d,2]*x^(m+1)/(c*((m-n+1)*a+(m+1)*b*x^n))]/((m+1)*Rt[-c*d,2]) /; +FreeQ[{a,b,c,d,e,f,j,k,m,n},x] && ZeroQ[k-2*(m+1)] && ZeroQ[j-2*n] && +ZeroQ[(m-n+1)^2*a^2*f-(m+1)^2*b^2*c] && ZeroQ[(m+1)*b*e-2*(m-n+1)*a*f] && NegQ[c*d] + + +(* ::Subsubsection::Closed:: *) +(*(a+b x^k+c x^(2k))^n Powers of symmetric trinomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.161.1a'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*z+c*z^2) == 2*c/(q*(b-q+2*c*z)) - 2*c/(q*(b+q+2*c*z)) where q=Sqrt[b^2-4*a*c]*) + + +Int[1/(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[2*c/q,Int[1/(b-q+2*c*x^k),x]] - + Dist[2*c/q,Int[1/(b+q+2*c*x^k),x]]] /; +FreeQ[{a,b,c,j,k},x] && Not[IntegerQ[k]] && j===2*k && NonzeroQ[b^2-4*a*c] && Not[NegativeQ[b^2-4*a*c]] + + +(* ::Item:: *) +(*Reference: G&R 2.161.1b?*) + + +Int[1/(a_+b_.*x_^k_+c_.*x_^j_),x_Symbol] := + Module[{q=2*Rt[a/c,2]-b/c}, + Dist[1/(2*c*Rt[a/c,2]*Rt[q,2]),Int[(Rt[q,2]+x^(k/2))/(Rt[a/c,2]+Rt[q,2]*x^(k/2)+x^k),x]] + + Dist[1/(2*c*Rt[a/c,2]*Rt[q,2]),Int[(Rt[q,2]-x^(k/2))/(Rt[a/c,2]-Rt[q,2]*x^(k/2)+x^k),x]] /; + PosQ[q]] /; +FreeQ[{a,b,c},x] && EvenQ[k] && k>0 && j===2*k && PosQ[a/c] && NegativeQ[b^2-4*a*c] + + +(* ::Item:: *) +(*Reference: G&R 2.161.5' (GR5 2.161.4 is a special case.)*) +(* Previously undiscovered rule ??? *) + + +Int[(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + -x*(b^2-2*a*c+b*c*x^k)*(a+b*x^k+c*x^j)^(n+1)/(k*a*(n+1)*(b^2-4*a*c)) + + Dist[(k*(n+1)*(b^2-4*a*c)+b^2-2*a*c)/(k*a*(n+1)*(b^2-4*a*c)),Int[(a+b*x^k+c*x^j)^(n+1),x]] + + Dist[(k*(2*n+3)+1)*b*c/(k*a*(n+1)*(b^2-4*a*c)),Int[x^k*(a+b*x^k+c*x^j)^(n+1),x]] /; +FreeQ[{a,b,c,j,k},x] && RationalQ[n] && Not[IntegerQ[k]] && j===2*k && n<-1 && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*1 / (x Sqrt[a+b x^k+c x^(2k)]) Reciprocals of products of x and square-roots of symmetric trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.266.7, CRC 260*) + + +Int[1/(x_*Sqrt[b_.*x_^k_.+c_.*x_^j_.]),x_Symbol] := + -2*Sqrt[b*x^k+c*x^j]/(b*k*x^k) /; +FreeQ[{b,c,j,k},x] && j===2*k + + +(* ::Item:: *) +(*Reference: G&R 2.266.1', CRC 258'*) + + +Int[1/(x_*Sqrt[a_+b_.*x_^k_.+c_.*x_^j_.]),x_Symbol] := + -ArcTanh[(2*a+b*x^k)/(2*Rt[a,2]*Sqrt[a+b*x^k+c*x^j])]/(k*Rt[a,2]) /; +FreeQ[{a,b,c,j,k},x] && j===2*k && PosQ[a] + + +(* ::Item:: *) +(*Reference: G&R 2.266.3, CRC 259*) + + +Int[1/(x_*Sqrt[a_+b_.*x_^k_.+c_.*x_^j_.]),x_Symbol] := + ArcTan[(2*a+b*x^k)/(2*Rt[-a,2]*Sqrt[a+b*x^k+c*x^j])]/(k*Rt[-a,2]) /; +FreeQ[{a,b,c,j,k},x] && j===2*k && NegQ[a] + + +(* ::Subsubsection::Closed:: *) +(*x^m / (a+b x^k+c x^(2k)) Quotients of monomials by symmetric trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.177.1', CRC 120'*) + + +(* Note: This rule does not use the obvious substitution u=x^k on the whole integrand reducing + it to 1/(x*(a+b*x+c*x^2)) so that Log[x] instead of Log[x^k] appears in the result *) +Int[1/(x_*(a_+b_.*x_^k_+c_.*x_^j_.)),x_Symbol] := +(* Dist[1/a,Int[x^(k-1)*(b+c*x^k)/(a+b*x^k+c*x^j),x]] /; *) + Log[x]/a - + Dist[1/(a*k),Subst[Int[(b+c*x)/(a+b*x+c*x^2),x],x,x^k]] /; +FreeQ[{a,b,c,j,k},x] && Not[IntegerQ[k]] && j===2*k + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.161.3'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: z/(a+b*z+c*z^2) == (1-b/q)/(b-q+2*c*z) + (1+b/q)/(b+q+2*c*z) where q=Sqrt[b^2-4*a*c]*) + + +Int[x_^k_/(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[(1-b/q),Int[1/(b-q+2*c*x^k),x]] + + Dist[(1+b/q),Int[1/(b+q+2*c*x^k),x]]] /; +FreeQ[{a,b,c,j,k},x] && Not[IntegerQ[k]] && j===2*k && NonzeroQ[b^2-4*a*c] && Not[NegativeQ[b^2-4*a*c]] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1', CRC 119'*) + + +Int[x_^m_./(a_+b_.*x_^k_+c_.*x_^j_),x_Symbol] := + x^(m-j+1)/(c*(m-j+1)) - + Dist[1/c,Int[x^(m-j)*(a+b*x^k)/(a+b*x^k+c*x^j),x]] /; +FreeQ[{a,b,c,j,k},x] && Not[IntegerQ[k]] && j===2*k && RationalQ[{m,k}] && 00 + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x^k+c x^(2k))^n Products of monomials and powers of symmetric trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.174.2'*) + + +(* Note: This should be generalized from quadratic to all symmetric trinomials! *) +Int[x_^m_*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + -x^(m-1)*(a+b*x+c*x^2)^(n+1)/(c*(m-1)) - + Dist[b/(2*c),Int[x^(m-1)*(a+b*x+c*x^2)^n,x]] + + Dist[1/c,Int[x^(m-2)*(a+b*x+c*x^2)^(n+1),x]] /; +FreeQ[{a,b,c},x] && RationalQ[{m,n}] && n<-1 && ZeroQ[m+2*n+1] && Not[IntegerQ[{m,n}]] + + +(* ::Item:: *) +(*Reference: G&R 2.160.4*) + + +Int[x_^m_*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^n/(m+j*n+1) + + Dist[a*j*n/(m+j*n+1),Int[x^m*(a+b*x^k+c*x^j)^(n-1),x]] + + Dist[b*k*n/(m+j*n+1),Int[x^(m+k)*(a+b*x^k+c*x^j)^(n-1),x]] /; +FreeQ[{a,b,c},x] && RationalQ[{j,k,m,n}] && j==2*k && j>0 && m<-1 && n>1 && NonzeroQ[m+j*n+1] && +Not[IntegerQ[{j,k,m,n}]] + + +(* ::Item:: *) +(*Reference: G&R 2.160.3'*) + + +Int[x_^m_*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x^(m-j+1)*(a+b*x^k+c*x^j)^(n+1)/(c*k*(n+1)) + + Dist[a/c,Int[x^(m-j)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c,n},x] && FractionQ[{j,k,m}] && j===2*k && 0=-1] && Not[IntegerQ[{j,k,m,n}]] + + +(* ::Item:: *) +(*Reference: G&R 2.160.3 (GR5 2.174.1 is a special case.)*) + + +Int[x_^m_*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x^(m-j+1)*(a+b*x^k+c*x^j)^(n+1)/(c*(m+j*n+1)) - + Dist[b*(m+k*(n-1)+1)/(c*(m+j*n+1)),Int[x^(m-k)*(a+b*x^k+c*x^j)^n,x]] - + Dist[a*(m-j+1)/(c*(m+j*n+1)),Int[x^(m-j)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[{j,k,m}] && j==2*k && 0=-1] && Not[IntegerQ[{j,k,m,n}]] + + +(* ::Item:: *) +(*Reference: G&R 2.160.1 special case*) + + +Int[x_^m_*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^(n+1)/(a*(m+1)) + + Dist[c/a,Int[x^(m+j)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[{j,k,m}] && j==2*k && j>0 && m<-1 && ZeroQ[m+1+k*(n+1)] && +Not[IntegerQ[{j,k,m,n}]] + + +(* ::Item:: *) +(*Reference: G&R 2.160.1 special case*) + + +Int[x_^m_*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^(n+1)/(a*(m+1)) - + Dist[b/(2*a),Int[x^(m+k)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[{j,k,m}] && j==2*k && j>0 && m<-1 && ZeroQ[m+1+j*(n+1)] && +Not[IntegerQ[{j,k,m,n}]] + + +(* ::Item:: *) +(*Reference: G&R 2.160.2*) + + +Int[x_^m_*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^n/(m+1) - + Dist[b*k*n/(m+1),Int[x^(m+k)*(a+b*x^k+c*x^j)^(n-1),x]] - + Dist[c*j*n/(m+1),Int[x^(m+j)*(a+b*x^k+c*x^j)^(n-1),x]] /; +FreeQ[{a,b,c},x] && RationalQ[{j,k,m,n}] && j==2*k && j>0 && m<-1 && n>1 && +Not[IntegerQ[{j,k,m,n}]] + + +(* ::Item:: *) +(*Reference: G&R 2.160.1*) + + +(* ::Item:: *) +(*Note: G&R 2.161.6 is a special case*) + + +Int[x_^m_*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^(n+1)/(a*(m+1)) - + Dist[b*(m+1+k*(n+1))/(a*(m+1)),Int[x^(m+k)*(a+b*x^k+c*x^j)^n,x]] - + Dist[c*(m+1+j*(n+1))/(a*(m+1)),Int[x^(m+j)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[{j,k,m}] && j==2*k && j>0 && m<-1 && NonzeroQ[m+1+k*(n+1)] && +NonzeroQ[m+1+j*(n+1)] && Not[RationalQ[n] && n>1] && Not[IntegerQ[{j,k,m,n}]] + + +(* Previously undiscovered rules ??? *) +Int[x_^k_.*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x*(b+2*c*x^k)*(a+b*x^k+c*x^j)^n/(2*c*(k*(2*n+1)+1)) - + Dist[b/(2*c*(k*(2*n+1)+1)),Int[(a+b*x^k+c*x^j)^n, x]] - + Dist[k*n*(b^2-4*a*c)/(2*c*(k*(2*n+1)+1)),Int[x^k*(a+b*x^k+c*x^j)^(n-1), x]] /; +FreeQ[{a,b,c,j,k},x] && RationalQ[n] && Not[IntegerQ[k]] && j===2*k && n>0 && NonzeroQ[b^2-4*a*c] && +NonzeroQ[k*(2*n+1)+1] + + +Int[x_^k_.*(a_+b_.*x_^k_.+c_.*x_^j_.)^n_,x_Symbol] := + x*(b+2*c*x^k)*(a+b*x^k+c*x^j)^(n+1)/(k*(n+1)*(b^2-4*a*c)) - + Dist[b/(k*(n+1)*(b^2-4*a*c)),Int[(a+b*x^k+c*x^j)^(n+1),x]] - + Dist[2*c*(k*(2*n+3)+1)/(k*(n+1)*(b^2-4*a*c)),Int[x^k*(a+b*x^k+c*x^j)^(n+1),x]] /; +FreeQ[{a,b,c,j,k},x] && RationalQ[n] && Not[IntegerQ[k]] && j===2*k && n<-1 && NonzeroQ[b^2-4*a*c] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* Note: Transforms quadratic trinomial into a quadratic binomial. *) +(* Int[x_^m_.*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + Subst[Int[Expand[(-b/(2*c)+x)^m*(a-b^2/(4*c)+c*x^2)^n],x],x,b/(2*c)+x] /; +FreeQ[{a,b,c},x] && IntegerQ[m] && m>0 && FractionQ[n] *) + + +(* ::Subsubsection::Closed:: *) +(*x^m (d+e x^k) / (a+b x^k+c x^(2k)) Products of monomials and quotients of binomials by symmetric trinomials*) + + +(* These way kool, and to my knowledge original, rules reduce the degree of monomial without + increasing the complexity of the integrands. *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: (d+e*z)/(a+b*z+c*z^2) == (e+(2*c*d-b*e)/q)/(b-q+2*c*z) + (e-(2*c*d-b*e)/q)/(b+q+2*c*z) where q=Sqrt[b^2-4*a*c]*) + + +(* Basis: (d+e*z)/(a+b*z+c*z^2) == (e+(2*c*d-b*e)/q)/(b-q+2*c*z) + (e-(2*c*d-b*e)/q)/(b+q+2*c*z) + where q=Sqrt[b^2-4*a*c] *) + + +Int[(d_+e_.*x_^k_)/(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[(e+(2*c*d-b*e)/q),Int[1/(b-q+2*c*x^k),x]] + + Dist[(e-(2*c*d-b*e)/q),Int[1/(b+q+2*c*x^k),x]]] /; +FreeQ[{a,b,c,d,e,j,k},x] && Not[IntegerQ[k]] && j===2*k && NonzeroQ[b^2-4*a*c] && Not[NegativeQ[b^2-4*a*c]] + + +(* Note: This rule does not use the obvious substitution u=x^k on the whole integrand reducing + it to (d+e*x)/(x*(a+b*x+c*x^2)) so that Log[x] instead of Log[x^k] appears in the result *) +Int[(d_.+e_.*x_^k_)/(x_*(a_+b_.*x_^k_+c_.*x_^j_.)),x_Symbol] := +(* Dist[1/a,Int[x^(k-1)*(b*d-a*e+c*d*x^k)/(a+b*x^k+c*x^j),x]] /; *) + d*Log[x]/a - + 1/(a*k)*Subst[Int[(b*d-a*e+c*d*x)/(a+b*x+c*x^2),x],x,x^k] /; +FreeQ[{a,b,c,d,e,j,k},x] && Not[IntegerQ[k]] && j===2*k + + +Int[x_^m_.*(d_.+e_.*x_^k_)/(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + e*x^(m-k+1)/(c*(m-k+1)) - + Dist[1/c,Int[x^(m-k)*(a*e+(b*e-c*d)*x^k)/(a+b*x^k+c*x^j),x]] /; +FreeQ[{a,b,c,d,e,j,k},x] && Not[IntegerQ[k]] && j===2*k && RationalQ[{m,k}] && 00 + + +(* ::Subsection::Closed:: *) +(*x^m ((a+b x)/(c+d x))^n Products of monomials and powers of quotients of linears*) + + +(* Int[(e_.*(a_.+b_.*x_)/(c_.+d_.*x_))^n_,x_Symbol] := + Dist[e*(b*c-a*d),Subst[Int[x^n/(b*e-d*x)^2,x],x,e*(a+b*x)/(c+d*x)]] /; +FreeQ[{a,b,c,d,e},x] && FractionQ[n] && NonzeroQ[b*c-a*d] *) + + +(* Int[x_^m_.*(e_.*(a_.+b_.*x_)/(c_.+d_.*x_))^n_,x_Symbol] := + Dist[e*(b*c-a*d),Subst[Int[x^n*(-a*e+c*x)^m/(b*e-d*x)^(m+2),x],x,e*(a+b*x)/(c+d*x)]] /; +FreeQ[{a,b,c,d,e},x] && IntegerQ[m] && FractionQ[n] && NonzeroQ[b*c-a*d] *) + + +(* Int[(f_+g_.*x_)^m_*(e_.*(a_.+b_.*x_)/(c_.+d_.*x_))^n_,x_Symbol] := + Dist[1/g,Subst[Int[x^m*(e*(a-b*f/g+b/g*x)/(c-d*f/g+d/g*x))^n,x],x,f+g*x]] /; +FreeQ[{a,b,c,d,e,f,g},x] && IntegerQ[m] && m<0 && FractionQ[n] && NonzeroQ[b*c-a*d] *) + + +(* ::Subsection::Closed:: *) +(*Sqrt[a x+Sqrt[b+a^2 x^2]] Nested square roots*) + + +Int[Sqrt[a_.*x_+Sqrt[b_+c_.*x_^2]], x_Symbol] := + 2*(2*a*x-Sqrt[b+c*x^2])*Sqrt[a*x+Sqrt[b+c*x^2]]/(3*a) /; +FreeQ[{a,b,c},x] && c===a^2 + + +Int[Sqrt[a_.*x_-Sqrt[b_+c_.*x_^2]], x_Symbol] := + 2*(2*a*x+Sqrt[b+c*x^2])*Sqrt[a*x-Sqrt[b+c*x^2]]/(3*a) /; +FreeQ[{a,b,c},x] && c===a^2 + + +(* ::Subsection::Closed:: *) +(*Sqrt[a+Sqrt[a^2+b x^2]] Nested square roots*) + + +Int[Sqrt[a_+Sqrt[c_+b_.*x_^2]], x_Symbol] := + 2*Sqrt[a+Sqrt[a^2+b*x^2]]*(-a^2+b*x^2+a*Sqrt[a^2+b*x^2])/(3*b*x) /; +FreeQ[{a,b,c},x] && c===a^2 + + +Int[Sqrt[a_-Sqrt[c_+b_.*x_^2]], x_Symbol] := + 2*Sqrt[a-Sqrt[a^2+b*x^2]]*(-a^2+b*x^2-a*Sqrt[a^2+b*x^2])/(3*b*x) /; +FreeQ[{a,b,c},x] && c===a^2 + + +(* ::Subsection::Closed:: *) +(*u / (v+Sqrt[w]) Rationalization of denominators*) + + +Int[u_./(a_.*x_^m_.+b_.*Sqrt[c_.*x_^n_]),x_Symbol] := + Int[u*(a*x^m-b*Sqrt[c*x^n])/(a^2*x^(2*m)-b^2*c*x^n),x] /; +FreeQ[{a,b,c,m,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If b*e^2=d*f^2, 1/(e*Sqrt[a+b*x^n]+f*Sqrt[c+d*x^n]) == (e*Sqrt[a+b*x^n]-f*Sqrt[c+d*x^n])/(a*e^2-c*f^2)*) + + +Int[u_.*(e_.*Sqrt[a_.+b_.*x_^n_.]+f_.*Sqrt[c_.+d_.*x_^n_.])^m_,x_Symbol] := + Dist[(a*e^2-c*f^2)^m,Int[u*(e*Sqrt[a+b*x^n]-f*Sqrt[c+d*x^n])^(-m),x]] /; +FreeQ[{a,b,c,d,e,f,n},x] && IntegerQ[m] && m<0 && ZeroQ[b*e^2-d*f^2] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If a*e^2=c*f^2, 1/(e*Sqrt[a+b*x^n]+f*Sqrt[c+d*x^n]) == (e*Sqrt[a+b*x^n]-f*Sqrt[c+d*x^n])/((b*e^2-d*f^2)*x^n)*) + + +Int[u_.*(e_.*Sqrt[a_.+b_.*x_^n_.]+f_.*Sqrt[c_.+d_.*x_^n_.])^m_,x_Symbol] := + Dist[(b*e^2-d*f^2)^m,Int[u*(e*Sqrt[a+b*x^n]-f*Sqrt[c+d*x^n])^(-m)*x^(m*n),x]] /; +FreeQ[{a,b,c,d,e,f,n},x] && IntegerQ[m] && m<0 && ZeroQ[a*e^2-c*f^2] + + +Int[u_./(a_+b_.*Sqrt[c_+d_.*x_^n_]),x_Symbol] := + Dist[-a/(b^2*d),Int[u/x^n,x]] + + Dist[1/(b*d),Int[u*Sqrt[c+d*x^n]/x^n,x]] /; +FreeQ[{a,b,c,d,n},x] && a^2===b^2*c + + +Int[u_./(a_.*x_^m_.+b_.*Sqrt[c_+d_.*x_^n_]),x_Symbol] := + Dist[-a/(b^2*c),Int[u*x^m,x]] + + Dist[1/(b*c),Int[u*Sqrt[c+d*x^n],x]] /; +FreeQ[{a,b,c,d,m,n},x] && n===2*m && a^2===b^2*d + + +Int[u_./(a_+b_.*x_^m_.+c_.*Sqrt[d_+e_.*x_^n_]),x_Symbol] := + Dist[1/(2*b),Int[u/x^m,x]] + + Dist[1/(2*a),Int[u,x]] - + Dist[c/(2*a*b),Int[u*Sqrt[d+e*x^n]/x^m,x]] /; +FreeQ[{a,b,c,d,m,n},x] && n===2*m && a^2===c^2*d && b^2===c^2*e + + +Int[u_./(a_+b_.*x_^m_.+c_.*Sqrt[d_+e_.*x_^n_]),x_Symbol] := + Dist[a/b^2,Int[u/x^(2*m),x]] + + Dist[1/b,Int[u/x^m,x]] - + Dist[c/b^2,Int[u*Sqrt[d+e*x^n]/x^(2*m),x]] /; +FreeQ[{a,b,c,d,m,n},x] && n===m && a^2===c^2*d && 2*a*b===c^2*e + + +(* Int[u_./(e_.*Sqrt[a_.+b_.*x_]+f_.*Sqrt[c_.+d_.*x_]),x_Symbol] := + Int[u*(e*Sqrt[a+b*x]-f*Sqrt[c+d*x])/(a*e^2-c*f^2+(b*e^2-d*f^2)*x),x] /; +FreeQ[{a,b,c,d,e,f},x] *) + + +Int[u_./(a_.*x_+b_.*Sqrt[c_.+d_.*x_^2]),x_Symbol] := + Dist[a,Int[x*u/(-b^2*c+(a^2-b^2*d)*x^2),x]] - + Dist[b,Int[u*Sqrt[c+d*x^2]/(-b^2*c+(a^2-b^2*d)*x^2),x]] /; +FreeQ[{a,b,c,d},x] + + +Int[u_./(e_.*Sqrt[(a_.+b_.*x_^n_.)^p_.]+f_.*Sqrt[(a_.+b_.*x_^n_.)^q_.]),x_Symbol] := + Int[u*(e*Sqrt[(a+b*x^n)^p]-f*Sqrt[(a+b*x^n)^q])/(e^2*(a+b*x^n)^p-f^2*(a+b*x^n)^q),x] /; +FreeQ[{a,b,e,f},x] && IntegerQ[{n,p,q}] + + +(* Int[u_./(v_+a_.*Sqrt[w_]),x_Symbol] := + Int[u*v/(v^2-a^2*w),x] - + Dist[a,Int[u*Sqrt[w]/(v^2-a^2*w),x]] /; +FreeQ[a,x] && PolynomialQ[v,x] *) + + +(* Int[u_./(a_.*x_+b_.*Sqrt[c_+d_.*x_]),x_Symbol] := + Int[(a*x*u-b*u*Sqrt[c+d*x])/(-b^2*c-b^2*d*x+a^2*x^2),x] /; +FreeQ[{a,b,c,d},x] *) + + +(* ::Subsection::Closed:: *) +(*u Sqrt[c+d x]/(a+b x) Rationalization of numerator*) + + +Int[u_.*Sqrt[c_+d_.*x_^2]/(a_+b_.*x_),x_Symbol] := + a*Int[u/Sqrt[c+d*x^2],x] - + b*Int[x*u/Sqrt[c+d*x^2],x] /; +FreeQ[{a,b,c,d},x] && c===a^2 && d===-b^2 + + +(* ::Subsection::Closed:: *) +(*Sqrt[a+b x^4] Integrands involving square roots of quartic binomials*) + + +Int[Sqrt[b_.*x_^2+Sqrt[a_+c_.*x_^4]]/Sqrt[a_+c_.*x_^4],x_Symbol] := + ArcTanh[Rt[2*b,2]*x/Sqrt[b*x^2+Sqrt[a+c*x^4]]]/Rt[2*b,2] /; +FreeQ[{a,b,c},x] && ZeroQ[b^2-c] && PosQ[b] + + +Int[Sqrt[b_.*x_^2+Sqrt[a_+c_.*x_^4]]/Sqrt[a_+c_.*x_^4],x_Symbol] := + ArcTan[Rt[-2*b,2]*x/Sqrt[b*x^2+Sqrt[a+c*x^4]]]/Rt[-2*b,2] /; +FreeQ[{a,b,c},x] && ZeroQ[b^2-c] && NegQ[b] + + +(* ::Item::Closed:: *) +(*Author: Martin*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If a>0, Sqrt[a+z^2] == Sqrt[Sqrt[a]+I*z]*Sqrt[Sqrt[a]-I*z]*) + + +(* ::Item:: *) +(*Basis: If a>0, Sqrt[z+Sqrt[a+z^2]]/Sqrt[a+z^2] == (1-I)/(2*Sqrt[Sqrt[a]-I*z]) + (1+I)/(2*Sqrt[Sqrt[a]+I*z])*) + + +Int[u_.*Sqrt[v_+Sqrt[a_+w_]]/Sqrt[a_+w_],x_Symbol] := + Dist[(1-I)/2, Int[u/Sqrt[Sqrt[a]-I*v],x]] + + Dist[(1+I)/2, Int[u/Sqrt[Sqrt[a]+I*v],x]] /; +FreeQ[a,x] && ZeroQ[w-v^2] && PositiveQ[a] && Not[LinearQ[v,x]] + + +(* ::Subsection::Closed:: *) +(*1 / (a+b f[c+d x]) Aggressively factor out constants to prevent them occurring in logarithms*) + + +(* Note: Constant factors in denominator are aggressively factored out to prevent them occurring + unnecessarily in logarithm of antiderivative! *) +If[ShowSteps, + +Int[1/(a_+b_.*u_),x_Symbol] := + Module[{lst=ConstantFactor[a+b*u,x]}, + ShowStep["","Int[1/(a*c+b*c*u),x]","c*Int[1/(a+b*u),x]",Hold[ + Dist[1/lst[[1]],Int[1/lst[[2]],x]]]] /; + lst[[1]]=!=1] /; +SimplifyFlag && FreeQ[{a,b},x] && ( + MatchQ[u,f_^(c_.+d_.*x) /; FreeQ[{c,d,f},x]] || + MatchQ[u,f_[c_.+d_.*x] /; FreeQ[{c,d},x] && MemberQ[{Tan,Cot,Tanh,Coth},f]]), + +Int[1/(a_+b_.*u_),x_Symbol] := + Module[{lst=ConstantFactor[a+b*u,x]}, + Dist[1/lst[[1]],Int[1/lst[[2]],x]] /; + lst[[1]]=!=1] /; +FreeQ[{a,b},x] && ( + MatchQ[u,f_^(c_.+d_.*x) /; FreeQ[{c,d,f},x]] || + MatchQ[u,f_[c_.+d_.*x] /; FreeQ[{c,d},x] && MemberQ[{Tan,Cot,Tanh,Coth},f]])] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/ErrorFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/ErrorFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/ErrorFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/ErrorFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,604 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Error and Fresnel Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Error Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Erf[a+b x]^n Powers of error function of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 5.41*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Erf[a_.+b_.*x_],x_Symbol] := + (a+b*x)*Erf[a+b*x]/b + 1/(b*Sqrt[Pi]*Exp[(a+b*x)^2]) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Erf[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*Erf[a+b*x]^2/b - + Dist[4/Sqrt[Pi],Int[(a+b*x)*Erf[a+b*x]/E^(a+b*x)^2,x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Erf[a+b x]^n Products of monomials and powers of error functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Erf[a_.+b_.*x_],x_Symbol] := + x^(m+1)*Erf[a+b*x]/(m+1) - + Dist[2*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)/Exp[(a+b*x)^2],x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Erf[b_.*x_]^2,x_Symbol] := + x^(m+1)*Erf[b*x]^2/(m+1) - + Dist[4*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)*E^(-b^2*x^2)*Erf[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m+1!=0 && (m>0 || OddQ[m]) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x, a+b*x], x] == Subst[Int[f[-a/b+x/b, x], x], x, a+b*x]/b*) + + +Int[x_^m_.*Erf[a_+b_.*x_]^2,x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*Erf[x]^2,x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m E^(-b^2 x^2) Erf[b x] Products of monomials, exponentials and error functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*E^(c_.*x_^2)*Erf[b_.*x_],x_Symbol] := + -E^(-b^2*x^2)*Erf[b*x]/(2*b^2) + + Dist[1/(b*Sqrt[Pi]),Int[E^(-2*b^2*x^2),x]] /; +FreeQ[{b,c},x] && c===-b^2 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_*E^(c_.*x_^2)*Erf[b_.*x_],x_Symbol] := + -x^(m-1)*E^(-b^2*x^2)*Erf[b*x]/(2*b^2) + + Dist[1/(b*Sqrt[Pi]),Int[x^(m-1)*E^(-2*b^2*x^2),x]] + + Dist[(m-1)/(2*b^2),Int[x^(m-2)*E^(-b^2*x^2)*Erf[b*x],x]] /; +FreeQ[{b,c},x] && c===-b^2 && IntegerQ[m] && m>1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*E^(c_.*x_^2)*Erf[b_.*x_],x_Symbol] := + x^(m+1)*E^(-b^2*x^2)*Erf[b*x]/(m+1) - + Dist[2*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)*E^(-2*b^2*x^2),x]] + + Dist[2*b^2/(m+1),Int[x^(m+2)*E^(-b^2*x^2)*Erf[b*x],x]] /; +FreeQ[{b,c},x] && c===-b^2 && EvenQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Complementary Error Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Erfc[a+b x]^n Powers of complementary error function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Erfc[a_.+b_.*x_],x_Symbol] := + (a+b*x)*Erfc[a+b*x]/b - 1/(b*Sqrt[Pi]*Exp[(a+b*x)^2]) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Erfc[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*Erfc[a+b*x]^2/b + + Dist[4/Sqrt[Pi],Int[(a+b*x)*Erfc[a+b*x]/E^(a+b*x)^2,x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Erfc[ a+b x]^n Products of monomials and powers of complementary error function*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Erfc[a_.+b_.*x_],x_Symbol] := + x^(m+1)*Erfc[a+b*x]/(m+1) + + Dist[2*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)/Exp[(a+b*x)^2],x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Erfc[b_.*x_]^2,x_Symbol] := + x^(m+1)*Erfc[b*x]^2/(m+1) + + Dist[4*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)*E^(-b^2*x^2)*Erfc[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m+1!=0 && (m>0 || OddQ[m]) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x, a+b*x], x] == Subst[Int[f[-a/b+x/b, x], x], x, a+b*x]/b*) + + +Int[x_^m_.*Erfc[a_+b_.*x_]^2,x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*Erfc[x]^2,x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m E^(-b^2 x^2) Erfc[b x] Products of monomials, exponentials and complementary error functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*E^(c_.*x_^2)*Erfc[b_.*x_],x_Symbol] := + -E^(-b^2*x^2)*Erfc[b*x]/(2*b^2) - + Dist[1/(b*Sqrt[Pi]),Int[E^(-2*b^2*x^2),x]] /; +FreeQ[{b,c},x] && c===-b^2 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_*E^(c_.*x_^2)*Erfc[b_.*x_],x_Symbol] := + -x^(m-1)*E^(-b^2*x^2)*Erfc[b*x]/(2*b^2) - + Dist[1/(b*Sqrt[Pi]),Int[x^(m-1)*E^(-2*b^2*x^2),x]] + + Dist[(m-1)/(2*b^2),Int[x^(m-2)*E^(-b^2*x^2)*Erfc[b*x],x]] /; +FreeQ[{b,c},x] && c===-b^2 && IntegerQ[m] && m>1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*E^(c_.*x_^2)*Erfc[b_.*x_],x_Symbol] := + x^(m+1)*E^(-b^2*x^2)*Erfc[b*x]/(m+1) + + Dist[2*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)*E^(-2*b^2*x^2),x]] + + Dist[2*b^2/(m+1),Int[x^(m+2)*E^(-b^2*x^2)*Erfc[b*x],x]] /; +FreeQ[{b,c},x] && c===-b^2 && EvenQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Imaginary Error Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Erfi[a+b x]^n Powers of imaginary error function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Erfi[a_.+b_.*x_],x_Symbol] := + (a+b*x)*Erfi[a+b*x]/b - Exp[(a+b*x)^2]/(b*Sqrt[Pi]) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Erfi[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*Erfi[a+b*x]^2/b - + Dist[4/Sqrt[Pi],Int[(a+b*x)*E^(a+b*x)^2*Erfi[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Erfi[a+b x]^n Products of monomials and powers of imaginary error functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Erfi[a_.+b_.*x_],x_Symbol] := + x^(m+1)*Erfi[a+b*x]/(m+1) - + Dist[2*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)*Exp[(a+b*x)^2],x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Erfi[b_.*x_]^2,x_Symbol] := + x^(m+1)*Erfi[b*x]^2/(m+1) - + Dist[4*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)*E^(b^2*x^2)*Erfi[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m+1!=0 && (m>0 || OddQ[m]) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x, a+b*x], x] == Subst[Int[f[-a/b+x/b, x], x], x, a+b*x]/b*) + + +Int[x_^m_.*Erfi[a_+b_.*x_]^2,x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*Erfi[x]^2,x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m E^(b^2 x^2) Erfi[b x] Products of monomials, exponentials and imaginary error functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*E^(c_.*x_^2)*Erfi[b_.*x_],x_Symbol] := + E^(b^2*x^2)*Erfi[b*x]/(2*b^2) - + Dist[1/(b*Sqrt[Pi]),Int[E^(2*b^2*x^2),x]] /; +FreeQ[{b,c},x] && c===b^2 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_*E^(c_.*x_^2)*Erfi[b_.*x_],x_Symbol] := + x^(m-1)*E^(b^2*x^2)*Erfi[b*x]/(2*b^2) - + Dist[1/(b*Sqrt[Pi]),Int[x^(m-1)*E^(2*b^2*x^2),x]] - + Dist[(m-1)/(2*b^2),Int[x^(m-2)*E^(b^2*x^2)*Erfi[b*x],x]] /; +FreeQ[{b,c},x] && c===b^2 && IntegerQ[m] && m>1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*E^(c_.*x_^2)*Erfi[b_.*x_],x_Symbol] := + x^(m+1)*E^(b^2*x^2)*Erfi[b*x]/(m+1) - + Dist[2*b/(Sqrt[Pi]*(m+1)),Int[x^(m+1)*E^(2*b^2*x^2),x]] - + Dist[2*b^2/(m+1),Int[x^(m+2)*E^(b^2*x^2)*Erfi[b*x],x]] /; +FreeQ[{b,c},x] && c===b^2 && EvenQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Fresnel Integral S Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*FresnelS[a+b x]^n Powers of Fresnel integral S functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[FresnelS[a_.+b_.*x_],x_Symbol] := + (a+b*x)*FresnelS[a+b*x]/b + Cos[Pi/2*(a+b*x)^2]/(b*Pi) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[FresnelS[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*FresnelS[a+b*x]^2/b - + Dist[2,Int[(a+b*x)*Sin[Pi/2*(a+b*x)^2]*FresnelS[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m FresnelS[a+b x]^n Products of monomials and powers of Fresnel integral S functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*FresnelS[a_.+b_.*x_],x_Symbol] := + x^(m+1)*FresnelS[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*Sin[Pi/2*(a+b*x)^2],x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Note: Also apply rule when m mod 4 = 1 when a closed-form antiderivative is defined for Cos[Pi/2*x^2]*FresnelS[x].*) + + +Int[x_^m_*FresnelS[b_.*x_]^2,x_Symbol] := + x^(m+1)*FresnelS[b*x]^2/(m+1) - + Dist[2*b/(m+1),Int[x^(m+1)*Sin[Pi/2*b^2*x^2]*FresnelS[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m+1!=0 && (m>0 && EvenQ[m] || Mod[m,4]==3) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x, a+b*x], x] == Subst[Int[f[-a/b+x/b, x], x], x, a+b*x]/b*) + + +(* ::Item:: *) +(*Note: Rule not necessary until a closed-form antiderivative is defined for Cos[Pi/2*x^2]*FresnelS[x].*) + + +(* Int[x_^m_.*FresnelS[a_+b_.*x_]^2,x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*FresnelS[x]^2,x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 *) + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[Pi/2 b^2 x^2] FresnelS[b x] Products of monomials, sines and Fresnel integral S functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*Sin[c_.*x_^2]*FresnelS[b_.*x_],x_Symbol] := + -Cos[Pi/2*b^2*x^2]*FresnelS[b*x]/(Pi*b^2) + + Dist[1/(2*b*Pi),Int[Sin[Pi*b^2*x^2],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Note: Also apply rule when m mod 4 = 2 when a closed-form antiderivative is defined for Cos[Pi/2*x^2]*FresnelS[x].*) + + +Int[x_^m_*Sin[c_.*x_^2]*FresnelS[b_.*x_],x_Symbol] := + -x^(m-1)*Cos[Pi/2*b^2*x^2]*FresnelS[b*x]/(Pi*b^2) + + Dist[1/(2*b*Pi),Int[x^(m-1)*Sin[Pi*b^2*x^2],x]] + + Dist[(m-1)/(Pi*b^2),Int[x^(m-2)*Cos[Pi/2*b^2*x^2]*FresnelS[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m>1 && Not[Mod[m,4]==2] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Sin[c_.*x_^2]*FresnelS[b_.*x_],x_Symbol] := + x^(m+1)*Sin[Pi/2*b^2*x^2]*FresnelS[b*x]/(m+1) - b*x^(m+2)/(2*(m+1)*(m+2)) + + Dist[b/(2*(m+1)),Int[x^(m+1)*Cos[Pi*b^2*x^2],x]] - + Dist[Pi*b^2/(m+1),Int[x^(m+2)*Cos[Pi/2*b^2*x^2]*FresnelS[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m<-2 && Mod[m,4]==0 + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[Pi/2 b^2 x^2] FresnelS[b x] Products of monomials, cosines and Fresnel integral S functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*Cos[c_.*x_^2]*FresnelS[b_.*x_],x_Symbol] := + Sin[Pi/2*b^2*x^2]*FresnelS[b*x]/(Pi*b^2) - x/(2*b*Pi) + + Dist[1/(2*b*Pi),Int[Cos[Pi*b^2*x^2],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_*Cos[c_.*x_^2]*FresnelS[b_.*x_],x_Symbol] := + x^(m-1)*Sin[Pi/2*b^2*x^2]*FresnelS[b*x]/(Pi*b^2) - x^m/(2*b*m*Pi) + + Dist[1/(2*b*Pi),Int[x^(m-1)*Cos[Pi*b^2*x^2],x]] - + Dist[(m-1)/(Pi*b^2),Int[x^(m-2)*Sin[Pi/2*b^2*x^2]*FresnelS[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m>1 && Not[Mod[m,4]==0] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Cos[c_.*x_^2]*FresnelS[b_.*x_],x_Symbol] := + x^(m+1)*Cos[Pi/2*b^2*x^2]*FresnelS[b*x]/(m+1) - + Dist[b/(2*(m+1)),Int[x^(m+1)*Sin[Pi*b^2*x^2],x]] + + Dist[Pi*b^2/(m+1),Int[x^(m+2)*Sin[Pi/2*b^2*x^2]*FresnelS[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m<-1 && Mod[m,4]==2 + + +(* ::Subsection::Closed:: *) +(*Fresnel Integral C Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*FresnelC[a+b x]^n Powers of Fresnel integral C functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[FresnelC[a_.+b_.*x_],x_Symbol] := + (a+b*x)*FresnelC[a+b*x]/b - Sin[Pi/2*(a+b*x)^2]/(b*Pi) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[FresnelC[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*FresnelC[a+b*x]^2/b - + Dist[2,Int[(a+b*x)*Cos[Pi/2*(a+b*x)^2]*FresnelC[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m FresnelC[a+b x]^n Products of monomials and powers of Fresnel integral C functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*FresnelC[a_.+b_.*x_],x_Symbol] := + x^(m+1)*FresnelC[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*Cos[Pi/2*(a+b*x)^2],x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Note: Also apply rule when m mod 4 = 1 when a closed-form antiderivative is defined for Sin[Pi/2*x^2]*FresnelC[x].*) + + +Int[x_^m_*FresnelC[b_.*x_]^2,x_Symbol] := + x^(m+1)*FresnelC[b*x]^2/(m+1) - + Dist[2*b/(m+1),Int[x^(m+1)*Cos[Pi/2*b^2*x^2]*FresnelC[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m+1!=0 && (m>0 && EvenQ[m] || Mod[m,4]==3) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x, a+b*x], x] == Subst[Int[f[-a/b+x/b, x], x], x, a+b*x]/b*) + + +(* ::Item:: *) +(*Note: Rule not necessary until a closed-form antiderivative is defined for Sin[Pi/2*x^2]*FresnelC[x].*) + + +(* Int[x_^m_.*FresnelC[a_+b_.*x_]^2,x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*FresnelC[x]^2,x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 *) + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[Pi/2 b^2 x^2] FresnelC[b x] Products of monomials, sines and Fresnel integral C functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*Sin[c_.*x_^2]*FresnelC[b_.*x_],x_Symbol] := + -Cos[Pi/2*b^2*x^2]*FresnelC[b*x]/(Pi*b^2) + x/(2*b*Pi) + + Dist[1/(2*b*Pi),Int[Cos[Pi*b^2*x^2],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_*Sin[c_.*x_^2]*FresnelC[b_.*x_],x_Symbol] := + -x^(m-1)*Cos[Pi/2*b^2*x^2]*FresnelC[b*x]/(Pi*b^2) + x^m/(2*b*m*Pi) + + Dist[1/(2*b*Pi),Int[x^(m-1)*Cos[Pi*b^2*x^2],x]] + + Dist[(m-1)/(Pi*b^2),Int[x^(m-2)*Cos[Pi/2*b^2*x^2]*FresnelC[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m>1 && Not[Mod[m,4]==0] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Sin[c_.*x_^2]*FresnelC[b_.*x_],x_Symbol] := + x^(m+1)*Sin[Pi/2*b^2*x^2]*FresnelC[b*x]/(m+1) - + Dist[b/(2*(m+1)),Int[x^(m+1)*Sin[Pi*b^2*x^2],x]] - + Dist[Pi*b^2/(m+1),Int[x^(m+2)*Cos[Pi/2*b^2*x^2]*FresnelC[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m<-1 && Mod[m,4]==2 + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[Pi/2 b^2 x^2] FresnelC[b x] Products of monomials, cosines and Fresnel integral C functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*Cos[c_.*x_^2]*FresnelC[b_.*x_],x_Symbol] := + Sin[Pi/2*b^2*x^2]*FresnelC[b*x]/(Pi*b^2) - + Dist[1/(2*b*Pi),Int[Sin[Pi*b^2*x^2],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Note: Also apply rule when m mod 4 = 2 when a closed-form antiderivative is defined for Sin[Pi/2*x^2]*FresnelC[x].*) + + +Int[x_^m_*Cos[c_.*x_^2]*FresnelC[b_.*x_],x_Symbol] := + x^(m-1)*Sin[Pi/2*b^2*x^2]*FresnelC[b*x]/(Pi*b^2) - + Dist[1/(2*b*Pi),Int[x^(m-1)*Sin[Pi*b^2*x^2],x]] - + Dist[(m-1)/(Pi*b^2),Int[x^(m-2)*Sin[Pi/2*b^2*x^2]*FresnelC[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m>1 && Not[Mod[m,4]==2] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Cos[c_.*x_^2]*FresnelC[b_.*x_],x_Symbol] := + x^(m+1)*Cos[Pi/2*b^2*x^2]*FresnelC[b*x]/(m+1) - b*x^(m+2)/(2*(m+1)*(m+2)) - + Dist[b/(2*(m+1)),Int[x^(m+1)*Cos[Pi*b^2*x^2],x]] + + Dist[Pi*b^2/(m+1),Int[x^(m+2)*Sin[Pi/2*b^2*x^2]*FresnelC[b*x],x]] /; +FreeQ[{b,c},x] && c===Pi/2*b^2 && IntegerQ[m] && m<-2 && Mod[m,4]==0 diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/ExponentialFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/ExponentialFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/ExponentialFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/ExponentialFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,736 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Exponential Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*f^(a+b x^n) Products of monomials and exponentials of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.311, CRC 519, A&S 4.2.54*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[E^x,x] == E^x*) + + +Int[E^(a_.+b_.*x_),x_Symbol] := + E^(a+b*x)/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.311, CRC 519, A&S 4.2.54*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[E^x,x] == E^x*) + + +Int[f_^(a_.+b_.*x_),x_Symbol] := + f^(a+b*x)/(b*Log[f]) /; +FreeQ[{a,b,f},x] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Erfi'[z] == 2*E^(z^2)/Sqrt[Pi]*) + + +Int[E^(a_.+b_.*x_^2),x_Symbol] := + E^a*Sqrt[Pi]*Erfi[x*Rt[b,2]]/(2*Rt[b,2]) /; +FreeQ[{a,b},x] && PosQ[b] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Erfi'[z] == 2*E^(z^2)/Sqrt[Pi]*) + + +Int[f_^(a_.+b_.*x_^2),x_Symbol] := + f^a*Sqrt[Pi]*Erfi[x*Rt[b*Log[f],2]]/(2*Rt[b*Log[f],2]) /; +FreeQ[{a,b,f},x] && PosQ[b*Log[f]] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Erf'[z] == 2*E^(-z^2)/Sqrt[Pi]*) + + +Int[E^(a_.+b_.*x_^2),x_Symbol] := + E^a*Sqrt[Pi]*Erf[x*Rt[-b,2]]/(2*Rt[-b,2]) /; +FreeQ[{a,b},x] && NegQ[b] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Erf'[z] == 2*E^(-z^2)/Sqrt[Pi]*) + + +Int[f_^(a_.+b_.*x_^2),x_Symbol] := + f^a*Sqrt[Pi]*Erf[x*Rt[-b*Log[f],2]]/(2*Rt[-b*Log[f],2]) /; +FreeQ[{a,b,f},x] && NegQ[b*Log[f]] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[Gamma[n,x],x] == -E^(-x)*x^(n-1)*) + + +Int[E^(a_.+b_.*x_^n_),x_Symbol] := + -E^a*x*Gamma[1/n,-b*x^n]/(n*(-b*x^n)^(1/n)) /; +FreeQ[{a,b,n},x] && Not[FractionOrNegativeQ[n]] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[Gamma[n,x],x] == -E^(-x)*x^(n-1)*) + + +Int[f_^(a_.+b_.*x_^n_),x_Symbol] := + -f^a*x*Gamma[1/n,-b*x^n*Log[f]]/(n*(-b*x^n*Log[f])^(1/n)) /; +FreeQ[{a,b,f,n},x] && Not[FractionOrNegativeQ[n]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Note: Although resulting integrand looks more complicated than original one,rules for + improper binomials rectify it. *) +Int[E^(a_.+b_.*x_^n_.),x_Symbol] := + x*E^(a+b*x^n) - + Dist[b*n,Int[x^n*E^(a+b*x^n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && n<0 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Note: Although resulting integrand looks more complicated than original one,rules for + improper binomials rectify it. *) +Int[f_^(a_.+b_.*x_^n_.),x_Symbol] := + x*f^(a+b*x^n) - + Dist[b*n*Log[f],Int[x^n*f^(a+b*x^n),x]] /; +FreeQ[{a,b,f},x] && IntegerQ[n] && n<0 + + +(* ::Subsection::Closed:: *) +(*x^m f^(a+b x^n) Products of monomials and exponentials of binomials*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: ExpIntegralEi'[z] == E^z/z*) + + +Int[E^(a_.+b_.*x_^n_.)/x_,x_Symbol] := + E^a*ExpIntegralEi[b*x^n]/n /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: ExpIntegralEi'[z] == E^z/z*) + + +Int[f_^(a_.+b_.*x_^n_.)/x_,x_Symbol] := + f^a*ExpIntegralEi[b*x^n*Log[f]]/n /; +FreeQ[{a,b,f,n},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.321.1, CRC 521, A&S 4.2.55*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m*f^(a+b*x^n) == x^(m-n+1)*(f^(a+b*x^n)*x^(n-1))*) + + +Int[x_^m_.*f_^(a_.+b_.*x_^n_.),x_Symbol] := + x^(m-n+1)*f^(a+b*x^n)/(b*n*Log[f]) - + Dist[(m-n+1)/(b*n*Log[f]),Int[x^(m-n)*f^(a+b*x^n),x]] /; +FreeQ[{a,b,f},x] && IntegerQ[n] && RationalQ[m] && 00 && m<-1 || 0<-n<=m+1) + + +Int[x_^m_.*f_^(a_.+b_.*x_^n_.),x_Symbol] := + -f^a*x^(m+1)*Gamma[(m+1)/n,-b*x^n*Log[f]]/(n*(-b*x^n*Log[f])^((m+1)/n)) /; +FreeQ[{a,b,f,m,n},x] && + NonzeroQ[m+1] && + NonzeroQ[m-n+1] && + Not[m===-1/2 && ZeroQ[n-1]] && + Not[IntegerQ[{m,n}] && n>0 && (m<-1 || m>=n)] && + Not[RationalQ[{m,n}] && (FractionQ[m] || FractionOrNegativeQ[n])] + + +(* ::Subsection::Closed:: *) +(*f^(a+b x+c x^2) Exponentials of quadratic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If b^2-4*a*c=0, a+b*x+c*x^2 == (b+2*c*x)^2/(4*c)*) + + +Int[f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + Int[f^((b+2*c*x)^2/(4*c)),x] /; +FreeQ[{a,b,c,f},x] && ZeroQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: a+b*x+c*x^2 == (b+2*c*x)^2/(4*c) - (b^2-4*a*c)/(4*c)*) + + +(* ::Item:: *) +(*Basis: f^(z-w) == f^z/f^w*) + + +Int[f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + f^(a-b^2/(4*c))*Int[f^((b+2*c*x)^2/(4*c)),x] /; +FreeQ[{a,b,c,f},x] + + +(* ::Subsection::Closed:: *) +(*(d+e x)^m f^(a+b x+c x^2) Products of linears and exponentials of quadratic trinomials*) +(**) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +(* Note: This rule unnecessary because derivative of quadratic divides linear factor. *) +(* Int[(d_.+e_.*x_)*f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + e*f^(a+b*x+c*x^2)/(2*c*Log[f]) /; +FreeQ[{a,b,c,d,e,f},x] && ZeroQ[b*e-2*c*d] *) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[(d_.+e_.*x_)*f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + e*f^(a+b*x+c*x^2)/(2*c*Log[f]) - + Dist[(b*e-2*c*d)/(2*c),Int[f^(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e,f},x] && NonzeroQ[b*e-2*c*d] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[(d_.+e_.*x_)^m_*f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + e*(d+e*x)^(m-1)*f^(a+b*x+c*x^2)/(2*c*Log[f]) - + Dist[(m-1)*e^2/(2*c*Log[f]),Int[(d+e*x)^(m-2)*f^(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e,f},x] && RationalQ[m] && m>1 && ZeroQ[b*e-2*c*d] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[(d_.+e_.*x_)^m_*f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + e*(d+e*x)^(m-1)*f^(a+b*x+c*x^2)/(2*c*Log[f]) - + Dist[(b*e-2*c*d)/(2*c),Int[(d+e*x)^(m-1)*f^(a+b*x+c*x^2),x]] - + Dist[(m-1)*e^2/(2*c*Log[f]),Int[(d+e*x)^(m-2)*f^(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e,f},x] && RationalQ[m] && m>1 && NonzeroQ[b*e-2*c*d] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(d_.+e_.*x_)^m_*f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + (d+e*x)^(m+1)*f^(a+b*x+c*x^2)/(e*(m+1)) - + Dist[2*c*Log[f]/(e^2*(m+1)),Int[(d+e*x)^(m+2)*f^(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e,f},x] && RationalQ[m] && m<-1 && ZeroQ[b*e-2*c*d] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(d_.+e_.*x_)^m_*f_^(a_.+b_.*x_+c_.*x_^2),x_Symbol] := + (d+e*x)^(m+1)*f^(a+b*x+c*x^2)/(e*(m+1)) - + Dist[(b*e-2*c*d)*Log[f]/(e^2*(m+1)),Int[(d+e*x)^(m+1)*f^(a+b*x+c*x^2),x]] - + Dist[2*c*Log[f]/(e^2*(m+1)),Int[(d+e*x)^(m+2)*f^(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e,f},x] && RationalQ[m] && m<-1 && NonzeroQ[b*e-2*c*d] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(a_.+b_.*x_)^m_*f_^((c_.+d_.*x_)^n_.),x_Symbol] := + (a+b*x)^(m+1)*f^((c+d*x)^n)/(b*(m+1)) - + Dist[d*n*Log[f]/(b*(m+1)),Int[(a+b*x)^(m+1)*f^((c+d*x)^n)*(c+d*x)^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && m<-1 && IntegerQ[n] && n>1 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Int[(a_.+b_.*x_)^m_*f_^u_,x_Symbol] := + (a+b*x)^(m+1)*f^u/(b*(m+1)) - + Dist[Log[f]/(b*(m+1)),Int[(a+b*x)^(m+1)*f^u*D[u,x],x]] /; +FreeQ[{a,b},x] && PolynomialQ[u,x] && Exponent[u,x]>1 && RationalQ[m] && m<-1 *) + + +(* ::Subsection::Closed:: *) +(*(a+b f^(c+d x))^n Powers of linear exponentials of linear binomials*) + + +(* ::Item:: *) +(*Reference: CRC 256*) + + +Int[1/(a_+b_.*f_^(c_.+d_.*x_)),x_Symbol] := + -Log[b+a*f^(-c-d*x)]/(a*d*Log[f]) /; +FreeQ[{a,b,c,d,f},x] && NegativeCoefficientQ[d] + + +(* ::Item:: *) +(*Reference: CRC 256*) + + +Int[1/(a_+b_.*f_^(c_.+d_.*x_)),x_Symbol] := + x/a-Log[a+b*f^(c+d*x)]/(a*d*Log[f]) /; +FreeQ[{a,b,c,d,f},x] + + +Int[1/Sqrt[a_+b_.*f_^(c_.+d_.*x_)],x_Symbol] := + -2*ArcTanh[Sqrt[a+b*f^(c+d*x)]/Sqrt[a]]/(Sqrt[a]*d*Log[f]) /; +FreeQ[{a,b,c,d,f},x] && PosQ[a] + + +Int[1/Sqrt[a_+b_.*f_^(c_.+d_.*x_)],x_Symbol] := + 2*ArcTan[Sqrt[a+b*f^(c+d*x)]/Sqrt[-a]]/(Sqrt[-a]*d*Log[f]) /; +FreeQ[{a,b,c,d,f},x] && NegQ[a] + + +Int[(a_+b_.*f_^(c_.+d_.*x_))^n_,x_Symbol] := + (a+b*f^(c+d*x))^n/(n*d*Log[f]) + + Dist[a,Int[(a+b*f^(c+d*x))^(n-1),x]] /; +FreeQ[{a,b,c,d,f},x] && FractionQ[n] && n>0 + + +Int[(a_+b_.*f_^(c_.+d_.*x_))^n_,x_Symbol] := + -(a+b*f^(c+d*x))^(n+1)/((n+1)*a*d*Log[f]) + + Dist[1/a,Int[(a+b*f^(c+d*x))^(n+1),x]] /; +FreeQ[{a,b,c,d,f},x] && RationalQ[n] && n<-1 + + +(* ::Subsection::Closed:: *) +(*x^m (a+b f^(c+d x))^n Products of monomials and powers of linear exponentials of linear binomials*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*z) == 1/a - b/a*z/(a+b*z)*) + + +Int[x_^m_./(a_+b_.*f_^(c_.+d_.*x_)), x_Symbol] := + x^(m+1)/(a*(m+1)) - + Dist[b/a,Int[x^m*f^(c+d*x)/(a+b*f^(c+d*x)),x]] /; +FreeQ[{a,b,c,d,f},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*(a_+b_.*f_^(c_.+d_.*x_))^n_, x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[(a+b*f^(c+d*x))^n,x]]}, + x^m*u - Dist[m,Int[x^(m-1)*u,x]]] /; +FreeQ[{a,b,c,d,f},x] && RationalQ[{m,n}] && m>0 && n<-1 + + +(* ::Subsection::Closed:: *) +(*x^m f^(c (a+b x)^n) Products of linears and exponentials of powers of linears*) + + +(* Yikes!!! Need to do something likes this for trig and hyperbolic too.Ug! *) + + +Int[x_^m_*f_^(c_.*(a_+b_.*x_)^2),x_Symbol] := + Int[x^m*f^(a^2*c+2*a*b*c*x+b^2*c*x^2),x] /; +FreeQ[{a,b,c,f},x] && FractionQ[m] && m>1 + + +Int[x_^m_.*f_^(c_.*(a_+b_.*x_)^n_),x_Symbol] := + Dist[1/b^m,Int[Expand[b^m*x^m-(a+b*x)^m,x]*f^(c*(a+b*x)^n),x]] + + Dist[1/b^(m+1),Subst[Int[x^m*f^(c*x^n),x],x,a+b*x]] /; +FreeQ[{a,b,c,f,n},x] && IntegerQ[m] && m>0 + + +(* ::Subsection::Closed:: *) +(*x^m f^(c+d x)/(a+b f^(c+d x)) Products of monomials and linear exponentials of linear binomials*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*f_^(c_.+d_.*x_)/(a_+b_.*f_^(c_.+d_.*x_)), x_Symbol] := + x^m*Log[1+b*f^(c+d*x)/a]/(b*d*Log[f]) - + Dist[m/(b*d*Log[f]),Int[x^(m-1)*Log[1+b/a*f^(c+d*x)],x]] /; +FreeQ[{a,b,c,d,f},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*f_^(c_.+d_.*x_)/(a_.+b_.*f_^v_),x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[f^(c+d*x)/(a+b*f^v),x]]}, + x^m*u - Dist[m,Int[x^(m-1)*u,x]]] /; +FreeQ[{a,b,c,d,f},x] && ZeroQ[2*(c+d*x)-v] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_./(a_.*f_^(c_.+d_.*x_)+b_.*f_^v_),x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[1/(a*f^(c+d*x)+b*f^v),x]]}, + x^m*u - Dist[m,Int[x^(m-1)*u,x]]] /; +FreeQ[{a,b,c,d,f},x] && ZeroQ[(c+d*x)+v] && RationalQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Note: The remaining inverse function integration rules in this section are required to integrate the expressions generated by the above rules.*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[1+c_.*f_^(a_.+b_.*x_)],x_Symbol] := + -PolyLog[2,-c*f^(a+b*x)]/(b*Log[f]) /; +FreeQ[{a,b,c,f},x] + + +(* ::Item:: *) +(*Basis: D[Log[c+d*g[x]],x] == D[Log[1+d/c*g[x]],x]*) + + +Int[Log[c_+d_.*f_^(a_.+b_.*x_)],x_Symbol] := + x*Log[c+d*f^(a+b*x)] - x*Log[1+d/c*f^(a+b*x)] + + Int[Log[1+d/c*f^(a+b*x)],x] /; +FreeQ[{a,b,c,d,f},x] && NonzeroQ[c-1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Log[1+c_.*f_^(a_.+b_.*x_)],x_Symbol] := + -x^m*PolyLog[2,-c*f^(a+b*x)]/(b*Log[f]) + + Dist[m/(b*Log[f]),Int[x^(m-1)*PolyLog[2,-c*f^(a+b*x)],x]] /; +FreeQ[{a,b,c,f},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Basis: D[Log[c+d*g[x]],x] == D[Log[1+d/c*g[x]],x]*) + + +Int[x_^m_.*Log[c_+d_.*f_^(a_.+b_.*x_)],x_Symbol] := + x^(m+1)*Log[c+d*f^(a+b*x)]/(m+1) - x^(m+1)*Log[1+d/c*f^(a+b*x)]/(m+1) + + Int[x^m*Log[1+d/c*f^(a+b*x)],x] /; +FreeQ[{a,b,c,d,f},x] && NonzeroQ[c-1] && RationalQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[PolyLog[n,z],z] == PolyLog[n-1,z]/z*) + + +Int[PolyLog[n_,c_.*f_^(a_.+b_.*x_)],x_Symbol] := + PolyLog[n+1,c*f^(a+b*x)]/(b*Log[f]) /; +FreeQ[{a,b,c,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*PolyLog[n_,c_.*f_^(a_.+b_.*x_)],x_Symbol] := + x^m*PolyLog[n+1,c*f^(a+b*x)]/(b*Log[f]) - + Dist[m/(b*Log[f]),Int[x^(m-1)*PolyLog[n+1,c*f^(a+b*x)],x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTanh[z] == 1/2*Log[1+z] - 1/2*Log[1-z]*) + + +Int[ArcTanh[b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[1/2,Int[Log[1+b*f^(c+d*x)],x]] - + Dist[1/2,Int[Log[1-b*f^(c+d*x)],x]] /; +FreeQ[{b,c,d,f},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTanh[z] == 1/2*Log[1+z] - 1/2*Log[1-z]*) + + +Int[x_^m_.*ArcTanh[b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[1/2,Int[x^m*Log[1+b*f^(c+d*x)],x]] - + Dist[1/2,Int[x^m*Log[1-b*f^(c+d*x)],x]] /; +FreeQ[{b,c,d,f},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCoth[z] == 1/2*Log[1+1/z] - 1/2*Log[1-1/z]*) + + +Int[ArcCoth[b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[1/2,Int[Log[1+1/(b*f^(c+d*x))],x]] - + Dist[1/2,Int[Log[1-1/(b*f^(c+d*x))],x]] /; +FreeQ[{b,c,d,f},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCoth[z] == 1/2*Log[1+1/z] - 1/2*Log[1-1/z]*) + + +Int[x_^m_.*ArcCoth[b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[1/2,Int[x^m*Log[1+1/(b*f^(c+d*x))],x]] - + Dist[1/2,Int[x^m*Log[1-1/(b*f^(c+d*x))],x]] /; +FreeQ[{b,c,d,f},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTan[z] == I/2*Log[1-I*z] - I/2*Log[1+I*z]*) + + +Int[ArcTan[b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[I/2,Int[Log[1-b*I*f^(c+d*x)],x]] - + Dist[I/2,Int[Log[1+b*I*f^(c+d*x)],x]] /; +FreeQ[{b,c,d,f},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTan[z] == I/2*Log[1-I*z] - I/2*Log[1+I*z]*) + + +Int[x_^m_.*ArcTan[a_.+b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[I/2,Int[x^m*Log[1-a*I-b*I*f^(c+d*x)],x]] - + Dist[I/2,Int[x^m*Log[1+a*I+b*I*f^(c+d*x)],x]] /; +FreeQ[{a,b,c,d,f},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCot[z] == I/2*Log[1-I/z] - I/2*Log[1+I/z]*) + + +Int[ArcCot[b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[I/2,Int[Log[1-I/(b*f^(c+d*x))],x]] - + Dist[I/2,Int[Log[1+I/(b*f^(c+d*x))],x]] /; +FreeQ[{b,c,d,f},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCot[z] == I/2*Log[1-I/z] - I/2*Log[1+I/z]*) + + +Int[x_^m_.*ArcCot[a_.+b_.*f_^(c_.+d_.*x_)],x_Symbol] := + Dist[I/2,Int[x^m*Log[1-I/(a+b*f^(c+d*x))],x]] - + Dist[I/2,Int[x^m*Log[1+I/(a+b*f^(c+d*x))],x]] /; +FreeQ[{a,b,c,d,f},x] && IntegerQ[m] && m>0 + + +(* ::Subsection::Closed:: *) +(*(a+b x)^m f^(e (c+d x)^n) Products of linears and exponentials of powers of linears*) + + +If[ShowSteps, + +Int[(a_.+b_.*x_)^m_.*(f_^(e_.*(c_.+d_.*x_)^n_.))^p_.,x_Symbol] := + ShowStep["","Int[(a+b*x)^m*f[x],x]","Subst[Int[x^m*f[-a/b+x/b],x],x,a+b*x]/b",Hold[ + Dist[1/b,Subst[Int[x^m*(f^(e*(c-a*d/b+d*x/b)^n))^p,x],x,a+b*x]]]] /; +SimplifyFlag && FreeQ[{a,b,c,d,e,f,m,n},x] && RationalQ[p] && Not[a===0 && b===1], + +Int[(a_.+b_.*x_)^m_.*(f_^(e_.*(c_.+d_.*x_)^n_.))^p_.,x_Symbol] := + Dist[1/b,Subst[Int[x^m*(f^(e*(c-a*d/b+d*x/b)^n))^p,x],x,a+b*x]] /; +FreeQ[{a,b,c,d,e,f,m,n},x] && RationalQ[p] && Not[a===0 && b===1]] + + +(* ::Subsection::Closed:: *) +(*f^((a+b x^4)/x^2) Exponentials of quotients of binomials and monomials*) + + +Int[f_^((a_.+b_.*x_^4)/x_^2),x_Symbol] := + Sqrt[Pi]*Exp[2*Sqrt[-a*Log[f]]*Sqrt[-b*Log[f]]]*Erf[(Sqrt[-a*Log[f]]+Sqrt[-b*Log[f]]*x^2)/x]/ + (4*Sqrt[-b*Log[f]]) - + Sqrt[Pi]*Exp[-2*Sqrt[-a*Log[f]]*Sqrt[-b*Log[f]]]*Erf[(Sqrt[-a*Log[f]]-Sqrt[-b*Log[f]]*x^2)/x]/ + (4*Sqrt[-b*Log[f]]) /; +FreeQ[{a,b,f},x] + + +(* ::Subsection::Closed:: *) +(*u / (a+b f^(d+e x)+c f^(g+h x)) Quotients by quadratic trinomial exponentials of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*f^z+c*f^(2*z)) == 1/a - f^z*(b+c*f^z)/(a*(a+b*f^z+c*f^(2*z)))*) + + +Int[1/(a_+b_.*f_^u_+c_.*f_^v_), x_Symbol] := + x/a - + Dist[1/a,Int[f^u*(b+c*f^u)/(a+b*f^u+c*f^v),x]] /; +FreeQ[{a,b,c,f},x] && LinearQ[u,x] && LinearQ[v,x] && ZeroQ[2*u-v] && +Not[RationalQ[Rt[b^2-4*a*c,2]]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: (d+e*f^z)/(a+b*f^z+c*f^(2*z)) == d/a - f^z*(b*d-a*e+c*d*f^z)/(a*(a+b*f^z+c*f^(2*z)))*) + + +Int[(d_+e_.*f_^u_)/(a_+b_.*f_^u_+c_.*f_^v_), x_Symbol] := + d*x/a - + Dist[1/a,Int[f^u*(b*d-a*e+c*d*f^u)/(a+b*f^u+c*f^v),x]] /; +FreeQ[{a,b,c,d,e,f},x] && LinearQ[u,x] && LinearQ[v,x] && ZeroQ[2*u-v] && +Not[RationalQ[Rt[b^2-4*a*c,2]]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*z+c/z) == z/(c+a*z+b*z^2)*) + + +Int[u_/(a_+b_.*f_^v_+c_.*f_^w_), x_Symbol] := + Int[u*f^v/(c+a*f^v+b*f^(2*v)),x] /; +FreeQ[{a,b,c,f},x] && LinearQ[v,x] && LinearQ[w,x] && ZeroQ[v+w] && +If[RationalQ[Coefficient[v,x,1]], Coefficient[v,x,1]>0, LeafCount[v]0 && NonzeroQ[n+1] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/GeneralIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/GeneralIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/GeneralIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/GeneralIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,1915 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*General Integration Rules*) + + +(* ::Section::Closed:: *) +(*Simplification Rules*) + + +(* ::Item:: *) +(*Derivation: Algebraic simplification*) + + +(* Note: This needs to be done before trying trig substitution! *) +Int[u_,x_Symbol] := + Module[{v=TrigSimplify[u]}, + Int[v,x] /; + v=!=u] /; +Not[MatchQ[u,w_.*(a_.+b_.*v_)^m_.*(c_.+d_.*v_)^n_. /; + FreeQ[{a,b,c,d},x] && IntegerQ[{m,n}] && m<0 && n<0]] + + +(* ::Section:: *) +(*Integration by Substitution Rules*) + + +(* ::Subsection::Closed:: *) +(*Derivative divides substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[g[x]]*g'[x], x] == Subst[Int[f[x], x], x, g[x]]*) + + +Int[u_*x_^m_.,x_Symbol] := + Dist[1/(m+1),Subst[Int[Regularize[SubstFor[x^(m+1),u,x],x],x],x,x^(m+1)]] /; +FreeQ[m,x] && NonzeroQ[m+1] && FunctionOfQ[x^(m+1),u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[g[x]]*g'[x], x] == Subst[Int[f[x], x], x, g[x]]*) + + +If[ShowSteps, + +Int[u_*f_[a1___,g_[b1___,h_[c1___,v_,c2___],b2___],a2___],x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + ShowStep["","Int[f[g[x]]*g'[x],x]","Subst[Int[f[x],x],x,g[x]]",Hold[ + Dist[z,Subst[Int[f[a1,g[b1,h[c1,x,c2],b2],a2],x],x,v]]]] /; + Not[FalseQ[z]]] /; +SimplifyFlag && FreeQ[{a1,a2,b1,b2,c1,c2,f,g},x], + +Int[u_*f_[a1___,g_[b1___,h_[c1___,v_,c2___],b2___],a2___],x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + Dist[z,Subst[Int[f[a1,g[b1,h[c1,x,c2],b2],a2],x],x,v]] /; + Not[FalseQ[z]]] /; +SimplifyFlag && FreeQ[{a1,a2,b1,b2,c1,c2,f,g},x]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[g[x]]*g'[x], x] == Subst[Int[f[x], x], x, g[x]]*) + + +If[ShowSteps, + +Int[u_*f_[a1___,g_[b1___,v_,b2___],a2___],x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + ShowStep["","Int[f[g[x]]*g'[x],x]","Subst[Int[f[x],x],x,g[x]]",Hold[ + Dist[z,Subst[Int[f[a1,g[b1,x,b2],a2],x],x,v]]]] /; + Not[FalseQ[z]]] /; +SimplifyFlag && FreeQ[{a1,a2,b1,b2,f,g},x], + +Int[u_*f_[a1___,g_[b1___,v_,b2___],a2___],x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + Dist[z,Subst[Int[f[a1,g[b1,x,b2],a2],x],x,v]] /; + Not[FalseQ[z]]] /; +SimplifyFlag && FreeQ[{a1,a2,b1,b2,f,g},x]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[g[x]]*g'[x], x] == Subst[Int[f[x], x], x, g[x]]*) + + +If[ShowSteps, + +Int[u_*f_[a1___,v_,a2___],x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + ShowStep["","Int[f[g[x]]*g'[x],x]","Subst[Int[f[x],x],x,g[x]]",Hold[ + Dist[z,Subst[Int[f[a1,x,a2],x],x,v]]]] /; + Not[FalseQ[z]]] /; +SimplifyFlag && FreeQ[{a1,a2,f},x], + +Int[u_*f_[a1___,v_,a2___],x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + Dist[z,Subst[Int[f[a1,x,a2],x],x,v]] /; + Not[FalseQ[z]]] /; +SimplifyFlag && FreeQ[{a1,a2,f},x]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[g[x]*g'[x], x] == Subst[Int[x, x], x, g[x]]*) + + +If[ShowSteps, + +Int[u_*v_,x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + ShowStep["","Int[g[x]*g'[x],x]","Subst[Int[x,x],x,g[x]]",Hold[ + Dist[z,Subst[Int[x,x],x,v]]]] /; + Not[FalseQ[z]]] /; +SimplifyFlag, + +Int[u_*v_,x_Symbol] := + Module[{z=DerivativeDivides[v,u,x]}, + Dist[z,Subst[Int[x,x],x,v]] /; + Not[FalseQ[z]]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n!=-1, Int[f[x]^n*g[x]^n*D[f[x]*g[x], x], x] == f[x]^(n+1)*g[x]^(n+1)/(n+1)*) + + +(* ::Item:: *) +(*Note: Need to generalize for any number of u' s raised to multiples of n!*) + + +If[ShowSteps, + +Int[u1_^n_*u2_^n_*v_,x_Symbol] := + Module[{w=DerivativeDivides[u1*u2,v,x]}, + ShowStep["If nonzero[n+1],","Int[f[x]^n*g[x]^n*D[f[x]*g[x],x],x]", + "f[x]^(n+1)*g[x]^(n+1)/(n+1)",Hold[ + w*u1^(n+1)*u2^(n+1)/(n+1)]] /; + Not[FalseQ[w]]] /; +SimplifyFlag && FreeQ[n,x] && NonzeroQ[n+1] && (SumQ[v] || NonsumQ[u1*u2] || NonzeroQ[n-1]), + +Int[u1_^n_*u2_^n_*v_,x_Symbol] := + Module[{w=DerivativeDivides[u1*u2,v,x]}, + w*u1^(n+1)*u2^(n+1)/(n+1) /; + Not[FalseQ[w]]] /; +FreeQ[n,x] && NonzeroQ[n+1] && (SumQ[v] || NonsumQ[u1*u2] || NonzeroQ[n-1])] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n!=-1, Int[f[x]^n*g[x]^n*D[f[x]*g[x], x], x] == f[x]^(n+1)*g[x]^(n+1)/(n+1)*) + + +If[ShowSteps, + +Int[x_^m_.*u_^n_.*v_,x_Symbol] := + Module[{w=DerivativeDivides[x*u,x^(m-n)*v,x]}, + ShowStep["If nonzero[n+1],","Int[f[x]^n*g[x]^n*D[f[x]*g[x],x],x]", + "f[x]^(n+1)*g[x]^(n+1)/(n+1)",Hold[ + w*x^(n+1)*u^(n+1)/(n+1)]] /; + Not[FalseQ[w]]] /; +SimplifyFlag && FreeQ[n,x] && NonzeroQ[n+1] && (SumQ[v] || NonsumQ[u] || NonzeroQ[n-1]), + +Int[x_^m_.*u_^n_.*v_,x_Symbol] := + Module[{w=DerivativeDivides[x*u,x^(m-n)*v,x]}, + w*x^(n+1)*u^(n+1)/(n+1) /; + Not[FalseQ[w]]] /; +FreeQ[n,x] && NonzeroQ[n+1] && (SumQ[v] || NonsumQ[u] || NonzeroQ[n-1])] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by parts & power rule for integration*) + + +(* ::Item:: *) +(*Basis: If n!=-1, Int[x^m*f[x]^n*f'[x], x] == x^m*f[x]^(n+1)/(n+1) - m/(n+1)*Int[x^(m-1)*f[x]^(n+1)*) + + +If[ShowSteps, + +Int[x_^m_.*u_^n_.*v_,x_Symbol] := + Module[{w=DerivativeDivides[u,v,x]}, + ShowStep["If nonzero[n+1],","Int[x^m*f[x]^n*f'[x],x]", + "x^m*f[x]^(n+1)/(n+1) - m/(n+1)*Int[x^(m-1)*f[x]^(n+1),x]",Hold[ + w*x^m*u^(n+1)/(n+1) - + Dist[m/(n+1)*w,Int[x^(m-1)*u^(n+1),x]]]] /; + Not[FalseQ[w]]] /; +SimplifyFlag && FreeQ[n,x] && NonzeroQ[n+1] && RationalQ[m] && m>0 && + (SumQ[v] || NonsumQ[u] || NonzeroQ[n-1]), + +Int[x_^m_.*u_^n_.*v_,x_Symbol] := + Module[{w=DerivativeDivides[u,v,x]}, + w*x^m*u^(n+1)/(n+1) - + Dist[m/(n+1)*w,Int[x^(m-1)*u^(n+1),x]] /; + Not[FalseQ[w]]] /; +FreeQ[n,x] && NonzeroQ[n+1] && RationalQ[m] && m>0 && (SumQ[v] || NonsumQ[u] || NonzeroQ[n-1])] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[Int[g[x], x]]*g[x], x] == Subst[Int[f[x], x], x, Int[g[x]]]*) + + +Int[u_*v_,x_Symbol] := + Module[{w=Block[{ShowSteps=False,StepCounter=Null}, Int[v,x]]}, + Subst[Int[Regularize[SubstFor[w,u,x],x],x],x,w] /; + FunctionOfQ[w,u,x]] /; +SumQ[v] && PolynomialQ[v,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[g[x]]*g'[x], x] == Subst[Int[f[x], x], x, g[x]]*) + + +Int[u_*(a_.+b_.*x_)^m_.,x_Symbol] := + Dist[1/(b*(m+1)),Subst[Int[Regularize[SubstFor[(a+b*x)^(m+1),u,x],x],x],x,(a+b*x)^(m+1)]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] && FunctionOfQ[(a+b*x)^(m+1),u,x] (* && NonsumQ[u] *) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[(c*x)^n]/x == f[(c*x)^n]/(n*(c*x)^n)*D[(c*x)^n,x]*) + + +(* ::Item:: *) +(*Basis: Int[f[(c*x)^n]/x, x] == Subst[Int[f[x]/x, x], x, (c*x)^n]/n*) + + +If[ShowSteps, + +Int[u_/x_,x_Symbol] := + Module[{lst=PowerVariableExpn[u,0,x]}, + ShowStep["","Int[f[(c*x)^n]/x,x]","Subst[Int[f[x]/x,x],x,(c*x)^n]/n",Hold[ + Dist[1/lst[[2]],Subst[Int[Regularize[lst[[1]]/x,x],x],x,(lst[[3]]*x)^lst[[2]]]]]] /; + Not[FalseQ[lst]] && NonzeroQ[lst[[2]]]] /; +SimplifyFlag && NonsumQ[u] && Not[RationalFunctionQ[u,x]], + +Int[u_/x_,x_Symbol] := + Module[{lst=PowerVariableExpn[u,0,x]}, + Dist[1/lst[[2]],Subst[Int[Regularize[lst[[1]]/x,x],x],x,(lst[[3]]*x)^lst[[2]]]] /; + Not[FalseQ[lst]] && NonzeroQ[lst[[2]]]] /; +NonsumQ[u] && Not[RationalFunctionQ[u,x]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: x^(n-1)*f[(c*x)^n] == f[(c*x)^n]/(c*n)*D[(c*x)^n,x]*) + + +(* ::Item:: *) +(*Basis: If g = GCD[m+1, n] > 1, Int[x^m*f[x^n], x] == Subst[Int[x^((m+1)/g-1)*f[x^(n/g)], x], x, x^g]/g*) + + +If[ShowSteps, + +Int[u_*x_^m_.,x_Symbol] := + Module[{lst=PowerVariableExpn[u,m+1,x]}, + ShowStep["If g=GCD[m+1,n]>1,","Int[x^m*f[x^n],x]", + "Subst[Int[x^((m+1)/g-1)*f[x^(n/g)],x],x,x^g]/g",Hold[ + Dist[1/lst[[2]],Subst[Int[Regularize[lst[[1]]/x,x],x],x,(lst[[3]]*x)^lst[[2]]]]]] /; + NotFalseQ[lst] && NonzeroQ[lst[[2]]-m-1]] /; +SimplifyFlag && IntegerQ[m] && m!=-1 && NonsumQ[u] && (m>0 || Not[AlgebraicFunctionQ[u,x]]), + +Int[u_*x_^m_.,x_Symbol] := + Module[{lst=PowerVariableExpn[u,m+1,x]}, + Dist[1/lst[[2]],Subst[Int[Regularize[lst[[1]]/x,x],x],x,(lst[[3]]*x)^lst[[2]]]] /; + NotFalseQ[lst] && NonzeroQ[lst[[2]]-m-1]] /; +IntegerQ[m] && m!=-1 && NonsumQ[u] && (m>0 || Not[AlgebraicFunctionQ[u,x]])] + + +(* ::Subsection::Closed:: *) +(*Trig function product expansion rules*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +Int[u_,x_Symbol] := + Int[NormalForm[Expand[TrigReduce[u],x],x],x] /; +ProductQ[u] && Catch[Scan[Function[If[Not[LinearSinCosQ[#,x]],Throw[False]]],u];True] + + +LinearSinCosQ[u_^n_.,x_Symbol] := + IntegerQ[n] && n>0 && (SinQ[u] || CosQ[u]) && LinearQ[u[[1]],x] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic function product expansion rules*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +Int[u_,x_Symbol] := + Int[NormalForm[Expand[TrigReduce[u],x],x],x] /; +ProductQ[u] && Catch[Scan[Function[If[Not[LinearSinhCoshQ[#,x]],Throw[False]]],u];True] + + +LinearSinhCoshQ[u_^n_.,x_Symbol] := + IntegerQ[n] && n>0 && (SinhQ[u] || CoshQ[u]) && LinearQ[u[[1]],x] + + +(* ::Subsection::Closed:: *) +(*Impure trig function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cos[z]]*Sin[z] == -f[Cos[z]] * Cos'[z]*) + + +Int[u_*Sin[c_.*(a_.+b_.*x_)],x_Symbol] := + -Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Cos[c*(a+b*x)],u,x],x],x],x,Cos[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cos[c*(a+b*x)],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sin[z]]*Cos[z] == f[Sin[z]] * Sin'[z]*) + + +Int[u_*Cos[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Sin[c*(a+b*x)],u,x],x],x],x,Sin[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sin[c*(a+b*x)],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is even, f[Tan[z]]*Sec[z]^n == f[Tan[z]]*(1+Tan[z]^2)^((n-2)/2) * Tan'[z]*) + + +Int[u_*Sec[c_.*(a_.+b_.*x_)]^n_,x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[(1+x^2)^((n-2)/2)*SubstFor[Tan[c*(a+b*x)],u,x],x],x],x,Tan[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && EvenQ[n] && FunctionOfQ[Tan[c*(a+b*x)],u,x] && NonsumQ[u] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is even, f[Cot[z]]*Csc[z]^n == -f[Cot[z]]*(1+Cot[z]^2)^((n-2)/2) * Cot'[z]*) + + +Int[u_*Csc[c_.*(a_.+b_.*x_)]^n_,x_Symbol] := + -Dist[1/(b*c),Subst[Int[Regularize[(1+x^2)^((n-2)/2)*SubstFor[Cot[c*(a+b*x)],u,x],x],x],x,Cot[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && EvenQ[n] && FunctionOfQ[Cot[c*(a+b*x)],u,x] && NonsumQ[u] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sin[z]]*Cos[z] == f[Sin[z]] * Sin'[z]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + ShowStep["","Int[f[Sin[a+b*x]]*Cos[a+b*x],x]","Subst[Int[f[x],x],x,Sin[a+b*x]]/b",Hold[ + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Sin[v],u/Cos[v],x],x],x],x,Sin[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Sin[v],u/Cos[v],x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Sin[v],u/Cos[v],x],x],x],x,Sin[v]]] /; + NotFalseQ[v] && FunctionOfQ[Sin[v],u/Cos[v],x]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cos[z]]*Sin[z] == -f[Cos[z]] * Cos'[z]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + ShowStep["","Int[f[Cos[a+b*x]]*Sin[a+b*x],x]","-Subst[Int[f[x],x],x,Cos[a+b*x]]/b",Hold[ + -Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cos[v],u/Sin[v],x],x],x],x,Cos[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Cos[v],u/Sin[v],x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + -Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cos[v],u/Sin[v],x],x],x],x,Cos[v]]] /; + NotFalseQ[v] && FunctionOfQ[Cos[v],u/Sin[v],x]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Log[Tan[z]]]*Sec[z]*Csc[z] == f[Log[Tan[z]]] * D[Log[Tan[z]], z]*) + + +Int[u_*Sec[a_.+b_.*x_]*Csc[a_.+b_.*x_],x_Symbol] := + Dist[1/b,Subst[Int[Regularize[SubstFor[Log[Tan[a+b*x]],u,x],x],x],x,Log[Tan[a+b*x]]]] /; +FreeQ[{a,b},x] && FunctionOfQ[Log[Tan[a+b*x]],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Log[Cot[z]]]*Sec[z]*Csc[z] == -f[Log[Cot[z]]] * D[Log[Cot[z]], z]*) + + +Int[u_*Sec[a_.+b_.*x_]*Csc[a_.+b_.*x_],x_Symbol] := + -Dist[1/b,Subst[Int[Regularize[SubstFor[Log[Cot[a+b*x]],u,x],x],x],x,Log[Cot[a+b*x]]]] /; +FreeQ[{a,b},x] && FunctionOfQ[Log[Cot[a+b*x]],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cos[z/2]*Sin[z/2]]*Cos[z] == 2*f[Cos[z/2]*Sin[z/2]] * D[Cos[z/2]*Sin[z/2], z]*) + + +Int[u_*Cos[a_.+b_.*x_],x_Symbol] := + Dist[2/b,Subst[Int[Regularize[SubstFor[Cos[a/2+b/2*x]*Sin[a/2+b/2*x],u,x],x],x],x, + Cos[a/2+b/2*x]*Sin[a/2+b/2*x]]] /; +NonsumQ[u] && FreeQ[{a,b},x] && FunctionOfQ[Cos[a/2+b/2*x]*Sin[a/2+b/2*x],u,x] + + +(* ::Subsection::Closed:: *) +(*Impure hyperbolic function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cosh[z]]*Sinh[z] == f[Cosh[z]] * Cosh'[z]*) + + +Int[u_*Sinh[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Cosh[c*(a+b*x)],u,x],x],x],x,Cosh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cosh[c*(a+b*x)],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sinh[z]]*Cosh[z] == f[Sinh[z]] * Sinh'[z]*) + + +Int[u_*Cosh[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Sinh[c*(a+b*x)],u,x],x],x],x,Sinh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sinh[c*(a+b*x)],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is even, f[Tanh[z]]*Sech[z]^n == f[Tanh[z]]*(1-Tanh[z]^2)^((n-2)/2) * Tanh'[z]*) + + +Int[u_*Sech[c_.*(a_.+b_.*x_)]^n_,x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[(1-x^2)^((n-2)/2)*SubstFor[Tanh[c*(a+b*x)],u,x],x],x],x,Tanh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && EvenQ[n] && FunctionOfQ[Tanh[c*(a+b*x)],u,x] && NonsumQ[u] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is even, f[Coth[z]]*Csch[z]^n == -f[Coth[z]]*(-1+Coth[z]^2)^((n-2)/2) * Coth'[z]*) + + +Int[u_*Csch[c_.*(a_.+b_.*x_)]^n_,x_Symbol] := + -Dist[1/(b*c),Subst[Int[Regularize[(-1+x^2)^((n-2)/2)*SubstFor[Coth[c*(a+b*x)],u,x],x],x],x,Coth[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && EvenQ[n] && FunctionOfQ[Coth[c*(a+b*x)],u,x] && NonsumQ[u] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[Sinh[a+b*x]]*Cosh[a+b*x], x] == Subst[Int[f[x], x], x, Sinh[a+b*x]]/b*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + ShowStep["","Int[f[Sinh[a+b*x]]*Cosh[a+b*x],x]","Subst[Int[f[x],x],x,Sinh[a+b*x]]/b",Hold[ + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Sinh[v],u/Cosh[v],x],x],x],x,Sinh[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Sinh[v],u/Cosh[v],x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Sinh[v],u/Cosh[v],x],x],x],x,Sinh[v]]] /; + NotFalseQ[v] && FunctionOfQ[Sinh[v],u/Cosh[v],x]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[Cosh[a+b*x]]*Sinh[a+b*x], x] == Subst[Int[f[x], x], x, Cosh[a+b*x]]/b*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + ShowStep["","Int[f[Cosh[a+b*x]]*Sinh[a+b*x],x]","Subst[Int[f[x],x],x,Cosh[a+b*x]]/b",Hold[ + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cosh[v],u/Sinh[v],x],x],x],x,Cosh[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Cosh[v],u/Sinh[v],x] (* && Not[FunctionOfQ[Tanh[v],u,x]] *)] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cosh[v],u/Sinh[v],x],x],x],x,Cosh[v]]] /; + NotFalseQ[v] && FunctionOfQ[Cosh[v],u/Sinh[v],x] (* && Not[FunctionOfQ[Tanh[v],u,x]] *)]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Log[Tanh[z]]]*Sech[z]*Csch[z] == f[Log[Tanh[z]]] * D[Log[Tanh[z]], z]*) + + +Int[u_*Sech[a_.+b_.*x_]*Csch[a_.+b_.*x_],x_Symbol] := + Dist[1/b,Subst[Int[Regularize[SubstFor[Log[Tanh[a+b*x]],u,x],x],x],x,Log[Tanh[a+b*x]]]] /; +FreeQ[{a,b},x] && FunctionOfQ[Log[Tanh[a+b*x]],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Log[Coth[z]]]*Sech[z]*Csch[z] == -f[Log[Coth[z]]] * D[Log[Coth[z]], z]*) + + +Int[u_*Sech[a_.+b_.*x_]*Csch[a_.+b_.*x_],x_Symbol] := + -Dist[1/b,Subst[Int[Regularize[SubstFor[Log[Coth[a+b*x]],u,x],x],x],x,Log[Coth[a+b*x]]]] /; +FreeQ[{a,b},x] && FunctionOfQ[Log[Coth[a+b*x]],u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cosh[z/2]*Sinh[z/2]]*Cosh[z] == 2*f[Cosh[z/2]*Sinh[z/2]] * D[Cosh[z/2]*Sinh[z/2], z]*) + + +Int[u_*Cosh[a_.+b_.*x_],x_Symbol] := + Dist[2/b,Subst[Int[Regularize[SubstFor[Cosh[a/2+b/2*x]*Sinh[a/2+b/2*x],u,x],x],x],x, + Cosh[a/2+b/2*x]*Sinh[a/2+b/2*x]]] /; +NonsumQ[u] && FreeQ[{a,b},x] && FunctionOfQ[Cosh[a/2+b/2*x]*Sinh[a/2+b/2*x],u,x] + + +(* ::Subsection::Closed:: *) +(*Derivative divides substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[x^m*f[x]^(-1+a*x^m)*f'[x], x] == f[x]^(a*x^m)/a - m*Int[x^(m-1)*f[x]^(a*x^m)*Log[f[x]], x]*) + + +If[ShowSteps, + +Int[x_^m_.*u_^(-1+a_.*x_^m_.)*v_,x_Symbol] := + Module[{w=DerivativeDivides[u,v,x]}, + ShowStep["If m>0,","Int[x^m*f[x]^(-1+a*x^m)*f'[x],x]", + "f[x]^(a*x^m)/a - m*Int[x^(m-1)*f[x]^(a*x^m)*Log[f[x]],x]",Hold[ + w*u^(a*x^m)/a - + Dist[m*w,Int[x^(m-1)*u^(a*x^m)*Log[u],x]]]] /; + Not[FalseQ[w]]] /; +SimplifyFlag && FreeQ[a,x] && RationalQ[m] && m>0, + +Int[x_^m_.*u_^(-1+a_.*x_^m_.)*v_,x_Symbol] := + Module[{w=DerivativeDivides[u,v,x]}, + w*u^(a*x^m)/a - + Dist[m*w,Int[x^(m-1)*u^(a*x^m)*Log[u],x]] /; + Not[FalseQ[w]]] /; +FreeQ[a,x] && RationalQ[m] && m>0] + + +(* ::Subsection:: *) +(*Trig function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cot[z]] == -f[Cot[z]]/(1+Cot[z]^2) * Cot'[z]*) + + +(* If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + ShowStep["","Int[f[Cot[a+b*x]],x]","-Subst[Int[f[x]/(1+x^2),x],x,Cot[a+b*x]]/b",Hold[ + -Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cot[v],u,x]/(1+x^2),x],x],x,Cot[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Cot[v],u,x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + -Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cot[v],u,x]/(1+x^2),x],x],x,Cot[v]]] /; + NotFalseQ[v] && FunctionOfQ[Cot[v],u,x]]] *) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Tan[z]] == f[Tan[z]]/(1+Tan[z]^2) * Tan'[z]*) + + +(* If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + ShowStep["","Int[f[Tan[a+b*x]],x]","Subst[Int[f[x]/(1+x^2),x],x,Tan[a+b*x]]/b",Hold[ + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Tan[v],u,x]/(1+x^2),x],x],x,Tan[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Tan[v],u,x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Tan[v],u,x]/(1+x^2),x],x],x,Tan[v]]] /; + NotFalseQ[v] && FunctionOfQ[Tan[v],u,x]]] *) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Tan[z]] == f[Tan[z]]/(1+Tan[z]^2) * Tan'[z]*) + + +Int[u_,x_Symbol] := + Subst[Int[Regularize[SubstFor[Tan[x],u,x]/(1+x^2),x],x],x,Tan[x]] /; +FunctionOfQ[Tan[x],u,x] && FunctionOfTanWeight[u,x,x]>=0 && TryTanSubst[u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cot[z]] == -f[Cot[z]]/(1+Cot[z]^2) * Cot'[z]*) + + +Int[u_,x_Symbol] := + -Subst[Int[Regularize[SubstFor[Cot[x],u,x]/(1+x^2),x],x],x,Cot[x]] /; +FunctionOfQ[Cot[x],u,x] && FunctionOfTanWeight[u,x,x]<0 && TryTanSubst[u,x] + + +TryTanSubst[u_,x_Symbol] := + FalseQ[FunctionOfLinear[u,x]] && + Not[MatchQ[u,r_.*(s_+t_)^n_. /; IntegerQ[n] && n>0]] && + Not[MatchQ[u,Log[f_[x]^2] /; SinCosQ[f]]] && + Not[MatchQ[u,1/(a_+b_.*f_[x]^n_) /; SinCosQ[f] && IntegerQ[n] && n>2]] && + Not[MatchQ[u,f_[m_.*x]*g_[n_.*x] /; IntegerQ[{m,n}] && SinCosQ[f] && SinCosQ[g]]] && + Not[MatchQ[u,r_.*(a_.*s_^m_)^p_ /; FreeQ[{a,m,p},x] && Not[m===2 && (s===Sec[x] || s===Csc[x])]]] && +(*u===TrigSimplify[u] && *) + u===ExpnExpand[u,x] + + +(* ::Subsection:: *) +(*Hyperbolic function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Tanh[z]] == f[Tanh[z]] / (1-Tanh[z]^2) * Tanh'[z]*) + + +Int[u_,x_Symbol] := + Subst[Int[Regularize[SubstFor[Tanh[x],u,x]/(1-x^2),x],x],x,Tanh[x]] /; +FunctionOfQ[Tanh[x],u,x] && FunctionOfTanhWeight[u,x,x]>=0 && TryTanhSubst[u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Coth[z]] == f[Coth[z]] / (1-Coth[z]^2) * Coth'[z]*) + + +Int[u_,x_Symbol] := + Subst[Int[Regularize[SubstFor[Coth[x],u,x]/(1-x^2),x],x],x,Coth[x]] /; +FunctionOfQ[Coth[x],u,x] && FunctionOfTanhWeight[u,x,x]<0 && TryTanhSubst[u,x] + + +TryTanhSubst[u_,x_Symbol] := + FalseQ[FunctionOfLinear[u,x]] && + Not[MatchQ[u,r_.*(s_+t_)^n_. /; IntegerQ[n] && n>0]] && + Not[MatchQ[u,Log[f_[x]^2] /; SinhCoshQ[f]]] && + Not[MatchQ[u,1/(a_+b_.*f_[x]^n_) /; SinhCoshQ[f] && IntegerQ[n] && n>2]] && + Not[MatchQ[u,f_[m_.*x]*g_[n_.*x] /; IntegerQ[{m,n}] && SinhCoshQ[f] && SinhCoshQ[g]]] && + Not[MatchQ[u,r_.*(a_.*s_^m_)^p_ /; FreeQ[{a,m,p},x] && Not[m===2 && (s===Sech[x] || s===Csch[x])]]] && +(*u===TrigSimplify[u] && *) + u===ExpnExpand[u,x] + + +(* ::Subsection::Closed:: *) +(*Exponential function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[E^(a+b*x)], x] == Subst[Int[f[x]/x, x], x, E^(a+b*x)]/b*) + + +(* ::Item:: *) +(*Basis: Int[g[f^(a+b*x)], x] == Subst[Int[g[x]/x, x], x, f^(a+b*x)]/(b*Log[f])*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfExponentialOfLinear[u,x]}, + If[lst[[4]]===E, + ShowStep["","Int[f[E^(a+b*x)],x]","Subst[Int[f[x]/x,x],x,E^(a+b*x)]/b",Hold[ + Dist[1/lst[[3]],Subst[Int[Regularize[lst[[1]]/x,x],x],x,E^(lst[[2]]+lst[[3]]*x)]]]], + ShowStep["","Int[g[f^(a+b*x)],x]","Subst[Int[g[x]/x,x],x,f^(a+b*x)]/(b*Log[f])",Hold[ + Dist[1/(lst[[3]]*Log[lst[[4]]]), + Subst[Int[Regularize[lst[[1]]/x,x],x],x,lst[[4]]^(lst[[2]]+lst[[3]]*x)]]]]] /; + Not[FalseQ[lst]]] /; +SimplifyFlag && +Not[MatchQ[u,v_^n_. /; SumQ[v] && IntegerQ[n] && n>0]] && +Not[MatchQ[u,v_^n_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,f},x] && SumQ[v] && IntegerQ[n] && n>0]] && +Not[MatchQ[u,1/(a_.+b_.*f_^(d_.+e_.*x)+c_.*f_^(g_.+h_.*x)) /; + FreeQ[{a,b,c,d,e,f,g,h},x] && ZeroQ[g-2*d] && ZeroQ[h-2*e]]] && +FalseQ[FunctionOfHyperbolic[u,x]] (* && u===ExpnExpand[u,x] *), + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfExponentialOfLinear[u,x]}, + Dist[1/(lst[[3]]*Log[lst[[4]]]), + Subst[Int[Regularize[lst[[1]]/x,x],x],x,lst[[4]]^(lst[[2]]+lst[[3]]*x)]] /; + Not[FalseQ[lst]]] /; +Not[MatchQ[u,v_^n_. /; SumQ[v] && IntegerQ[n] && n>0]] && +Not[MatchQ[u,v_^n_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,f},x] && SumQ[v] && IntegerQ[n] && n>0]] && +Not[MatchQ[u,1/(a_.+b_.*f_^(d_.+e_.*x)+c_.*f_^(g_.+h_.*x)) /; + FreeQ[{a,b,c,d,e,f,g,h},x] && ZeroQ[g-2*d] && ZeroQ[h-2*e]]] && +FalseQ[FunctionOfHyperbolic[u,x]] (* && u===ExpnExpand[u,x] *) ] + + +(* ::Subsection::Closed:: *) +(*Improper binomial subexpressions substitution rules*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*f_^(a_.+b_.*x_^n_.),x_Symbol] := + -Subst[Int[f^(a+b*x^(-n))/x^(m+2),x],x,1/x] /; +FreeQ[{a,b,f},x] && IntegerQ[{m,n}] && n<0 && m<-1 && GCD[m+1,n]==1 + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*f_[a_.+b_.*x_^n_]^p_.,x_Symbol] := + -Subst[Int[f[a+b*x^(-n)]^p/x^(m+2),x],x,1/x] /; +FreeQ[{a,b,f,p},x] && IntegerQ[{m,n}] && n<0 && m<-1 && GCD[m+1,n]==1 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification and distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(a+b*x^n)^m/(x^(m*n)*(b+a/x^n)^m), x] == 0*) + + +Int[u_*(a_+b_.*x_^n_)^m_,x_Symbol] := + (a+b*x^n)^m/(x^(m*n)*(b+a/x^n)^m)*Int[u*x^(m*n)*(b+a/x^n)^m,x] /; +FreeQ[{a,b},x] && FractionQ[m] && IntegerQ[n] && n<-1 && u===ExpnExpand[u,x] + + +(* ::Subsection::Closed:: *) +(*Fractional power subexpressions substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[(a+b*x)^(1/n), x], x] == n/b*Subst[Int[x^(n-1)*f[x, -a/b+x^n/b], x], x, (a+b*x)^(1/n)]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=SubstForFractionalPowerOfLinear[u,x]}, + ShowStep["","Int[f[(a+b*x)^(1/n),x],x]", + "n/b*Subst[Int[x^(n-1)*f[x,-a/b+x^n/b],x],x,(a+b*x)^(1/n)]",Hold[ + Dist[lst[[2]]*lst[[4]],Subst[Int[lst[[1]],x],x,lst[[3]]^(1/lst[[2]])]]]] /; + NotFalseQ[lst] && SubstForFractionalPowerQ[u,lst[[3]],x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=SubstForFractionalPowerOfLinear[u,x]}, + Dist[lst[[2]]*lst[[4]],Subst[Int[lst[[1]],x],x,lst[[3]]^(1/lst[[2]])]] /; + NotFalseQ[lst] && SubstForFractionalPowerQ[u,lst[[3]],x]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[((a+b*x)/(c+d*x))^(1/n), x], x] == *) +(* n*(b*c-a*d)*Subst[Int[x^(n-1)*f[x, (-a+c*x^n)/(b-d*x^n)]/(b-d*x^n)^2, x], x, ((a+b*x)/(c+d*x))^(1/n)]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=SubstForFractionalPowerOfQuotientOfLinears[u,x]}, + ShowStep["","Int[f[((a+b*x)/(c+d*x))^(1/n),x],x]", + "n*(b*c-a*d)*Subst[Int[x^(n-1)*f[x,(-a+c*x^n)/(b-d*x^n)]/(b-d*x^n)^2,x],x,((a+b*x)/(c+d*x))^(1/n)]",Hold[ + Dist[lst[[2]]*lst[[4]],Subst[Int[lst[[1]],x],x,lst[[3]]^(1/lst[[2]])]]]] /; + NotFalseQ[lst]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=SubstForFractionalPowerOfQuotientOfLinears[u,x]}, + Dist[lst[[2]]*lst[[4]],Subst[Int[lst[[1]],x],x,lst[[3]]^(1/lst[[2]])]] /; + NotFalseQ[lst]]] + + +(* ::Subsection::Closed:: *) +(*Linear subexpressions substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b*x], x] == Subst[Int[f[x], x], x, a+b*x]/b*) + + +Int[u_*(a_+b_.*x_)^m_.,x_Symbol] := + Dist[1/b,Subst[Int[x^m*Regularize[SubstFor[a+b*x,u,x],x],x],x,a+b*x]] /; +FreeQ[{a,b,m},x] && FunctionOfQ[a+b*x,u,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b*x, x], x] == Subst[Int[f[x, -a/b+x/b], x], x, a+b*x]/b*) + + +Int[x_^m_./(a_+b_.*(c_+d_.*x_)^n_), x_Symbol] := + Dist[1/d,Subst[Int[(-c/d+x/d)^m/(a+b*x^n),x],x,c+d*x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[{m,n}] && n>2 + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[(e_+f_.*x_)^m_.*(a_+b_.*(c_+d_.*x_)^n_)^p_, x_Symbol] := + Dist[(f/d)^m/d,Subst[Int[x^m*(a+b*x^n)^p,x],x,c+d*x]] /; +FreeQ[{a,b,c,d,e,f},x] && IntegerQ[{m,n,p}] && ZeroQ[d*e-c*f] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b*x, x], x] == Subst[Int[f[x, -a/b+x/b], x], x, a+b*x]/b*) + + +Int[(a_.+b_.*x_)^m_.*f_[c_.+d_.*x_]^p_.,x_Symbol] := + Dist[1/b,Subst[Int[x^m*f[c-a*d/b+d*x/b]^p,x],x,a+b*x]] /; +FreeQ[{a,b,c,d,m},x] && RationalQ[p] && Not[a===0 && b===1] && + MemberQ[{Sin,Cos,Sec,Csc,Sinh,Cosh,Sech,Csch},f] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b*x, x], x] == Subst[Int[f[x, -a/b+x/b], x], x, a+b*x]/b*) + + +Int[(a_.+b_.*x_)^m_*(c_.+d_.*x_+e_.*x_^2)^n_,x_Symbol] := + Dist[1/b,Subst[Int[x^m*(c-a*d/b+a^2*e/b^2+(d/b-2*a*e/b^2)*x+e*x^2/b^2)^n,x],x,a+b*x]] /; +FreeQ[{a,b,c,d,e,m,n},x] && FractionQ[n] && Not[a===0 && b===1] + + +(* ::Section::Closed:: *) +(*Integration by Parts Rules*) + + +(* ::Subsection::Closed:: *) +(*Extended integration by parts rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: Int[(g[x]+h[x])^n*g'[x],x] == (g[x]+h[x])^(n+1)/(n+1) - Int[(g[x]+h[x])^n*h'[x], x]*) + + +Int[(u_+x_^p_.)^n_*v_,x_Symbol] := + Module[{z=DerivativeDivides[u,v,x]}, + z*(u+x^p)^(n+1)/(n+1) - + Dist[z*p,Int[x^(p-1)*(u+x^p)^n,x]] /; + Not[FalseQ[z]]] /; +IntegerQ[p] && RationalQ[n] && NonzeroQ[n+1] && Not[AlgebraicFunctionQ[v,x]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: Int[f[x]*(g[x]+h[x])^n*g'[x],x] == f[x]*(g[x]+h[x])^(n+1)/(n+1) - Int[f[x]*(g[x]+h[x])^n*h'[x], x] - Int[f'[x]*(g[x]+h[x])^(n+1), x]/(n+1)*) + + +Int[x_^m_.*(u_+x_^p_.)^n_*v_,x_Symbol] := + Module[{z=DerivativeDivides[u,v,x]}, + z*x^m*(u+x^p)^(n+1)/(n+1) - + Dist[z*p,Int[x^(m+p-1)*(u+x^p)^n,x]] - + Dist[z*m/(n+1),Int[x^(m-1)*(u+x^p)^(n+1),x]] /; + Not[FalseQ[z]]] /; +IntegerQ[{m,p}] && RationalQ[n] && NonzeroQ[n+1] + + +(* ::Subsection::Closed:: *) +(*Logarithm rules (move to log rules!)*) + + +(* ::Item::Closed:: *) +(*Reference: A&S 4.1.53*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[u_],x_Symbol] := + x*Log[u] - + Int[Regularize[x*D[u,x]/u,x],x] /; +InverseFunctionFreeQ[u,x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.727.2*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[u_]/x_,x_Symbol] := + Module[{v=D[u,x]/u}, + Log[u]*Log[x] - + Int[Regularize[Log[x]*v,x],x] /; + RationalFunctionQ[v,x]] /; +Not[BinomialTest[u,x] && BinomialTest[u,x][[3]]^2===1] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.727.2*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[u_]/(a_+b_.*x_),x_Symbol] := + Module[{v=D[u,x]/u}, + Log[u]*Log[a+b*x]/b - + Dist[1/b,Int[Regularize[Log[a+b*x]*v,x],x]] /; + RationalFunctionQ[v,x]] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.725.1, A&S 4.1.54*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(a_.+b_.*x_)^m_.*Log[u_],x_Symbol] := + Module[{v=D[u,x]/u}, + (a+b*x)^(m+1)*Log[u]/(b*(m+1)) - + Dist[1/(b*(m+1)),Int[Regularize[(a+b*x)^(m+1)*v,x],x]]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] && InverseFunctionFreeQ[u,x] && + Not[FunctionOfQ[x^(m+1),u,x]] && + FalseQ[PowerVariableExpn[u,m+1,x]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[v_*Log[u_],x_Symbol] := + Module[{w=Block[{ShowSteps=False,StepCounter=Null}, Int[v,x]]}, + w*Log[u] - + Int[Regularize[w*D[u,x]/u,x],x] /; + InverseFunctionFreeQ[w,x]] /; +InverseFunctionFreeQ[u,x] && + Not[MatchQ[v, x^m_. /; FreeQ[m,x]]] && + FalseQ[FunctionOfLinear[v*Log[u],x]] + + +(* ::Section::Closed:: *) +(*Algebraic Expansion Rules*) + + +(* ::Subsection::Closed:: *) +(*Reciprocals of quadratic trinomial expansion rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[-a/b], z/(a+b*z^2) == q/(2*(a+b*q*z)) - q/(2*(a-b*q*z))*) + + +Int[u_.*x_/(a_+b_.*x_^2),x_Symbol] := + Module[{q=Rt[-a/b,2]}, + Dist[q/2,Int[u/(a+b*q*x),x]] - + Dist[q/2,Int[u/(a-b*q*x),x]]] /; +FreeQ[{a,b},x] && Not[MatchQ[u,r_*s_. /; SumQ[r]]] && Not[RationalFunctionQ[u,x]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4*a*c], z/(a+b*z+c*z^2) == (1+b/q)/(b+q+2*c*z) + (1-b/q)/(b-q+2*c*z))*) + + +Int[u_.*v_^m_./(a_+b_.*v_+c_.*w_),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[(1+b/q),Int[u*v^(m-1)/(b+q+2*c*v),x]] + Dist[(1-b/q),Int[u*v^(m-1)/(b-q+2*c*v),x]] /; + NonzeroQ[q]] /; +FreeQ[{a,b,c},x] && RationalQ[m] && m==1 && ZeroQ[w-v^2] && + Not[MatchQ[u,r_*s_. /; SumQ[r]]] && (Not[RationalFunctionQ[u,x]] || Not[RationalFunctionQ[v,x]]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4*a*c], (d+e*z)/(a+b*z+c*z^2) == (e-2*c*d/q+b*e/q)/(b+q+2*c*z)) + (e+2*c*d/q-b*e/q)/(b-q+2*c*z)*) + + +Int[(d_.+e_.*v_)/(a_+b_.*v_+c_.*w_),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[e+(b*e-2*c*d)/q,Int[1/(b+q+2*c*v),x]] + Dist[e-(b*e-2*c*d)/q,Int[1/(b-q+2*c*v),x]] /; + NonzeroQ[q]] /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[w-v^2] && NonzeroQ[2*c*d-b*e] && Not[RationalFunctionQ[v,x]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.161.1 a'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4*a*c], 1/(a+b*z+c*z^2) == 2*c/(q*(b-q+2*c*z)) - 2*c/(q*(b+q+2*c*z))*) + + +Int[u_./(a_+b_.*v_+c_.*w_),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[2*c/q,Int[u/(b-q+2*c*v),x]] - Dist[2*c/q,Int[u/(b+q+2*c*v),x]] /; + NonzeroQ[q]] /; +FreeQ[{a,b,c},x] && ZeroQ[w-v^2] && Not[MatchQ[u,v^m_ /; RationalQ[m]]] && + Not[MatchQ[u,r_*s_. /; SumQ[r]]] && (Not[RationalFunctionQ[u,x]] || Not[RationalFunctionQ[v,x]]) + + +(* ::Subsection::Closed:: *) +(*General algebraic simplification rules*) + + +(* ::Item:: *) +(*Derivation: Algebraic simplification*) + + +Int[u_,x_Symbol] := + Module[{v=SimplifyExpression[u,x]}, + Int[v,x] /; + v=!=u ] + + +(* ::Subsection::Closed:: *) +(*Fractional powers of powers and products distribution rules*) + + +(* ::Item:: *) +(*Derivation: Distribution of fractional powers*) + + +Int[u_.*(v_^m_.*w_^n_.*t_^q_.)^p_,x_Symbol] := + Int[u*v^(m*p)*w^(n*p)*t^(p*q),x] /; +FreeQ[p,x] && Not[PowerQ[v]] && Not[PowerQ[w]] && Not[PowerQ[t]] && + ZeroQ[Simplify[(v^m*w^n*t^q)^p-v^(m*p)*w^(n*p)*t^(p*q)]] + + +(* ::Item:: *) +(*Derivation: Distribution of fractional powers*) + + +Int[u_.*(v_^m_.*w_^n_.*t_^q_.)^p_,x_Symbol] := + Module[{r=Simplify[(v^m*w^n*t^q)^p/(v^(m*p)*w^(n*p)*t^(p*q))],lst}, + ( lst=SplitFreeFactors[v^(m*p)*w^(n*p)*t^(p*q),x]; + r*lst[[1]]*Int[Regularize[u*lst[[2]],x],x] ) /; + NonzeroQ[r-1]] /; +FreeQ[p,x] && Not[PowerQ[v]] && Not[PowerQ[w]] && Not[PowerQ[t]] + + +(* ::Subsection::Closed:: *) +(*General algebraic expansion rules*) + + +(* ::Item::Closed:: *) +(*Author: Martin 13 July 2010*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, a+b*z^n == b*Product[z - (-a/b)^(1/n)*(-1)^(2*k/n), {k, 1, n}]*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, a+b*z^n == a*Product[1 - z/((-a/b)^(1/n)*(-1)^(2*k/n)), {k, 1, 4}]*) + + +(* ::Item:: *) +(*Basis: If m and n are integers and 0<=m0 is an integer let q=(-a/b)^(1/n), then 1/(a+b*z^n) == q*Sum[(-1)^(2*k/n)/(q*(-1)^(2*k/n) - z), {k, 1, n}]/(a*n)*) + + +Int[u_/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[-a/b,n]], s=Denominator[Rt[-a/b,n]]}, + Dist[r/(a*n), Sum[Int[u*(-1)^(2*k/n)/(r*(-1)^(2*k/n)-s*x),x],{k,1,n}]]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 && Not[AlgebraicFunctionQ[u,x]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, a+b*z^n == b*Product[z - (-a/b)^(1/n)*(-1)^(2*k/n), {k, 1, n}]*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, z^(n-1)/(a+b*z^n) == Sum[1/(z - (-a/b)^(1/n)*(-1)^(2*k/n)), {k, 1, n}]/(b*n)*) + + +Int[u_.*v_^m_/(a_+b_.*v_^n_),x_Symbol] := + Dist[1/(b*n),Sum[Int[Together[u/(v-Rt[-a/b,n]*(-1)^(2*k/n))],x],{k,1,n}]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 && ZeroQ[m-n+1] && Not[AlgebraicFunctionQ[u,x] && AlgebraicFunctionQ[v,x]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, a+b*z^n == a*Product[1 - z/((-a/b)^(1/n)*(-1)^(2*k/n)), {k, 1, 4}]*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, 1/(a+b*z^n) == Sum[1/(1 - z/((-a/b)^(1/n)*(-1)^(2*k/n))), {k, 1, n}]/(a*n)*) + + +Int[u_./(a_+b_.*v_^n_),x_Symbol] := + Dist[1/(a*n),Sum[Int[Together[u/(1-v/(Rt[-a/b,n]*(-1)^(2*k/n)))],x],{k,1,n}]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 && Not[AlgebraicFunctionQ[u,x] && AlgebraicFunctionQ[v,x]] + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +Int[u_,x_Symbol] := + Module[{v=ExpnExpand[u,x]}, + Int[v,x] /; + v=!=u ] + + +(* ::Subsection::Closed:: *) +(*Function of linear binomial substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[1/(a+b*x)], x] == -Subst[Int[f[x]/x^2, x], x, 1/(a+b*x)]/b*) + + +(* ::Item:: *) +(*Basis: Int[f[(a+b*x)/(c+d*x)], x] == -Subst[Int[f[b/d+(a*d-b*c)/d*x]/x^2, x], x, 1/(c+d*x)]/d*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=SubstForInverseLinear[u,x]}, + ShowStep["","Int[f[1/(a+b*x)],x]","-Subst[Int[f[x]/x^2,x],x,1/(a+b*x)]/b",Hold[ + -Dist[1/lst[[3]],Subst[Int[lst[[1]]/x^2,x],x,1/lst[[2]]]]]] /; + NotFalseQ[lst]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=SubstForInverseLinear[u,x]}, + -Dist[1/lst[[3]],Subst[Int[lst[[1]]/x^2,x],x,1/lst[[2]]]] /; + NotFalseQ[lst]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b*x], x] == Subst[Int[f[x], x], x, a+b*x]/b*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfLinear[u,x]}, + ShowStep["","Int[f[a+b*x],x]","Subst[Int[f[x],x],x,a+b*x]/b",Hold[ + Dist[1/lst[[3]],Subst[Int[lst[[1]],x],x,lst[[2]]+lst[[3]]*x]]]] /; + Not[FalseQ[lst]]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfLinear[u,x]}, + Dist[1/lst[[3]],Subst[Int[lst[[1]],x],x,lst[[2]]+lst[[3]]*x]] /; + Not[FalseQ[lst]]]] + + +(* ::Subsection::Closed:: *) +(*Negative powers of binomials expansion rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is even, 1/(a+b*z^n) == 2/(a*n)*Sum[1/(1-z^2/((-a/b)^(2/n)*(-1)^(4*k/n))), {k, 1, n/2}]*) + + +Int[u_./(a_+b_.*v_^n_),x_Symbol] := + Dist[2/(a*n),Sum[Int[Together[u/(1-v^2/(Rt[-a/b,n/2]*(-1)^(4*k/n)))],x],{k,1,n/2}]] /; +FreeQ[{a,b},x] && EvenQ[n] && n>2 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is even, a+b*z^n == a*Product[1-(-1)^(4*k/n)*(-b/a)^(2/n)*z^2, {k, 1, n/2}]*) + + +Int[u_.*(a_+b_.*v_^n_)^m_,x_Symbol] := + Dist[a^m,Int[u*Product[(1-(-1)^(4*k/n)*Rt[-b/a,n/2]*v^2)^m,{k,1,n/2}],x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m<-1 && EvenQ[n] && n>2 (* && NegQ[b/a] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, a+b*z^n == b*Product[-(-a/b)^(1/n)*(-1)^(2*k/n) + z, {k, 1, n}]*) + + +(* ::Item:: *) +(*Basis: If n>0 is an integer, a+b*z^n == a*Product[1-(-1)^(2*k/n)*(-b/a)^(1/n)*z, {k, 1, n}]*) + + +(* ::Item:: *) +(*Basis: If n>0 is odd, a+b*z^n == a*Product[1+(-1)^(2*k/n)*(b/a)^(1/n)*z, {k, 1, n}]*) + + +Int[u_.*(a_+b_.*v_^n_)^m_,x_Symbol] := + Dist[a^m,Int[u*Product[(1+(-1)^(2*k/n)*Rt[b/a,n]*v)^m,{k,1,n}],x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m<-1 && OddQ[n] && n>1 + + +(* ::Subsection::Closed:: *) +(*Negative powers of trinomials expansion rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: a+b*z+c*z^2 == (b-Sqrt[b^2-4*a*c]+2*c*z)*(b+Sqrt[b^2-4*a*c]+2*c*z)/(4*c)*) + + +Int[u_.*(a_+b_.*v_+c_.*w_)^m_,x_Symbol] := + Dist[1/(4*c)^m,Int[u*(b-Sqrt[b^2-4*a*c]+2*c*v)^m*(b+Sqrt[b^2-4*a*c]+2*c*v)^m,x]] /; +FreeQ[{a,b,c},x] && IntegerQ[m] && m<0 && ZeroQ[w-v^2] + + +(* ::Subsection::Closed:: *) +(*Normalization rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Note: Replace this rule with specific rules for each normalization.*) + + +Int[u_,x_Symbol] := + Module[{v=NormalForm[u,x]}, + Int[v,x] /; + Not[v===u]] + + +(* ::Subsection::Closed:: *) +(*Fractional powers of powers and products distribution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(f[x]^m)^p/f[x]^(m*p), x] == 0*) + + +Int[u_.*(v_^m_)^p_, x_Symbol] := + Module[{q=FractionalPart[p]}, + (v^m)^q/v^(m*q)*Int[u*v^(m*p),x]] /; +FreeQ[m,x] && FractionQ[p] + + +(* ::Item::Closed:: *) +(*Derivation: Distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(a*f[x]^m)^p/f[x]^(m*p), x] == 0*) + + +Int[u_.*(a_*v_^m_.)^p_, x_Symbol] := + Module[{q=FractionalPart[p]}, + a^(p-q)*(a*v^m)^q/v^(m*q)*Int[u*v^(m*p),x]] /; +FreeQ[{a,m},x] && FractionQ[p] + + +(* ::Item::Closed:: *) +(*Derivation: Distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(a*f[x]^m*g[x]^n)^p/(f[x]^(m*p)*g[x]^(n*p)), x] == 0*) + + +Int[u_.*(a_.*v_^m_.*w_^n_.)^p_, x_Symbol] := + Module[{q=FractionalPart[p]}, + a^(p-q)*(a*v^m*w^n)^q/(v^(m*q)*w^(n*q))*Int[u*v^(m*p)*w^(n*p),x]] /; +FreeQ[a,x] && RationalQ[{m,n,p}] + + +(* ::Item::Closed:: *) +(*Derivation: Distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(f[x]^m)^p/f[x]^(m*p), x] == 0*) + + +Int[u_.*(v_^m_)^p_,x_Symbol] := + Int[u*v^(m*p),x] /; +FreeQ[p,x] && Not[PowerQ[v]] && ZeroQ[Simplify[(v^m)^p-v^(m*p)]] + + +(* ::Item::Closed:: *) +(*Derivation: Distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(f[x]^m)^p/f[x]^(m*p), x] == 0*) + + +Int[u_.*(v_^m_)^p_,x_Symbol] := + Module[{r=Simplify[(v^m)^p/v^(m*p)]}, + r*Int[Regularize[u*v^(m*p),x],x] /; + NonzeroQ[r-1]] /; +FreeQ[p,x] && Not[PowerQ[v]] + + +(* ::Item::Closed:: *) +(*Derivation: Distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(f[x]^m*g[x]^n)^p/(f[x]^(m*p)*g[x]^(n*p)), x] == 0*) + + +Int[u_.*(v_^m_.*w_^n_.)^p_,x_Symbol] := + Int[u*v^(m*p)*w^(n*p),x] /; +FreeQ[p,x] && Not[PowerQ[v]] && Not[PowerQ[w]] && ZeroQ[Simplify[(v^m*w^n)^p-v^(m*p)*w^(n*p)]] + + +(* ::Item::Closed:: *) +(*Derivation: Distribution of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[(f[x]^m*g[x]^n)^p/(f[x]^(m*p)*g[x]^(n*p)), x] == 0*) + + +(* Valid because the derivative of (f[x]^m*g[x]^n)^p/(f[x]^(m*p)*g[x]^(n*p)) wrt x is 0. *) +Int[u_.*(v_^m_.*w_^n_.)^p_,x_Symbol] := + Module[{r=Simplify[(v^m*w^n)^p/(v^(m*p)*w^(n*p))],lst}, + ( lst=SplitFreeFactors[v^(m*p)*w^(n*p),x]; + r*lst[[1]]*Int[Regularize[u*lst[[2]],x],x] ) /; + NonzeroQ[r-1]] /; +FreeQ[p,x] && Not[PowerQ[v]] && Not[PowerQ[w]] + + +(* ::Subsection::Closed:: *) +(*Products of fractional powers collection rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Collection of fractional powers*) + + +(* ::Item:: *) +(*Basis: D[f[x]^m/g[x]^m/(f[x]/g[x])^m, x] == 0*) + + +(* ::Item:: *) +(*Basis: Int[v^m/w^m, x] == v^m/w^m/(v/w)^m*Int[(v/w)^m, x]*) + + +Int[u_.*v_^m_*w_^n_,x_Symbol] := + Module[{q=Cancel[v/w]}, + (v^m*w^n)/q^m*Int[u*q^m,x] /; + PolynomialQ[q,x]] /; +FractionQ[{m,n}] && m+n==0 && PolynomialQ[{v,w},x] + + +(* ::Subsection::Closed:: *) +(*Fractional power of linear subexpression substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[(a+b*x)^(1/n), x], x] == n/b*Subst[Int[x^(n-1)*f[x, -a/b+x^n/b], x], x, (a+b*x)^(1/n)]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=SubstForFractionalPowerOfLinear[u,x]}, + ShowStep["","Int[f[(a+b*x)^(1/n),x],x]", + "n/b*Subst[Int[x^(n-1)*f[x,-a/b+x^n/b],x],x,(a+b*x)^(1/n)]",Hold[ + Dist[lst[[2]]*lst[[4]],Subst[Int[lst[[1]],x],x,lst[[3]]^(1/lst[[2]])]]]] /; + NotFalseQ[lst] (* && AlgebraicFunctionQ[lst[[1]],x] *) ] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=SubstForFractionalPowerOfLinear[u,x]}, + Dist[lst[[2]]*lst[[4]],Subst[Int[lst[[1]],x],x,lst[[3]]^(1/lst[[2]])]] /; + NotFalseQ[lst] (* && AlgebraicFunctionQ[lst[[1]],x] *) ]] + + +(* ::Subsection::Closed:: *) +(*Quadratic binomial expansion rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*z^2) == 1/(2*(a+b*Sqrt[-a/b]*z)) + 1/(2*(a-b*Sqrt[-a/b]*z))*) + + +(* ::Item:: *) +(*Note: This rule necessary because ExpnExpand cannot expand Sqrt[x + 1]/((1 - I*x)*(1 + I*x)).*) + + +Int[u_./(a_+b_.*v_^2),x_Symbol] := + Dist[1/2,Int[u/(a+b*Rt[-a/b,2]*v),x]] + Dist[1/2,Int[u/(a-b*Rt[-a/b,2]*v),x]] /; +FreeQ[{a,b},x] (* && Not[PositiveQ[-a/b]] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: a+b*z^2 == a*(1+Sqrt[-b/a]*z)*(1-Sqrt[-b/a]*z)*) + + +Int[u_.*(a_+b_.*v_^2)^m_,x_Symbol] := + Dist[a^m,Int[u*(1+Rt[-b/a,2]*v)^m*(1-Rt[-b/a,2]*v)^m,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && (m<-1 || m==-1 && PositiveQ[-b/a]) + + +(* ::Subsection::Closed:: *) +(*Exponential function expansion rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: f^(z+w) == f^z*f^w*) + + +Int[u_.*f_^(a_+v_)*g_^(b_+w_),x_Symbol] := + Dist[f^a*g^b,Int[u*f^v*g^w,x]] /; +FreeQ[{a,b,f,g},x] && Not[MatchQ[v,c_+t_ /; FreeQ[c,x]]] && Not[MatchQ[w,c_+t_ /; FreeQ[c,x]]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: f^(z+w) == f^z*f^w*) + + +Int[u_.*f_^(a_+v_),x_Symbol] := + Dist[f^a,Int[u*f^v,x]] /; +FreeQ[{a,f},x] && Not[MatchQ[v,b_+w_ /; FreeQ[b,x]]] + + +(* ::Section::Closed:: *) +(*Nuclear Option Rules*) + + +(* ::Subsection::Closed:: *) +(*Tangent \[Theta]/2 substitution rules for linear trigonometric expressions*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 484*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Sin[x] == 2*Tan[x/2]/(1+Tan[x/2]^2)*) + + +(* ::Item:: *) +(*Basis: Cos[x] == (1-Tan[x/2]^2)/(1+Tan[x/2]^2)*) + + +(* ::Item:: *) +(*Basis: 1+Tan[x/2]^2 == Tan'[x/2]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + ShowStep["","Int[f[Sin[x],Cos[x]],x]", + "2*Subst[Int[f[2*x/(1+x^2),(1-x^2)/(1+x^2)]/(1+x^2),x],x,Tan[x/2]]",Hold[ + Dist[2,Subst[Int[Regularize[SubstForTrig[u,2*x/(1+x^2),(1-x^2)/(1+x^2),x,x]/(1+x^2),x],x],x,Tan[x/2]]]]] /; +SimplifyFlag && FunctionOfTrigQ[u,x,x], + +Int[u_,x_Symbol] := + Dist[2,Subst[Int[Regularize[SubstForTrig[u,2*x/(1+x^2),(1-x^2)/(1+x^2),x,x]/(1+x^2),x],x],x,Tan[x/2]]] /; +FunctionOfTrigQ[u,x,x]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Sinh[x] == 2*Tanh[x/2]/(1-Tanh[x/2]^2)*) + + +(* ::Item:: *) +(*Basis: Cosh[x] == (1+Tanh[x/2]^2)/(1-Tanh[x/2]^2)*) + + +(* ::Item:: *) +(*Basis: 1-Tanh[x/2]^2 == Tanh'[x/2]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + ShowStep["","Int[f[Sinh[x],Cosh[x]],x]", + "2*Subst[Int[f[2*x/(1-x^2),(1+x^2)/(1-x^2)]/(1-x^2),x],x,Tanh[x/2]]",Hold[ + Dist[2,Subst[Int[Regularize[SubstForHyperbolic[u,2*x/(1-x^2),(1+x^2)/(1-x^2),x,x]/(1-x^2),x],x],x,Tanh[x/2]]]]] /; +SimplifyFlag && FunctionOfHyperbolicQ[u,x,x], + +Int[u_,x_Symbol] := + Dist[2,Subst[Int[Regularize[SubstForHyperbolic[u,2*x/(1-x^2),(1+x^2)/(1-x^2),x,x]/(1-x^2),x],x],x,Tanh[x/2]]] /; +FunctionOfHyperbolicQ[u,x,x]] + + +(* ::Subsection::Closed:: *) +(*Euler's substitution rules for subexpressions of the form Sqrt[a+b x+c x^2]*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.251.1*) + + +(* ::Item:: *) +(*Derivation: Integration by Euler substitution for a>0*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfSquareRootOfQuadratic[u,x]}, + ShowStep["","Int[f[Sqrt[a+b*x+c*x^2],x],x]", + "2*Subst[Int[f[(c*Sqrt[a]-b*x+Sqrt[a]*x^2)/(c-x^2),(-b+2*Sqrt[a]*x)/(c-x^2)]* + (c*Sqrt[a]-b*x+Sqrt[a]*x^2)/(c-x^2)^2,x],x,(-Sqrt[a]+Sqrt[a+b*x+c*x^2])/x]", + Hold[Dist[2,Subst[Int[lst[[1]],x],x,lst[[2]]]]]] /; + Not[FalseQ[lst]] && lst[[3]]===1] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfSquareRootOfQuadratic[u,x]}, + Dist[2,Subst[Int[lst[[1]],x],x,lst[[2]]]] /; + Not[FalseQ[lst]]]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.251.2*) + + +(* ::Item:: *) +(*Derivation: Integration by Euler substitution for c>0*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfSquareRootOfQuadratic[u,x]}, + ShowStep["","Int[f[Sqrt[a+b*x+c*x^2],x],x]", + "2*Subst[Int[f[(a*Sqrt[c]+b*x+Sqrt[c]*x^2)/(b+2*Sqrt[c]*x),(-a+x^2)/(b+2*Sqrt[c]*x)]* + (a*Sqrt[c]+b*x+Sqrt[c]*x^2)/(b+2*Sqrt[c]*x)^2,x],x,Sqrt[c]*x+Sqrt[a+b*x+c*x^2]]", + Hold[Dist[2,Subst[Int[lst[[1]],x],x,lst[[2]]]]]] /; + Not[FalseQ[lst]] && lst[[3]]===2] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfSquareRootOfQuadratic[u,x]}, + Dist[2,Subst[Int[lst[[1]],x],x,lst[[2]]]] /; + Not[FalseQ[lst]]]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.251.3*) + + +(* ::Item:: *) +(*Derivation: Integration by Euler substitution*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfSquareRootOfQuadratic[u,x]}, + ShowStep["","Int[f[Sqrt[a+b*x+c*x^2],x],x]", + "-2*Sqrt[b^2-4*a*c]*Subst[Int[f[-Sqrt[b^2-4*a*c]*x/(c-x^2), + (b*c+c*Sqrt[b^2-4*a*c]+(-b+Sqrt[b^2-4*a*c])*x^2)/(-2*c*(c-x^2))]*x/(c-x^2)^2,x], + x,2*c*Sqrt[a+b*x+c*x^2]/(b-Sqrt[b^2-4*a*c]+2*c*x)]", + Hold[Dist[2,Subst[Int[lst[[1]],x],x,lst[[2]]]]]] /; + Not[FalseQ[lst]] && lst[[3]]===3] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{lst=FunctionOfSquareRootOfQuadratic[u,x]}, + Dist[2,Subst[Int[lst[[1]],x],x,lst[[2]]]] /; + Not[FalseQ[lst]]]] + + +(* ::Subsection::Closed:: *) +(*Inverse function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[z]/Sqrt[1-z^2] == f[Sin[ArcSin[z]]]*ArcSin'[z]*) + + +Int[u_*(1-(a_.+b_.*x_)^2)^n_.,x_Symbol] := + Module[{tmp=InverseFunctionOfLinear[u,x]}, + Dist[1/b,Subst[Int[Regularize[SubstForInverseFunction[u,tmp,x]*Cos[x]^(2*n+1),x],x],x,tmp]] /; + NotFalseQ[tmp] && tmp===ArcSin[a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[2*n] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[z]/Sqrt[1-z^2] == -f[Cos[ArcCos[z]]]*ArcCos'[z]*) + + +Int[u_*(1-(a_.+b_.*x_)^2)^n_.,x_Symbol] := + Module[{tmp=InverseFunctionOfLinear[u,x]}, + -Dist[1/b,Subst[Int[Regularize[SubstForInverseFunction[u,tmp,x]*Sin[x]^(2*n+1),x],x],x,tmp]] /; + NotFalseQ[tmp] && tmp===ArcCos[a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[2*n] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[z]/Sqrt[1+z^2] == f[Sinh[ArcSinh[z]]]*ArcSinh'[z]*) + + +Int[u_*(1+(a_.+b_.*x_)^2)^n_.,x_Symbol] := + Module[{tmp=InverseFunctionOfLinear[u,x]}, + Dist[1/b,Subst[Int[Regularize[SubstForInverseFunction[u,tmp,x]*Cosh[x]^(2*n+1),x],x],x,tmp]] /; + NotFalseQ[tmp] && tmp===ArcSinh[a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[2*n] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If h[g[x]] == x, Int[f[x, g[a+b*x]], x] == Subst[Int[f[-a/b+h[x]/b, x]*h'[x], x], x, g[a+b*x]]/b*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=SubstForInverseFunctionOfLinear[u,x]}, + ShowStep["If h[g[x]]==x","Int[f[x,g[a+b*x]],x]", + "Subst[Int[f[-a/b+h[x]/b,x]*h'[x],x],x,g[a+b*x]]/b",Hold[ + Dist[1/lst[[3]],Subst[Int[lst[[1]],x],x,lst[[2]]]]]] /; + NotFalseQ[lst]] /; +SimplifyFlag && Not[NotIntegrableQ[u,x]], + +Int[u_,x_Symbol] := + Module[{lst=SubstForInverseFunctionOfLinear[u,x]}, + Dist[1/lst[[3]],Subst[Int[lst[[1]],x],x,lst[[2]]]] /; + NotFalseQ[lst]] /; +Not[NotIntegrableQ[u,x]]] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If h[g[x]] == x, *) +(* Int[f[x, g[(a+b*x)/(c+d*x)]], x] == (b*c-a*d)*Subst[Int[f[(-a+c*h[x])/(b-d*h[x]), x]*h'[x]/(b-d*h[x])^2, x], x, g[(a+b*x)/(c+d*x)]]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=SubstForInverseFunctionOfQuotientOfLinears[u,x]}, + ShowStep["If h[g[x]]==x","Int[f[x,g[(a+b*x)/(c+d*x)]],x]", + "(b*c-a*d)*Subst[Int[f[(-a+c*h[x])/(b-d*h[x]),x]*h'[x]/(b-d*h[x])^2,x],x,g[(a+b*x)/(c+d*x)]]",Hold[ + Dist[lst[[3]],Subst[Int[lst[[1]],x],x,lst[[2]]]]]] /; + NotFalseQ[lst]] /; +SimplifyFlag && Not[NotIntegrableQ[u,x]], + +Int[u_,x_Symbol] := + Module[{lst=SubstForInverseFunctionOfQuotientOfLinears[u,x]}, + Dist[lst[[3]],Subst[Int[lst[[1]],x],x,lst[[2]]]] /; + NotFalseQ[lst]] /; +Not[NotIntegrableQ[u,x]]] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/HyperbolicFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/HyperbolicFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/HyperbolicFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/HyperbolicFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,4384 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Hyperbolic Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Sine Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b x]^n Powers of sines of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.20, CRC 554, A&S 4.5.77*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Cosh'[z] == -Sinh[z]*) + + +Int[Sinh[a_.+b_.*x_],x_Symbol] := + Cosh[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.414.2, CRC 566*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[Sinh[a_.+b_.*x_]^2,x_Symbol] := + -x/2 + Cosh[a+b*x]*Sinh[a+b*x]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, Sinh[z]^n == (-1+Cosh[z]^2)^((n-1)/2)*Cosh'[z]*) + + +Int[Sinh[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(-1+x^2)^((n-1)/2),x],x],x,Cosh[a+b*x]]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Sinh[c+d x])^n Powers of linear binomials of sines of linears*) + + +Int[1/(a_+b_.*Sinh[c_.+d_.*x_]),x_Symbol] := + -Cosh[c+d*x]/(d*(b-a*Sinh[c+d*x])) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.441.3b*) + + +Int[1/(a_+b_.*Sinh[c_.+d_.*x_]),x_Symbol] := + -2*ArcTanh[(b-a*Tanh[(c+d*x)/2])/Rt[a^2+b^2,2]]/(d*Rt[a^2+b^2,2]) /; +FreeQ[{a,b,c,d},x] && PosQ[a^2+b^2] + + +Int[1/(a_+b_.*Sinh[c_.+d_.*x_]),x_Symbol] := + 2*ArcTan[(b-a*Tanh[(c+d*x)/2])/Rt[-a^2-b^2,2]]/(d*Rt[-a^2-b^2,2]) /; +FreeQ[{a,b,c,d},x] && NegQ[a^2+b^2] + + +(* ::ItemParagraph:: *) +(**) + + +Int[Sqrt[a_+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + 2*b*Cosh[c+d*x]/(d*Sqrt[a+b*Sinh[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Basis: D[EllipticE[x,n],x] == Sqrt[1-n*Sin[x]^2]*) + + +Int[Sqrt[a_.+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + 2*I*Sqrt[a-I*b]*EllipticE[(Pi/2-I*(c+d*x))/2,2*b/(a*I+b)]/d /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] && PositiveQ[a-I*b] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[Sqrt[a+b*f[c+d*x]]/Sqrt[(a+b*f[c+d*x])/(a+b)],x] == 0*) + + +Int[Sqrt[a_.+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + Sqrt[a+b*Sinh[c+d*x]]/Sqrt[(a+b*Sinh[c+d*x])/(a-I*b)]*Int[Sqrt[a/(a-I*b)+b/(a-I*b)*Sinh[c+d*x]],x] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] && Not[PositiveQ[a-I*b]] + + +(* ::ItemParagraph:: *) +(**) + + +Int[1/Sqrt[a_+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + -2*ArcTanh[Cosh[(c+Pi*I/2+d*x)/2]]*Sinh[(c+Pi*I/2+d*x)/2]/(d*Sqrt[a+b*Sinh[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a-b*I] + + +Int[1/Sqrt[a_+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + 2*ArcTan[Sinh[(c+Pi*I/2+d*x)/2]]*Cosh[(c+Pi*I/2+d*x)/2]/(d*Sqrt[a+b*Sinh[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a+b*I] + + +(* ::Item:: *) +(*Basis: D[EllipticF[x,n],x] == 1/Sqrt[1-n*Sin[x]^2]*) + + +Int[1/Sqrt[a_.+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + 2*I*EllipticF[(Pi/2-I*(c+d*x))/2,2*b/(a*I+b)]/(d*Sqrt[a-I*b]) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] && PositiveQ[a-I*b] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[Sqrt[(a+b*f[c+d*x])/(a+b)]/Sqrt[a+b*f[c+d*x]],x] == 0*) + + +Int[1/Sqrt[a_.+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + Sqrt[(a+b*Sinh[c+d*x])/(a-I*b)]/Sqrt[a+b*Sinh[c+d*x]]*Int[1/Sqrt[a/(a-I*b)+b/(a-I*b)*Sinh[c+d*x]],x] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] && Not[PositiveQ[a-I*b]] + + +(* ::ItemParagraph:: *) +(**) + + +Int[(a_+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + b*Cosh[c+d*x]*(a+b*Sinh[c+d*x])^(n-1)/(d*n) + + Dist[a*(2*n-1)/n,Int[(a+b*Sinh[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && ZeroQ[a^2+b^2] + + +Int[(a_+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + -b*Cosh[c+d*x]*(a+b*Sinh[c+d*x])^n/(a*d*(2*n+1)) + + Dist[(n+1)/(a*(2*n+1)),Int[(a+b*Sinh[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && ZeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.441.1 inverted*) + + +(* This results in an infinite loop!!! *) +(* Int[(a_+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + -b*Cosh[c+d*x]*(a+b*Sinh[c+d*x])^n/(a*d*n) + + Dist[(a^2+b^2)/a,Int[(a+b*Sinh[c+d*x])^(n-1),x]] + + Dist[b*(n+1)/(a*n),Int[Sinh[c+d*x]*(a+b*Sinh[c+d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>0 && NonzeroQ[a^2+b^2] *) + + +Int[1/(a_+b_.*Sinh[c_.+d_.*x_])^2,x_Symbol] := + -b*Cosh[c+d*x]/(d*(a^2+b^2)*(a+b*Sinh[c+d*x])) + + Dist[a/(a^2+b^2),Int[1/(a+b*Sinh[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] + + +Int[(a_+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + b*Cosh[c+d*x]*(a+b*Sinh[c+d*x])^(n+1)/(d*(n+1)*(a^2+b^2)) + + Dist[1/((n+1)*(a^2+b^2)),Int[(a*(n+1)-b*(n+2)*Sinh[c+d*x])*(a+b*Sinh[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2+b^2] + + +(* ::ItemParagraph::Closed:: *) +(**) + + +(* ::Item:: *) +(*Reference: G&R 2.411.2, CRC 567b*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Sinh[a_.+b_.*x_])^n_,x_Symbol] := + c*Cosh[a+b*x]*(c*Sinh[a+b*x])^(n-1)/(b*n) - + Dist[(n-1)*c^2/n,Int[(c*Sinh[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[OddQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.5, CRC 568a*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Sinh[a_.+b_.*x_])^n_,x_Symbol] := + Cosh[a+b*x]*(c*Sinh[a+b*x])^(n+1)/(c*b*(n+1)) - + Dist[(n+2)/((n+1)*c^2),Int[(c*Sinh[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Sinh[x])^n/Sinh[x]^n,x] == 0*) + + +Int[(c_*Sinh[a_.+b_.*x_])^n_,x_Symbol] := + (c*Sinh[a+b*x])^n/Sinh[a+b*x]^n*Int[Sinh[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -10 + + +(* ::Subsubsection::Closed:: *) +(*(A+B Sinh[c+d x]) (a+b Sinh[c+d x])^n Products of powers of linear binomials of sines*) + + +(* ::Item:: *) +(*Basis: (A+B*z)/Sqrt[a+b*z] == (b*A-a*B)/(b*Sqrt[a+b*z]) + B/b*Sqrt[a+b*z]*) + + +Int[(A_.+B_.*Sinh[c_.+d_.*x_])/Sqrt[a_+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + Dist[(b*A-a*B)/b,Int[1/Sqrt[a+b*Sinh[c+d*x]],x]] + + Dist[B/b,Int[Sqrt[a+b*Sinh[c+d*x]],x]] /; +FreeQ[{a,b,c,d,A,B},x] && NonzeroQ[b*A-a*B] + + +(* ::Item:: *) +(*Reference: G&R 2.441.1 inverted*) + + +Int[(A_.+B_.*Sinh[c_.+d_.*x_])*(a_+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + B*Cosh[c+d*x]*(a+b*Sinh[c+d*x])^n/(d*(n+1)) + + Dist[1/(n+1),Int[(-b*B*n+a*A*(n+1) + (a*B*n+b*A*(n+1))*Sinh[c+d*x])*(a+b*Sinh[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n>1 && NonzeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.441.1 special case*) + + +Int[(A_+B_.*Sinh[c_.+d_.*x_])/(a_+b_.*Sinh[c_.+d_.*x_])^2,x_Symbol] := + B*Cosh[c+d*x]/(a*d*(a+b*Sinh[c+d*x])) /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A+b*B] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*(A_+B_.*Sinh[c_.+d_.*x_])/(a_+b_.*Sinh[c_.+d_.*x_])^2,x_Symbol] := + B*x*Cosh[c+d*x]/(a*d*(a+b*Sinh[c+d*x])) - + Dist[B/(a*d),Int[Cosh[c+d*x]/(a+b*Sinh[c+d*x]),x]] /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A+b*B] + + +(* ::Item:: *) +(*Reference: G&R 2.441.1*) + + +Int[(A_.+B_.*Sinh[c_.+d_.*x_])*(a_.+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + -(a*B-b*A)*Cosh[c+d*x]*(a+b*Sinh[c+d*x])^(n+1)/(d*(n+1)*(a^2+b^2)) + + Dist[1/((n+1)*(a^2+b^2)),Int[((n+1)*(a*A+b*B)+(n+2)*(a*B-b*A)*Sinh[c+d*x])*(a+b*Sinh[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2+b^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Sinh[c+d x]^2)^n Products of monomials and powers of quadratic binomials of sines of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sinh[z]^2 == (-1 + Cosh[2*z])/2*) + + +Int[x_^m_./(a_+b_.*Sinh[c_.+d_.*x_]^2),x_Symbol] := + Dist[2,Int[x^m/(2*a-b+b*Cosh[2*c+2*d*x]),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 && NonzeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a+b*Cosh[z]^2+c*Sinh[z]^2 == (2*a+b-c + (b+c)*Cosh[2*z])/2*) + + +Int[x_^m_./(a_.+b_.*Cosh[d_.+e_.*x_]^2+c_.*Sinh[d_.+e_.*x_]^2),x_Symbol] := + Dist[2,Int[x^m/(2*a+b-c+(b+c)*Cosh[2*d+2*e*x]),x]] /; +FreeQ[{a,b,c,d,e},x] && IntegerQ[m] && m>0 && NonzeroQ[a+b] && NonzeroQ[a-c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sinh[z]^2 == (-1 + Cosh[2*z])/2*) + + +Int[(a_+b_.*Sinh[c_.+d_.*x_]^2)^n_,x_Symbol] := + Dist[1/2^n,Int[(2*a-b+b*Cosh[2*c+2*d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a-b] && HalfIntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Sinh[c+d x] Cosh[c+d x])^n Products of monomials and powers involving products of sines and cosines*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sinh[z]*Cosh[z] == Sinh[2*z]/2*) + + +Int[x_^m_./(a_+b_.*Sinh[c_.+d_.*x_]*Cosh[c_.+d_.*x_]),x_Symbol] := + Int[x^m/(a+b*Sinh[2*c+2*d*x]/2),x] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sinh[z]*Cosh[z] == Sinh[2*z]/2*) + + +Int[(a_+b_.*Sinh[c_.+d_.*x_]*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + Int[(a+b*Sinh[2*c+2*d*x]/2)^n,x] /; +FreeQ[{a,b,c,d},x] && HalfIntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b x]^m Cosh[a+b x]^n Products of powers of sines and cosines*) + + +Int[Sinh[a_.+b_.*x_]^m_.*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Sinh[a+b*x]^(m+1)*Cosh[a+b*x]^(n+1)/(b*(m+1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+2] && NonzeroQ[m+1] && PosQ[m] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, Cosh[z]^n == (1+Sinh[z]^2)^((n-1)/2)*Sinh'[z]*) + + +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[x^m*(1+x^2)^((n-1)/2),x],x],x,Sinh[a+b*x]]] /; +FreeQ[{a,b,m},x] && OddQ[n] && Not[OddQ[m] && 01 && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.411.2, CRC 567b, A&S 4.5.85b*) + + +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Sinh[a+b*x]^(m-1)*Cosh[a+b*x]^(n+1)/(b*(m+n)) - + Dist[(m-1)/(m+n),Int[Sinh[a+b*x]^(m-2)*Cosh[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[OddQ[m]] && NonzeroQ[m+n] && +Not[OddQ[n] && n>1] + + +(* ::Item:: *) +(*Reference: G&R 2.411.5, CRC 568a, A&S 4.5.86a*) + + +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Sinh[a+b*x]^(m+1)*Cosh[a+b*x]^(n+1)/(b*(m+1)) - + Dist[(m+n+2)/(m+1),Int[Sinh[a+b*x]^(m+2)*Cosh[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n+2] + + +(* Kool rule *) +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/(b*m),Subst[Int[x^(1/m)/(1-x^(2/m)),x],x,Sinh[a+b*x]^m*Cosh[a+b*x]^n]] /; +FreeQ[{a,b},x] && FractionQ[{m,n}] && ZeroQ[m+n] && IntegerQ[1/m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b x]^m Tanh[a+b x]^n Products of powers of sines and tangents*) +(**) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.423.18'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[z]*Tanh[z] == Cosh[z]-Sech[z]*) + + +Int[Sinh[a_.+b_.*x_]*Tanh[a_.+b_.*x_],x_Symbol] := + Sinh[a+b*x]/b - Int[Sech[a+b*x],x] /; +FreeQ[{a,b},x] + + +Int[Sinh[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol]:= + Sinh[a+b*x]^m*Tanh[a+b*x]^(n-1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-1] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[Sinh[a_.+b_.*x_]^m_.*Tanh[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(-1+x^2)^((m+n-1)/2)/x^n,x],x],x,Cosh[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && OddQ[m+n] + + +(* ::Item:: *) +(*Reference: G&R 2.411.1, CRC 567a*) + + +Int[Sinh[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + Sinh[a+b*x]^m*Tanh[a+b*x]^(n+1)/(b*m) - + Dist[(n+1)/m,Int[Sinh[a+b*x]^(m-2)*Tanh[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m>1 && n<-1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.6, CRC 568b*) + + +Int[Sinh[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + Sinh[a+b*x]^(m+2)*Tanh[a+b*x]^(n-1)/(b*(n-1)) - + Dist[(m+2)/(n-1),Int[Sinh[a+b*x]^(m+2)*Tanh[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.2, CRC 567b*) + + +Int[Sinh[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_.,x_Symbol]:= + Sinh[a+b*x]^m*Tanh[a+b*x]^(n-1)/(b*m) - + Dist[(m+n-1)/m,Int[Sinh[a+b*x]^(m-2)*Tanh[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.3*) + + +Int[Sinh[a_.+b_.*x_]^m_.*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + -Sinh[a+b*x]^m*Tanh[a+b*x]^(n-1)/(b*(n-1)) + + Dist[(m+n-1)/(n-1),Int[Sinh[a+b*x]^m*Tanh[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.5, CRC 568a*) + + +Int[Sinh[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_.,x_Symbol]:= + Sinh[a+b*x]^(m+2)*Tanh[a+b*x]^(n-1)/(b*(m+n+1)) - + Dist[(m+2)/(m+n+1),Int[Sinh[a+b*x]^(m+2)*Tanh[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.4*) + + +Int[Sinh[a_.+b_.*x_]^m_.*Tanh[a_.+b_.*x_]^n_,x_Symbol]:= + Sinh[a+b*x]^m*Tanh[a+b*x]^(n+1)/(b*(m+n+1)) + + Dist[(n+1)/(m+n+1),Int[Sinh[a+b*x]^m*Tanh[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b x^n] Sines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: FresnelS'[z] == Sin[Pi*z^2/2]*) + + +(* Note: This rule introduces I;whereas,converting to exponentials does not. *) +(* Int[Sinh[b_.*x_^2],x_Symbol] := + -I*Sqrt[Pi/2]*FresnelS[Rt[I*b,2]*x/Sqrt[Pi/2]]/Rt[I*b,2] /; +FreeQ[b,x] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[z] == E^z/2 - E^(-z)/2*) + + +Int[Sinh[a_.+b_.*x_^n_],x_Symbol] := + Dist[1/2,Int[E^(a+b*x^n),x]] - + Dist[1/2,Int[E^(-a-b*x^n),x]] /; +FreeQ[{a,b,n},x] && Not[FractionOrNegativeQ[n]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Note: Although resulting integrand looks more complicated than original one, rules for + improper binomials rectify it. *) +Int[Sinh[a_.+b_.*x_^n_],x_Symbol] := + x*Sinh[a+b*x^n] - + Dist[b*n,Int[x^n*Cosh[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && n<0 + + +(* ::Subsubsection::Closed:: *) +(*x^m Sinh[a+b x^n] Products of monomials and sines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: SinhIntegral'[z] == Sinh[z]/z*) + + +Int[Sinh[a_.*x_^n_.]/x_,x_Symbol] := + SinhIntegral[a*x^n]/n /; +FreeQ[{a,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[w+z] == Sinh[w]*Cosh[z] + Cosh[w]*Sinh[z]*) + + +Int[Sinh[a_+b_.*x_^n_.]/x_,x_Symbol] := + Dist[Sinh[a],Int[Cosh[b*x^n]/x,x]] + + Dist[Cosh[a],Int[Sinh[b*x^n]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 392h, A&S 4.5.83*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m*Sinh[a+b*x^n] == x^(m-n+1)*(Sinh[a+b*x^n]*x^(n-1))*) + + +Int[x_^m_.*Sinh[a_.+b_.*x_^n_.],x_Symbol] := + x^(m-n+1)*Cosh[a+b*x^n]/(b*n) - + Dist[(m-n+1)/(b*n),Int[x^(m-n)*Cosh[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[m] && 00 && m<-1 || 0<-n1 && ZeroQ[m-2*n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.471.1b' w/ q=0*) + + +Int[x_^m_.*Sinh[a_.+b_.*x_^n_.]^p_,x_Symbol] := + -(m-n+1)*x^(m-2*n+1)*Sinh[a+b*x^n]^p/(b^2*n^2*p^2) + + x^(m-n+1)*Cosh[a+b*x^n]*Sinh[a+b*x^n]^(p-1)/(b*n*p) - + Dist[(p-1)/p,Int[x^m*Sinh[a+b*x^n]^(p-2),x]] + + Dist[(m-n+1)*(m-2*n+1)/(b^2*n^2*p^2),Int[x^(m-2*n)*Sinh[a+b*x^n]^p,x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[{m,p}] && p>1 && 0<2*n1 && m<-1 && n>0 && NonzeroQ[m+n+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sinh[a+b (c+d x)^n]^p Products of monomials and powers of sines of binomials of linears*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b x,x],x] == Subst[Int[f[x,-a/b+x/b],x],x,a+b x]/b*) + + +Int[x_^m_.*Sinh[a_.+b_.*(c_+d_.*x_)^n_]^p_.,x_Symbol] := + Dist[1/d,Subst[Int[(-c/d+x/d)^m*Sinh[a+b*x^n]^p,x],x,c+d*x]] /; +FreeQ[{a,b,c,d,n},x] && IntegerQ[m] && m>0 && RationalQ[p] + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b x+c x^2] Sines of quadratic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If b^2-4*a*c=0, a+b*x+c*x^2 == (b+2*c*x)^2/(4*c)*) + + +Int[Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Int[Sinh[(b+2*c*x)^2/(4*c)],x] /; +FreeQ[{a,b,c},x] && ZeroQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[z] == E^z/2 - E^(-z)/2*) + + +Int[Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Dist[1/2,Int[E^(a+b*x+c*x^2),x]] - + Dist[1/2,Int[E^(-a-b*x-c*x^2),x]] /; +FreeQ[{a,b,c},x] && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*(d+e x)^m Sinh[a+b x+c x^2] Products of monomials and sines of quadratic trinomials*) +(**) + + +Int[(d_.+e_.*x_)*Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*Cosh[a+b*x+c*x^2]/(2*c) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)*Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*Cosh[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[Sinh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*(d+e*x)^(m-1)*Cosh[a+b*x+c*x^2]/(2*c) - + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Cosh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*(d+e*x)^(m-1)*Cosh[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[(d+e*x)^(m-1)*Sinh[a+b*x+c*x^2],x]] - + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Cosh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Sinh[a+b*x+c*x^2]/(e*(m+1)) - + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Cosh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sinh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Sinh[a+b*x+c*x^2]/(e*(m+1)) - + Dist[(b*e-2*c*d)/(e^2*(m+1)),Int[(d+e*x)^(m+1)*Cosh[a+b*x+c*x^2],x]] - + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Cosh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && NonzeroQ[b*e-2*c*d] + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b Log[c x^n]]^p Powers of sines of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sinh[b*Log[c*x^n]] == (c*x^n)^b/2 - 1/(2*(c*x^n)^b)*) + + +Int[Sinh[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[((c*x^n)^b/2 - 1/(2*(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,n,p}] + + +Int[Sinh[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + x*Sinh[a+b*Log[c*x^n]]/(1-b^2*n^2) - + b*n*x*Cosh[a+b*Log[c*x^n]]/(1-b^2*n^2) /; +FreeQ[{a,b,c,n},x] && NonzeroQ[1-b^2*n^2] + + +Int[Sqrt[Sinh[a_.+b_.*Log[c_.*x_^n_.]]],x_Symbol] := + x*Sqrt[Sinh[a+b*Log[c*x^n]]]/Sqrt[-1+E^(2*a)*(c*x^n)^(4/n)]* + Int[Sqrt[-1+E^(2*a)*(c*x^n)^(4/n)]/x,x] /; +FreeQ[{a,b,c,n},x] && ZeroQ[b*n-2] + + +(* Int[1/Sqrt[Sinh[a_.+b_.*Log[c_.*x_^n_.]]],x_Symbol] := + ??? /; +FreeQ[{a,b,c,n},x] && ZeroQ[b*n-2] *) + + +Int[Sinh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Coth[a+b*Log[c*x^n]]*Sinh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + x*Sinh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) /; +FreeQ[{a,b,c,n,p},x] && NonzeroQ[p+1] && NonzeroQ[p+2] && ZeroQ[b^2*n^2*(p+2)^2-1] + + +Int[Sinh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Sinh[a+b*Log[c*x^n]]^p/(1-b^2*n^2*p^2) - + b*n*p*x*Cosh[a+b*Log[c*x^n]]*Sinh[a+b*Log[c*x^n]]^(p-1)/(1-b^2*n^2*p^2) + + Dist[b^2*n^2*p*(p-1)/(1-b^2*n^2*p^2),Int[Sinh[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && NonzeroQ[1-b^2*n^2*p^2] + + +Int[Sinh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Coth[a+b*Log[c*x^n]]*Sinh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + x*Sinh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) - + Dist[(b^2*n^2*(p+2)^2-1)/(b^2*n^2*(p+1)*(p+2)),Int[Sinh[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && p!=-2 && NonzeroQ[b^2*n^2*(p+2)^2-1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sinh[a+b Log[c x^n]]^p Products of monomials and powers of sines of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sinh[b*Log[c*x^n]] == (c*x^n)^b/2 - 1/(2*(c*x^n)^b)*) + + +Int[x_^m_.*Sinh[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[x^m*((c*x^n)^b/2 - 1/(2*(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,m,n,p}] + + +Int[x_^m_.*Sinh[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + (m+1)*x^(m+1)*Sinh[a+b*Log[c*x^n]]/((m+1)^2-b^2*n^2) - + b*n*x^(m+1)*Cosh[a+b*Log[c*x^n]]/((m+1)^2-b^2*n^2) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[(m+1)^2-b^2*n^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Sinh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x^(m+1)*Coth[a+b*Log[c*x^n]]*Sinh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + (m+1)*x^(m+1)*Sinh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) /; +FreeQ[{a,b,c,m,n,p},x] && NonzeroQ[p+1] && NonzeroQ[p+2] && ZeroQ[(m+1)^2-b^2*n^2*(p+2)^2] + + +Int[x_^m_.*Sinh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + (m+1)*x^(m+1)*Sinh[a+b*Log[c*x^n]]^p/((m+1)^2-b^2*n^2*p^2) - + b*n*p*x^(m+1)*Cosh[a+b*Log[c*x^n]]*Sinh[a+b*Log[c*x^n]]^(p-1)/((m+1)^2-b^2*n^2*p^2) + + Dist[b^2*n^2*p*(p-1)/((m+1)^2-b^2*n^2*p^2),Int[x^m*Sinh[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && NonzeroQ[(m+1)^2-b^2*n^2*p^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Sinh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x^(m+1)*Coth[a+b*Log[c*x^n]]*Sinh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + (m+1)*x^(m+1)*Sinh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) + + Dist[((m+1)^2-b^2*n^2*(p+2)^2)/(b^2*n^2*(p+1)*(p+2)),Int[x^m*Sinh[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && p!=-2 && NonzeroQ[m+1] && NonzeroQ[(m+1)^2-b^2*n^2*(p+2)^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sinh[a x^n Log[b x]^p Log[b x]^p Products of sines and powers of logarithms*) +(**) + + +Int[Sinh[a_.*x_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + Cosh[a*x*Log[b*x]^p]/a - + Dist[p,Int[Sinh[a*x*Log[b*x]^p]*Log[b*x]^(p-1),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p>0 + + +Int[Sinh[a_.*x_^n_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + Cosh[a*x^n*Log[b*x]^p]/(a*n*x^(n-1)) - + Dist[p/n,Int[Sinh[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] + + Dist[(n-1)/(a*n),Int[Cosh[a*x^n*Log[b*x]^p]/x^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{n,p}] && p>0 + + +Int[x_^m_*Sinh[a_.*x_^n_.*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + x^(m-n+1)*Cosh[a*x^n*Log[b*x]^p]/(a*n) - + Dist[p/n,Int[x^m*Sinh[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] - + Dist[(m-n+1)/(a*n),Int[x^(m-n)*Cosh[a*x^n*Log[b*x]^p],x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>0 + + +(* ::Subsubsection::Closed:: *) +(*u Sinh[v]^2 Products involving squares of sines*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[z]^2 == -1/2 + 1/2*Cosh[2*z]*) + + +Int[u_*Sinh[v_]^2,x_Symbol] := + Dist[-1/2,Int[u,x]] + + Dist[1/2,Int[u*Cosh[2*v],x]] /; +FunctionOfHyperbolicQ[u,2*v,x] + + +(* ::Subsubsection::Closed:: *) +(*u Sinh[v] Hyper[w] Products of hyperbolic trig functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[v]*Cosh[w] == Sinh[v+w]/2 + Sinh[v-w]/2*) + + +Int[u_.*Sinh[v_]*Cosh[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Sinh[v+w],x],x]] + + Dist[1/2,Int[u*Regularize[Sinh[v-w],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && PosQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[v]*Sinh[w] == Cosh[v+w]/2 - Cosh[v-w]/2*) + + +Int[u_.*Sinh[v_]*Sinh[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Cosh[v+w],x],x]] - + Dist[1/2,Int[u*Regularize[Cosh[v-w],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[v]*Tanh[w] == Cosh[v] - Cosh[v-w]*Sech[w]*) + + +Int[u_.*Sinh[v_]*Tanh[w_]^n_.,x_Symbol] := + Int[u*Cosh[v]*Tanh[w]^(n-1),x] - Cosh[v-w]*Int[u*Sech[w]*Tanh[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[v]*Coth[w] == Cosh[v] + Sinh[v-w]*Csch[w]*) + + +Int[u_.*Sinh[v_]*Coth[w_]^n_.,x_Symbol] := + Int[u*Cosh[v]*Coth[w]^(n-1),x] + Sinh[v-w]*Int[u*Csch[w]*Coth[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[v]*Sech[w] == Cosh[v-w]*Tanh[w] + Sinh[v-w]*) + + +Int[u_.*Sinh[v_]*Sech[w_]^n_.,x_Symbol] := + Cosh[v-w]*Int[u*Tanh[w]*Sech[w]^(n-1),x] + Sinh[v-w]*Int[u*Sech[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[v]*Csch[w] == Sinh[v-w]*Coth[w] + Cosh[v-w]*) + + +Int[u_.*Sinh[v_]*Csch[w_]^n_.,x_Symbol] := + Sinh[v-w]*Int[u*Coth[w]*Csch[w]^(n-1),x] + Cosh[v-w]*Int[u*Csch[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Cosine Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b x]^n Powers of cosines of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.21, CRC 555, A&S 4.5.78*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Sinh'[z] == Cosh[z]*) + + +Int[Cosh[a_.+b_.*x_],x_Symbol] := + Sinh[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.414.9, CRC 572*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[Cosh[a_.+b_.*x_]^2,x_Symbol] := + x/2 + Cosh[a+b*x]*Sinh[a+b*x]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, Cosh[z]^n == (1+Sinh[z]^2)^((n-1)/2)*Sinh'[z]*) + + +Int[Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(1+x^2)^((n-1)/2),x],x],x,Sinh[a+b*x]]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Cosh[c+d x])^n Powers of linear binomials of cosines of linears*) + + +(* ::Item:: *) +(*Reference: G&R 2.446.2'*) + + +Int[1/(a_+b_.*Cosh[c_.+d_.*x_]),x_Symbol] := + Sinh[c+d*x]/(d*(b+a*Cosh[c+d*x])) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.443.3c'*) + + +Int[1/(a_+b_.*Cosh[c_.+d_.*x_]),x_Symbol] := + 2*ArcTanh[((a-b)*Tanh[(c+d*x)/2])/Rt[a^2-b^2,2]]/(d*Rt[a^2-b^2,2]) /; +FreeQ[{a,b,c,d},x] && PosQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.443.3a'*) + + +Int[1/(a_+b_.*Cosh[c_.+d_.*x_]),x_Symbol] := + -2*ArcTan[((a-b)*Tanh[(c+d*x)/2])/Rt[b^2-a^2,2]]/(d*Rt[b^2-a^2,2]) /; +FreeQ[{a,b,c,d},x] && NegQ[a^2-b^2] + + +(* ::ItemParagraph:: *) +(**) + + +Int[Sqrt[a_+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + 2*b*Sinh[c+d*x]/(d*Sqrt[a+b*Cosh[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Basis: D[EllipticE[x,n],x] == Sqrt[1-n*Sin[x]^2]*) + + +Int[Sqrt[a_.+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + -2*I*Sqrt[a+b]*EllipticE[I*(c+d*x)/2,2*b/(a+b)]/d /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && PositiveQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[Sqrt[a+b*f[c+d*x]]/Sqrt[(a+b*f[c+d*x])/(a+b)],x] == 0*) + + +Int[Sqrt[a_.+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + Sqrt[a+b*Cosh[c+d*x]]/Sqrt[(a+b*Cosh[c+d*x])/(a+b)]*Int[Sqrt[a/(a+b)+b/(a+b)*Cosh[c+d*x]],x] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && Not[PositiveQ[a+b]] + + +(* ::ItemParagraph:: *) +(**) + + +Int[1/Sqrt[a_+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + 2*ArcTan[Sinh[(c+d*x)/2]]*Cosh[(c+d*x)/2]/(d*Sqrt[a+b*Cosh[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a-b] + + +Int[1/Sqrt[a_+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + -2*ArcTanh[Cosh[(c+d*x)/2]]*Sinh[(c+d*x)/2]/(d*Sqrt[a+b*Cosh[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a+b] + + +(* ::Item:: *) +(*Basis: D[EllipticF[x,n],x] == 1/Sqrt[1-n*Sin[x]^2]*) + + +Int[1/Sqrt[a_.+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + -2*I*EllipticF[I*(c+d*x)/2,2*b/(a+b)]/(d*Sqrt[a+b]) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && PositiveQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[Sqrt[(a+b*f[c+d*x])/(a+b)]/Sqrt[a+b*f[c+d*x]],x] == 0*) + + +Int[1/Sqrt[a_+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + Sqrt[(a+b*Cosh[c+d*x])/(a+b)]/Sqrt[a+b*Cosh[c+d*x]]*Int[1/Sqrt[a/(a+b)+b/(a+b)*Cosh[c+d*x]],x] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && Not[PositiveQ[a+b]] + + +(* ::ItemParagraph:: *) +(**) + + +Int[(a_+b_.*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + b*Sinh[c+d*x]*(a+b*Cosh[c+d*x])^(n-1)/(d*n) + + Dist[a*(2*n-1)/n,Int[(a+b*Cosh[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.446.1'*) + + +Int[(a_+b_.*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + -b*Sinh[c+d*x]*(a+b*Cosh[c+d*x])^n/(a*d*(2*n+1)) + + Dist[(n+1)/(a*(2*n+1)),Int[(a+b*Cosh[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.443.1 inverted*) + + +(* Note: This results in an infinite loop!!! *) +(* Int[(a_+b_.*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + -b*Sinh[c+d*x]*(a+b*Cosh[c+d*x])^n/(a*d*n) + + Dist[(a^2-b^2)/a,Int[(a+b*Cosh[c+d*x])^(n-1),x]] + + Dist[b*(n+1)/(a*n),Int[Cosh[c+d*x]*(a+b*Cosh[c+d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>0 && NonzeroQ[a^2-b^2] *) + + +(* ::Item:: *) +(*Reference: G&R 2.443.1*) + + +Int[1/(a_+b_.*Cosh[c_.+d_.*x_])^2,x_Symbol] := + -b*Sinh[c+d*x]/(d*(a^2-b^2)*(a+b*Cosh[c+d*x])) + + Dist[a/(a^2-b^2),Int[1/(a+b*Cosh[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.443.1*) + + +Int[(a_+b_.*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + b*Sinh[c+d*x]*(a+b*Cosh[c+d*x])^(n+1)/(d*(n+1)*(a^2-b^2)) + + Dist[1/((n+1)*(a^2-b^2)),Int[(a*(n+1)-b*(n+2)*Cosh[c+d*x])*(a+b*Cosh[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2] + + +(* ::ItemParagraph::Closed:: *) +(**) + + +(* ::Item:: *) +(*Reference: G&R 2.411.1, CRC 305h*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Cosh[a_.+b_.*x_])^n_,x_Symbol] := + c*Sinh[a+b*x]*(c*Cosh[a+b*x])^(n-1)/(b*n) + + Dist[(n-1)*c^2/n,Int[(c*Cosh[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[OddQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.6, CRC 568b*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Cosh[a_.+b_.*x_])^n_,x_Symbol] := + -Sinh[a+b*x]*(c*Cosh[a+b*x])^(n+1)/(b*c*(n+1)) + + Dist[(n+2)/((n+1)*c^2),Int[(c*Cosh[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Cosh[x])^n/Cosh[x]^n,x] == 0*) + + +Int[(c_*Cosh[a_.+b_.*x_])^n_,x_Symbol] := + (c*Cosh[a+b*x])^n/Cosh[a+b*x]^n*Int[Cosh[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -10 + + +(* ::Subsubsection::Closed:: *) +(*(A+B Cosh[c+d x]) (a+b Cosh[c+d x])^n Products of powers of linear binomials of cosines*) + + +(* ::Item:: *) +(*Basis: (A+B*z)/Sqrt[a+b*z] == (b*A-a*B)/(b*Sqrt[a+b*z]) + B/b*Sqrt[a+b*z]*) + + +Int[(A_.+B_.*Cosh[c_.+d_.*x_])/Sqrt[a_+b_.*Cosh[c_.+d_.*x_]],x_Symbol] := + Dist[(b*A-a*B)/b,Int[1/Sqrt[a+b*Cosh[c+d*x]],x]] + + Dist[B/b,Int[Sqrt[a+b*Cosh[c+d*x]],x]] /; +FreeQ[{a,b,c,d,A,B},x] && NonzeroQ[b*A-a*B] + + +(* ::Item:: *) +(*Reference: G&R 2.443.1 inverted*) + + +Int[(A_.+B_.*Cosh[c_.+d_.*x_])*(a_+b_.*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + B*Sinh[c+d*x]*(a+b*Cosh[c+d*x])^n/(d*(n+1)) + + Dist[1/(n+1),Int[(b*B*n+a*A*(n+1) + (a*B*n+b*A*(n+1))*Cosh[c+d*x])*(a+b*Cosh[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n>1 && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.443.1 special case*) + + +Int[(A_+B_.*Cosh[c_.+d_.*x_])/(a_+b_.*Cosh[c_.+d_.*x_])^2,x_Symbol] := + B*Sinh[c+d*x]/(a*d*(a+b*Cosh[c+d*x])) /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A-b*B] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*(A_+B_.*Cosh[c_.+d_.*x_])/(a_+b_.*Cosh[c_.+d_.*x_])^2,x_Symbol] := + B*x*Sinh[c+d*x]/(a*d*(a+b*Cosh[c+d*x])) - + Dist[B/(a*d),Int[Sinh[c+d*x]/(a+b*Cosh[c+d*x]),x]] /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A-b*B] + + +(* ::Item:: *) +(*Reference: G&R 2.443.1*) + + +Int[(A_.+B_.*Cosh[c_.+d_.*x_])*(a_.+b_.*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + -(a*B-b*A)*Sinh[c+d*x]*(a+b*Cosh[c+d*x])^(n+1)/(d*(n+1)*(a^2-b^2)) + + Dist[1/((n+1)*(a^2-b^2)),Int[((n+1)*(a*A-b*B)+(n+2)*(a*B-b*A)*Cosh[c+d*x])*(a+b*Cosh[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Cosh[c+d x]^2)^n Products of monomials and powers of quadratic binomials of sines of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Cosh[z]^2 == (1 + Cosh[2*z])/2*) + + +Int[x_^m_./(a_+b_.*Cosh[c_.+d_.*x_]^2),x_Symbol] := + Dist[2,Int[x^m/(2*a+b+b*Cosh[2*c+2*d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a+b] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Cosh[z]^2 == (1 + Cosh[2*z])/2*) + + +Int[(a_+b_.*Cosh[c_.+d_.*x_]^2)^n_,x_Symbol] := + Dist[1/2^n,Int[(2*a+b+b*Cosh[2*c+2*d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a+b] && HalfIntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b x]^n Sinh[a+b x]^m Products of powers of cosines and sines*) + + +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_.,x_Symbol] := + -Sinh[a+b*x]^(m+1)*Cosh[a+b*x]^(n+1)/(b*(n+1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+2] && NonzeroQ[n+1] && PosQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m is odd, Sinh[z]^m == (-1+Cosh[z]^2)^((m-1)/2)*Cosh'[z]*) + + +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[x^n*(-1+x^2)^((m-1)/2),x],x],x,Cosh[a+b*x]]] /; +FreeQ[{a,b,n},x] && OddQ[m] && Not[OddQ[n] && 01 + + +(* ::Item:: *) +(*Reference: G&R 2.411.1, CRC 567a, A&S 4.5.85a*) + + +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Sinh[a+b*x]^(m+1)*Cosh[a+b*x]^(n-1)/(b*(m+n)) + + Dist[(n-1)/(m+n),Int[Sinh[a+b*x]^m*Cosh[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[OddQ[n]] && NonzeroQ[m+n] && +Not[OddQ[m] && m>1] + + +(* ::Item:: *) +(*Reference: G&R 2.411.6, CRC 568b, A&S 4.5.86b*) + + +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + -Sinh[a+b*x]^(m+1)*Cosh[a+b*x]^(n+1)/(b*(n+1)) + + Dist[(m+n+2)/(n+1),Int[Sinh[a+b*x]^m*Cosh[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n+2] + + +(* Kool rule *) +Int[Sinh[a_.+b_.*x_]^m_*Cosh[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/(b*n),Subst[Int[x^(1/n)/(1-x^(2/n)),x],x,Sinh[a+b*x]^m*Cosh[a+b*x]^n]] /; +FreeQ[{a,b},x] && FractionQ[{m,n}] && ZeroQ[m+n] && IntegerQ[1/n] && n>0 + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b x]^m Coth[a+b x]^n Products of powers of cosines and cotangents*) +(**) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.423.34'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[z]*Coth[z] == Sinh[z]+Csch[z]*) + + +Int[Cosh[a_.+b_.*x_]*Coth[a_.+b_.*x_],x_Symbol] := + Cosh[a+b*x]/b + Int[Csch[a+b*x],x] /; +FreeQ[{a,b},x] + + +Int[Cosh[a_.+b_.*x_]^m_*Coth[a_.+b_.*x_]^n_,x_Symbol] := + Cosh[a+b*x]^m*Coth[a+b*x]^(n-1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-1] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[Cosh[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(1+x^2)^((m+n-1)/2)/x^n,x],x],x,Sinh[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && OddQ[m+n] + + +(* ::Item:: *) +(*Reference: G&R 2.411.2, CRC 567b*) + + +Int[Cosh[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + Cosh[a+b*x]^m*Coth[a+b*x]^(n+1)/(b*m) + + Dist[(n+1)/m,Int[Cosh[a+b*x]^(m-2)*Coth[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m>1 && n<-1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.5, CRC 568a*) + + +Int[Cosh[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + -Cosh[a+b*x]^(m+2)*Coth[a+b*x]^(n-1)/(b*(n-1)) + + Dist[(m+2)/(n-1),Int[Cosh[a+b*x]^(m+2)*Coth[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.1, CRC 567a*) + + +Int[Cosh[a_.+b_.*x_]^m_*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + Cosh[a+b*x]^m*Coth[a+b*x]^(n-1)/(b*m) + + Dist[(m+n-1)/m,Int[Cosh[a+b*x]^(m-2)*Coth[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.4*) + + +Int[Cosh[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_,x_Symbol] := + -Cosh[a+b*x]^m*Coth[a+b*x]^(n-1)/(b*(n-1)) + + Dist[(m+n-1)/(n-1),Int[Cosh[a+b*x]^m*Coth[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.6, CRC 568b*) + + +Int[Cosh[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + -Cosh[a+b*x]^(m+2)*Coth[a+b*x]^(n-1)/(b*(m+n+1)) + + Dist[(m+2)/(m+n+1),Int[Cosh[a+b*x]^(m+2)*Coth[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.3*) + + +Int[Cosh[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + Cosh[a+b*x]^m*Coth[a+b*x]^(n+1)/(b*(m+n+1)) + + Dist[(n+1)/(m+n+1),Int[Cosh[a+b*x]^m*Coth[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b x^n] Cosines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: FresnelC'[z] == Cos[Pi*z^2/2]*) + + +(* Note: This rule introduces I;whereas,converting to exponentials does not. *) +(* Int[Cosh[b_.*x_^2],x_Symbol] := + Sqrt[Pi/2]*FresnelC[Rt[I*b,2]*x/Sqrt[Pi/2]]/Rt[I*b,2] /; +FreeQ[b,x] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[z] == E^(-z)/2 + E^z/2*) + + +Int[Cosh[a_.+b_.*x_^n_],x_Symbol] := + Dist[1/2,Int[E^(-a-b*x^n),x]] + + Dist[1/2,Int[E^(a+b*x^n),x]] /; +FreeQ[{a,b,n},x] && Not[FractionOrNegativeQ[n]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Note: Although resulting integrand looks more complicated than original one, rules for + improper binomials rectify it. *) +Int[Cosh[a_.+b_.*x_^n_],x_Symbol] := + x*Cosh[a+b*x^n] - + Dist[b*n,Int[x^n*Sinh[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && n<0 + + +(* ::Subsubsection::Closed:: *) +(*x^m Cosh[a+b x^n] Products of monomials and cosines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: CoshIntegral'[z] == Cosh[z]/z*) + + +Int[Cosh[a_.*x_^n_.]/x_,x_Symbol] := + CoshIntegral[a*x^n]/n /; +FreeQ[{a,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[w+z] == Cosh[w]*Cosh[z] + Sinh[w]*Sinh[z]*) + + +Int[Cosh[a_+b_.*x_^n_.]/x_,x_Symbol] := + Dist[Cosh[a],Int[Cosh[b*x^n]/x,x]] + + Dist[Sinh[a],Int[Sinh[b*x^n]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 396h, A&S 4.5.84*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m*Cosh[a+b*x^n] == x^(m-n+1)*(Cosh[a+b*x^n]*x^(n-1))*) + + +Int[x_^m_.*Cosh[a_.+b_.*x_^n_.],x_Symbol] := + x^(m-n+1)*Sinh[a+b*x^n]/(b*n) - + Dist[(m-n+1)/(b*n),Int[x^(m-n)*Sinh[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[m] && 00 && m<-1 || 0<-n1 && ZeroQ[m-2*n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.471.1a' w/ p=0*) + + +Int[x_^m_.*Cosh[a_.+b_.*x_^n_.]^p_,x_Symbol] := + -(m-n+1)*x^(m-2*n+1)*Cosh[a+b*x^n]^p/(b^2*n^2*p^2) + + x^(m-n+1)*Sinh[a+b*x^n]*Cosh[a+b*x^n]^(p-1)/(b*n*p) + + Dist[(p-1)/p,Int[x^m*Cosh[a+b*x^n]^(p-2),x]] + + Dist[(m-n+1)*(m-2*n+1)/(b^2*n^2*p^2),Int[x^(m-2*n)*Cosh[a+b*x^n]^p,x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[{m,p}] && p>1 && 0<2*n1 && m<-1 && n>0 && NonzeroQ[m+n+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cosh[a+b (c+d x)^n]^p Products of monomials and powers of cosines of binomials of linears*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b x,x],x] == Subst[Int[f[x,-a/b+x/b],x],x,a+b x]/b*) + + +Int[x_^m_.*Cosh[a_.+b_.*(c_+d_.*x_)^n_]^p_.,x_Symbol] := + Dist[1/d,Subst[Int[(-c/d+x/d)^m*Cosh[a+b*x^n]^p,x],x,c+d*x]] /; +FreeQ[{a,b,c,d,n},x] && IntegerQ[m] && m>0 && RationalQ[p] + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b x+c x^2] Cosines of quadratic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If b^2-4*a*c=0, a+b*x+c*x^2 == (b+2*c*x)^2/(4*c)*) + + +Int[Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Int[Cosh[(b+2*c*x)^2/(4*c)],x] /; +FreeQ[{a,b,c},x] && ZeroQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[z] == E^(-z)/2 + E^z/2*) + + +Int[Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Dist[1/2,Int[E^(-a-b*x-c*x^2),x]] + + Dist[1/2,Int[E^(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c},x] && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*(d+e x)^m Cosh[a+b x+c x^2] Products of monomials and cosines of quadratic trinomials*) +(**) + + +Int[(d_.+e_.*x_)*Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*Sinh[a+b*x+c*x^2]/(2*c) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)*Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*Sinh[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[Cosh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*(d+e*x)^(m-1)*Sinh[a+b*x+c*x^2]/(2*c) - + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Sinh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*(d+e*x)^(m-1)*Sinh[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[(d+e*x)^(m-1)*Cosh[a+b*x+c*x^2],x]] - + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Sinh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Cosh[a+b*x+c*x^2]/(e*(m+1)) - + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Sinh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cosh[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Cosh[a+b*x+c*x^2]/(e*(m+1)) - + Dist[(b*e-2*c*d)/(e^2*(m+1)),Int[(d+e*x)^(m+1)*Sinh[a+b*x+c*x^2],x]] - + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Sinh[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && NonzeroQ[b*e-2*c*d] + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b Log[c x^n]]^p Powers of cosines of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Cosh[b*Log[c*x^n]] == (c*x^n)^b/2 + 1/(2*(c*x^n)^b)*) + + +Int[Cosh[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[((c*x^n)^b/2 + 1/(2*(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,n,p}] + + +Int[Cosh[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + x*Cosh[a+b*Log[c*x^n]]/(1-b^2*n^2) - + b*n*x*Sinh[a+b*Log[c*x^n]]/(1-b^2*n^2) /; +FreeQ[{a,b,c,n},x] && NonzeroQ[1-b^2*n^2] + + +Int[Sqrt[Cosh[a_.+b_.*Log[c_.*x_^n_.]]],x_Symbol] := + x*Sqrt[Cosh[a+b*Log[c*x^n]]]/Sqrt[1+E^(2*a)*(c*x^n)^(4/n)]* + Int[Sqrt[1+E^(2*a)*(c*x^n)^(4/n)]/x,x] /; +FreeQ[{a,b,c,n},x] && ZeroQ[b*n-2] + + +Int[Cosh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x*Tanh[a+b*Log[c*x^n]]*Cosh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) + + x*Cosh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) /; +FreeQ[{a,b,c,n,p},x] && NonzeroQ[p+1] && NonzeroQ[p+2] && ZeroQ[b^2*n^2*(p+2)^2-1] + + +Int[Cosh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Cosh[a+b*Log[c*x^n]]^p/(1-b^2*n^2*p^2) - + b*n*p*x*Cosh[a+b*Log[c*x^n]]^(p-1)*Sinh[a+b*Log[c*x^n]]/(1-b^2*n^2*p^2) - + Dist[b^2*n^2*p*(p-1)/(1-b^2*n^2*p^2),Int[Cosh[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && NonzeroQ[1-b^2*n^2*p^2] + + +Int[Cosh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x*Tanh[a+b*Log[c*x^n]]*Cosh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) + + x*Cosh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) + + Dist[(b^2*n^2*(p+2)^2-1)/(b^2*n^2*(p+1)*(p+2)),Int[Cosh[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && p!=-2 && NonzeroQ[b^2*n^2*(p+2)^2-1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cosh[a+b Log[c x^n]]^p Products of monomials and powers of cosines of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Cosh[b*Log[c*x^n]] == (c*x^n)^b/2 + 1/(2*(c*x^n)^b)*) + + +Int[x_^m_.*Cosh[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[x^m*((c*x^n)^b/2 + 1/(2*(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,m,n,p}] + + +Int[x_^m_.*Cosh[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + (m+1)*x^(m+1)*Cosh[a+b*Log[c*x^n]]/((m+1)^2-b^2*n^2) - + b*n*x^(m+1)*Sinh[a+b*Log[c*x^n]]/((m+1)^2-b^2*n^2) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[(m+1)^2-b^2*n^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Cosh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x^(m+1)*Tanh[a+b*Log[c*x^n]]*Cosh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) + + (m+1)*x^(m+1)*Cosh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) /; +FreeQ[{a,b,c,m,n,p},x] && NonzeroQ[p+1] && NonzeroQ[p+2] && ZeroQ[(m+1)^2-b^2*n^2*(p+2)^2] + + +Int[x_^m_.*Cosh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + (m+1)*x^(m+1)*Cosh[a+b*Log[c*x^n]]^p/((m+1)^2-b^2*n^2*p^2) - + b*n*p*x^(m+1)*Cosh[a+b*Log[c*x^n]]^(p-1)*Sinh[a+b*Log[c*x^n]]/((m+1)^2-b^2*n^2*p^2) - + Dist[b^2*n^2*p*(p-1)/((m+1)^2-b^2*n^2*p^2),Int[x^m*Cosh[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && NonzeroQ[(m+1)^2-b^2*n^2*p^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Cosh[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x^(m+1)*Tanh[a+b*Log[c*x^n]]*Cosh[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) + + (m+1)*x^(m+1)*Cosh[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) - + Dist[((m+1)^2-b^2*n^2*(p+2)^2)/(b^2*n^2*(p+1)*(p+2)),Int[x^m*Cosh[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && p!=-2 && NonzeroQ[m+1] && NonzeroQ[(m+1)^2-b^2*n^2*(p+2)^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cosh[a x^n Log[b x]^p Log[b x]^p Products of cosines and powers of logarithms*) +(**) + + +Int[Cosh[a_.*x_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + Sinh[a*x*Log[b*x]^p]/a - + Dist[p,Int[Cosh[a*x*Log[b*x]^p]*Log[b*x]^(p-1),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p>0 + + +Int[Cosh[a_.*x_^n_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + Sinh[a*x^n*Log[b*x]^p]/(a*n*x^(n-1)) - + Dist[p/n,Int[Cosh[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] + + Dist[(n-1)/(a*n),Int[Sinh[a*x^n*Log[b*x]^p]/x^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{n,p}] && p>0 + + +Int[x_^m_*Cosh[a_.*x_^n_.*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + x^(m-n+1)*Sinh[a*x^n*Log[b*x]^p]/(a*n) - + Dist[p/n,Int[x^m*Cosh[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] - + Dist[(m-n+1)/(a*n),Int[x^(m-n)*Sinh[a*x^n*Log[b*x]^p],x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>0 + + +(* ::Subsubsection::Closed:: *) +(*u Cosh[v]^2 Products involving squares of cosines*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[z]^2 == 1/2 + 1/2*Cosh[2*z]*) + + +Int[u_*Cosh[v_]^2,x_Symbol] := + Dist[1/2,Int[u,x]] + + Dist[1/2,Int[u*Cosh[2*v],x]] /; +FunctionOfHyperbolicQ[u,2*v,x] + + +(* ::Subsubsection::Closed:: *) +(*u Cosh[v] Hyper[w] Products of hyperbolic trig functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[v]*Cosh[w] == Sinh[w+v]/2 - Sinh[w-v]/2*) + + +Int[u_.*Sinh[v_]*Cosh[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Sinh[w+v],x],x]] - + Dist[1/2,Int[u*Regularize[Sinh[w-v],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && PosQ[w-v] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[v]*Cosh[w] == Cosh[v+w]/2 + Cosh[v-w]/2*) + + +Int[u_.*Cosh[v_]*Cosh[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Cosh[v+w],x],x]] + + Dist[1/2,Int[u*Regularize[Cosh[v-w],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[v]*Tanh[w] == Sinh[v] - Sinh[v-w]*Sech[w]*) + + +Int[u_.*Cosh[v_]*Tanh[w_]^n_.,x_Symbol] := + Int[u*Sinh[v]*Tanh[w]^(n-1),x] - Sinh[v-w]*Int[u*Sech[w]*Tanh[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[v]*Coth[w] == Sinh[v] + Cosh[v-w]*Csch[w]*) + + +Int[u_.*Cosh[v_]*Coth[w_]^n_.,x_Symbol] := + Int[u*Sinh[v]*Coth[w]^(n-1),x] + Cosh[v-w]*Int[u*Csch[w]*Coth[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[v]*Sech[w] == Sinh[v-w]*Tanh[w] + Cosh[v-w]*) + + +Int[u_.*Cosh[v_]*Sech[w_]^n_.,x_Symbol] := + Sinh[v-w]*Int[u*Tanh[w]*Sech[w]^(n-1),x] + Cosh[v-w]*Int[u*Sech[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[v]*Csch[w] == Cosh[v-w]*Coth[w] + Sinh[v-w]*) + + +Int[u_.*Cosh[v_]*Csch[w_]^n_.,x_Symbol] := + Cosh[v-w]*Int[u*Coth[w]*Csch[w]^(n-1),x] + Sinh[v-w]*Int[u*Csch[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Tangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*(c Tanh[a+b x])^n Powers of tangents of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.243.17, CRC 556, A&S 4.5.79*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule*) + + +(* ::Item:: *) +(*Basis: Tanh[z] == Sinh[z]/Cosh[z]*) + + +Int[Tanh[a_.+b_.*x_],x_Symbol] := + Log[Cosh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.423.22, CRC 569*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Tanh[z]^2 == 1-Sech[z]^2*) + + +Int[Tanh[a_.+b_.*x_]^2,x_Symbol] := + x - Tanh[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.3, CRC 570, A&S 4.5.87*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +(* ::Item:: *) +(*Basis: Tanh[z]^n == Tanh[z]^(n-1)/Cosh[z]*Sinh[z]*) + + +Int[(c_.*Tanh[a_.+b_.*x_])^n_,x_Symbol] := + -c*(c*Tanh[a+b*x])^(n-1)/(b*(n-1)) + + Dist[c^2,Int[(c*Tanh[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.4, CRC 574'*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Tanh[a_.+b_.*x_])^n_,x_Symbol] := + (c*Tanh[a+b*x])^(n+1)/(b*c*(n+1)) + + Dist[1/c^2,Int[(c*Tanh[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Tanh[c+d x])^n Powers of binomials of tangents where a^2-b^2 is zero*) + + +Int[Sqrt[a_+b_.*Tanh[c_.+d_.*x_]],x_Symbol] := + (Sqrt[2]*b*ArcTanh[Sqrt[a+b*Tanh[c+d*x]]/(Sqrt[2]*Rt[a,2])])/(d*Rt[a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] && PosQ[a] + + +Int[Sqrt[a_+b_.*Tanh[c_.+d_.*x_]],x_Symbol] := + -(Sqrt[2]*b*ArcTan[Sqrt[a+b*Tanh[c+d*x]]/(Sqrt[2]*Rt[-a,2])])/(d*Rt[-a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] && NegQ[a] + + +Int[(a_+b_.*Tanh[c_.+d_.*x_])^n_,x_Symbol] := + -a^2*(a+b*Tanh[c+d*x])^(n-1)/(b*d*(n-1)) + + Dist[2*a,Int[(a+b*Tanh[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && ZeroQ[a^2-b^2] + + +Int[1/(a_+b_.*Tanh[c_.+d_.*x_]),x_Symbol] := + x/(2*a) - a/(2*b*d*(a+b*Tanh[c+d*x])) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +Int[(a_+b_.*Tanh[c_.+d_.*x_])^n_,x_Symbol] := + a*(a+b*Tanh[c+d*x])^n/(2*b*d*n) + + Dist[1/(2*a),Int[(a+b*Tanh[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<0 && ZeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*1 / (a+b Tanh[c+d x]^2) Reciprocals of binomials of tangents*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*Tanh[z]) == Cosh[z]/(a*Cosh[z]+b*Sinh[z])*) + + +Int[1/(a_+b_.*Tanh[c_.+d_.*x_]),x_Symbol] := + a*x/(a^2-b^2) - b*Log[a*Cosh[c+d*x]+b*Sinh[c+d*x]]/(d*(a^2-b^2)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +Int[1/(a_+b_.*Tanh[c_.+d_.*x_]^2),x_Symbol] := + x/(a+b) + Sqrt[b]*ArcTan[(Sqrt[b]*Tanh[c+d*x])/Sqrt[a]]/(Sqrt[a]*d*(a+b)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a+b] + + +(* ::Subsubsection::Closed:: *) +(*x^m Tanh[a+b x^n]^p Products of monomials and powers of tangents of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Tanh[z] == 1 - 2/(1+E^(2*z))*) + + +Int[x_^m_.*Tanh[a_.+b_.*x_^n_.],x_Symbol] := + x^(m+1)/(m+1) - + Dist[2,Int[x^m/(1+E^(2*a+2*b*x^n)),x]] /; +FreeQ[{a,b,m,n},x] && NonzeroQ[m-n+1] && IntegerQ[m] && m>0 + + +(* Note: Rule not in literature ??? *) +Int[x_^m_.*Tanh[a_.+b_.*x_^n_.]^p_,x_Symbol] := + -x^(m-n+1)*Tanh[a+b*x^n]^(p-1)/(b*n*(p-1)) + + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Tanh[a+b*x^n]^(p-1),x]] + + Int[x^m*Tanh[a+b*x^n]^(p-2),x] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>1 && NonzeroQ[m-n+1] && 01 *) + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Cotangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*(c Coth[a+b x])^n Powers of cotangents of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.423.33, CRC 557, A&S 4.5.82*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule*) + + +(* ::Item:: *) +(*Basis: Coth[z] == Cosh[z]/Sinh[z]*) + + +Int[Coth[a_.+b_.*x_],x_Symbol] := + Log[Sinh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.423.38, CRC 573*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Coth[z]^2 == 1+Csch[z]^2*) + + +Int[Coth[a_.+b_.*x_]^2,x_Symbol] := + x - Coth[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.4, CRC 574, A&S 4.5.88*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +(* ::Item:: *) +(*Basis: Coth[z]^n == Coth[z]^(n-1)/Sinh[z]*Cosh[z]*) + + +Int[(c_.*Coth[a_.+b_.*x_])^n_,x_Symbol] := + -c*(c*Coth[a+b*x])^(n-1)/(b*(n-1)) + + Dist[c^2,Int[(c*Coth[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.3, CRC 570'*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Coth[a_.+b_.*x_])^n_,x_Symbol] := + (c*Coth[a+b*x])^(n+1)/(b*c*(n+1)) + + Dist[1/c^2,Int[(c*Coth[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Coth[c+d x])^n Powers of binomials of cotangents where a^2-b^2 is zero*) + + +Int[Sqrt[a_+b_.*Coth[c_.+d_.*x_]],x_Symbol] := + (Sqrt[2]*b*ArcCoth[Sqrt[a+b*Coth[c+d*x]]/(Sqrt[2]*Rt[a,2])])/(d*Rt[a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] && PosQ[a] + + +Int[Sqrt[a_+b_.*Coth[c_.+d_.*x_]],x_Symbol] := + (Sqrt[2]*b*ArcCot[Sqrt[a+b*Coth[c+d*x]]/(Sqrt[2]*Rt[-a,2])])/(d*Rt[-a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] && NegQ[a] + + +Int[(a_+b_.*Coth[c_.+d_.*x_])^n_,x_Symbol] := + -a^2*(a+b*Coth[c+d*x])^(n-1)/(b*d*(n-1)) + + Dist[2*a,Int[(a+b*Coth[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && ZeroQ[a^2-b^2] + + +Int[1/(a_+b_.*Coth[c_.+d_.*x_]),x_Symbol] := + x/(2*a) - a/(2*b*d*(a+b*Coth[c+d*x])) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +Int[(a_+b_.*Coth[c_.+d_.*x_])^n_,x_Symbol] := + a*(a+b*Coth[c+d*x])^n/(2*b*d*n) + + Dist[1/(2*a),Int[(a+b*Coth[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<0 && ZeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*1 / (a+b Coth[c+d x]^n) Reciprocals of binomials of cotangents*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*Coth[z]) == Sinh[z]/(a*Sinh[z]+b*Cosh[z])*) + + +Int[1/(a_+b_.*Coth[c_.+d_.*x_]),x_Symbol] := + a*x/(a^2-b^2) - b*Log[b*Cosh[c+d*x]+a*Sinh[c+d*x]]/(d*(a^2-b^2)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +Int[1/(a_+b_.*Coth[c_.+d_.*x_]^2),x_Symbol] := + x/(a+b) + Sqrt[b]*ArcTan[(Sqrt[b]*Coth[c+d*x])/Sqrt[a]]/(Sqrt[a]*d*(a+b)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a+b] + + +(* ::Subsubsection::Closed:: *) +(*x^m Coth[a+b x^n]^p Products of monomials and powers of cotangents of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Coth[z] == 1 - 2/(1-E^(2*z))*) + + +Int[x_^m_.*Coth[a_.+b_.*x_^n_.],x_Symbol] := + x^(m+1)/(m+1) - + Dist[2,Int[x^m/(1-E^(2*a+2*b*x^n)),x]] /; +FreeQ[{a,b,m,n},x] && NonzeroQ[m-n+1] && IntegerQ[m] && m>0 + + +(* Note: Rule not in literature ??? *) +Int[x_^m_.*Coth[a_.+b_.*x_^n_.]^p_,x_Symbol] := + -x^(m-n+1)*Coth[a+b*x^n]^(p-1)/(b*n*(p-1)) + + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Coth[a+b*x^n]^(p-1),x]] + + Int[x^m*Coth[a+b*x^n]^(p-2),x] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>1 && NonzeroQ[m-n+1] && 01 *) + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Secant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Sech[a+b x]^n Powers of secants of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.423.9, CRC 558, A&S 4.5.81*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Sech[z] == 1/(1+Sinh[z]^2)*Sinh'[z]*) + + +Int[Sech[a_.+b_.*x_],x_Symbol] := +(* -ArcCot[Sinh[a+b*x]]/b *) + ArcTan[Sinh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* Note: This entirely redundant is required due to idem potent problem in Mathematica 6 & 7. *) +Int[1/Sqrt[Sech[a_.+b_.*x_]],x_Symbol] := + Sqrt[Cosh[a+b*x]]*Sqrt[Sech[a+b*x]]*Int[Sqrt[Cosh[a+b*x]],x] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Sech[x])^n*Cosh[x]^n,x] == 0*) + + +Int[(c_.*Sech[a_.+b_.*x_])^n_,x_Symbol] := + (c*Sech[a+b*x])^n*Cosh[a+b*x]^n*Int[1/Cosh[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -11 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.6, CRC 568b*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Sech[a_.+b_.*x_])^n_,x_Symbol] := + c*Sinh[a+b*x]*(c*Sech[a+b*x])^(n-1)/(b*(n-1)) + + Dist[(n-2)*c^2/(n-1),Int[(c*Sech[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[EvenQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.1, CRC 567a*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Sech[a_.+b_.*x_])^n_,x_Symbol] := + -Sinh[a+b*x]*(c*Sech[a+b*x])^(n+1)/(b*c*n) + + Dist[(n+1)/(c^2*n),Int[(c*Sech[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m Sech[a+b x]^n Products of monomials and powers of secants of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sech[a_.+b_.*x_],x_Symbol] := + 2*x^m*ArcTan[E^(a+b*x)]/b - + Dist[2*m/b,Int[x^(m-1)*ArcTan[E^(a+b*x)],x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: CRC 430h*) + + +Int[x_^m_.*Sech[a_.+b_.*x_]^2,x_Symbol] := + x^m*Tanh[a+b*x]/b - + Dist[m/b,Int[x^(m-1)*Tanh[a+b*x],x]] /; +FreeQ[{a,b},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: G&R 2.643.2h, CRC 431h*) + + +Int[x_*Sech[a_.+b_.*x_]^n_,x_Symbol] := + x*Tanh[a+b*x]*Sech[a+b*x]^(n-2)/(b*(n-1)) + + Sech[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) + + Dist[(n-2)/(n-1),Int[x*Sech[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 && n!=2 + + +(* ::Item:: *) +(*Reference: G&R 2.643.2h*) + + +Int[x_^m_*Sech[a_.+b_.*x_]^n_,x_Symbol] := + x^m*Tanh[a+b*x]*Sech[a+b*x]^(n-2)/(b*(n-1)) + + m*x^(m-1)*Sech[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) + + Dist[(n-2)/(n-1),Int[x^m*Sech[a+b*x]^(n-2),x]] - + Dist[m*(m-1)/(b^2*(n-1)*(n-2)),Int[x^(m-2)*Sech[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n>1 && n!=2 && m>1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.3h*) + + +Int[x_*Sech[a_.+b_.*x_]^n_,x_Symbol] := + -Sech[a+b*x]^n/(b^2*n^2) - + x*Sinh[a+b*x]*Sech[a+b*x]^(n+1)/(b*n) + + Dist[(n+1)/n,Int[x*Sech[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.3h*) + + +Int[x_^m_*Sech[a_.+b_.*x_]^n_,x_Symbol] := + -m*x^(m-1)*Sech[a+b*x]^n/(b^2*n^2) - + x^m*Sinh[a+b*x]*Sech[a+b*x]^(n+1)/(b*n) + + Dist[(n+1)/n,Int[x^m*Sech[a+b*x]^(n+2),x]] + + Dist[m*(m-1)/(b^2*n^2),Int[x^(m-2)*Sech[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n<-1 && m>1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Sech[c+d x])^n Powers of constant plus secants of linears where a^2-b^2 is zero*) + + +Int[Sqrt[a_+b_.*Sech[c_.+d_.*x_]],x_Symbol] := + 2*a*ArcTan[Sqrt[-1+a/b*Sech[c+d*x]]]*Tanh[c+d*x]/ + (d*Sqrt[-1+a/b*Sech[c+d*x]]*Sqrt[a+b*Sech[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* Note: There should be a simpler antiderivative! *) +Int[1/Sqrt[a_+b_.*Sech[c_.+d_.*x_]],x_Symbol] := + -(Sqrt[2]*ArcTan[(Sqrt[2]*Sqrt[a])/Sqrt[-a+b*Sech[x]]]+2*ArcTan[Sqrt[-a+b*Sech[x]]/Sqrt[a]])* + Sqrt[-a+b*Sech[x]]*Sqrt[a+b*Sech[x]]*Coth[x]/a^(3/2) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*(a+b Sech[c+d x]^n)^m Powers of constant plus powers of secants of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Sech[z]^n == (b+a*Cosh[z]^n)/Cosh[z]^n*) + + +Int[(a_+b_.*Sech[v_]^n_.)^m_,x_Symbol] := + Int[(b+a*Cosh[v]^n)^m/Cosh[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m<0 && n>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Sech[z]^n == (b+a*Cosh[z]^n)/Cosh[z]^n*) + + +Int[Cosh[v_]^p_.*(a_+b_.*Sech[v_]^n_.)^m_,x_Symbol] := + Int[Cosh[v]^(p-m*n)*(b+a*Cosh[v]^n)^m,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n,p}] && m<0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*Sech[a+b x]^n Csch[a+b x]^m Products of powers of secants and cosecants*) + + +(* ::Item:: *) +(*Reference: G&R 2.423.49*) + + +Int[Csch[a_.+b_.*x_]*Sech[a_.+b_.*x_],x_Symbol] := + Log[Tanh[a+b*x]]/b /; +FreeQ[{a,b},x] && PosQ[b] + + +Int[Csch[a_.+b_.*x_]^m_*Sech[a_.+b_.*x_]^n_,x_Symbol] := + Csch[a+b*x]^(m-1)*Sech[a+b*x]^(n-1)/(b*(n-1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-2] && NonzeroQ[n-1] && PosQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m and n are integers and m + n is even, Csch[z]^m*Sech[z]^n == (1-Tanh[z]^2)^((m+n)/2-1)/Tanh[z]^m*Tanh'[z]*) + + +Int[Csch[a_.+b_.*x_]^m_.*Sech[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(1-x^2)^((m+n)/2-1)/x^m,x],x],x,Tanh[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && EvenQ[m+n] && 01 + + +(* ::Item:: *) +(*Reference: G&R 2.411.6, CRC 568b, A&S 4.5.86b*) + + +Int[Csch[a_.+b_.*x_]^m_.*Sech[a_.+b_.*x_]^n_,x_Symbol] := + Csch[a+b*x]^(m-1)*Sech[a+b*x]^(n-1)/(b*(n-1)) + + Dist[(m+n-2)/(n-1),Int[Csch[a+b*x]^m*Sech[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[EvenQ[m+n]] && Not[EvenQ[n] && OddQ[m] && m>1] + + +(* ::Item:: *) +(*Reference: G&R 2.411.1, CRC 567a, A&S 4.5.85a*) + + +Int[Csch[a_.+b_.*x_]^m_.*Sech[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^(m-1)*Sech[a+b*x]^(n+1)/(b*(m+n)) + + Dist[(n+1)/(m+n),Int[Csch[a+b*x]^m*Sech[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n] + + +(* ::Subsubsection::Closed:: *) +(*Sech[a+b x]^m Tanh[a+b x]^n Products of powers of secants and tangents*) +(**) + + +(* ::Item:: *) +(*Derivation: Power rule for integration*) + + +Int[Sech[a_.+b_.*x_]^m_.*Tanh[a_.+b_.*x_]^n_.,x_Symbol] := + -Sech[a+b*x]^m/(b*m) /; +FreeQ[{a,b,m},x] && n===1 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m is even, Sech[z]^m == (1-Tanh[z]^2)^((m-2)/2)*Tanh'[z]*) + + +Int[Sech[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[x^n*(1-x^2)^((m-2)/2),x],x],x,Tanh[a+b*x]]] /; +FreeQ[{a,b,n},x] && EvenQ[m] && m>2 && Not[OddQ[n] && 01 && n<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.2, CRC 567b*) + + +Int[Sech[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + -Sech[a+b*x]^m*Tanh[a+b*x]^(n-1)/(b*m) + + Dist[(n-1)/m,Int[Sech[a+b*x]^(m+2)*Tanh[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.1, CRC 567a*) + + +Int[Sech[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + -Sech[a+b*x]^m*Tanh[a+b*x]^(n+1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+1] + + +Int[Sech[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + -Sech[a+b*x]^m*Tanh[a+b*x]^(n+1)/(b*m) + + Dist[(m+n+1)/m,Int[Sech[a+b*x]^(m+2)*Tanh[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.6, CRC 568b*) + + +Int[Sech[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + Sech[a+b*x]^(m-2)*Tanh[a+b*x]^(n+1)/(b*(m+n-1)) + + Dist[(m-2)/(m+n-1),Int[Sech[a+b*x]^(m-2)*Tanh[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.3*) + + +Int[Sech[a_.+b_.*x_]^m_.*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + -Sech[a+b*x]^m*Tanh[a+b*x]^(n-1)/(b*(m+n-1)) + + Dist[(n-1)/(m+n-1),Int[Sech[a+b*x]^m*Tanh[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.4*) + + +Int[Sech[a_.+b_.*x_]^m_*Tanh[a_.+b_.*x_]^n_,x_Symbol] := + Sech[a+b*x]^m*Tanh[a+b*x]^(n+1)/(b*(n+1)) + + Dist[(m+n+1)/(n+1),Int[Sech[a+b*x]^m*Tanh[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && Not[EvenQ[m]] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sech[a+b x^n]^p Sinh[a+b x^n] Products of monomials, sines and powers of secants of binomials*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sech[a_.+b_.*x_^n_.]^p_*Sinh[a_.+b_.*x_^n_.],x_Symbol] := + -x^(m-n+1)*Sech[a+b*x^n]^(p-1)/(b*n*(p-1)) + + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Sech[a+b*x^n]^(p-1),x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && NonzeroQ[p-1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sech[a+b x^n]^p Tanh[a+b x^n] Products of monomials, tangents and powers of secants of binomials*) +(**) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sech[a_.+b_.*x_^n_.]^p_.*Tanh[a_.+b_.*x_^n_.]^q_.,x_Symbol] := + -x^(m-n+1)*Sech[a+b*x^n]^p/(b*n*p) + + Dist[(m-n+1)/(b*n*p),Int[x^(m-n)*Sech[a+b*x^n]^p,x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && q===1 (* Required so InputForm is matchable *) + + +(* ::Subsubsection::Closed:: *) +(*Sech[a+b Log[c x^n]]^p Powers of secants of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sech[b*Log[c*x^n]] == 2 / ((c*x^n)^b + 1/(c*x^n)^b)*) + + +Int[Sech[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[(2/((c*x^n)^b+1/(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,n,p}] + + +Int[Sech[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Tanh[a+b*Log[c*x^n]]*Sech[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) + + x*Sech[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) - + Dist[(1-b^2*n^2*(p-2)^2)/(b^2*n^2*(p-1)*(p-2)),Int[Sech[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[Sech[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Sech[a+b*Log[c*x^n]]^p/(1-b^2*n^2*p^2) + + b*n*p*x*Sech[a+b*Log[c*x^n]]^(p+1)*Sinh[a+b*Log[c*x^n]]/(1-b^2*n^2*p^2) - + Dist[b^2*n^2*p*(p+1)/(1-b^2*n^2*p^2),Int[Sech[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && NonzeroQ[1-b^2*n^2*p^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sech[a+b Log[c x^n]]^p Products of monomials and powers of secants of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sech[b*Log[c*x^n]] == 2 / ((c*x^n)^b + 1/(c*x^n)^b)*) + + +Int[x_^m_.Sech[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[x^m*(2/((c*x^n)^b+1/(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,m,n,p}] + + +Int[Sech[a_.+b_.*Log[c_.*x_^n_.]]^2/x_,x_Symbol] := + Tanh[a+b*Log[c*x^n]]/(b*n) /; +FreeQ[{a,b,c,n},x] + + +Int[Sech[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + Tanh[a+b*Log[c*x^n]]*Sech[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) + + Dist[(p-2)/(p-1),Int[Sech[a+b*Log[c*x^n]]^(p-2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 + + +Int[Sech[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + -Sech[a+b*Log[c*x^n]]^(p+1)*Sinh[a+b*Log[c*x^n]]/(b*n*p) + + Dist[(p+1)/p,Int[Sech[a+b*Log[c*x^n]]^(p+2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 + + +Int[x_^m_.*Sech[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x^(m+1)*Tanh[a+b*Log[c*x^n]]*Sech[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) + + (m+1)*x^(m+1)*Sech[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) - + Dist[(b^2*n^2*(p-2)^2-(m+1)^2)/(b^2*n^2*(p-1)*(p-2)),Int[x^m*Sech[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[x_^m_.*Sech[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -(m+1)*x^(m+1)*Sech[a+b*Log[c*x^n]]^p/(b^2*n^2*p^2-(m+1)^2) - + b*n*p*x^(m+1)*Sech[a+b*Log[c*x^n]]^(p+1)*Sinh[a+b*Log[c*x^n]]/(b^2*n^2*p^2-(m+1)^2) + + Dist[b^2*n^2*p*(p+1)/(b^2*n^2*p^2-(m+1)^2),Int[x^m*Sech[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && NonzeroQ[b^2*n^2*p^2-(m+1)^2] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Cosecant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Csch[a+b x]^n Powers of cosecants of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.423.1', CRC 559', A&S 4.5.80'*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Csch[z] == -1/(1-Cosh[z]^2)*Cosh'[z]*) + + +Int[Csch[a_.+b_.*x_],x_Symbol] := +(* -ArcTanh[Cosh[a+b*x]]/b *) + -ArcCoth[Cosh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* Note: This entirely redundant is required due to idem potent problem in Mathematica 6 & 7. *) +Int[1/Sqrt[Csch[a_.+b_.*x_]],x_Symbol] := + Sqrt[Csch[a+b*x]]*Sqrt[Sinh[a+b*x]]*Int[Sqrt[Sinh[a+b*x]],x] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Csch[x])^n*Sinh[x]^n,x] == 0*) + + +Int[(c_.*Csch[a_.+b_.*x_])^n_,x_Symbol] := + (c*Csch[a+b*x])^n*Sinh[a+b*x]^n*Int[1/Sinh[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -11 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.5, CRC 568a*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Csch[a_.+b_.*x_])^n_,x_Symbol] := + -c*Cosh[a+b*x]*(c*Csch[a+b*x])^(n-1)/(b*(n-1)) - + Dist[(n-2)*c^2/(n-1),Int[(c*Csch[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[EvenQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.411.2, CRC 567b*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Csch[a_.+b_.*x_])^n_,x_Symbol] := + -Cosh[a+b*x]*(c*Csch[a+b*x])^(n+1)/(b*c*n) - + Dist[(n+1)/(c^2*n),Int[(c*Csch[a+b*x])^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m Csch[a+b x]^n Products of monomials and powers of cosecants of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Csch[a_.+b_.*x_],x_Symbol] := + -2*x^m*ArcTanh[E^(a+b x)]/b + + Dist[2*m/b,Int[x^(m-1)*ArcTanh[E^(a+b x)],x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: CRC 428h*) + + +Int[x_^m_.*Csch[a_.+b_.*x_]^2,x_Symbol] := + -x^m*Coth[a+b*x]/b + + Dist[m/b,Int[x^(m-1)*Coth[a+b*x],x]] /; +FreeQ[{a,b},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: G&R 2.643.1h, CRC 429h*) + + +Int[x_*Csch[a_.+b_.*x_]^n_,x_Symbol] := + -x*Coth[a+b*x]*Csch[a+b*x]^(n-2)/(b*(n-1)) - + Csch[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) - + Dist[(n-2)/(n-1),Int[x*Csch[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 && n!=2 + + +(* ::Item:: *) +(*Reference: G&R 2.643.1h*) + + +Int[x_^m_*Csch[a_.+b_.*x_]^n_,x_Symbol] := + -x^m*Coth[a+b*x]*Csch[a+b*x]^(n-2)/(b*(n-1)) - + m*x^(m-1)*Csch[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) - + Dist[(n-2)/(n-1),Int[x^m*Csch[a+b*x]^(n-2),x]] + + Dist[m*(m-1)/(b^2*(n-1)*(n-2)),Int[x^(m-2)*Csch[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n>1 && n!=2 && m>1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.2h*) + + +Int[x_*Csch[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^n/(b^2*n^2) - + x*Cosh[a+b*x]*Csch[a+b*x]^(n+1)/(b*n) - + Dist[(n+1)/n,Int[x*Csch[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.2h*) + + +Int[x_^m_*Csch[a_.+b_.*x_]^n_,x_Symbol] := + -m*x^(m-1)*Csch[a+b*x]^n/(b^2*n^2) - + x^m*Cosh[a+b*x]*Csch[a+b*x]^(n+1)/(b*n) - + Dist[(n+1)/n,Int[x^m*Csch[a+b*x]^(n+2),x]] + + Dist[m*(m-1)/(b^2*n^2),Int[x^(m-2)*Csch[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n<-1 && m>1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Csch[c+d x])^n Powers of constant plus cosecants of linears where a^2+b^2 is zero*) + + +Int[Sqrt[a_+b_.*Csch[c_.+d_.*x_]],x_Symbol] := + 2*a*ArcTan[Sqrt[-1-a/b*Csch[c+d*x]]]*Coth[c+d*x]/ + (d*Sqrt[-1-a/b*Csch[c+d*x]]*Sqrt[a+b*Csch[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] + + +(* Note: There should be a simpler antiderivative! *) +Int[1/Sqrt[a_+b_.*Csch[c_.+d_.*x_]],x_Symbol] := + -(Sqrt[2]*ArcTan[(Sqrt[2]*Sqrt[a])/Sqrt[-a+b*Csch[x]]]+2*ArcTan[Sqrt[-a+b*Csch[x]]/Sqrt[a]])* + Sqrt[-a+b*Csch[x]]*Sqrt[a+b*Csch[x]]*Tanh[x]/a^(3/2) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] + + +(* ::Subsubsection::Closed:: *) +(*(a+b Csch[c+d x]^n)^m Powers of constant plus powers of cosecants of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Csch[z]^n == (b+a*Sinh[z]^n)/Sinh[z]^n*) + + +Int[(a_+b_.*Csch[v_]^n_.)^m_,x_Symbol] := + Int[(b+a*Sinh[v]^n)^m/Sinh[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m<0 && n>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Csch[z]^n == (b+a*Sinh[z]^n)/Sinh[z]^n*) + + +Int[Sinh[v_]^p_.*(a_+b_.*Csch[v_]^n_.)^m_,x_Symbol] := + Int[Sinh[v]^(p-m*n)*(b+a*Sinh[v]^n)^m,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n,p}] && m<0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*Csch[a+b x]^m Sech[a+b x]^n Products of powers of cosecants and secants*) + + +(* ::Item:: *) +(*Reference: G&R 2.423.49'*) + + +Int[Csch[a_.+b_.*x_]*Sech[a_.+b_.*x_],x_Symbol] := + -Log[Coth[a+b*x]]/b /; +FreeQ[{a,b},x] && NegQ[b] + + +Int[Csch[a_.+b_.*x_]^m_*Sech[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^(m-1)*Sech[a+b*x]^(n-1)/(b*(m-1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-2] && NonzeroQ[m-1] && PosQ[m] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m and n are integers and m+n is even, Csch[z]^m*Sech[z]^n == -(-1+Coth[z]^2)^((m+n)/2-1)/Coth[z]^n*Coth'[z]*) + + +Int[Csch[a_.+b_.*x_]^m_*Sech[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[-1/b,Subst[Int[Regularize[(-1+x^2)^((m+n)/2-1)/x^n,x],x],x,Coth[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && EvenQ[m+n] && 01 && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.411.5, CRC 568a, A&S 4.5.86a*) + + +Int[Csch[a_.+b_.*x_]^m_*Sech[a_.+b_.*x_]^n_.,x_Symbol] := + -Csch[a+b*x]^(m-1)*Sech[a+b*x]^(n-1)/(b*(m-1)) - + Dist[(m+n-2)/(m-1),Int[Csch[a+b*x]^(m-2)*Sech[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[EvenQ[m+n]] && Not[EvenQ[m] && OddQ[n] && n>1] + + +(* ::Item:: *) +(*Reference: G&R 2.411.2, CRC 567b, A&S 4.5.85b*) + + +Int[Csch[a_.+b_.*x_]^m_*Sech[a_.+b_.*x_]^n_.,x_Symbol] := + -Csch[a+b*x]^(m+1)*Sech[a+b*x]^(n-1)/(b*(m+n)) - + Dist[(m+1)/(m+n),Int[Csch[a+b*x]^(m+2)*Sech[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n] + + +(* ::Subsubsection::Closed:: *) +(*Csch[a+b x]^m Coth[a+b x]^n Products of powers of cosecants and cotangents*) +(**) + + +(* ::Item:: *) +(*Derivation: Power rule for integration*) + + +Int[Csch[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + -Csch[a+b*x]^m/(b*m) /; +FreeQ[{a,b,m},x] && n===1 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m is even, Csch[z]^m == -(-1+Coth[z]^2)^((m-2)/2)*Coth'[z]*) + + +Int[Csch[a_.+b_.*x_]^m_*Coth[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[-1/b,Subst[Int[Regularize[x^n*(-1+x^2)^((m-2)/2),x],x],x,Coth[a+b*x]]] /; +FreeQ[{a,b,n},x] && EvenQ[m] && m>2 && Not[OddQ[n] && 01 && n<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.1, CRC 567a*) + + +Int[Csch[a_.+b_.*x_]^m_*Coth[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^m*Coth[a+b*x]^(n-1)/(b*m) - + Dist[(n-1)/m,Int[Csch[a+b*x]^(m+2)*Coth[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.2, CRC 567b*) + + +Int[Csch[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^m*Coth[a+b*x]^(n+1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+1] + + +Int[Csch[a_.+b_.*x_]^m_*Coth[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^m*Coth[a+b*x]^(n+1)/(b*m) - + Dist[(m+n+1)/m,Int[Csch[a+b*x]^(m+2)*Coth[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.5, CRC 568a*) + + +Int[Csch[a_.+b_.*x_]^m_*Coth[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^(m-2)*Coth[a+b*x]^(n+1)/(b*(m+n-1)) - + Dist[(m-2)/(m+n-1),Int[Csch[a+b*x]^(m-2)*Coth[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.4*) + + +Int[Csch[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_,x_Symbol] := + -Csch[a+b*x]^m*Coth[a+b*x]^(n-1)/(b*(m+n-1)) + + Dist[(n-1)/(m+n-1),Int[Csch[a+b*x]^m*Coth[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.411.3*) + + +Int[Csch[a_.+b_.*x_]^m_.*Coth[a_.+b_.*x_]^n_,x_Symbol] := + Csch[a+b*x]^m*Coth[a+b*x]^(n+1)/(b*(n+1)) + + Dist[(m+n+1)/(n+1),Int[Csch[a+b*x]^m*Coth[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && Not[EvenQ[m]] + + +(* ::Subsubsection::Closed:: *) +(*x^m Csch[a+b x^n]^p Cosh[a+b x^n] Products of monomials, cosines and powers of cosecants of binomials*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Csch[a_.+b_.*x_^n_.]^p_*Cosh[a_.+b_.*x_^n_.],x_Symbol] := + -x^(m-n+1)*Csch[a+b*x^n]^(p-1)/(b*n*(p-1)) + + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Csch[a+b*x^n]^(p-1),x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && NonzeroQ[p-1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Csch[a+b x^n]^p Coth[a+b x^n] Products of monomials, cotangents and powers of cosecants of binomials*) +(**) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Csch[a_.+b_.*x_^n_.]^p_.*Coth[a_.+b_.*x_^n_.]^q_.,x_Symbol] := + -x^(m-n+1)*Csch[a+b*x^n]^p/(b*n*p) + + Dist[(m-n+1)/(b*n*p),Int[x^(m-n)*Csch[a+b*x^n]^p,x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && q===1 (* Required so InputForm is matchable *) + + +(* ::Subsubsection::Closed:: *) +(*Csch[a+b Log[c x^n]]^p Powers of cosecants of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Csch[b*Log[c*x^n]] == 2 / ((c*x^n)^b - 1/(c*x^n)^b)*) + + +Int[Csch[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[(2/((c*x^n)^b - 1/(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,n,p}] + + +Int[Csch[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x*Coth[a+b*Log[c*x^n]]*Csch[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) - + x*Csch[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) + + Dist[(1-b^2*n^2*(p-2)^2)/(b^2*n^2*(p-1)*(p-2)),Int[Csch[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[Csch[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Csch[a+b*Log[c*x^n]]^p/(1-b^2*n^2*p^2) + + b*n*p*x*Cosh[a+b*Log[c*x^n]]*Csch[a+b*Log[c*x^n]]^(p+1)/(1-b^2*n^2*p^2) + + Dist[b^2*n^2*p*(p+1)/(1-b^2*n^2*p^2),Int[Csch[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && NonzeroQ[1-b^2*n^2*p^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m Csch[a+b Log[c x^n]]^p Products of monomials and powers of cosecants of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Csch[b*Log[c*x^n]] == 2 / ((c*x^n)^b - 1/(c*x^n)^b)*) + + +Int[x_^m_.*Csch[b_.*Log[c_.*x_^n_.]]^p_.,x_Symbol] := + Int[x^m*(2/((c*x^n)^b - 1/(c*x^n)^b))^p,x] /; +FreeQ[c,x] && RationalQ[{b,m,n,p}] + + +Int[Csch[a_.+b_.*Log[c_.*x_^n_.]]^2/x_,x_Symbol] := + -Coth[a+b*Log[c*x^n]]/(b*n) /; +FreeQ[{a,b,c,n},x] + + +Int[Csch[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + -Coth[a+b*Log[c*x^n]]*Csch[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) - + Dist[(p-2)/(p-1),Int[Csch[a+b*Log[c*x^n]]^(p-2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 + + +Int[Csch[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + -Cosh[a+b*Log[c*x^n]]*Csch[a+b*Log[c*x^n]]^(p+1)/(b*n*p) - + Dist[(p+1)/p,Int[Csch[a+b*Log[c*x^n]]^(p+2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 + + +Int[x_^m_.*Csch[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x^(m+1)*Coth[a+b*Log[c*x^n]]*Csch[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) - + (m+1)*x^(m+1)*Csch[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) - + Dist[(b^2*n^2*(p-2)^2-(m+1)^2)/(b^2*n^2*(p-1)*(p-2)),Int[x^m*Csch[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[x_^m_.*Csch[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -(m+1)*x^(m+1)*Csch[a+b*Log[c*x^n]]^p/(b^2*n^2*p^2-(m+1)^2) - + b*n*p*x^(m+1)*Cosh[a+b*Log[c*x^n]]*Csch[a+b*Log[c*x^n]]^(p+1)/(b^2*n^2*p^2-(m+1)^2) - + Dist[b^2*n^2*p*(p+1)/(b^2*n^2*p^2-(m+1)^2),Int[x^m*Csch[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && NonzeroQ[b^2*n^2*p^2-(m+1)^2] + + +(* ::Subsection::Closed:: *) +(*Powers of sums of Hyperbolic Trig Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*(a Cosh[c+d x] + b Sinh[c+d x])^n Powers of sums of sines and cosines*) + + +Int[(a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + a*(a*Cosh[c+d*x]+b*Sinh[c+d*x])^n/(b*d*n) /; +FreeQ[{a,b,c,d,n},x] && ZeroQ[a^2-b^2] + + +Int[1/(a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_])^2,x_Symbol] := + Sinh[c+d*x]/(a*d*(a*Cosh[c+d*x]+b*Sinh[c+d*x])) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Basis: a*Cosh[z]+b*Sinh[z] == -I*Sqrt[a^2-b^2]*Sinh[z+I*ArcTan[I*b,a]]*) + + +Int[Sqrt[a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + 2*I*EllipticE[(Pi/2-I*(c+d*x+I*ArcTan[I*b,a]))/2,2]* + Sqrt[a*Cosh[c+d*x]+b*Sinh[c+d*x]]/ + (d*Sqrt[-(a*Cosh[c+d*x]+b*Sinh[c+d*x])/Sqrt[a^2-b^2]]) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Basis: a*Cosh[z]+b*Sinh[z] == -I*Sqrt[a^2-b^2]*Sinh[z+I*ArcTan[I*b,a]]*) + + +Int[1/Sqrt[a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_]],x_Symbol] := + 2*I*EllipticF[(Pi/2-I*(c+d*x+I*ArcTan[I*b,a]))/2,2]* + Sqrt[-(a*Cosh[c+d*x]+b*Sinh[c+d*x])/Sqrt[a^2-b^2]]/ + (d*Sqrt[a*Cosh[c+d*x]+b*Sinh[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.449'*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, (a*Cosh[z]+b*Sinh[z])^n == (a^2-b^2+u^2)^((n-1)/2)*D[u,z] where u = b*Cosh[z]+a*Sinh[z]*) + + +(* Note: For odd n<-1, might as well stay in the trig world using 2nd rule below ??? *) +Int[(a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + Dist[1/d,Subst[Int[Regularize[(a^2-b^2+x^2)^((n-1)/2),x],x],x,b*Cosh[c+d*x]+a*Sinh[c+d*x]]] /; +FreeQ[{a,b,c,d},x] && OddQ[n] && n>=-1 && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + (b*Cosh[c+d*x]+a*Sinh[c+d*x])*(a*Cosh[c+d*x]+b*Sinh[c+d*x])^(n-1)/(d*n) + + Dist[(n-1)*(a^2-b^2)/n,Int[(a*Cosh[c+d*x]+b*Sinh[c+d*x])^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n>1 && NonzeroQ[a^2-b^2] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + -(b*Cosh[c+d*x]+a*Sinh[c+d*x])*(a*Cosh[c+d*x]+b*Sinh[c+d*x])^(n+1)/(d*(n+1)*(a^2-b^2)) + + Dist[(n+2)/((n+1)*(a^2-b^2)),Int[(a*Cosh[c+d*x]+b*Sinh[c+d*x])^(n+2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*(a Csch[c+d x] + a Sinh[c+d x])^n where a-b is zero*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Csch[z]+Sinh[z] == Cosh[z]*Coth[z]*) + + +Int[(a_.*Csch[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_])^n_,x_Symbol] := + Int[(a*Cosh[c+d*x]*Coth[c+d*x])^n,x] /; +FreeQ[{a,b,c,d,n},x] && ZeroQ[a-b] + + +(* ::Subsubsection::Closed:: *) +(*(a Sech[c+d x] + a Cosh[c+d x])^n where a+b is zero*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sech[z]-Cosh[z] == -Sinh[z]*Tanh[z]*) + + +Int[(a_.*Sech[c_.+d_.*x_]+b_.*Cosh[c_.+d_.*x_])^n_,x_Symbol] := + Int[(-a*Sinh[c+d*x]*Tanh[c+d*x])^n,x] /; +FreeQ[{a,b,c,d,n},x] && ZeroQ[a+b] + + +(* ::Subsection::Closed:: *) +(*Rational functions of Hyperbolic Trig Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*u Hyper[c+d x]^n / (a Cosh[c+d x]+b Sinh[c+d x]) where a^2-b^2 is nonzero*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[z]^2/(a*Cosh[z]+b*Sinh[z]) == -b/(a^2-b^2)*Sinh[z] + a/(a^2-b^2)*Cosh[z] - a^2/(a^2-b^2)/(a*Cosh[z]+b*Sinh[z])*) + + +Int[u_.*Sinh[c_.+d_.*x_]^n_/(a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_]),x_Symbol] := + Dist[-b/(a^2-b^2),Int[u*Sinh[c+d*x]^(n-1),x]] + + Dist[a/(a^2-b^2),Int[u*Sinh[c+d*x]^(n-2)*Cosh[c+d*x],x]] - + Dist[a^2/(a^2-b^2),Int[u*Sinh[c+d*x]^(n-2)/(a*Cosh[c+d*x]+b*Sinh[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && IntegerQ[n] && n>1 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[z]^2/(a*Cosh[z]+b*Sinh[z]) == a/(a^2-b^2)*Cosh[z] - b/(a^2-b^2)*Sinh[z] - b^2/(a^2-b^2)/(a*Cosh[z]+b*Sinh[z])*) + + +Int[u_.*Cosh[c_.+d_.*x_]^n_/(a_.*Cosh[c_.+d_.*x_]+b_.*Sinh[c_.+d_.*x_]),x_Symbol] := + Dist[a/(a^2-b^2),Int[u*Cosh[c+d*x]^(n-1),x]] - + Dist[b/(a^2-b^2),Int[u*Cosh[c+d*x]^(n-2)*Sinh[c+d*x],x]] - + Dist[b^2/(a^2-b^2),Int[u*Cosh[c+d*x]^(n-2)/(a*Cosh[c+d*x]+b*Sinh[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && IntegerQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Cosh[d+e x]+c Sinh[d+e x])^n where a^2-b^2+c^2 is zero*) + + +(* ::Item:: *) +(*Reference: G&R 2.451.4d*) + + +Int[1/(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + -2/(e*(c-(a-b)*Tanh[(d+e*x)/2])) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a^2-b^2+c^2] + + +Int[Sqrt[a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]],x_Symbol] := + 2*(c*Cosh[d+e*x]+b*Sinh[d+e*x])/(e*Sqrt[a+b*Cosh[d+e*x]+c*Sinh[d+e*x]]) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a^2-b^2+c^2] + + +Int[(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_])^n_,x_Symbol] := + (c*Cosh[d+e*x]+b*Sinh[d+e*x])*(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n-1)/(e*n) + + Dist[a*(2*n-1)/n,Int[(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n-1),x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[n] && n>1 && ZeroQ[a^2-b^2+c^2] + + +Int[(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_])^n_,x_Symbol] := + -(c*Cosh[d+e*x]+b*Sinh[d+e*x])*(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^n/(a*e*(2*n+1)) + + Dist[(n+1)/(a*(2*n+1)),Int[(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[n] && n<-1 && ZeroQ[a^2-b^2+c^2] + + +(* ::Subsubsection::Closed:: *) +(*(a+b Cosh[d+e x]+c Sinh[d+e x])^n where a^2-b^2+c^2 is nonzero*) + + +(* ::Item:: *) +(*Reference: G&R 2.451.4c*) + + +(* Note: The following two rules should be unified! *) +Int[1/(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + Log[a+c*Tanh[(d+e*x)/2]]/(c*e) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a-b] + + +Int[1/(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + -Log[a-c*Coth[(d+e*x)/2]]/(c*e) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a+b] + + +(* ::Item:: *) +(*Reference: G&R 2.451.4a*) + + +Int[1/(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + 2*ArcTan[(c-(a-b)*Tanh[(d+e*x)/2])/Rt[-a^2+b^2-c^2,2]]/(e*Rt[-a^2+b^2-c^2,2]) /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[a^2-b^2] && NegQ[a^2-b^2+c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.451.4b'*) + + +Int[1/(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + -2*ArcTanh[(c-(a-b)*Tanh[(d+e*x)/2])/Rt[a^2-b^2+c^2,2]]/(e*Rt[a^2-b^2+c^2,2]) /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[a^2-b^2] && PosQ[a^2-b^2+c^2] + + +(* ::Item:: *) +(*Basis: a+b*Cosh[z]+c*Sinh[z] == a-I*Sqrt[b^2-c^2]*Sinh[z+I*ArcTan[I*c,b]]*) + + +Int[Sqrt[a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]],x_Symbol] := + 2*I*EllipticE[(Pi/2-I*(d+e*x+I*ArcTan[I*c,b]))/2,2/(1-a/Sqrt[b^2-c^2])]* + Sqrt[a+b*Cosh[d+e*x]+c*Sinh[d+e*x]]/ + (e*Sqrt[(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])/(a-Sqrt[b^2-c^2])]) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2+c^2] + + +(* ::Item:: *) +(*Basis: a+b*Cosh[z]+c*Sinh[z] == a-I*Sqrt[b^2-c^2]*Sinh[z+I*ArcTan[I*c,b]]*) + + +Int[1/Sqrt[a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]],x_Symbol] := + 2*I*EllipticF[(Pi/2-I*(d+e*x+I*ArcTan[I*c,b]))/2,2/(1-a/Sqrt[b^2-c^2])]* + Sqrt[(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])/(a-Sqrt[b^2-c^2])]/ + (e*Sqrt[a+b*Cosh[d+e*x]+c*Sinh[d+e*x]]) /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[a^2-b^2+c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.451.1*) + + +Int[(a_+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_])^n_,x_Symbol] := + (c*Cosh[d+e*x]+b*Sinh[d+e*x])*(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1)/(e*(n+1)*(a^2-b^2+c^2)) + + 1/((n+1)*(a^2-b^2+c^2))* + Int[((n+1)*a-(n+2)*b*Cosh[d+e*x]-(n+2)*c*Sinh[d+e*x])*(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1),x] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2+c^2] + + +(* ::Subsubsection::Closed:: *) +(*(A+B Cosh[d+e x]+C Sinh[d+e x]) (a+b Cosh[d+e x]+c Sinh[d+e x])^n where a^2-b^2+c^2 is nonzero*) +(**) + + +(* ::Item:: *) +(*Reference: G&R 2.451.2*) + + +Int[(A_.+C_.*Sinh[d_.+e_.*x_])/(a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + b*C*Log[a+b*Cosh[d+e*x]+c*Sinh[d+e*x]]/(e*(b^2-c^2)) - + c*C*(d+e*x)/(e*(b^2-c^2)) + + Dist[(A+a*c*C/(b^2-c^2)),Int[1/(a+b*Cosh[d+e*x]+c*Sinh[d+e*x]),x]] /; +FreeQ[{a,b,c,d,e,A,C},x] && NonzeroQ[b^2-c^2] && NonzeroQ[A+a*c*C/(b^2-c^2)] + + +(* ::Item:: *) +(*Reference: G&R 2.451.2*) + + +Int[(A_.+B_.*Cosh[d_.+e_.*x_])/(a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + -c*B*Log[a+b*Cosh[d+e*x]+c*Sinh[d+e*x]]/(e*(b^2-c^2)) + + b*B*(d+e*x)/(e*(b^2-c^2)) + + Dist[(A-a*b*B/(b^2-c^2)),Int[1/(a+b*Cosh[d+e*x]+c*Sinh[d+e*x]),x]] /; +FreeQ[{a,b,c,d,e,A,B},x] && NonzeroQ[b^2-c^2] && NonzeroQ[A-a*b*B/(b^2-c^2)] + + +(* ::Item:: *) +(*Reference: G&R 2.451.2*) + + +Int[(A_.+B_.*Cosh[d_.+e_.*x_]+C_.*Sinh[d_.+e_.*x_])/(a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_]),x_Symbol] := + -(c*B-b*C)*Log[a+b*Cosh[d+e*x]+c*Sinh[d+e*x]]/(e*(b^2-c^2)) + + (b*B-c*C)*(d+e*x)/(e*(b^2-c^2)) + + Dist[(A-a*(b*B-c*C)/(b^2-c^2)),Int[1/(a+b*Cosh[d+e*x]+c*Sinh[d+e*x]),x]] /; +FreeQ[{a,b,c,d,e,A,B,C},x] && NonzeroQ[b^2-c^2] && NonzeroQ[A-a*(b*B-c*C)/(b^2-c^2)] + + +(* ::Item:: *) +(*Reference: G&R 2.451.1*) + + +Int[(A_.+C_.*Sinh[d_.+e_.*x_])*(a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_])^n_,x_Symbol] := + (-b*C+(c*A-a*C)*Cosh[d+e*x]+b*A*Sinh[d+e*x])*(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1)/ + (e*(n+1)*(a^2-b^2+c^2)) + + Dist[1/((n+1)*(a^2-b^2+c^2)), + Int[((n+1)*(a*A+c*C)-(n+2)*b*A*Cosh[d+e*x]-(n+2)*(c*A-a*C)*Sinh[d+e*x])* + (a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e,A,C},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2+c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.451.1*) + + +Int[(A_.+B_.*Cosh[d_.+e_.*x_])*(a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_])^n_,x_Symbol] := + (c*B+c*A*Cosh[d+e*x]+(b*A-a*B)*Sinh[d+e*x])*(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1)/ + (e*(n+1)*(a^2-b^2+c^2)) + + Dist[1/((n+1)*(a^2-b^2+c^2)), + Int[((n+1)*(a*A-b*B)-(n+2)*(b*A-a*B)*Cosh[d+e*x]-(n+2)*c*A*Sinh[d+e*x])* + (a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e,A,B},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2+c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.451.1*) + + +Int[(A_.+B_.*Cosh[d_.+e_.*x_]+C_.*Sinh[d_.+e_.*x_])*(a_.+b_.*Cosh[d_.+e_.*x_]+c_.*Sinh[d_.+e_.*x_])^n_,x_Symbol] := + (c*B-b*C+(c*A-a*C)*Cosh[d+e*x]+(b*A-a*B)*Sinh[d+e*x])*(a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1)/ + (e*(n+1)*(a^2-b^2+c^2)) + + Dist[1/((n+1)*(a^2-b^2+c^2)), + Int[((n+1)*(a*A-b*B+c*C)-(n+2)*(b*A-a*B)*Cosh[d+e*x]-(n+2)*(c*A-a*C)*Sinh[d+e*x])* + (a+b*Cosh[d+e*x]+c*Sinh[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e,A,B,C},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2+c^2] + + +(* ::Subsubsection::Closed:: *) +(*u (a+b Tanh[c+d x])^n*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: (a+b*Tanh[z])/Sech[z] == a*Cosh[z] + b*Sinh[z]*) + + +Int[Sech[v_]^m_.*(a_+b_.*Tanh[v_])^n_., x_Symbol] := + Int[(a*Cosh[v]+b*Sinh[v])^n,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m+n==0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: (a+b*Coth[z])/Csch[z] == b*Cosh[z] + a*Sinh[z]*) + + +Int[Csch[v_]^m_.*(a_+b_.*Coth[v_])^n_., x_Symbol] := + Int[(b*Cosh[v]+a*Sinh[v])^n,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m+n==0 + + +(* ::Subsection::Closed:: *) +(*Exponential and Hyperbolic Trig Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Sinh[c + d x]^n Products of exponentials and powers of sines of linears*) + + +(* ::Item:: *) +(*Reference: CRC 533, A&S 4.3.136*) + + +Int[E^(a_.+b_.*x_)*Sinh[c_.+d_.*x_],x_Symbol] := + -d*E^(a+b*x)*Cosh[c+d*x]/(b^2-d^2) + b*E^(a+b*x)*Sinh[c+d*x]/(b^2-d^2) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[b^2-d^2] + + +(* ::Item:: *) +(*Reference: CRC 542, A&S 4.3.138*) + + +Int[E^(a_.+b_.*x_)*Sinh[c_.+d_.*x_]^n_,x_Symbol] := + -d*n*E^(a+b*x)*Cosh[c+d*x]*Sinh[c+d*x]^(n-1)/(b^2-d^2*n^2) + + b*E^(a+b*x)*Sinh[c+d*x]^n/(b^2-d^2*n^2) + + Dist[n*(n-1)*d^2/(b^2-d^2*n^2),Int[E^(a+b*x)*Sinh[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Cosh[c + d x]^n Products of exponentials and powers of cosines of linears*) + + +(* ::Item:: *) +(*Reference: CRC 538, A&S 4.3.137*) + + +Int[E^(a_.+b_.*x_)*Cosh[c_.+d_.*x_],x_Symbol] := + b*E^(a+b*x)*Cosh[c+d*x]/(b^2-d^2) - d*E^(a+b*x)*Sinh[c+d*x]/(b^2-d^2) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[b^2-d^2] + + +(* ::Item:: *) +(*Reference: CRC 543, A&S 4.3.139*) + + +Int[E^(a_.+b_.*x_)*Cosh[c_.+d_.*x_]^n_,x_Symbol] := + b*E^(a+b*x)*Cosh[c+d*x]^n/(b^2-d^2*n^2) - + d*n*E^(a+b*x)*Cosh[c+d*x]^(n-1)*Sinh[c+d*x]/(b^2-d^2*n^2) - + Dist[n*(n-1)*d^2/(b^2-d^2*n^2),Int[E^(a+b*x)*Cosh[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Sech[c + d x]^n Products of exponentials and powers of secants of linears*) + + +(* ::Item:: *) +(*Reference: CRC 552*) + + +Int[E^(a_.+b_.*x_)*Sech[c_.+d_.*x_]^n_,x_Symbol] := + b*E^(a+b*x)*Sech[c+d*x]^(n-2)/(d^2*(n-2)*(n-1)) + + E^(a+b*x)*Sech[c+d*x]^(n-1)*Sinh[c+d*x]/(d*(n-1)) - + Dist[(b^2-d^2*(n-2)^2)/(d^2*(n-1)*(n-2)),Int[E^(a+b*x)*Sech[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && n!=2 + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Csch[c + d x]^n Products of exponentials and powers of cosecants of linears*) +(**) + + +(* ::Item:: *) +(*Reference: CRC 551*) + + +Int[E^(a_.+b_.*x_)*Csch[c_.+d_.*x_]^n_,x_Symbol] := + -b*E^(a+b*x)*Csch[c+d*x]^(n-2)/(d^2*(n-1)*(n-2)) - + E^(a+b*x)*Cosh[c+d*x]*Csch[c+d*x]^(n-1)/(d*(n-1)) + + Dist[(b^2-d^2*(n-2)^2)/(d^2*(n-1)*(n-2)),Int[E^(a+b*x)*Csch[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && n!=2 + + +(* ::Subsubsection::Closed:: *) +(*x^m Exp[a + b x] Sinh[c + d x]^n Products of monomials, exponentials and powers of sines of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*E^(a_.+b_.*x_)*Sinh[c_.+d_.*x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[E^(a+b*x)*Sinh[c+d*x]^n,x]]}, + x^m*u - + Dist[m,Int[x^(m-1)*u,x]]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && m>0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m Exp[a + b x] Cosh[c + d x]^n Products of exponentials and powers of cosines of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*E^(a_.+b_.*x_)*Cosh[c_.+d_.*x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[E^(a+b*x)*Cosh[c+d*x]^n,x]]}, + x^m*u - + Dist[m,Int[x^(m-1)*u,x]]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && m>0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*u f^v Hyper[w] Products of exponentials and hyperbolic functions of polynomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[z] == 1/2*(E^z - 1/E^z) *) + + +Int[f_^v_*Sinh[w_],x_Symbol] := + Dist[1/2,Int[f^v*E^w,x]] - + Dist[1/2,Int[f^v/E^w,x]] /; +FreeQ[f,x] && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sinh[z] == 1/2*(E^z - 1/E^z) *) + + +Int[f_^v_*Sinh[w_]^n_,x_Symbol] := + Dist[1/2^n,Int[f^v*(E^w-1/E^w)^n,x]] /; +FreeQ[f,x] && IntegerQ[n] && n>0 && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[z] == 1/2*(E^z + 1/E^z)*) + + +Int[f_^v_*Cosh[w_],x_Symbol] := + Dist[1/2,Int[f^v*E^w,x]] + + Dist[1/2,Int[f^v/E^w,x]] /; +FreeQ[f,x] && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cosh[z] == 1/2*(E^z + 1/E^z)*) + + +Int[f_^v_*Cosh[w_]^n_,x_Symbol] := + Dist[1/2^n,Int[f^v*(E^w+1/E^w)^n,x]] /; +FreeQ[f,x] && IntegerQ[n] && n>0 && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Function Simplification Rules*) + + +(* ::Subsubsection::Closed:: *) +(*u (a-a Hyper[v]^2)^n*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1+Sinh[z]^2 == Cosh[z]^2*) + + +Int[u_.*(a_+b_.*Sinh[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Cosh[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: -1 + Cosh[z]^2 == Sinh[z]^2*) + + +Int[u_.*(a_+b_.*Cosh[v_]^2)^n_.,x_Symbol] := + Dist[b^n,Int[u*Sinh[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 - Tanh[z]^2 == Sech[z]^2*) + + +Int[u_.*(a_+b_.*Tanh[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Sech[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: -1 + Coth[z]^2 == Csch[z]^2*) + + +Int[u_.*(a_+b_.*Coth[v_]^2)^n_.,x_Symbol] := + Dist[b^n,Int[u*Csch[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 - Sech[z]^2 == Tanh[z]^2*) + + +Int[u_.*(a_+b_.*Sech[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Tanh[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 + Csch[z]^2 == Coth[z]^2*) + + +Int[u_.*(a_+b_.*Csch[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Coth[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a-b] + + +(* ::Subsubsection::Closed:: *) +(*u (a Tanh[v]^m+b Sech[v]^m)^n Simplify sum of powers of hyperbolic functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If a^2+b^2=0, then a*Tanh[z]+b*Sech[z] == a*Tanh[z/2-a/b*Pi/4]*) + + +(* Int[(a_.*Tanh[v_]+b_.*Sech[v_])^n_,x_Symbol] := + Dist[a^n,Int[Tanh[v/2-a/b*Pi/4]^n,x]] /; +FreeQ[{a,b},x] && ZeroQ[a^2+b^2] && EvenQ[n] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a*Sech[z]+b*Tanh[z] == (a+b*Sinh[z])/Cosh[z]*) + + +Int[u_.*(a_.*Sech[v_]^m_.+b_.*Tanh[v_]^m_.)^n_.,x_Symbol] := + Int[u*(a+b*Sinh[v]^m)^n/Cosh[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && (OddQ[m*n] || m*n<0) && Not[m==2 && ZeroQ[a-b]] + + +(* ::Subsubsection::Closed:: *) +(*u (a Coth[v]^m+b Csch[v]^m)^n Simplify sum of powers of hyperbolic functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If a^2-b^2=0, then a*Coth[z]+b*Csch[z] == a*Coth[z/2+(a/b-1)*Pi*I/4]*) + + +Int[(a_.*Coth[v_]+b_.*Csch[v_])^n_,x_Symbol] := + Dist[a^n,Int[Coth[v/2+(a/b-1)*Pi*I/4]^n,x]] /; +FreeQ[{a,b},x] && ZeroQ[a^2-b^2] && EvenQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a*Csch[z]+b*Coth[z] == (a+b*Cosh[z])/Sinh[z]*) + + +Int[u_.*(a_.*Csch[v_]^m_.+b_.*Coth[v_]^m_.)^n_.,x_Symbol] := + Int[u*(a+b*Cosh[v]^m)^n/Sinh[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && (OddQ[m*n] || m*n<0) && Not[m==2 && ZeroQ[a+b]] + + +(* ::Subsubsection::Closed:: *) +(*x^m Hyper[u]^n Hyper[v]^p*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sinh[z]*Cosh[z] == Sinh[2*z]/2*) + + +(* Int[x_^m_.*Sinh[v_]^n_.*Cosh[v_]^n_.,x_Symbol] := + Dist[1/2^n,Int[x^m*Sinh[Dist[2,v]]^n,x]] /; +IntegerQ[n] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sech[z]*Csch[z] == 2*Csch[2*z]*) + + +Int[x_^m_.*Sech[v_]^n_.*Csch[v_]^n_.,x_Symbol] := + Dist[2^n,Int[x^m*Csch[Dist[2,v]]^n,x]] /; +IntegerQ[{m,n}] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Convert hyperbolic function to complex exponentials*) + + +(* Got to improve x^m*f[e^x] integration before doing this! *) +(* Int[x_^m_.*f_[u_]^n_.*g_[v_]^p_.,x_Symbol] := + Int[x^m*TrigToExp[f[u]]^n*TrigToExp[g[v]]^p,x] /; +IntegerQ[{m,n,p}] && HyperbolicQ[f] && HyperbolicQ[g] *) + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Function Substitution Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Pure hyperbolic sine function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sinh[z]]*Cosh[z] == f[Sinh[z]] * Sinh'[z]*) + + +Int[u_*Cosh[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Sinh[c*(a+b*x)],u,x],x],x],x,Sinh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sinh[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sinh[z]]*Coth[z] == f[Sinh[z]]/Sinh[z] * Sinh'[z]*) + + +Int[u_*Coth[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Sinh[c*(a+b*x)],u,x]/x,x],x],x,Sinh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sinh[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sinh[z]]*Sinh[2*z] == 2*f[Sinh[z]]*Sinh[z] * Sinh'[z]*) + + +Int[u_*Sinh[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[4/(b*c),Subst[Int[Regularize[x*SubstFor[Sinh[c*(a+b*x)/2],u,x],x],x],x,Sinh[c*(a+b*x)/2]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sinh[c*(a+b*x)/2],u,x,True] + + +(* ::Subsubsection::Closed:: *) +(*Pure hyperbolic cosine function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cosh[z]]*Sinh[z] == f[Cosh[z]] * Cosh'[z]*) + + +Int[u_*Sinh[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Cosh[c*(a+b*x)],u,x],x],x],x,Cosh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cosh[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cosh[z]]*Tanh[z] == f[Cosh[z]]/Cosh[z] * Cosh'[z]*) + + +Int[u_*Tanh[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Cosh[c*(a+b*x)],u,x]/x,x],x],x,Cosh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cosh[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cosh[z]]*Sinh[2*z] == 2*f[Cosh[z]]*Cosh[z] * Cosh'[z]*) + + +Int[u_*Sinh[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[4/(b*c),Subst[Int[Regularize[x*SubstFor[Cosh[c*(a+b*x)/2],u,x],x],x],x,Cosh[c*(a+b*x)/2]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cosh[c*(a+b*x)/2],u,x,True] + + +(* ::Subsubsection::Closed:: *) +(*Pure hyperbolic cotangent function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is an integer, f[Coth[z]]*Tanh[z]^n == f[Coth[z]]/(Coth[z]^n*(1-Coth[z]^2)) * Coth'[z]*) + + +Int[u_*Tanh[c_.*(a_.+b_.*x_)]^n_.,x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Coth[c*(a+b*x)],u,x]/(x^n*(1-x^2)),x],x],x,Coth[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && IntegerQ[n] && FunctionOfQ[Coth[c*(a+b*x)],u,x,True] && TryPureTanhSubst[u*Tanh[c*(a+b*x)]^n,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Coth[z]] == f[Coth[z]]/(1-Coth[z]^2) * Coth'[z]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + ShowStep["","Int[f[Coth[a+b*x]],x]","Subst[Int[f[x]/(1-x^2),x],x,Coth[a+b*x]]/b",Hold[ + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Coth[v],u,x]/(1-x^2),x],x],x,Coth[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Coth[v],u,x,True] && TryPureTanhSubst[u,x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Coth[v],u,x]/(1-x^2),x],x],x,Coth[v]]] /; + NotFalseQ[v] && FunctionOfQ[Coth[v],u,x,True] && TryPureTanhSubst[u,x]]] + + +(* ::Subsubsection::Closed:: *) +(*Pure hyperbolic tangent function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is an integer, f[Tanh[z]]*Coth[z]^n == f[Tanh[z]]/(Tanh[z]^n*(1-Tanh[z]^2)) * Tanh'[z]*) + + +Int[u_*Coth[c_.*(a_.+b_.*x_)]^n_.,x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Tanh[c*(a+b*x)],u,x]/(x^n*(1-x^2)),x],x],x,Tanh[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && IntegerQ[n] && FunctionOfQ[Tanh[c*(a+b*x)],u,x,True] && TryPureTanhSubst[u*Coth[c*(a+b*x)]^n,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Tanh[z]] == f[Tanh[z]]/(1-Tanh[z]^2) * Tanh'[z]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + ShowStep["","Int[f[Tanh[a+b*x]],x]","Subst[Int[f[x]/(1-x^2),x],x,Tanh[a+b*x]]/b",Hold[ + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Tanh[v],u,x]/(1-x^2),x],x],x,Tanh[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Tanh[v],u,x,True] && TryPureTanhSubst[u,x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfHyperbolic[u,x]}, + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Tanh[v],u,x]/(1-x^2),x],x],x,Tanh[v]]] /; + NotFalseQ[v] && FunctionOfQ[Tanh[v],u,x,True] && TryPureTanhSubst[u,x]]] + + +TryPureTanhSubst[u_,x_Symbol] := + Not[MatchQ[u,ArcTanh[a_.*Tanh[v_]] /; FreeQ[a,x]]] && + Not[MatchQ[u,ArcTanh[a_.*Coth[v_]] /; FreeQ[a,x]]] && + Not[MatchQ[u,ArcCoth[a_.*Tanh[v_]] /; FreeQ[a,x]]] && + Not[MatchQ[u,ArcCoth[a_.*Coth[v_]] /; FreeQ[a,x]]] && + u===ExpnExpand[u,x] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/IntegralFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/IntegralFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/IntegralFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/IntegralFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,827 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Integral Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Exponential Integral En Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ExpIntegralE[n,a+b x] Exponential integral E function of linears*) + + +(* ::Item:: *) +(*Basis: D[ExpIntegralE[n,z],z] == -ExpIntegralE[n-1,z]*) + + +Int[ExpIntegralE[n_,a_.+b_.*x_],x_Symbol] := + -ExpIntegralE[n+1,a+b*x]/b /; +FreeQ[{a,b,n},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m ExpIntegralE[n,a+b x] Products of monomials and exponential integral E function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ExpIntegralE[n_,a_.+b_.*x_],x_Symbol] := + x^(m+1)*ExpIntegralE[n,a+b*x]/(m+1) + + Dist[b/(m+1),Int[x^(m+1)*ExpIntegralE[n-1,a+b*x],x]] /; +FreeQ[{a,b,m},x] && IntegerQ[n] && n>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*ExpIntegralE[n_,a_.+b_.*x_],x_Symbol] := + -x^m*ExpIntegralE[n+1,a+b*x]/b + + Dist[m/b,Int[x^(m-1)*ExpIntegralE[n+1,a+b*x],x]] /; +FreeQ[{a,b,m},x] && IntegerQ[n] && n<0 + + +(* ::Subsection::Closed:: *) +(*Exponential Integral Ei Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ExpIntegralEi[a+b x]^n Powers of exponential integral function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ExpIntegralEi[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ExpIntegralEi[a+b*x]/b - E^(a+b*x)/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ExpIntegralEi[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*ExpIntegralEi[a+b*x]^2/b - + Dist[2,Int[E^(a+b*x)*ExpIntegralEi[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m ExpIntegralEi[a+b x]^n Products of monomials and powers of exponential integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ExpIntegralEi[a_.+b_.*x_],x_Symbol] := + x^(m+1)*ExpIntegralEi[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*E^(a+b*x)/(a+b*x),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ExpIntegralEi[b_.*x_]^2,x_Symbol] := + x^(m+1)*ExpIntegralEi[b*x]^2/(m+1) - + Dist[2/(m+1),Int[x^m*E^(b*x)*ExpIntegralEi[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[x_^m_.*ExpIntegralEi[a_+b_.*x_]^2,x_Symbol] := + x^(m+1)*ExpIntegralEi[a+b*x]^2/(m+1) + + a*x^m*ExpIntegralEi[a+b*x]^2/(b*(m+1)) - + Dist[2/(m+1),Int[x^m*E^(a+b*x)*ExpIntegralEi[a+b*x],x]] - + Dist[a*m/(b*(m+1)),Int[x^(m-1)*ExpIntegralEi[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +(* Int[x_^m_.*ExpIntegralEi[a_+b_.*x_]^2,x_Symbol] := + b*x^(m+2)*ExpIntegralEi[a+b*x]^2/(a*(m+1)) + + x^(m+1)*ExpIntegralEi[a+b*x]^2/(m+1) - + Dist[2*b/(a*(m+1)),Int[x^(m+1)*E^(a+b*x)*ExpIntegralEi[a+b*x],x]] - + Dist[b*(m+2)/(a*(m+1)),Int[x^(m+1)*ExpIntegralEi[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m<-2 *) + + +(* ::Subsubsection::Closed:: *) +(*E^(a+b x) ExpIntegralEi[c+d x] Products of exponential and exponential integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[E^(a_.+b_.*x_)*ExpIntegralEi[c_.+d_.*x_],x_Symbol] := + E^(a+b*x)*ExpIntegralEi[c+d*x]/b - + Dist[d/b,Int[E^(a+b*x)*E^(c+d*x)/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m E^(a+b x) ExpIntegralEi[c+d x] Products of monomials, exponential and exponential integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*E^(a_.+b_.*x_)*ExpIntegralEi[c_.+d_.*x_],x_Symbol] := + x^m*E^(a+b*x)*ExpIntegralEi[c+d*x]/b - + Dist[d/b,Int[x^m*E^(a+b*x)*E^(c+d*x)/(c+d*x),x]] - + Dist[m/b,Int[x^(m-1)*E^(a+b*x)*ExpIntegralEi[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*E^(a_.+b_.*x_)*ExpIntegralEi[c_.+d_.*x_],x_Symbol] := + x^(m+1)*E^(a+b*x)*ExpIntegralEi[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*E^(a+b*x)*E^(c+d*x)/(c+d*x),x]] - + Dist[b/(m+1),Int[x^(m+1)*E^(a+b*x)*ExpIntegralEi[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Sine Integral Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*SinIntegral[a+b x]^n Powers of sine integral function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[SinIntegral[a_.+b_.*x_],x_Symbol] := + (a+b*x)*SinIntegral[a+b*x]/b + Cos[a+b*x]/b/; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[SinIntegral[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*SinIntegral[a+b*x]^2/b - + Dist[2,Int[Sin[a+b*x]*SinIntegral[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m SinIntegral[a+b x]^n Products of monomials and powers of sine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*SinIntegral[a_.+b_.*x_],x_Symbol] := + x^(m+1)*SinIntegral[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*Sin[a+b*x]/(a+b*x),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*SinIntegral[b_.*x_]^2,x_Symbol] := + x^(m+1)*SinIntegral[b*x]^2/(m+1) - + Dist[2/(m+1),Int[x^m*Sin[b*x]*SinIntegral[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[x_^m_.*SinIntegral[a_+b_.*x_]^2,x_Symbol] := + x^(m+1)*SinIntegral[a+b*x]^2/(m+1) + + a*x^m*SinIntegral[a+b*x]^2/(b*(m+1)) - + Dist[2/(m+1),Int[x^m*Sin[a+b*x]*SinIntegral[a+b*x],x]] - + Dist[a*m/(b*(m+1)),Int[x^(m-1)*SinIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +(* Int[x_^m_.*SinIntegral[a_+b_.*x_]^2,x_Symbol] := + b*x^(m+2)*SinIntegral[a+b*x]^2/(a*(m+1)) + + x^(m+1)*SinIntegral[a+b*x]^2/(m+1) - + Dist[2*b/(a*(m+1)),Int[x^(m+1)*Sin[a+b*x]*SinIntegral[a+b*x],x]] - + Dist[b*(m+2)/(a*(m+1)),Int[x^(m+1)*SinIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m<-2 *) + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b x] SinIntegral[c+d x] Products of sine and sine integral functions*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 5.32.2*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sin[a_.+b_.*x_]*SinIntegral[c_.+d_.*x_],x_Symbol] := + -Cos[a+b*x]*SinIntegral[c+d*x]/b + + Dist[d/b,Int[Cos[a+b*x]*Sin[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[a+b x] SinIntegral[c+d x] Products of monomials, sine and sine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sin[a_.+b_.*x_]*SinIntegral[c_.+d_.*x_],x_Symbol] := + -x^m*Cos[a+b*x]*SinIntegral[c+d*x]/b + + Dist[d/b,Int[x^m*Cos[a+b*x]*Sin[c+d*x]/(c+d*x),x]] + + Dist[m/b,Int[x^(m-1)*Cos[a+b*x]*SinIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Sin[a_.+b_.*x_]*SinIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Sin[a+b*x]*SinIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Sin[a+b*x]*Sin[c+d*x]/(c+d*x),x]] - + Dist[b/(m+1),Int[x^(m+1)*Cos[a+b*x]*SinIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b x] SinIntegral[c+d x] Products of cosine and sine integral functions*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 5.32.1*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Cos[a_.+b_.*x_]*SinIntegral[c_.+d_.*x_],x_Symbol] := + Sin[a+b*x]*SinIntegral[c+d*x]/b - + Dist[d/b,Int[Sin[a+b*x]*Sin[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[a+b x] SinIntegral[c+d x] Products of monomials, cosine and sine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Cos[a_.+b_.*x_]*SinIntegral[c_.+d_.*x_],x_Symbol] := + x^m*Sin[a+b*x]*SinIntegral[c+d*x]/b - + Dist[d/b,Int[x^m*Sin[a+b*x]*Sin[c+d*x]/(c+d*x),x]] - + Dist[m/b,Int[x^(m-1)*Sin[a+b*x]*SinIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*Cos[a_.+b_.*x_]*SinIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Cos[a+b*x]*SinIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Cos[a+b*x]*Sin[c+d*x]/(c+d*x),x]] + + Dist[b/(m+1),Int[x^(m+1)*Sin[a+b*x]*SinIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Cosine Integral Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*CosIntegral[a+b x]^n Powers of cosine integral function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[CosIntegral[a_.+b_.*x_],x_Symbol] := + (a+b*x)*CosIntegral[a+b*x]/b - Sin[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[CosIntegral[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*CosIntegral[a+b*x]^2/b - + Dist[2,Int[Cos[a+b*x]*CosIntegral[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m CosIntegral[a+b x]^n Products of monomials and powers of cosine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*CosIntegral[a_.+b_.*x_],x_Symbol] := + x^(m+1)*CosIntegral[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*Cos[a+b*x]/(a+b*x),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*CosIntegral[b_.*x_]^2,x_Symbol] := + x^(m+1)*CosIntegral[b*x]^2/(m+1) - + Dist[2/(m+1),Int[x^m*Cos[b*x]*CosIntegral[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[x_^m_.*CosIntegral[a_+b_.*x_]^2,x_Symbol] := + x^(m+1)*CosIntegral[a+b*x]^2/(m+1) + + a*x^m*CosIntegral[a+b*x]^2/(b*(m+1)) - + Dist[2/(m+1),Int[x^m*Cos[a+b*x]*CosIntegral[a+b*x],x]] - + Dist[a*m/(b*(m+1)),Int[x^(m-1)*CosIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +(* Int[x_^m_.*CosIntegral[a_+b_.*x_]^2,x_Symbol] := + b*x^(m+2)*CosIntegral[a+b*x]^2/(a*(m+1)) + + x^(m+1)*CosIntegral[a+b*x]^2/(m+1) - + Dist[2*b/(a*(m+1)),Int[x^(m+1)*Cos[a+b*x]*CosIntegral[a+b*x],x]] - + Dist[b*(m+2)/(a*(m+1)),Int[x^(m+1)*CosIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m<-2 *) + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b x] CosIntegral[c+d x] Products of sine and cosine integral functions*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 5.31.2*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sin[a_.+b_.*x_]*CosIntegral[c_.+d_.*x_],x_Symbol] := + -Cos[a+b*x]*CosIntegral[c+d*x]/b + + Dist[d/b,Int[Cos[a+b*x]*Cos[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[a+b x] CosIntegral[c+d x] Products of monomials, sine and cosine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sin[a_.+b_.*x_]*CosIntegral[c_.+d_.*x_],x_Symbol] := + -x^m*Cos[a+b*x]*CosIntegral[c+d*x]/b + + Dist[d/b,Int[x^m*Cos[a+b*x]*Cos[c+d*x]/(c+d*x),x]] + + Dist[m/b,Int[x^(m-1)*Cos[a+b*x]*CosIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Sin[a_.+b_.*x_]*CosIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Sin[a+b*x]*CosIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Sin[a+b*x]*Cos[c+d*x]/(c+d*x),x]] - + Dist[b/(m+1),Int[x^(m+1)*Cos[a+b*x]*CosIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b x] CosIntegral[c+d x] Products of cosine and cosine integral functions*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 5.31.1*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Cos[a_.+b_.*x_]*CosIntegral[c_.+d_.*x_],x_Symbol] := + Sin[a+b*x]*CosIntegral[c+d*x]/b - + Dist[d/b,Int[Sin[a+b*x]*Cos[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[a+b x] CosIntegral[c+d x] Products of monomials, cosine and cosine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Cos[a_.+b_.*x_]*CosIntegral[c_.+d_.*x_],x_Symbol] := + x^m*Sin[a+b*x]*CosIntegral[c+d*x]/b - + Dist[d/b,Int[x^m*Sin[a+b*x]*Cos[c+d*x]/(c+d*x),x]] - + Dist[m/b,Int[x^(m-1)*Sin[a+b*x]*CosIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*Cos[a_.+b_.*x_]*CosIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Cos[a+b*x]*CosIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Cos[a+b*x]*Cos[c+d*x]/(c+d*x),x]] + + Dist[b/(m+1),Int[x^(m+1)*Sin[a+b*x]*CosIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Sine Integral Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*SinhIntegral[a+b x]^n Powers of hyperbolic sine integral function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[SinhIntegral[a_.+b_.*x_],x_Symbol] := + (a+b*x)*SinhIntegral[a+b*x]/b - Cosh[a+b*x]/b/; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[SinhIntegral[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*SinhIntegral[a+b*x]^2/b - + Dist[2,Int[Sinh[a+b*x]*SinhIntegral[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m SinhIntegral[a+b x]^n Products of monomials and powers of hyperbolic sine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*SinhIntegral[a_.+b_.*x_],x_Symbol] := + x^(m+1)*SinhIntegral[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*Sinh[a+b*x]/(a+b*x),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*SinhIntegral[b_.*x_]^2,x_Symbol] := + x^(m+1)*SinhIntegral[b*x]^2/(m+1) - + Dist[2/(m+1),Int[x^m*Sinh[b*x]*SinhIntegral[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[x_^m_.*SinhIntegral[a_+b_.*x_]^2,x_Symbol] := + x^(m+1)*SinhIntegral[a+b*x]^2/(m+1) + + a*x^m*SinhIntegral[a+b*x]^2/(b*(m+1)) - + Dist[2/(m+1),Int[x^m*Sinh[a+b*x]*SinhIntegral[a+b*x],x]] - + Dist[a*m/(b*(m+1)),Int[x^(m-1)*SinhIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +(* Int[x_^m_.*SinhIntegral[a_+b_.*x_]^2,x_Symbol] := + b*x^(m+2)*SinhIntegral[a+b*x]^2/(a*(m+1)) + + x^(m+1)*SinhIntegral[a+b*x]^2/(m+1) - + Dist[2*b/(a*(m+1)),Int[x^(m+1)*Sinh[a+b*x]*SinhIntegral[a+b*x],x]] - + Dist[b*(m+2)/(a*(m+1)),Int[x^(m+1)*SinhIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m<-2 *) + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b x] SinhIntegral[c+d x] Products of hyperbolic sine and hyperbolic sine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sinh[a_.+b_.*x_]*SinhIntegral[c_.+d_.*x_],x_Symbol] := + Cosh[a+b*x]*SinhIntegral[c+d*x]/b - + Dist[d/b,Int[Cosh[a+b*x]*Sinh[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sinh[a+b x] SinhIntegral[c+d x] Products of monomials, hyperbolic sine and hyperbolic sine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sinh[a_.+b_.*x_]*SinhIntegral[c_.+d_.*x_],x_Symbol] := + x^m*Cosh[a+b*x]*SinhIntegral[c+d*x]/b - + Dist[d/b,Int[x^m*Cosh[a+b*x]*Sinh[c+d*x]/(c+d*x),x]] - + Dist[m/b,Int[x^(m-1)*Cosh[a+b*x]*SinhIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Sinh[a_.+b_.*x_]*SinhIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Sinh[a+b*x]*SinhIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Sinh[a+b*x]*Sinh[c+d*x]/(c+d*x),x]] - + Dist[b/(m+1),Int[x^(m+1)*Cosh[a+b*x]*SinhIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b x] SinhIntegral[c+d x] Products of hyperbolic cosine and hyperbolic sine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Cosh[a_.+b_.*x_]*SinhIntegral[c_.+d_.*x_],x_Symbol] := + Sinh[a+b*x]*SinhIntegral[c+d*x]/b - + Dist[d/b,Int[Sinh[a+b*x]*Sinh[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cosh[a+b x] SinhIntegral[c+d x] Products of monomials, hyperbolic cosine and hyperbolic sine integrals*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Cosh[a_.+b_.*x_]*SinhIntegral[c_.+d_.*x_],x_Symbol] := + x^m*Sinh[a+b*x]*SinhIntegral[c+d*x]/b - + Dist[d/b,Int[x^m*Sinh[a+b*x]*Sinh[c+d*x]/(c+d*x),x]] - + Dist[m/b,Int[x^(m-1)*Sinh[a+b*x]*SinhIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*Cosh[a_.+b_.*x_]*SinhIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Cosh[a+b*x]*SinhIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Cosh[a+b*x]*Sinh[c+d*x]/(c+d*x),x]] - + Dist[b/(m+1),Int[x^(m+1)*Sinh[a+b*x]*SinhIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Cosine Integral Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*CoshIntegral[a+b x]^n Powers of hyperbolic cosine integral function of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[CoshIntegral[a_.+b_.*x_],x_Symbol] := + (a+b*x)*CoshIntegral[a+b*x]/b - Sinh[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[CoshIntegral[a_.+b_.*x_]^2,x_Symbol] := + (a+b*x)*CoshIntegral[a+b*x]^2/b - + Dist[2,Int[Cosh[a+b*x]*CoshIntegral[a+b*x],x]] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m CoshIntegral[a+b x]^n Products of monomials and powers of hyperbolic cosine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*CoshIntegral[a_.+b_.*x_],x_Symbol] := + x^(m+1)*CoshIntegral[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*Cosh[a+b*x]/(a+b*x),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*CoshIntegral[b_.*x_]^2,x_Symbol] := + x^(m+1)*CoshIntegral[b*x]^2/(m+1) - + Dist[2/(m+1),Int[x^m*Cosh[b*x]*CoshIntegral[b*x],x]] /; +FreeQ[b,x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[x_^m_.*CoshIntegral[a_+b_.*x_]^2,x_Symbol] := + x^(m+1)*CoshIntegral[a+b*x]^2/(m+1) + + a*x^m*CoshIntegral[a+b*x]^2/(b*(m+1)) - + Dist[2/(m+1),Int[x^m*Cosh[a+b*x]*CoshIntegral[a+b*x],x]] - + Dist[a*m/(b*(m+1)),Int[x^(m-1)*CoshIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +(* Int[x_^m_.*CoshIntegral[a_+b_.*x_]^2,x_Symbol] := + b*x^(m+2)*CoshIntegral[a+b*x]^2/(a*(m+1)) + + x^(m+1)*CoshIntegral[a+b*x]^2/(m+1) - + Dist[2*b/(a*(m+1)),Int[x^(m+1)*Cosh[a+b*x]*CoshIntegral[a+b*x],x]] - + Dist[b*(m+2)/(a*(m+1)),Int[x^(m+1)*CoshIntegral[a+b*x]^2,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m<-2 *) + + +(* ::Subsubsection::Closed:: *) +(*Sinh[a+b x] CoshIntegral[c+d x] Products of hyperbolic sine and hyperbolic cosine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sinh[a_.+b_.*x_]*CoshIntegral[c_.+d_.*x_],x_Symbol] := + Cosh[a+b*x]*CoshIntegral[c+d*x]/b - + Dist[d/b,Int[Cosh[a+b*x]*Cosh[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sinh[a+b x] CoshIntegral[c+d x] Products of monomials, hyperbolic sine and hyperbolic cosine integrals*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sinh[a_.+b_.*x_]*CoshIntegral[c_.+d_.*x_],x_Symbol] := + x^m*Cosh[a+b*x]*CoshIntegral[c+d*x]/b - + Dist[d/b,Int[x^m*Cosh[a+b*x]*Cosh[c+d*x]/(c+d*x),x]] - + Dist[m/b,Int[x^(m-1)*Cosh[a+b*x]*CoshIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*Sinh[a_.+b_.*x_]*CoshIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Sinh[a+b*x]*CoshIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Sinh[a+b*x]*Cosh[c+d*x]/(c+d*x),x]] - + Dist[b/(m+1),Int[x^(m+1)*Cosh[a+b*x]*CoshIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*Cosh[a+b x] CoshIntegral[c+d x] Products of hyperbolic sine and hyperbolic cosine integral functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Cosh[a_.+b_.*x_]*CoshIntegral[c_.+d_.*x_],x_Symbol] := + Sinh[a+b*x]*CoshIntegral[c+d*x]/b - + Dist[d/b,Int[Sinh[a+b*x]*Cosh[c+d*x]/(c+d*x),x]] /; +FreeQ[{a,b,c,d},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cosh[a+b x] CoshIntegral[c+d x]Products of monomials, hyperbolic cosine and hyperbolic cosine integrals*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Cosh[a_.+b_.*x_]*CoshIntegral[c_.+d_.*x_],x_Symbol] := + x^m*Sinh[a+b*x]*CoshIntegral[c+d*x]/b - + Dist[d/b,Int[x^m*Sinh[a+b*x]*Cosh[c+d*x]/(c+d*x),x]] - + Dist[m/b,Int[x^(m-1)*Sinh[a+b*x]*CoshIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*Cosh[a_.+b_.*x_]*CoshIntegral[c_.+d_.*x_],x_Symbol] := + x^(m+1)*Cosh[a+b*x]*CoshIntegral[c+d*x]/(m+1) - + Dist[d/(m+1),Int[x^(m+1)*Cosh[a+b*x]*Cosh[c+d*x]/(c+d*x),x]] - + Dist[b/(m+1),Int[x^(m+1)*Sinh[a+b*x]*CoshIntegral[c+d*x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m<-1 + + +(* ::Subsection::Closed:: *) +(*Logarithmic Integral Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*LogIntegral[a+b x]^n Powers of log integral of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[LogIntegral[a_.+b_.*x_],x_Symbol] := + (a+b*x)*LogIntegral[a+b*x]/b - ExpIntegralEi[2*Log[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m LogIntegral[a+b x] Products of monomials and log integral of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*LogIntegral[a_.+b_.*x_],x_Symbol] := + x^(m+1)*LogIntegral[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)/Log[a+b*x],x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/InverseHyperbolicFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/InverseHyperbolicFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/InverseHyperbolicFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/InverseHyperbolicFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,1690 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Inverse Hyperbolic Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Arcsine Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcSinh[a+b x]^n Powers of arcsines of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 579, A&S 4.6.43*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcSinh[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcSinh[a+b*x]/b - Sqrt[1+(a+b*x)^2]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/ArcSinh[z] == Cosh[ArcSinh[z]]/ArcSinh[z]*ArcSinh'[z]*) + + +Int[1/ArcSinh[a_.+b_.*x_],x_Symbol] := + CoshIntegral[ArcSinh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[1/ArcSinh[a_.+b_.*x_]^2,x_Symbol] := + -Sqrt[1+(a+b*x)^2]/(b*ArcSinh[a+b*x]) + SinhIntegral[ArcSinh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* Replace the above with following when able to integrate result! *) +(* Int[1/ArcSinh[x_]^2,x_Symbol] := + -Sqrt[1+x^2]/(ArcSinh[x]) + + Int[x/(Sqrt[1+x^2]*ArcSinh[x]),x] *) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/Sqrt[ArcSinh[z]] == Cosh[ArcSinh[z]]/Sqrt[ArcSinh[z]]*ArcSinh'[z]*) + + +Int[1/Sqrt[ArcSinh[a_.+b_.*x_]],x_Symbol] := + Sqrt[Pi]/2*(Erf[Sqrt[ArcSinh[a+b*x]]]+Erfi[Sqrt[ArcSinh[a+b*x]]])/b /; +FreeQ[{a,b},x] + + +(* Replace the above with following when able to integrate result! *) +(* Int[1/Sqrt[ArcSinh[x_]],x_Symbol] := + Subst[Int[Cosh[x]/Sqrt[x],x],x,ArcSinh[x]] *) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sqrt[ArcSinh[a_.+b_.*x_]],x_Symbol] := + (a+b*x)*Sqrt[ArcSinh[a+b*x]]/b - + Sqrt[Pi]/4*(-Erf[Sqrt[ArcSinh[a+b*x]]]+Erfi[Sqrt[ArcSinh[a+b*x]]])/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[ArcSinh[a_.+b_.*x_]^n_,x_Symbol] := + (a+b*x)*ArcSinh[a+b*x]^n/b - + n*Sqrt[1+(a+b*x)^2]*ArcSinh[a+b*x]^(n-1)/b + + Dist[n*(n-1),Int[ArcSinh[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts twice*) + + +Int[ArcSinh[a_.+b_.*x_]^n_,x_Symbol] := + -(a+b*x)*ArcSinh[a+b*x]^(n+2)/(b*(n+1)*(n+2)) + + Sqrt[1+(a+b*x)^2]*ArcSinh[a+b*x]^(n+1)/(b*(n+1)) + + Dist[1/((n+1)*(n+2)),Int[ArcSinh[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 && n!=-2 + + +Int[ArcSinh[a_.+b_.*x_]^n_,x_Symbol] := + ArcSinh[a+b*x]^n*Gamma[n+1,-ArcSinh[a+b*x]]/(2*b*(-ArcSinh[a+b*x])^n) - + Gamma[n+1,ArcSinh[a+b*x]]/(2*b) /; +FreeQ[{a,b,n},x] && (Not[RationalQ[n]] || -10 + + +(* ::Subsubsection::Closed:: *) +(*x ArcSinh[a+b x]^n/Sqrt[1+(a+b x)^2] Products of x and powers of arcsines of linears divided by sqrt of linear*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*ArcSinh[a_.+b_.*x_]^n_/Sqrt[u_],x_Symbol] := + Sqrt[u]*ArcSinh[a+b*x]^n/b^2 - + Dist[n/b,Int[ArcSinh[a+b*x]^(n-1),x]] - + Dist[a/b,Int[ArcSinh[a+b*x]^n/Sqrt[u],x]] /; +FreeQ[{a,b},x] && ZeroQ[u-1-(a+b*x)^2] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*u ArcSinh[c / (a+b x^n)]^m Powers of arcsines of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcSinh[z] == ArcCsch[1/z]*) + + +Int[u_.*ArcSinh[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcCsch[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcSinh[x]] / Sqrt[1+x^2] Products of functions of arcsines and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/Sqrt[1+z^2] == ArcSinh'[z]*) + + +(* Int[u_/Sqrt[1+x_^2],x_Symbol] := + Subst[Int[Regularize[SubstFor[ArcSinh[x],u,x],x],x],x,ArcSinh[x]] /; +FunctionOfQ[ArcSinh[x],u,x] *) + + +(* ::Subsubsection::Closed:: *) +(*u ArcSinh[v] Products of expressions and arcsines of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcSinh[u_],x_Symbol] := + x*ArcSinh[u] - + Int[Regularize[x*D[u,x]/Sqrt[1+u^2],x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Subsubsection::Closed:: *) +(*f^(c ArcSinh[a+b x]) Exponentials of arcsines of linears*) + + +Int[f_^(c_.*ArcSinh[a_.+b_.*x_]),x_Symbol] := + f^(c*ArcSinh[a+b*x])*(a+b*x-c*Sqrt[1+(a+b*x)^2]*Log[f])/(b*(1-c^2*Log[f]^2)) /; +FreeQ[{a,b,c,f},x] && NonzeroQ[1-c^2*Log[f]^2] + + +(* ::Subsubsection::Closed:: *) +(*u E^(n ArcSinh[v]) Products of expressions and exponentials of arcsines *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcSinh[z]) == (z+Sqrt[1+z^2])^n*) + + +Int[E^(n_.*ArcSinh[v_]), x_Symbol] := + Int[(v+Sqrt[1+v^2])^n,x] /; +IntegerQ[n] && PolynomialQ[v,x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcSinh[z]) == (z+Sqrt[1+z^2])^n*) + + +Int[x_^m_.*E^(n_.*ArcSinh[v_]), x_Symbol] := + Int[x^m*(v+Sqrt[1+v^2])^n,x] /; +RationalQ[m] && IntegerQ[n] && PolynomialQ[v,x] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Arccosine Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcCosh[a+b x]^n Powers of arccosines of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 582', A&S 4.6.44*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Note: Should be simpler, analagous to that for ArcSinh. *) +Int[ArcCosh[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcCosh[a+b*x]/b - Sqrt[-1+a+b*x]*Sqrt[1+a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/ArcCosh[z] == Sinh[ArcCosh[z]]/ArcCosh[z]*ArcCosh'[z]*) + + +Int[1/ArcCosh[a_.+b_.*x_],x_Symbol] := + SinhIntegral[ArcCosh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[1/ArcCosh[a_.+b_.*x_]^2,x_Symbol] := + -Sqrt[-1+a+b*x]*Sqrt[1+a+b*x]/(b*ArcCosh[a+b*x]) + CoshIntegral[ArcCosh[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/Sqrt[ArcCosh[x]] == Sinh[ArcCosh[x]]/Sqrt[ArcCosh[x]]*ArcCosh'[x]*) + + +Int[1/Sqrt[ArcCosh[a_.+b_.*x_]],x_Symbol] := + Sqrt[Pi]/2*(-Erf[Sqrt[ArcCosh[a+b*x]]] + Erfi[Sqrt[ArcCosh[a+b*x]]])/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sqrt[ArcCosh[a_.+b_.*x_]],x_Symbol] := + (a+b*x)*Sqrt[ArcCosh[a+b*x]]/b - + Sqrt[Pi]/4*(Erf[Sqrt[ArcCosh[a+b*x]]]+Erfi[Sqrt[ArcCosh[a+b*x]]])/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[ArcCosh[a_.+b_.*x_]^n_,x_Symbol] := + (a+b*x)*ArcCosh[a+b*x]^n/b - + n*Sqrt[-1+a+b*x]*Sqrt[1+a+b*x]*ArcCosh[a+b*x]^(n-1)/b + + Dist[n*(n-1),Int[ArcCosh[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts twice*) + + +Int[ArcCosh[a_.+b_.*x_]^n_,x_Symbol] := + -(a+b*x)*ArcCosh[a+b*x]^(n+2)/(b*(n+1)*(n+2)) + + Sqrt[-1+a+b*x]*Sqrt[1+a+b*x]*ArcCosh[a+b*x]^(n+1)/(b*(n+1)) + + Dist[1/((n+1)*(n+2)),Int[ArcCosh[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 && n!=-2 + + +Int[ArcCosh[a_.+b_.*x_]^n_,x_Symbol] := + ArcCosh[a+b*x]^n*Gamma[n+1,-ArcCosh[a+b*x]]/(2*b*(-ArcCosh[a+b*x])^n) + + Gamma[n+1,ArcCosh[a+b*x]]/(2*b) /; +FreeQ[{a,b,n},x] && (Not[RationalQ[n]] || -10 + + +(* ::Subsubsection::Closed:: *) +(*x ArcCosh[a+b x]^n/Sqrt[1+(a+b x)^2] Products of x and powers of arccosines of linears divided by sqrt of linear*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Int[x_*ArcCosh[a_.+b_.*x_]^n_/Sqrt[u_],x_Symbol] := + ??? /; +FreeQ[{a,b},x] && ZeroQ[u-1+(a+b*x)^2] && RationalQ[n] && n>1 *) + + +(* ::Subsubsection::Closed:: *) +(*u ArcCosh[c / (a+b x^n)]^m Powers of arccosines of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCosh[z] == ArcSech[1/z]*) + + +Int[u_.*ArcCosh[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcSech[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcCosh[x]] / Sqrt[1+x^2] Products of functions of arccosines and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/(Sqrt[1+z]*Sqrt[-1+z]) == ArcCosh'[z]*) + + +(* Int[u_/(Sqrt[1+x_]*Sqrt[-1+x_]),x_Symbol] := + Subst[Int[Regularize[SubstFor[ArcCosh[x],u,x],x],x],x,ArcCosh[x]] /; +FunctionOfQ[ArcCosh[x],u,x] *) + + +(* ::Subsubsection::Closed:: *) +(*u ArcCosh[v] Products of expressions and arccosines of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCosh[u_],x_Symbol] := + x*ArcCosh[u] - + Int[Regularize[x*D[u,x]/(Sqrt[-1+u]*Sqrt[1+u]),x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Subsubsection::Closed:: *) +(*f^(c ArcCosh[a+b x]) Exponentials of arccosines of linears*) + + +Int[f_^(c_.*ArcCosh[a_.+b_.*x_]),x_Symbol] := + f^(c*ArcCosh[a+b*x])*(a+b*x-c*Sqrt[(-1+a+b*x)/(1+a+b*x)]*(1+a+b*x)*Log[f])/ + (b*(1-c^2*Log[f]^2)) /; +FreeQ[{a,b,c,f},x] && NonzeroQ[1-c^2*Log[f]^2] + + +(* ::Subsubsection::Closed:: *) +(*u E^(n ArcCosh[v]) Products of expressions and exponentials of arccosines *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCosh[z]) == (z+Sqrt[-1+z]*Sqrt[1+z])^n*) + + +(* ::Item:: *) +(*Basis: If n is an integer, E^(n*ArcCosh[z]) == (z + Sqrt[(-1+z)/(1+z)] + z*Sqrt[(-1+z)/(1+z)])^n*) + + +Int[E^(n_.*ArcCosh[v_]), x_Symbol] := + Int[(v+Sqrt[-1+v]*Sqrt[1+v])^n,x] /; +IntegerQ[n] && PolynomialQ[v,x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCosh[z]) == (z+Sqrt[-1+z]*Sqrt[1+z])^n*) + + +(* ::Item:: *) +(*Basis: If n is an integer, E^(n*ArcCosh[z]) == (z + Sqrt[(-1+z)/(1+z)] + z*Sqrt[(-1+z)/(1+z)])^n*) + + +Int[x_^m_.*E^(n_.*ArcCosh[v_]), x_Symbol] := + Int[x^m*(v+Sqrt[-1+v]*Sqrt[1+v])^n,x] /; +RationalQ[m] && IntegerQ[n] && PolynomialQ[v,x] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Arctangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcTanh[a+b x^n] Arctangents of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 585, A&S 4.6.45*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcTanh[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcTanh[a+b*x]/b + Log[1-(a+b*x)^2]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcTanh[a_.+b_.*x_^n_],x_Symbol] := + x*ArcTanh[a+b*x^n] - + Dist[b*n,Int[x^n/(1-a^2-2*a*b*x^n-b^2*x^(2*n)),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcTanh[a+b x^n] Products of monomials and arctangents of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: ArcTanh[z] == 1/2*Log[1+z] - 1/2*Log[1-z]*) + + +Int[ArcTanh[a_.+b_.*x_^n_.]/x_,x_Symbol] := + Dist[1/2,Int[Log[1+a+b*x^n]/x,x]] - + Dist[1/2,Int[Log[1-a-b*x^n]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 588, A&S 4.6.54*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcTanh[a_.+b_.*x_^n_.],x_Symbol] := + x^(m+1)*ArcTanh[a+b*x^n]/(m+1) - + Dist[b*n/(m+1),Int[x^(m+n)/(1-a^2-2*a*b*x^n-b^2*x^(2*n)),x]] /; +FreeQ[{a,b,m},x] && IntegerQ[n] && NonzeroQ[m+1] && NonzeroQ[m-n+1] + + +(* ::Subsubsection::Closed:: *) +(*(1-x^2)^m ArcTanh[x]^n Products of integer powers of binomials and powers of arctangents*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(1-x_^2)^m_*ArcTanh[x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[(1-x^2)^m,x]]}, + u*ArcTanh[x]^n - + Dist[n,Int[Expand[u*ArcTanh[x]^(n-1)/(1-x^2)],x]]] /; +IntegerQ[{m,n}] && m<-1 && n>0 + + +(* Ug. (-1+x^2)^m should automatically evaluate to (-1)^m*(1-x^2)^m for integer m! *) +Int[(-1+x_^2)^m_*ArcTanh[x_]^n_.,x_Symbol] := + Dist[(-1)^m,Int[(1-x^2)^m*ArcTanh[x]^n,x]] /; +IntegerQ[{m,n}] && m<-1 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*(1-x^2)^m ArcCoth[x]^n ArcTanh[x]^p Products of powers of binomials, arccotangents and arctangents*) + + +Int[1/((1-x_^2)*ArcCoth[x_]*ArcTanh[x_]),x_Symbol] := + (-Log[ArcCoth[x]]+Log[ArcTanh[x]])/(ArcCoth[x]-ArcTanh[x]) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCoth[x_]^n_.*ArcTanh[x_]^p_./(1-x_^2),x_Symbol] := + ArcCoth[x]^(n+1)*ArcTanh[x]^p/(n+1) - + Dist[p/(n+1),Int[ArcCoth[x]^(n+1)*ArcTanh[x]^(p-1)/(1-x^2),x]] /; +IntegerQ[{n,p}] && 01 + + +Int[x_*ArcTanh[a_.+b_.*x_]^n_,x_Symbol] := + -(1-(a+b*x)^2)*ArcTanh[a+b*x]^n/(2*b^2) + + Dist[n/(2*b),Int[ArcTanh[a+b*x]^(n-1),x]] - + Dist[a/b,Int[ArcTanh[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*u ArcTanh[c / (a+b x^n)] Arctangent of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTanh[z] == ArcCoth[1/z]*) + + +Int[u_.*ArcTanh[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcCoth[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[x, ArcTanh[a+b x]] / (1-(a+b x)^2) Products of functions involving arctangents of linears and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[z]/(1-z^2) == f[Tanh[ArcTanh[z]]]*ArcTanh'[z]*) + + +(* ::Item:: *) +(*Basis: r + s*x + t*x^2 == -(s^2-4*r*t)/(4*t)*(1 - (s+2*t*x)^2/(s^2-4*r*t))*) + + +(* ::Item:: *) +(*Basis: 1-Tanh[z]^2 == Sech[z]^2*) + + +If[ShowSteps, + +Int[u_*v_^n_.,x_Symbol] := + Module[{tmp=InverseFunctionOfLinear[u,x]}, + ShowStep["","Int[f[x,ArcTanh[a+b*x]]/(1-(a+b*x)^2),x]", + "Subst[Int[f[-a/b+Tanh[x]/b,x],x],x,ArcTanh[a+b*x]]/b",Hold[ + Dist[(-Discriminant[v,x]/(4*Coefficient[v,x,2]))^n/Coefficient[tmp[[1]],x,1], + Subst[Int[Regularize[SubstForInverseFunction[u,tmp,x]*Sech[x]^(2*(n+1)),x],x], x, tmp]]]] /; + NotFalseQ[tmp] && Head[tmp]===ArcTanh && ZeroQ[Discriminant[v,x]*tmp[[1]]^2-D[v,x]^2]] /; +SimplifyFlag && QuadraticQ[v,x] && IntegerQ[n] && n<0 && PosQ[Discriminant[v,x]], + +Int[u_*v_^n_.,x_Symbol] := + Module[{tmp=InverseFunctionOfLinear[u,x]}, + Dist[(-Discriminant[v,x]/(4*Coefficient[v,x,2]))^n/Coefficient[tmp[[1]],x,1], + Subst[Int[Regularize[SubstForInverseFunction[u,tmp,x]*Sech[x]^(2*(n+1)),x],x], x, tmp]] /; + NotFalseQ[tmp] && Head[tmp]===ArcTanh && ZeroQ[Discriminant[v,x]*tmp[[1]]^2-D[v,x]^2]] /; +QuadraticQ[v,x] && IntegerQ[n] && n<0 && PosQ[Discriminant[v,x]]] + + +(* ::Subsubsection::Closed:: *) +(*u E^(n ArcTanh[v]) Products of expressions and exponentials of arctangents*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z]) == (1+z)^(n/2)/(1-z)^(n/2)*) + + +Int[u_.*E^(n_.*ArcTanh[v_]),x_Symbol] := + Int[u*(1+v)^(n/2)/(1-v)^(n/2),x] /; +EvenQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z]) == (1+z)^(n/2)/(1-z)^(n/2)*) + + +Int[E^(n_.*ArcTanh[v_]),x_Symbol] := + Int[(1+v)^(n/2)/(1-v)^(n/2),x] /; +RationalQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z]) == ((1+z)/Sqrt[1-z^2])^n*) + + +Int[x_^m_.*E^(n_.*ArcTanh[v_]), x_Symbol] := + Int[x^m*(1+v)^n/(1-v^2)^(n/2),x] /; +RationalQ[m] && OddQ[n] && PolynomialQ[v,x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z])*(1-z^2)^m == (1-z)^(m-n/2)*(1+z)^(m+n/2)*) + + +Int[u_.*E^(n_.*ArcTanh[v_])*(1-v_^2)^m_.,x_Symbol] := + Int[u*(1-v)^(m-n/2)*(1+v)^(m+n/2),x] /; +RationalQ[{m,n}] && IntegerQ[m-n/2] && IntegerQ[m+n/2] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z])*(1-z^2)^m == (1-z)^(m-n/2)*(1+z)^(m+n/2)*) + + +Int[u_.*E^(n_.*ArcTanh[v_])*(a_+b_.*v_^2)^m_.,x_Symbol] := + (a+b*v^2)^m/(1-v^2)^m*Int[u*(1-v)^(m-n/2)*(1+v)^(m+n/2),x] /; +FreeQ[{a,b},x] && ZeroQ[a+b] && RationalQ[{m,n}] && IntegerQ[m-n/2] && IntegerQ[m+n/2] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z]) == (1+z)^n/(1-z^2)^(n/2)*) + + +Int[u_.*E^(n_.*ArcTanh[v_])*(1-v_^2)^m_.,x_Symbol] := + Int[u*(1+v)^n*(1-v^2)^(m-n/2),x] /; +RationalQ[n] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z]) == (1+z)^n/(1-z^2)^(n/2)*) + + +Int[u_.*E^(n_.*ArcTanh[v_])*(1+v_)^m_.,x_Symbol] := + Int[u*(1+v)^(m+n)/(1-v^2)^(n/2),x] /; +RationalQ[{m,n}] && IntegerQ[m+n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z]) == (1+z)^(n/2)/(1-z)^(n/2)*) + + +Int[u_.*E^(n_.*ArcTanh[v_])*(1+v_)^m_.,x_Symbol] := + Int[u*(1+v)^(m+n/2)/(1-v)^(n/2),x] /; +RationalQ[{m,n}] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcTanh[z]) == (1+z)^(n/2)/(1-z)^(n/2)*) + + +Int[u_.*E^(n_.*ArcTanh[v_])*(1-v_)^m_.,x_Symbol] := + Int[u*(1+v)^(n/2)*(1-v)^(m-n/2),x] /; +RationalQ[{m,n}] + + +(* ::Item:: *) +(*Derivation: Algebraic simplification*) + + +Int[u_.*E^(n_.*ArcTanh[v_])*(a_+b_.*v_)^m_.,x_Symbol] := + Dist[a^m,Int[u*E^(n*ArcTanh[v])*(1+b/a*v)^m,x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && RationalQ[n] && NonzeroQ[a-1] && ZeroQ[a^2-b^2] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If m is an integer, E^ArcTanh[z]*(a-a/z^2)^m == (-a)^m*(1+z)*(1-z^2)^(m-1/2)/z^(2*m)*) + + +Int[u_.*E^ArcTanh[v_]*(a_+b_./v_^2)^m_.,x_Symbol] := + b^m*Int[u*(1-v^2)^(m-1/2)/v^(2*m),x] + + b^m*Int[u*(1-v^2)^(m-1/2)/v^(2*m-1),x] /; +FreeQ[{a,b},x] && ZeroQ[a+b] && IntegerQ[m] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcTanh[x]] (1-x^2)^n Products of functions of arctangents and its derivative*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[a^n,Subst[Int[Regularize[Cosh[x]^(-2*(n+1))*SubstFor[ArcTanh[x],u,x],x],x],x,ArcTanh[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTanh[x],u,x] && ZeroQ[a+b] && HalfIntegerQ[n] && n<-1 && + PositiveQ[a] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[1/a,Subst[Int[Regularize[(a*Sech[x]^2)^(n+1)*SubstFor[ArcTanh[x],u,x],x],x],x,ArcTanh[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTanh[x],u,x] && ZeroQ[a+b] && HalfIntegerQ[n] && n<-1 + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* Int[u_*(a_+b_./x_^2)^n_,x_Symbol] := + Subst[Int[Regularize[(b*Csch[x]^2)^n*Sech[x]^2*SubstFor[ArcTanh[x],u,x],x],x],x,ArcTanh[x]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTanh[x],u,x] && ZeroQ[a+b] && HalfIntegerQ[n] *) + + +(* ::Subsubsection::Closed:: *) +(*x^m f[ArcTanh[x]] (1-x^2)^n Products of monomials, functions of arctangents and its derivative*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[a^n,Subst[Int[Regularize[Tanh[x]^m*Cosh[x]^(-2*(n+1))*SubstFor[ArcTanh[x],u,x],x],x],x,ArcTanh[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTanh[x],u,x] && ZeroQ[a+b] && HalfIntegerQ[n] && n<-1 && + PositiveQ[a] && IntegerQ[m] + + +(* ::Subsubsection::Closed:: *) +(*u ArcTanh[v] Products of expressions and arctangents of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcTanh[u_],x_Symbol] := + x*ArcTanh[u] - + Int[Regularize[x*D[u,x]/(1-u^2),x],x] /; +InverseFunctionFreeQ[u,x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcTanh[u_],x_Symbol] := + x^(m+1)*ArcTanh[u]/(m+1) - + Dist[1/(m+1),Int[Regularize[x^(m+1)*D[u,x]/(1-u^2),x],x]] /; +FreeQ[m,x] && NonzeroQ[m+1] && InverseFunctionFreeQ[u,x] && + Not[FunctionOfQ[x^(m+1),u,x]] && + FalseQ[PowerVariableExpn[u,m+1,x]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[v_*ArcTanh[u_],x_Symbol] := + Module[{w=Block[{ShowSteps=False,StepCounter=Null}, Int[v,x]]}, + w*ArcTanh[u] - + Int[Regularize[w*D[u,x]/(1-u^2),x],x] /; + InverseFunctionFreeQ[w,x]] /; +InverseFunctionFreeQ[u,x] && + Not[MatchQ[v, x^m_. /; FreeQ[m,x]]] && + FalseQ[FunctionOfLinear[v*ArcTanh[u],x]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTanh[z] == Log[1+z]/2 - Log[1-z]/2*) + + +Int[ArcTanh[b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[1/2,Int[Log[1+b*x]/(c+d*x^n),x]] - + Dist[1/2,Int[Log[1-b*x]/(c+d*x^n),x]] /; +FreeQ[{b,c,d},x] && IntegerQ[n] && Not[n==2 && ZeroQ[b^2*c+d]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTanh[z] == Log[1+z]/2 - Log[1-z]/2*) + + +Int[ArcTanh[a_+b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[1/2,Int[Log[1+a+b*x]/(c+d*x^n),x]] - + Dist[1/2,Int[Log[1-a-b*x]/(c+d*x^n),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[n] && Not[n==1 && ZeroQ[a*d-b*c]] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Arccotangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcCoth[a+b x^n] Arccotangents of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 586, A&S 4.6.48*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCoth[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcCoth[a+b*x]/b + Log[1-(a+b*x)^2]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCoth[a_.+b_.*x_^n_],x_Symbol] := + x*ArcCoth[a+b*x^n] - + Dist[b*n,Int[x^n/(1-a^2-2*a*b*x^n-b^2*x^(2*n)),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcCoth[a+b x^n] Products of monomials and arccotangents of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: ArcCoth[z] == 1/2*Log[1+1/z] - 1/2*Log[1-1/z]*) + + +Int[ArcCoth[a_.+b_.*x_^n_.]/x_,x_Symbol] := + Dist[1/2,Int[Log[1+1/(a+b*x^n)]/x,x]] - + Dist[1/2,Int[Log[1-1/(a+b*x^n)]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 590*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcCoth[a_.+b_.*x_^n_.],x_Symbol] := + x^(m+1)*ArcCoth[a+b*x^n]/(m+1) - + Dist[b*n/(m+1),Int[x^(m+n)/(1-a^2-2*a*b*x^n-b^2*x^(2*n)),x]] /; +FreeQ[{a,b,m},x] && IntegerQ[n] && NonzeroQ[m+1] && NonzeroQ[m-n+1] + + +(* ::Subsubsection::Closed:: *) +(*(1-x^2)^m ArcCoth[x]^n Products of powers of binomials and powers of arccotangents*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(1-x_^2)^m_*ArcCoth[x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[(1-x^2)^m,x]]}, + u*ArcCoth[x]^n- + Dist[n,Int[Expand[u*ArcCoth[x]^(n-1)/(1-x^2)],x]]] /; +IntegerQ[{m,n}] && m<-1 && n>0 + + +(* Ug. (-1+x^2)^m should automatically evaluate to (-1)^m*(1-x^2)^m for integer m! *) +Int[(-1+x_^2)^m_*ArcCoth[x_]^n_.,x_Symbol] := + Dist[(-1)^m,Int[(1-x^2)^m*ArcCoth[x]^n,x]] /; +IntegerQ[{m,n}] && m<-1 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*(1-x^2)^m ArcCoth[x]^n ArcTanh[x]^p Products of powers of binomials, arccotangents and arctangents*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCoth[x_]^n_.*ArcTanh[x_]^p_/(1-x_^2),x_Symbol] := + ArcCoth[x]^n*ArcTanh[x]^(p+1)/(p+1) - + Dist[n/(p+1),Int[ArcCoth[x]^(n-1)*ArcTanh[x]^(p+1)/(1-x^2),x]] /; +IntegerQ[{n,p}] && 01 && n>1 + + +(* Ug. (-1+x^2)^m should automatically evaluate to (-1)^m*(1-x^2)^m for integer m! *) +Int[(-1+x_^2)^m_.*ArcCoth[x_]^n_.*ArcTanh[x_]^p_.,x_Symbol] := + Dist[(-1)^m,Int[(1-x^2)^m*ArcCoth[x]^n*ArcTanh[x]^p,x]] /; +IntegerQ[{m,n,p}] && m<-1 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*x ArcCoth[a+b x]^n Products of x and powers of arccotangents of linears*) + + +Int[x_*ArcCoth[a_.*x_]^n_,x_Symbol] := + (-1+a^2*x^2)*ArcCoth[a*x]^n/(2*a^2)+ + Dist[n/(2*a),Int[ArcCoth[a*x]^(n-1),x]] /; +FreeQ[a,x] && RationalQ[n] && n>1 + + +Int[x_*ArcCoth[a_.+b_.*x_]^n_,x_Symbol] := + (-1+(a+b*x)^2)*ArcCoth[a+b*x]^n/(2*b^2) + + Dist[n/(2*b),Int[ArcCoth[a+b*x]^(n-1),x]] - + Dist[a/b,Int[ArcCoth[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*u ArcCoth[c / (a+b x^n)] Arccotangent of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCoth[z] == ArcTanh[1/z]*) + + +Int[u_.*ArcCoth[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcTanh[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[x, ArcCoth[a+b x]] / (1-(a+b x)^2) Products of functions involving arccotangents of linears and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[z]/(1-z^2) == f[Coth[ArcCoth[z]]]*ArcCoth'[z]*) + + +(* ::Item:: *) +(*Basis: r + s*x + t*x^2 == -(s^2-4*r*t)/(4*t)*(1 - (s+2*t*x)^2/(s^2-4*r*t))*) + + +(* ::Item:: *) +(*Basis: 1-Coth[z]^2 == -Csch[z]^2*) + + +If[ShowSteps, + +Int[u_*v_^n_.,x_Symbol] := + Module[{tmp=InverseFunctionOfLinear[u,x]}, + ShowStep["","Int[f[x,ArcCoth[a+b*x]]/(1-(a+b*x)^2),x]", + "Subst[Int[f[-a/b+Coth[x]/b,x],x],x,ArcCoth[a+b*x]]/b",Hold[ + Dist[(-Discriminant[v,x]/(4*Coefficient[v,x,2]))^n/Coefficient[tmp[[1]],x,1], + Subst[Int[Regularize[SubstForInverseFunction[u,tmp,x]*(-Csch[x]^2)^(n+1),x],x], x, tmp]]]] /; + NotFalseQ[tmp] && Head[tmp]===ArcCoth && ZeroQ[Discriminant[v,x]*tmp[[1]]^2-D[v,x]^2]] /; +SimplifyFlag && QuadraticQ[v,x] && IntegerQ[n] && n<0 && PosQ[Discriminant[v,x]], + +Int[u_*v_^n_.,x_Symbol] := + Module[{tmp=InverseFunctionOfLinear[u,x]}, + Dist[(-Discriminant[v,x]/(4*Coefficient[v,x,2]))^n/Coefficient[tmp[[1]],x,1], + Subst[Int[Regularize[SubstForInverseFunction[u,tmp,x]*(-Csch[x]^2)^(n+1),x],x], x, tmp]] /; + NotFalseQ[tmp] && Head[tmp]===ArcCoth && ZeroQ[Discriminant[v,x]*tmp[[1]]^2-D[v,x]^2]] /; +QuadraticQ[v,x] && IntegerQ[n] && n<0 && PosQ[Discriminant[v,x]]] + + +(* ::Subsubsection::Closed:: *) +(*u E^(n ArcCoth[v]) Products of expressions and exponentials of arccotangents*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is even, E^(n*ArcCoth[z]) == (1+z)^(n/2)/(-1+z)^(n/2)*) + + +Int[u_.*E^(n_.*ArcCoth[v_]),x_Symbol] := + Int[u*(1+v)^(n/2)/(-1+v)^(n/2),x] /; +EvenQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == (z*(1+z)/(Sqrt[z^2]*Sqrt[-1+z^2]))^n*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == (1/Sqrt[1-1/z^2] + 1/(z*Sqrt[1-1/z^2]))^n*) + + +Int[E^(n_.*ArcCoth[v_]),x_Symbol] := + Int[Expand[(1/Sqrt[1-1/v^2] + 1/(x*Sqrt[1-1/v^2]))^n],x] /; +OddQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == (1+1/z)^(n/2)/(1-1/z)^(n/2)*) + + +(* Int[E^(n_.*ArcCoth[v_]),x_Symbol] := + Int[(1+1/v)^(n/2)/(1-1/v)^(n/2),x] /; +RationalQ[n] *) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[E^(ArcCoth[a_.+b_.*x_]/2), x_Symbol] := + x*E^(ArcCoth[a+b*x]/2) - + Dist[b/2,Int[x*E^(ArcCoth[a+b*x]/2)/(1-(a+b*x)^2),x]] /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*E^(ArcCoth[a_.+b_.*x_]/2), x_Symbol] := + x^(m+1)*E^(ArcCoth[a+b*x]/2)/(m+1) - + Dist[b/(2*(m+1)),Int[x^(m+1)*E^(ArcCoth[a+b*x]/2)/(1-(a+b*x)^2),x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == (z*(1+z)/(Sqrt[z^2]*Sqrt[-1+z^2]))^n*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == (1/Sqrt[1-1/z^2] + 1/(z*Sqrt[1-1/z^2]))^n*) + + +Int[x_^m_.*E^(n_.*ArcCoth[v_]),x_Symbol] := + Int[Expand[x^m*(1/Sqrt[1-1/v^2] + 1/(x*Sqrt[1-1/v^2]))^n],x] /; +RationalQ[m] && OddQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == ((1+1/z)/Sqrt[1-1/z^2])^n*) + + +(* ::Item:: *) +(*Basis: If n is an integer, E^(n*ArcCoth[z]) == (1+z)^n/(z^n*(1-1/z^2)^(n/2))*) + + +(* Int[x_^m_.*E^(n_.*ArcCoth[v_]), x_Symbol] := + Int[x^m*(1+v)^n/(v^n*(1-1/v^2)^(n/2)),x] /; +RationalQ[m] && OddQ[n] && PolynomialQ[v,x] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is odd, E^(n*ArcCoth[z])*(1-z^2)^m == -(-1)^((n-1)/2)*z*Sqrt[1-1/z^2]/Sqrt[1-z^2]*(1-z)^(m-n/2)*(1+z)^(m+n/2)*) + + +(* ::Item:: *) +(*Basis: D[f[x]*Sqrt[a-a/f[x]^2]/Sqrt[1-f[x]^2],x] == 0*) + + +Int[u_.*E^(n_.*ArcCoth[v_])*(1-v_^2)^m_.,x_Symbol] := + -(-1)^((n-1)/2)*v*Sqrt[1-1/v^2]/Sqrt[1-v^2]*Int[u*(1-v)^(m-n/2)*(1+v)^(m+n/2),x] /; +OddQ[n] && HalfIntegerQ[m] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^ArcCoth[z]*(1-z^2) == -z*(1+z)*Sqrt[1-1/z^2]*) + + +Int[u_.*E^ArcCoth[v_]*(1-v_^2)^m_.,x_Symbol] := + -Int[Expand[u*v*(1+v)*Sqrt[1-1/v^2]*(1-v^2)^(m-1),x],x] /; +IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Basis: D[(a-a*f[x]^2)^m/(1-f[x]^2)^m,x] == 0*) + + +Int[u_.*E^ArcCoth[v_]*(a_+b_.*v_^2)^m_.,x_Symbol] := + (a+b*v^2)^m/(1-v^2)^m*Int[u*E^ArcCoth[v]*(1-v^2)^m,x] /; +FreeQ[{a,b},x] && ZeroQ[a+b] && NonzeroQ[a-1] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == (1+1/z)^n/(1-1/z^2)^(n/2)*) + + +Int[u_.*E^(n_.*ArcCoth[v_])*(1-1/v_^2)^m_.,x_Symbol] := + Int[u*(1+v)^(m+n/2)*(-1+v)^(m-n/2)/v^(2*m),x] /; +IntegerQ[n] && IntegerQ[m-n/2] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCoth[z]) == (1+1/z)^n/(1-1/z^2)^(n/2)*) + + +Int[u_.*E^(n_.*ArcCoth[v_])*(1-1/v_^2)^m_.,x_Symbol] := + Int[Expand[u*(1+1/v)^n*(1-1/v^2)^(m-n/2),x],x] /; +RationalQ[n] && IntegerQ[2*m] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^ArcCoth[z] == (1+1/z)/Sqrt[1-1/z^2]*) + + +(* ::Item:: *) +(*Basis: D[(a-a/f[x]^2)^m/(1-1/f[x]^2)^m,x] == 0*) + + +Int[u_.*E^ArcCoth[v_]*(a_+b_./v_^2)^m_.,x_Symbol] := + Int[u*(1+1/v)*(1-v^(-2))^(m-1/2),x]*(a+b*v^(-2))^m/(1-v^(-2))^m /; +FreeQ[{a,b},x] && ZeroQ[a+b] && IntegerQ[2*m] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcCoth[x]] (1-x^2)^n Products of functions of arccotangents and its derivative*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[1/a,Subst[Int[Regularize[(b*Csch[x]^2)^(n+1)*SubstFor[ArcCoth[x],u,x],x],x],x,ArcCoth[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcCoth[x],u,x] && ZeroQ[a+b] && HalfIntegerQ[n] *) + + +(* ::Subsubsection::Closed:: *) +(*x^m f[ArcCoth[x]] (1-x^2)^n Products of monomials, functions of arctangents and its derivative*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[-b^n,Subst[Int[Regularize[Coth[x]^m*Sinh[x]^(-2*(n+1))*SubstFor[ArcCoth[x],u,x],x],x],x,ArcCoth[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcCoth[x],u,x] && ZeroQ[a+b] && HalfIntegerQ[n] && n<-1 && + PositiveQ[a] && IntegerQ[m] + + +(* ::Subsubsection::Closed:: *) +(*u ArcCoth[v] Products of expressions and arccotangents of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCoth[u_],x_Symbol] := + x*ArcCoth[u] - + Int[Regularize[x*D[u,x]/(1-u^2),x],x] /; +InverseFunctionFreeQ[u,x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcCoth[u_],x_Symbol] := + x^(m+1)*ArcCoth[u]/(m+1) - + Dist[1/(m+1),Int[Regularize[x^(m+1)*D[u,x]/(1-u^2),x],x]] /; +FreeQ[m,x] && NonzeroQ[m+1] && InverseFunctionFreeQ[u,x] && + Not[FunctionOfQ[x^(m+1),u,x]] && + FalseQ[PowerVariableExpn[u,m+1,x]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[v_*ArcCoth[u_],x_Symbol] := + Module[{w=Block[{ShowSteps=False,StepCounter=Null}, Int[v,x]]}, + w*ArcCoth[u] - + Int[Regularize[w*D[u,x]/(1-u^2),x],x] /; + InverseFunctionFreeQ[w,x]] /; +InverseFunctionFreeQ[u,x] && + Not[MatchQ[v, x^m_. /; FreeQ[m,x]]] && + FalseQ[FunctionOfLinear[v*ArcCoth[u],x]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCoth[z] == Log[1+1/z]/2 - Log[1-1/z]/2*) + + +Int[ArcCoth[b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[1/2,Int[Log[1+1/(b*x)]/(c+d*x^n),x]] - + Dist[1/2,Int[Log[1-1/(b*x)]/(c+d*x^n),x]] /; +FreeQ[{b,c,d},x] && IntegerQ[n] && Not[n==2 && ZeroQ[b^2*c+d]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCoth[z] == Log[1+1/z]/2 - Log[1-1/z]/2*) + + +Int[ArcCoth[a_+b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[1/2,Int[Log[1+1/(a+b*x)]/(c+d*x^n),x]] - + Dist[1/2,Int[Log[1-1/(a+b*x)]/(c+d*x^n),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[n] && Not[n==1 && ZeroQ[a*d-b*c]] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Arcsecant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcSech[a+b x]^n Powers of arcsecants of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 591', A&S 4.6.47'*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcSech[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcSech[a+b*x]/b - 2*ArcTan[Sqrt[(1-a-b*x)/(1+a+b*x)]]/b /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcSech[a+b x] Products of monomials and arcsecants of monomials*) + + +Int[ArcSech[a_.*x_^n_.]/x_,x_Symbol] := +(* Int[ArcCosh[1/a*x^(-n)]/x,x] /; *) + -ArcSech[a*x^n]^2/(2*n) - + ArcSech[a*x^n]*Log[1+E^(-2*ArcSech[a*x^n])]/n + + PolyLog[2,-E^(-2*ArcSech[a*x^n])]/(2*n) /; +(* -ArcSech[a*x^n]^2/(2*n) - + ArcSech[a*x^n]*Log[1+1/(1/(a*x^n)+Sqrt[-1+1/(a*x^n)]*Sqrt[1+1/(a*x^n)])^2]/n + + PolyLog[2,-1/(1/(a*x^n)+Sqrt[-1+1/(a*x^n)]*Sqrt[1+1/(a*x^n)])^2]/(2*n) /; *) +FreeQ[{a,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*ArcSech[a_+b_.*x_],x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*ArcSech[x],x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Reference: CRC 593', A&S 4.6.58'*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: D[ArcSech[x],x] == -Sqrt[1/(1+x)]*Sqrt[1+x]/(x*Sqrt[1+x]*Sqrt[1-x])*) + + +(* ::Item:: *) +(*Basis: D[Sqrt[1/(1+a+b*x^n)]*Sqrt[1+a+b*x^n],x] == 0*) + + +Int[x_^m_.*ArcSech[a_.*x_],x_Symbol] := + x^(m+1)*ArcSech[a*x]/(m+1) + +(* Dist[1/(m+1),Int[x^m*Sqrt[(1-a*x)/(1+a*x)]/(1-a*x),x]] /; *) + Dist[1/(m+1),Int[x^m/(Sqrt[(1-a*x)/(1+a*x)]*(1+a*x)),x]] /; +FreeQ[{a,m},x] && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*u ArcSech[c / (a+b x^n)] Inverse secant of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcSech[z] == ArcCosh[1/z]*) + + +Int[u_.*ArcSech[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcCosh[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*u ArcSech[v] Products of expressions and arcsecants of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Int[ArcSech[u_],x_Symbol] := + x*ArcSech[u] + + Int[Regularize[x*D[u,x]/(u^2*Sqrt[-1+1/u]*Sqrt[1+1/u]),x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] *) + + +(* ::Subsubsection::Closed:: *) +(*u E^(n ArcSech[v]) Products of expressions and exponentials of arccosines *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcSech[z]) == (Sqrt[-1+1/z]*Sqrt[1+1/z] + 1/z)^n*) + + +(* ::Item:: *) +(*Basis: If n is an integer, E^(n*ArcSech[z]) == (1/z + Sqrt[(1-z)/(1+z)] + Sqrt[(1-z)/(1+z)]/z)^n*) + + +(* ::Item:: *) +(*Basis: If n is an integer, E^(n*ArcSech[z]) == ((1+Sqrt[1-z]/Sqrt[1/(1+z)])/z)^n*) + + +Int[E^(n_.*ArcSech[v_]), x_Symbol] := + Int[(1/v + Sqrt[(1-v)/(1+v)] + Sqrt[(1-v)/(1+v)]/v)^n,x] /; +IntegerQ[n] && PolynomialQ[v,x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcSech[z]) == (Sqrt[-1+1/z]*Sqrt[1+1/z] + 1/z)^n*) + + +Int[x_^m_.*E^(n_.*ArcSech[v_]), x_Symbol] := + Int[x^m*(1/v + Sqrt[(1-v)/(1+v)] + Sqrt[(1-v)/(1+v)]/v)^n,x] /; +RationalQ[m] && IntegerQ[n] && PolynomialQ[v,x] + + +(* ::Subsection::Closed:: *) +(*Hyperbolic Arccosecant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcCsch[a+b x]^n Powers of arcsecants of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 594', A&S 4.6.46'*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCsch[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcCsch[a+b*x]/b + ArcTanh[Sqrt[1+1/(a+b*x)^2]]/b /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcCsch[a x^n] Products of monomials and arccosecants of monomials*) + + +Int[ArcCsch[a_.*x_^n_.]/x_,x_Symbol] := +(* Int[ArcSinh[1/a*x^(-n)]/x,x] /; *) + -ArcCsch[a*x^n]^2/(2*n) - + ArcCsch[a*x^n]*Log[1-E^(-2*ArcCsch[a*x^n])]/n + + PolyLog[2,E^(-2*ArcCsch[a*x^n])]/(2*n) /; +(* -ArcCsch[a*x^n]^2/(2*n) - + ArcCsch[a*x^n]*Log[1-1/(1/(a*x^n)+Sqrt[1+1/(a^2*x^(2*n))])^2]/n + + PolyLog[2,1/(1/(a*x^n)+Sqrt[1+1/(a^2*x^(2*n))])^2]/(2*n) /; *) +FreeQ[{a,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*ArcCsch[a_+b_.*x_],x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*ArcCsch[x],x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Reference: CRC 596, A&S 4.6.56*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcCsch[a_.+b_.*x_],x_Symbol] := + x^(m+1)*ArcCsch[a+b*x]/(m+1) + + Dist[b/(m+1),Int[x^(m+1)/((a+b*x)^2*Sqrt[1+1/(a+b*x)^2]),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*u ArcCsch[c / (a+b x^n)] Inverse cosecant of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCsch[z] == ArcSinh[1/z]*) + + +Int[u_.*ArcCsch[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcSinh[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*u ArcCsch[v] Products of expressions and arccosecants of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCsch[u_],x_Symbol] := + x*ArcCsch[u] + + Int[Regularize[x*D[u,x]/(u^2*Sqrt[1+1/u^2]),x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Subsubsection::Closed:: *) +(*u E^(n ArcCsch[v]) Products of expressions and exponentials of arccosines *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCsch[z]) == (1/z+Sqrt[1+1/z^2])^n*) + + +Int[E^(n_.*ArcCsch[v_]), x_Symbol] := + Int[(1/v+Sqrt[1+1/v^2])^n,x] /; +IntegerQ[n] && PolynomialQ[v,x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: E^(n*ArcCsch[z]) == (1/z+Sqrt[1+1/z^2])^n*) + + +Int[x_^m_.*E^(n_.*ArcCsch[v_]), x_Symbol] := + Int[x^m*(1/v+Sqrt[1+1/v^2])^n,x] /; +RationalQ[m] && IntegerQ[n] && PolynomialQ[v,x] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/InverseTrigFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/InverseTrigFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/InverseTrigFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/InverseTrigFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,1227 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Inverse Trig Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Arcsine Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcSin[a+b x]^n Powers of arcsines of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.813.1, CRC 441, A&S 4.4.58*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcSin[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcSin[a+b*x]/b + Sqrt[1-(a+b*x)^2]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/ArcSin[z] == Cos[ArcSin[z]]/ArcSin[z]*ArcSin'[z]*) + + +Int[1/ArcSin[a_.+b_.*x_],x_Symbol] := + CosIntegral[ArcSin[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[1/ArcSin[a_.+b_.*x_]^2,x_Symbol] := + -Sqrt[1-(a+b*x)^2]/(b*ArcSin[a+b*x]) - SinIntegral[ArcSin[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/Sqrt[ArcSin[z]] == Cos[ArcSin[z]]/Sqrt[ArcSin[z]]*ArcSin'[z]*) + + +Int[1/Sqrt[ArcSin[a_.+b_.*x_]],x_Symbol] := + Sqrt[2*Pi]*FresnelC[Sqrt[2/Pi]*Sqrt[ArcSin[a+b*x]]]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sqrt[ArcSin[a_.+b_.*x_]],x_Symbol] := + (a+b*x)*Sqrt[ArcSin[a+b*x]]/b - + Sqrt[Pi/2]*FresnelS[Sqrt[2/Pi]*Sqrt[ArcSin[a+b*x]]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 465*) + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[ArcSin[a_.+b_.*x_]^n_,x_Symbol] := + (a+b*x)*ArcSin[a+b*x]^n/b + + n*Sqrt[1-(a+b*x)^2]*ArcSin[a+b*x]^(n-1)/b - + Dist[n*(n-1),Int[ArcSin[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts twice*) + + +Int[ArcSin[a_.+b_.*x_]^n_,x_Symbol] := + (a+b*x)*ArcSin[a+b*x]^(n+2)/(b*(n+1)*(n+2)) + + Sqrt[1-(a+b*x)^2]*ArcSin[a+b*x]^(n+1)/(b*(n+1)) - + Dist[1/((n+1)*(n+2)),Int[ArcSin[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 && n!=-2 + + +Int[ArcSin[a_.+b_.*x_]^n_,x_Symbol] := + I*ArcSin[a+b*x]^n*(-(I*ArcSin[a+b*x])^n*Gamma[n+1,-I*ArcSin[a+b*x]] + + (-I*ArcSin[a+b*x])^n*Gamma[n+1,I*ArcSin[a+b*x]])/(2*b*(ArcSin[a+b*x]^2)^n) /; +FreeQ[{a,b,n},x] && (Not[RationalQ[n]] || -10 + + +(* ::Subsubsection::Closed:: *) +(*x ArcSin[a+b x]^n/Sqrt[1-(a+b x)^2] Products of x and powers of arcsines of linears divided by sqrt of linear*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*ArcSin[a_.+b_.*x_]^n_/Sqrt[u_],x_Symbol] := + -Sqrt[u]*ArcSin[a+b*x]^n/b^2 + + Dist[n/b,Int[ArcSin[a+b*x]^(n-1),x]] - + Dist[a/b,Int[ArcSin[a+b*x]^n/Sqrt[u],x]] /; +FreeQ[{a,b},x] && ZeroQ[u-1+(a+b*x)^2] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*u ArcSin[c / (a+b x^n)]^m Powers of arcsines of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcSin[z] == ArcCsc[1/z]*) + + +Int[u_.*ArcSin[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcCsc[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcSin[x]] / Sqrt[1-x^2] Products of functions of inverse sines and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[ArcSin[x]]/Sqrt[1-x^2] == f[ArcSin[x]]*ArcSin'[x]*) + + +(* Int[u_/Sqrt[1-x_^2],x_Symbol] := + Subst[Int[Regularize[SubstFor[ArcSin[x],u,x],x],x],x,ArcSin[x]] /; +FunctionOfQ[ArcSin[x],u,x] *) + + +(* ::Subsubsection::Closed:: *) +(*u ArcSin[v] Products of expressions and arcsines of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcSin[u_],x_Symbol] := + x*ArcSin[u] - + Int[Regularize[x*D[u,x]/Sqrt[1-u^2],x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Subsubsection::Closed:: *) +(*f^(c ArcSin[a+b x]) Exponentials of arcsines of linears*) + + +Int[f_^(c_.*ArcSin[a_.+b_.*x_]),x_Symbol] := + f^(c*ArcSin[a+b*x])*(a+b*x+c*Sqrt[1-(a+b*x)^2]*Log[f])/(b*(1+c^2*Log[f]^2)) /; +FreeQ[{a,b,c,f},x] && NonzeroQ[1+c^2*Log[f]^2] + + +(* ::Subsection::Closed:: *) +(*Arccosine Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcCos[a+b x]^n Powers of arccosines of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.814.1, CRC 442, A&S 4.4.59*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCos[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcCos[a+b*x]/b - Sqrt[1-(a+b*x)^2]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/ArcCos[z] == -Sin[ArcCos[z]]/ArcCos[z]*ArcCos'[z]*) + + +Int[1/ArcCos[a_.+b_.*x_],x_Symbol] := + -SinIntegral[ArcCos[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[1/ArcCos[a_.+b_.*x_]^2,x_Symbol] := + Sqrt[1-(a+b*x)^2]/(b*ArcCos[a+b*x]) - CosIntegral[ArcCos[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/Sqrt[ArcCos[z]] == -Sin[ArcCos[z]]/Sqrt[ArcCos[z]]*ArcCos'[z]*) + + +Int[1/Sqrt[ArcCos[a_.+b_.*x_]],x_Symbol] := + -Sqrt[2*Pi]*FresnelS[Sqrt[2/Pi]*Sqrt[ArcCos[a+b*x]]]/b /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Sqrt[ArcCos[a_.+b_.*x_]],x_Symbol] := + (a+b*x)*Sqrt[ArcCos[a+b*x]]/b - Sqrt[Pi/2]*FresnelC[Sqrt[2/Pi]*Sqrt[ArcCos[a+b*x]]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 466*) + + +(* ::Item:: *) +(*Derivation: Iterated integration by parts*) + + +Int[ArcCos[a_.+b_.*x_]^n_,x_Symbol] := + (a+b*x)*ArcCos[a+b*x]^n/b - + n*Sqrt[1-(a+b*x)^2]*ArcCos[a+b*x]^(n-1)/b - + Dist[n*(n-1),Int[ArcCos[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts twice*) + + +Int[ArcCos[a_.+b_.*x_]^n_,x_Symbol] := + (a+b*x)*ArcCos[a+b*x]^(n+2)/(b*(n+1)*(n+2)) - + Sqrt[1-(a+b*x)^2]*ArcCos[a+b*x]^(n+1)/(b*(n+1)) - + Dist[1/((n+1)*(n+2)),Int[ArcCos[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 && n!=-2 + + +Int[ArcCos[a_.+b_.*x_]^n_,x_Symbol] := + ArcCos[a+b*x]^n*((I*ArcCos[a+b*x])^n*Gamma[n+1,-I*ArcCos[a+b*x]] + + (-I*ArcCos[a+b*x])^n*Gamma[n+1,I*ArcCos[a+b*x]])/(2*b*(ArcCos[a+b*x]^2)^n) /; +FreeQ[{a,b,n},x] && (Not[RationalQ[n]] || -10 + + +(* ::Subsubsection::Closed:: *) +(*x ArcCos[a+b x]^n/Sqrt[1-(a+b x)^2] Products of x and powers of arccosines of linears divided by sqrt of linear*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*ArcCos[a_.+b_.*x_]^n_/Sqrt[u_],x_Symbol] := + -Sqrt[u]*ArcCos[a+b*x]^n/b^2 - + Dist[n/b,Int[ArcCos[a+b*x]^(n-1),x]] - + Dist[a/b,Int[ArcCos[a+b*x]^n/Sqrt[u],x]] /; +FreeQ[{a,b},x] && ZeroQ[u-1+(a+b*x)^2] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*u ArcCos[c / (a+b x^n)]^m Powers of arccosines of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCos[z] == ArcSec[1/z]*) + + +Int[u_.*ArcCos[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcSec[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcCos[x]] / Sqrt[1-x^2] Products of functions of inverse cosines and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/Sqrt[1-z^2] == -ArcCos'[z]*) + + +(* Int[u_/Sqrt[1-x_^2],x_Symbol] := + -Subst[Int[Regularize[SubstFor[ArcCos[x],u,x],x],x],x,ArcCos[x]] /; +FunctionOfQ[ArcCos[x],u,x] *) + + +(* ::Subsubsection::Closed:: *) +(*u ArcCos[v] Products of expressions and arccosines of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCos[u_],x_Symbol] := + x*ArcCos[u] + + Int[Regularize[x*D[u,x]/Sqrt[1-u^2],x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Subsubsection::Closed:: *) +(*f^(c ArcCos[a+b x]) Exponentials of arccosines of linears*) + + +Int[f_^(c_.*ArcCos[a_.+b_.*x_]),x_Symbol] := + f^(c*ArcCos[a+b*x])*(a+b*x-c*Sqrt[1-(a+b*x)^2]*Log[f])/(b*(1+c^2*Log[f]^2)) /; +FreeQ[{a,b,c,f},x] && NonzeroQ[1+c^2*Log[f]^2] + + +(* ::Subsection::Closed:: *) +(*Arctangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcTan[a+b x^n] Arctangents of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.822.1, CRC 443, A&S 4.4.60*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcTan[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcTan[a+b*x]/b - Log[1+(a+b*x)^2]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcTan[a_.+b_.*x_^n_],x_Symbol] := + x*ArcTan[a+b*x^n] - + Dist[b*n,Int[x^n/(1+a^2+2*a*b*x^n+b^2*x^(2*n)),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcTan[a+b x^n] Products of monomials and arctangents of binomials*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: ArcTan[z] == I/2*Log[1-I*z] - I/2*Log[1+I*z]*) + + +Int[ArcTan[a_.+b_.*x_^n_.]/x_,x_Symbol] := + Dist[I/2,Int[Log[1-I*a-I*b*x^n]/x,x]] - + Dist[I/2,Int[Log[1+I*a+I*b*x^n]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Int[ArcTan[a_.+b_.*x_]/x_,x_Symbol] := + Log[x]*ArcTan[a+b*x] - + Dist[b,Int[Log[x]/(1+(a+b*x)^2),x]] /; +FreeQ[{a,b},x] *) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.851, CRC 456, A&S 4.4.69*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcTan[a_.+b_.*x_^n_.],x_Symbol] := + x^(m+1)*ArcTan[a+b*x^n]/(m+1) - + Dist[b*n/(m+1),Int[x^(m+n)/(1+a^2+2*a*b*x^n+b^2*x^(2*n)),x]] /; +FreeQ[{a,b,m},x] && IntegerQ[n] && NonzeroQ[m+1] && NonzeroQ[m-n+1] + + +(* ::Subsubsection::Closed:: *) +(*(1+x^2)^m ArcTan[x]^n Products of powers of binomials and powers of arctangents*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(1+x_^2)^m_*ArcTan[x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[(1+x^2)^m,x]]}, + u*ArcTan[x]^n - + Dist[n,Int[u*ArcTan[x]^(n-1)/(1+x^2),x]]] /; +IntegerQ[{m,n}] && m<-1 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*(1+x^2)^m ArcCot[x]^n ArcTan[x]^p Products of powers of binomials, arccotangents and arctangents*) + + +Int[1/((1+x_^2)*ArcCot[x_]*ArcTan[x_]),x_Symbol] := + (-Log[ArcCot[x]]+Log[ArcTan[x]])/(ArcCot[x]+ArcTan[x]) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCot[x_]^n_.*ArcTan[x_]^p_./(1+x_^2),x_Symbol] := + -ArcCot[x]^(n+1)*ArcTan[x]^p/(n+1) + + Dist[p/(n+1),Int[ArcCot[x]^(n+1)*ArcTan[x]^(p-1)/(1+x^2),x]] /; +IntegerQ[{n,p}] && 01 + + +Int[x_*ArcTan[a_+b_.*x_]^n_,x_Symbol] := + ((a+b*x)^2+1)*ArcTan[a+b*x]^n/(2*b^2) - + Dist[n/(2*b),Int[ArcTan[a+b*x]^(n-1),x]] - + Dist[a/b,Int[ArcTan[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*u ArcTan[c / (a+b x^n)] Arctangents of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTan[z] == ArcCot[1/z]*) + + +Int[u_.*ArcTan[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcCot[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcTan[x]] (1+x^2)^n Products of functions of arctangents and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/(1+z^2) == ArcTan'[z]*) + + +Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[a^n,Subst[Int[Regularize[Cos[x]^(-2*(n+1))*SubstFor[ArcTan[x],u,x],x],x],x,ArcTan[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTan[x],u,x] && ZeroQ[a-b] && IntegerQ[n] && n<-1 + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[a^n,Subst[Int[Regularize[Cos[x]^(-2*(n+1))*SubstFor[ArcTan[x],u,x],x],x],x,ArcTan[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTan[x],u,x] && ZeroQ[a-b] && HalfIntegerQ[n] && n<-1 && + PositiveQ[a] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[1/a,Subst[Int[Regularize[(a*Sec[x]^2)^(n+1)*SubstFor[ArcTan[x],u,x],x],x],x,ArcTan[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTan[x],u,x] && ZeroQ[a-b] && HalfIntegerQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m f[ArcTan[x]] (1+x^2)^n Products of monomials, functions of arctangents and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/(1+z^2) == ArcTan'[z]*) + + +Int[x_^m_.*u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[a^n,Subst[Int[Regularize[Tan[x]^m*Cos[x]^(-2*(n+1))*SubstFor[ArcTan[x],u,x],x],x],x,ArcTan[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTan[x],u,x] && ZeroQ[a-b] && IntegerQ[{m,n}] && n<0 + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[a^n,Subst[Int[Regularize[Tan[x]^m*Cos[x]^(-2*(n+1))*SubstFor[ArcTan[x],u,x],x],x],x,ArcTan[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcTan[x],u,x] && ZeroQ[a-b] && HalfIntegerQ[n] && n<-1 && + PositiveQ[a] && IntegerQ[m] +(* Need to generalize for arbitrary functions of ArcTan[Sqrt[b/a]*x] *) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* Int[f_[ArcTan[c_.*x_]]/(a_+b_.*x_^2),x_Symbol] := + Dist[1/(a*Sqrt[b/a]),Subst[Int[f[x],x],x,ArcTan[c*x]]] /; +FreeQ[{a,b,c,f},x] && c===Sqrt[b/a] *) + + +(* ::Subsubsection::Closed:: *) +(*v ArcTan[u] Products of expressions and arctangents of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcTan[u_],x_Symbol] := + x*ArcTan[u] - + Int[Regularize[x*D[u,x]/(1+u^2),x],x] /; +InverseFunctionFreeQ[u,x] && + Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcTan[u_],x_Symbol] := + x^(m+1)*ArcTan[u]/(m+1) - + Dist[1/(m+1),Int[Regularize[x^(m+1)*D[u,x]/(1+u^2),x],x]] /; +FreeQ[m,x] && NonzeroQ[m+1] && InverseFunctionFreeQ[u,x] && + Not[FunctionOfQ[x^(m+1),u,x]] && + FalseQ[PowerVariableExpn[u,m+1,x]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[v_*ArcTan[u_],x_Symbol] := + Module[{w=Block[{ShowSteps=False,StepCounter=Null}, Int[v,x]]}, + w*ArcTan[u] - + Int[Regularize[w*D[u,x]/(1+u^2),x],x] /; + InverseFunctionFreeQ[w,x]] /; +InverseFunctionFreeQ[u,x] && + Not[MatchQ[v, x^m_. /; FreeQ[m,x]]] && + FalseQ[FunctionOfLinear[v*ArcTan[u],x]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTan[z] == I/2*Log[1-I*z] - I/2*Log[1+I*z]*) + + +Int[ArcTan[b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[I/2,Int[Log[1-I*b*x]/(c+d*x^n),x]] - + Dist[I/2,Int[Log[1+I*b*x]/(c+d*x^n),x]] /; +FreeQ[{b,c,d},x] && IntegerQ[n] && Not[n==2 && ZeroQ[b^2*c-d]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcTan[z] == I/2*Log[1-I*z] - I/2*Log[1+I*z]*) + + +Int[ArcTan[a_+b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[I/2,Int[Log[1-I*a-I*b*x]/(c+d*x^n),x]] - + Dist[I/2,Int[Log[1+I*a+I*b*x]/(c+d*x^n),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[n] && Not[n==1 && ZeroQ[a*d-b*c]] + + +(* ::Subsection::Closed:: *) +(*Arccotangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcCot[a+b x^n] Arccotangents of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.822.2, CRC 444, A&S 4.4.63*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCot[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcCot[a+b*x]/b + Log[1+(a+b*x)^2]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCot[a_.+b_.*x_^n_],x_Symbol] := + x*ArcCot[a+b*x^n] + + Dist[b*n,Int[x^n/(1+a^2+2*a*b*x^n+b^2*x^(2*n)),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcCot[a+b x^n] Products of monomials and arccotangents of binomials*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: ArcCot[z] == I/2*Log[1-I/z] - I/2*Log[1+I/z]*) + + +Int[ArcCot[a_.+b_.*x_^n_.]/x_,x_Symbol] := + Dist[I/2,Int[Log[1-I/(a+b*x^n)]/x,x]] - + Dist[I/2,Int[Log[1+I/(a+b*x^n)]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Int[ArcCot[a_.+b_.*x_]/x_,x_Symbol] := + Log[x]*ArcCot[a+b*x] + + Dist[b,Int[Log[x]/(1+(a+b*x)^2),x]] /; +FreeQ[{a,b},x] *) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.852, CRC 458, A&S 4.4.71*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcCot[a_.+b_.*x_^n_.],x_Symbol] := + x^(m+1)*ArcCot[a+b*x^n]/(m+1) + + Dist[b*n/(m+1),Int[x^(m+n)/(1+a^2+2*a*b*x^n+b^2*x^(2*n)),x]] /; +FreeQ[{a,b,m},x] && IntegerQ[n] && NonzeroQ[m+1] && NonzeroQ[m-n+1] + + +(* ::Subsubsection::Closed:: *) +(*(1+x^2)^m ArcCot[x]^n Products of powers of binomials and powers of arccotangents*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(1+x_^2)^m_*ArcCot[x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[(1+x^2)^m,x]]}, + u*ArcCot[x]^n + + Dist[n,Int[u*ArcCot[x]^(n-1)/(1+x^2),x]]] /; +IntegerQ[{m,n}] && m<-1 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*(1+x^2)^m ArcCot[x]^n ArcTan[x]^p Products of powers of binomials, arccotangents and arctangents*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCot[x_]^n_.*ArcTan[x_]^p_/(1+x_^2),x_Symbol] := + ArcCot[x]^n*ArcTan[x]^(p+1)/(p+1) + + Dist[n/(p+1),Int[ArcCot[x]^(n-1)*ArcTan[x]^(p+1)/(1+x^2),x]] /; +IntegerQ[{n,p}] && 00 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*x ArcCot[a+b x]^n Products of x and powers of arccotangents of linears*) + + +Int[x_*ArcCot[b_.*x_]^n_,x_Symbol] := + ((b*x)^2+1)*ArcCot[b*x]^n/(2*b^2) + + Dist[n/(2*b),Int[ArcCot[b*x]^(n-1),x]] /; +FreeQ[b,x] && RationalQ[n] && n>1 + + +Int[x_*ArcCot[a_.+b_.*x_]^n_,x_Symbol] := + ((a+b*x)^2+1)*ArcCot[a+b*x]^n/(2*b^2) + + Dist[n/(2*b),Int[ArcCot[a+b*x]^(n-1),x]] - + Dist[a/b,Int[ArcCot[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*u ArcCot[c / (a+b x^n)] Inverse cotangent of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCot[z] == ArcTan[1/z]*) + + +Int[u_.*ArcCot[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcTan[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*f[ArcCot[x]] (1+x^2)^n Products of functions of arccotangents and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/(1+z^2) == -ArcCot'[z]*) + + +Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[-a^n,Subst[Int[Regularize[Sin[x]^(-2*(n+1))*SubstFor[ArcCot[x],u,x],x],x],x,ArcCot[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcCot[x],u,x] && ZeroQ[a-b] && IntegerQ[n] && n<-1 + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[-1/a,Subst[Int[Regularize[(a*Csc[x]^2)^(n+1)*SubstFor[ArcCot[x],u,x],x],x],x,ArcCot[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcCot[x],u,x] && ZeroQ[a-b] && HalfIntegerQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m f[ArcCot[x]] (1+x^2)^n Products of monomials, functions of arccotangents and its derivative*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/(1+z^2) == -ArcCot'[z]*) + + +Int[x_^m_.*u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[-a^n,Subst[Int[Regularize[Cot[x]^m*Sin[x]^(-2*(n+1))*SubstFor[ArcCot[x],u,x],x],x],x,ArcCot[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcCot[x],u,x] && ZeroQ[a-b] && IntegerQ[{m,n}] && n<0 + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ??? *) +Int[x_^m_.*u_*(a_+b_.*x_^2)^n_,x_Symbol] := + Dist[-a^n,Subst[Int[Regularize[Cot[x]^m*Sin[x]^(-2*(n+1))*SubstFor[ArcCot[x],u,x],x],x],x,ArcCot[x]]] /; +FreeQ[{a,b},x] && FunctionOfQ[ArcCot[x],u,x] && ZeroQ[a-b] && HalfIntegerQ[n] && n<-1 && + PositiveQ[a] && IntegerQ[m] + + +(* ::Subsubsection::Closed:: *) +(*v ArcCot[u] Products of expressions and arccotangents of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCot[u_],x_Symbol] := + x*ArcCot[u] + + Int[Regularize[x*D[u,x]/(1+u^2),x],x] /; +InverseFunctionFreeQ[u,x] && + Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcCot[u_],x_Symbol] := + x^(m+1)*ArcCot[u]/(m+1) + + Dist[1/(m+1),Int[Regularize[x^(m+1)*D[u,x]/(1+u^2),x],x]] /; +FreeQ[m,x] && NonzeroQ[m+1] && InverseFunctionFreeQ[u,x] && + Not[FunctionOfQ[x^(m+1),u,x]] && + FalseQ[PowerVariableExpn[u,m+1,x]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[v_*ArcCot[u_],x_Symbol] := + Module[{w=Block[{ShowSteps=False,StepCounter=Null}, Int[v,x]]}, + w*ArcCot[u] + + Int[Regularize[w*D[u,x]/(1+u^2),x],x] /; + InverseFunctionFreeQ[w,x]] /; +InverseFunctionFreeQ[u,x] && + Not[MatchQ[v, x^m_. /; FreeQ[m,x]]] && + FalseQ[FunctionOfLinear[v*ArcCot[u],x]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCot[z] == I/2*Log[1-I/z] - I/2*Log[1+I/z]*) + + +Int[ArcCot[b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[I/2,Int[Log[1-I/(b*x)]/(c+d*x^n),x]] - + Dist[I/2,Int[Log[1+I/(b*x)]/(c+d*x^n),x]] /; +FreeQ[{b,c,d},x] && IntegerQ[n] && Not[n==2 && ZeroQ[b^2*c-d]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCot[z] == I/2*Log[1-I/z] - I/2*Log[1+I/z]*) + + +Int[ArcCot[a_+b_.*x_]/(c_+d_.*x_^n_.),x_Symbol] := + Dist[I/2,Int[Log[1-I/(a+b*x)]/(c+d*x^n),x]] - + Dist[I/2,Int[Log[1+I/(a+b*x)]/(c+d*x^n),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[n] && Not[n==1 && ZeroQ[a*d-b*c]] + + +(* ::Subsection::Closed:: *) +(*Arcsecant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcSec[a+b x]^n Powers of arcsecants of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.821.2, CRC 445', A&S 4.4.62'*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcSec[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcSec[a+b*x]/b - + Int[1/((a+b*x)*Sqrt[1-1/(a+b*x)^2]),x] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcSec[a+b x] Products of monomials and arcsecants of binomials*) + + +Int[ArcSec[a_.*x_^n_.]/x_,x_Symbol] := + I*ArcSec[a*x^n]^2/(2*n) - + ArcSec[a*x^n]*Log[1-1/(I/(x^n*a)+Sqrt[1-1/(x^(2*n)*a^2)])^2]/n + + I*PolyLog[2,1/(I/(x^n*a)+Sqrt[1-1/(x^(2*n)*a^2)])^2]/(2*n) /; +(* Sqrt[-1/a^2]*a*ArcCsc[a*x^n]^2/(2*n) + + Pi*Log[x]/2 - + Sqrt[-1/a^2]*a*ArcSinh[Sqrt[-1/a^2]/x^n]*Log[1-1/(Sqrt[-(1/a^2)]/x^n+Sqrt[1-1/(x^(2*n)*a^2)])^2]/n + + Sqrt[-1/a^2]*a*PolyLog[2, 1/(Sqrt[-1/a^2]/x^n+Sqrt[1-1/(x^(2*n)*a^2)])^2]/(2*n) *) +FreeQ[{a,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*ArcSec[a_+b_.*x_],x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*ArcSec[x],x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Reference: CRC 474*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcSec[a_.*x_],x_Symbol] := + x^(m+1)*ArcSec[a*x]/(m+1) - + Dist[1/(a*(m+1)),Int[x^(m-1)/Sqrt[1-1/(a*x)^2],x]] /; +FreeQ[{a,m},x] && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Reference: CRC 474*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcSec[a_.+b_.*x_],x_Symbol] := + x^(m+1)*ArcSec[a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)/(Sqrt[1-1/(a+b*x)^2]*(a+b*x)^2),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*u ArcSec[c / (a+b x^n)]^m Powers of arcsecants of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcSec[z] == ArcCos[1/z]*) + + +Int[u_.*ArcSec[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcCos[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*v ArcSec[u] Products of expressions and arcsecants of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcSec[u_],x_Symbol] := + x*ArcSec[u] - + Int[Regularize[x*D[u,x]/(u^2*Sqrt[1-1/u^2]),x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] + + +(* ::Subsection::Closed:: *) +(*Arccosecant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ArcCsc[a+b x]^n Powers of arcsecants of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.821.1, CRC 446', A&S 4.4.61'*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCsc[a_.+b_.*x_],x_Symbol] := + (a+b*x)*ArcCsc[a+b*x]/b + + Int[1/((a+b*x)*Sqrt[1-1/(a+b*x)^2]),x] /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m ArcCsc[a+b x] Products of monomials and arccosecants of binomials*) + + +Int[ArcCsc[a_.*x_^n_.]/x_,x_Symbol] := +(* Int[ArcSin[1/a*x^(-n)]/x,x] /; *) + I*ArcCsc[a*x^n]^2/(2*n) - + ArcCsc[a*x^n]*Log[1-(I/(x^n*a)+Sqrt[1-1/(x^(2*n)*a^2)])^2]/n + + I*PolyLog[2,(I/(x^n*a)+Sqrt[1-1/(x^(2*n)*a^2)])^2]/(2*n) /; +(* -Sqrt[-1/a^2]*a*ArcCsc[a*x^n]^2/(2*n) - + ArcCsc[a*x^n]*Log[2*(1/(x^n*a^2) + Sqrt[-1/a^2]*Sqrt[1-1/(x^(2*n)*a^2)])/x^n]/n - + Sqrt[-1/a^2]*a*PolyLog[2, 1-2*(1/(x^n*a^2)+Sqrt[-1/a^2]*Sqrt[1-1/(x^(2*n)*a^2)])/x^n]/(2*n) /; *) +FreeQ[{a,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_.*ArcCsc[a_+b_.*x_],x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*ArcCsc[x],x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Reference: CRC 477*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcCsc[a_.*x_],x_Symbol] := + x^(m+1)*ArcCsc[a*x]/(m+1) + + Dist[1/(a*(m+1)),Int[x^(m-1)/Sqrt[1-1/(a*x)^2],x]] /; +FreeQ[{a,m},x] && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Reference: CRC 477*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ArcCsc[a_.+b_.*x_],x_Symbol] := + x^(m+1)*ArcCsc[a+b*x]/(m+1) + + Dist[b/(m+1),Int[x^(m+1)/(Sqrt[1-1/(a+b*x)^2]*(a+b*x)^2),x]] /; +FreeQ[{a,b,m},x] && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*u ArcCsc[c / (a+b x^n)] Inverse cosecant of reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: ArcCsc[z] == ArcSin[1/z]*) + + +Int[u_.*ArcCsc[c_./(a_.+b_.*x_^n_.)]^m_.,x_Symbol] := + Int[u*ArcSin[a/c+b*x^n/c]^m,x] /; +FreeQ[{a,b,c,n,m},x] + + +(* ::Subsubsection::Closed:: *) +(*v ArcCsc[u] Products of expressions and arccosecants of inverse free functions*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ArcCsc[u_],x_Symbol] := + x*ArcCsc[u] + + Int[Regularize[x*D[u,x]/(u^2*Sqrt[1-1/u^2]),x],x] /; +InverseFunctionFreeQ[u,x] && Not[MatchQ[u,c_.+d_.*f_^(a_.+b_.*x) /; FreeQ[{a,b,c,d,f},x]]] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/LogarithmFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/LogarithmFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/LogarithmFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/LogarithmFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,654 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Logarithm Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Log[c (a+b x)^n] Logarithms of powers of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.711.1, CRC 499, A&S 4.1.49*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(a_.+b_.*x_)^n_.],x_Symbol] := + (a+b*x)*Log[c*(a+b*x)^n]/b - n*x /; +FreeQ[{a,b,c,n},x] + + +(* ::Subsection::Closed:: *) +(*(d+e x)^m Log[c (a+b x)^n] Products of powers of linears and logarithms of powers of linears*) +(**) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.728.2*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[-PolyLog[2, d+e*x]/e, x] == Log[1-d-e*x]/(d+e*x)*) + + +Int[Log[c_.*(a_.+b_.*x_)]/(d_+e_.*x_),x_Symbol] := + -PolyLog[2,1-a*c-b*c*x]/e /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a*c*e-b*c*d-e] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(a_.+b_.*x_)^n_.]/(d_+e_.*x_),x_Symbol] := + Log[c*(a+b*x)^n]*Log[b*(d+e*x)/(b*d-a*e)]/e + + n*PolyLog[2,-e*(a+b*x)/(b*d-a*e)]/e /; +FreeQ[{a,b,c,d,e,n},x] && NonzeroQ[b*d-a*e] + + +(* ::Subsection::Closed:: *) +(*Log[c (a+b x^n)^p] Logarithms of powers of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.728.1*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(b_.*x_^n_)^p_.],x_Symbol] := + x*Log[c*(b*x^n)^p] - n*p*x /; +FreeQ[{b,c,n,p},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.728.1*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(a_+b_.*x_^n_)^p_.],x_Symbol] := + x*Log[c*(a+b*x^n)^p] - + Dist[b*n*p,Int[1/(b+a*x^(-n)),x]] /; +FreeQ[{a,b,c,p},x] && RationalQ[n] && n<0 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.728.1*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(a_+b_.*x_^n_)^p_.],x_Symbol] := + x*Log[c*(a+b*x^n)^p] - n*p*x + + Dist[a*n*p,Int[1/(a+b*x^n),x]] /; +FreeQ[{a,b,c,n,p},x] + + +(* ::Subsection::Closed:: *) +(*x^m Log[c (a+b x^n)^p] Products of monomials and logarithms of powers of binomials*) +(**) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.728.2*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[PolyLog[2,-x],x] == -Log[1+x]/x*) + + +Int[Log[1+b_.*x_^n_.]/x_,x_Symbol] := + -PolyLog[2,-b*x^n]/n /; +FreeQ[{b,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If a>0, Log[a*z] == Log[a] + Log[z]*) + + +Int[Log[c_.*(a_+b_.*x_^n_.)]/x_,x_Symbol] := + Log[a*c]*Log[x] + + Int[Log[1+b*x^n/a]/x,x] /; +FreeQ[{a,b,c,n},x] && PositiveQ[a*c] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(a_+b_.*x_^n_.)^p_.]/x_,x_Symbol] := + Log[c*(a+b*x^n)^p]*Log[-b*x^n/a]/n - + Dist[b*p,Int[x^(n-1)*Log[-b*x^n/a]/(a+b*x^n),x]] /; +(* p*PolyLog[2,1+b*x^n/a]/n /; *) +FreeQ[{a,b,c,n,p},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.728.1, CRC 501, A&S 4.1.50'*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Log[c_.*(b_.*x_^n_.)^p_.],x_Symbol] := + x^(m+1)*Log[c*(b*x^n)^p]/(m+1) - n*p*x^(m+1)/(m+1)^2 /; +FreeQ[{b,c,m,n,p},x] && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.728.1, CRC 501, A&S 4.1.50'*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Log[c_.*(a_+b_.*x_^n_.)^p_.],x_Symbol] := + x^(m+1)*Log[c*(a+b*x^n)^p]/(m+1) - + Dist[b*n*p/(m+1),Int[x^(m+n)/(a+b*x^n),x]] /; +FreeQ[{a,b,c,m,n,p},x] && NonzeroQ[m+1] && NonzeroQ[m-n+1] + + +(* ::Subsection::Closed:: *) +(*(a+b Log[c (d+e x)^n])^p Powers of linear binomials of logarithms*) + + +(* ::Item::Closed:: *) +(*Reference: CRC 492*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[LogIntegral[x],x] == 1/Log[x]*) + + +Int[1/Log[c_.*(d_.+e_.*x_)],x_Symbol] := + LogIntegral[c*(d+e*x)]/(c*e) /; +FreeQ[{c,d,e},x] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[ExpIntegralEi[x],x] == E^x/x*) + + +Int[1/(a_.+b_.*Log[c_.*(d_.+e_.*x_)^n_.]),x_Symbol] := + (d+e*x)*ExpIntegralEi[(a+b*Log[c*(d+e*x)^n])/(b*n)]/(b*e*n*E^(a/(b*n))*(c*(d+e*x)^n)^(1/n)) /; +FreeQ[{a,b,c,d,e,n},x] + + +Int[1/Sqrt[a_.+b_.*Log[c_.*(d_.+e_.*x_)^n_.]],x_Symbol] := + Sqrt[Pi]*(d+e*x)*Erfi[Rt[1/(b*n),2]*Sqrt[a+b*Log[c*(d+e*x)^n]]]/ + (b*e*n*Rt[1/(b*n),2]*E^(a/(b*n))*(c*(d+e*x)^n)^(1/n)) /; +FreeQ[{a,b,c,d,e,n},x] && PosQ[1/(b*n)] + + +Int[1/Sqrt[a_.+b_.*Log[c_.*(d_.+e_.*x_)^n_.]],x_Symbol] := + Sqrt[Pi]*(d+e*x)*Erf[Rt[-1/(b*n),2]*Sqrt[a+b*Log[c*(d+e*x)^n]]]/ + (b*e*n*Rt[-1/(b*n),2]*E^(a/(b*n))*(c*(d+e*x)^n)^(1/n)) /; +FreeQ[{a,b,c,d,e,n},x] && NegQ[1/(b*n)] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.711.1, CRC 490*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(a_.+b_.*Log[c_.*x_^n_.])^p_,x_Symbol] := + x*(a+b*Log[c*x^n])^p - + Dist[b*n*p,Int[(a+b*Log[c*x^n])^(p-1),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>0 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.711.1, CRC 490*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(d_.+e_.*x_)^n_.]^p_,x_Symbol] := + (d+e*x)*Log[c*(d+e*x)^n]^p/e - + Dist[n*p,Int[Log[c*(d+e*x)^n]^(p-1),x]] /; +FreeQ[{c,d,e,n},x] && RationalQ[p] && p>0 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.711.1, CRC 490*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(a_.+b_.*Log[c_.*(d_.+e_.*x_)^n_.])^p_,x_Symbol] := + x*(a+b*Log[c*(d+e*x)^n])^p - + Dist[b*e*n*p,Int[x*(a+b*Log[c*(d+e*x)^n])^(p-1)/(d+e*x),x]] /; +FreeQ[{a,b,c,d,e,n},x] && RationalQ[p] && p>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[(a_.+b_.*Log[c_.*x_^n_.])^p_,x_Symbol] := + x*(a+b*Log[c*x^n])^(p+1)/(b*n*(p+1)) - + Dist[1/(b*n*(p+1)),Int[(a+b*Log[c*x^n])^(p+1),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[Log[c_.*(d_.+e_.*x_)^n_.]^p_,x_Symbol] := + (d+e*x)*Log[c*(d+e*x)^n]^(p+1)/(e*n*(p+1)) - + Dist[1/(n*(p+1)),Int[Log[c*(d+e*x)^n]^(p+1),x]] /; +FreeQ[{c,d,e,n},x] && RationalQ[p] && p<-1 + + +Int[(a_.+b_.*Log[c_.*(d_.+e_.*x_)^n_.])^p_,x_Symbol] := + (d+e*x)*Gamma[p+1,-(a+b*Log[c*(d+e*x)^n])/(b*n)]*(a+b*Log[c*(d+e*x)^n])^p/ + (e*(-(a+b*Log[c*(d+e*x)^n])/(b*n))^p*E^(a/(b*n))*(c*(d+e*x)^n)^(1/n)) /; +FreeQ[{a,b,c,d,e,n,p},x] && NonzeroQ[p+1] + + +(* ::Subsection::Closed:: *) +(*x^m (a+b Log[c x^n])^p Products of monomials and powers of linear binomials of logarithms*) +(**) + + +Int[x_^m_./(a_.+b_.*Log[c_.*x_^n_.]),x_Symbol] := + x^(m+1)*ExpIntegralEi[(m+1)*(a+b*Log[c*x^n])/(b*n)]/(b*n*E^(a*(m+1)/(b*n))*(c*x^n)^((m+1)/n)) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[m+1] + + +Int[x_^m_./Sqrt[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + Sqrt[Pi]*x^(m+1)*Erfi[Rt[(m+1)/(b*n),2]*Sqrt[a+b*Log[c*x^n]]]/ + (b*n*Rt[(m+1)/(b*n),2]*E^(a*(m+1)/(b*n))*(c*x^n)^((m+1)/n)) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[m+1] && PosQ[(m+1)/(b*n)] + + +Int[x_^m_./Sqrt[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + Sqrt[Pi]*x^(m+1)*Erf[Rt[-(m+1)/(b*n),2]*Sqrt[a+b*Log[c*x^n]]]/ + (b*n*Rt[-(m+1)/(b*n),2]*E^(a*(m+1)/(b*n))*(c*x^n)^((m+1)/n)) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[m+1] && NegQ[(m+1)/(b*n)] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.721.1, CRC 496, A&S 4.1.51*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*(a_.+b_.*Log[c_.*x_^n_.])^p_,x_Symbol] := + x^(m+1)*(a+b*Log[c*x^n])^p/(m+1) - + Dist[b*n*p/(m+1),Int[x^m*(a+b*Log[c*x^n])^(p-1),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>0 && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.724.1, CRC 495*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*(a_.+b_.*Log[c_.*x_^n_.])^p_,x_Symbol] := + x^(m+1)*(a+b*Log[c*x^n])^(p+1)/(b*n*(p+1)) - + Dist[(m+1)/(b*n*(p+1)),Int[x^m*(a+b*Log[c*x^n])^(p+1),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && NonzeroQ[m+1] + + +Int[x_^m_.*(a_.+b_.*Log[c_.*x_^n_.])^p_,x_Symbol] := + x^(m+1)*Gamma[p+1,-(m+1)*(a+b*Log[c*x^n])/(b*n)]*(a+b*Log[c*x^n])^p/ + ((m+1)*E^(a*(m+1)/(b*n))*(c*x^n)^((m+1)/n)*(-(m+1)*(a+b*Log[c*x^n])/(b*n))^p) /; +FreeQ[{a,b,c,m,n,p},x] && NonzeroQ[m+1] + + +(* Need a rule for arbitrarily deep nesting of powers! *) +Int[Log[a_.*(b_.*x_^n_.)^p_]^q_.,x_Symbol] := + Subst[Int[Log[x^(n*p)]^q,x],x^(n*p),a*(b*x^n)^p] /; +FreeQ[{a,b,n,p,q},x] + + +Int[Log[a_.*(b_.*(c_.*x_^n_.)^p_)^q_]^r_.,x_Symbol] := + Subst[Int[Log[x^(n*p*q)]^r,x],x^(n*p*q),a*(b*(c*x^n)^p)^q] /; +FreeQ[{a,b,c,n,p,q,r},x] + + +Int[x_^m_.*Log[a_.*(b_.*x_^n_.)^p_]^q_.,x_Symbol] := + Subst[Int[x^m*Log[x^(n*p)]^q,x],x^(n*p),a*(b*x^n)^p] /; +FreeQ[{a,b,m,n,p,q},x] && NonzeroQ[m+1] && Not[x^(n*p)===a*(b*x^n)^p] + + +Int[x_^m_.*Log[a_.*(b_.*(c_.*x_^n_.)^p_)^q_]^r_.,x_Symbol] := + Subst[Int[x^m*Log[x^(n*p*q)]^r,x],x^(n*p*q),a*(b*(c*x^n)^p)^q] /; +FreeQ[{a,b,c,m,n,p,q,r},x] && NonzeroQ[m+1] && Not[x^(n*p*q)===a*(b*(c*x^n)^p)^q] + + +(* ::Subsection::Closed:: *) +(*Log[c (a+b x)^n]^p / (d+e x) Quotients of powers of logarithms of powers of binomials by x*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[c_.*(a_+b_.*x_)^n_.]^p_./(d_.+e_.*x_),x_Symbol] := + Log[c*(a+b*x)^n]^p*Log[b*(d+e*x)/(b*d-a*e)]/e - + Dist[b*n*p/e,Int[Log[c*(a+b*x)^n]^(p-1)*Log[b*(d+e*x)/(b*d-a*e)]/(a+b*x),x]] /; +FreeQ[{a,b,c,d,e,n},x] && RationalQ[p] && p>0 && NonzeroQ[b*d-a*e] + + +(* ::Item:: *) +(*Note: Log[z] == -PolyLog[1, 1-z]*) + + +Int[Log[c_.*(a_+b_.*x_)^n_.]^p_.*Log[h_.*(f_.+g_.*x_)]/(d_+e_.*x_),x_Symbol] := + Module[{q=Simplify[1-h*(f+g*x)]}, + -Log[c*(a+b*x)^n]^p*PolyLog[2,q]/e + + Dist[b*n*p/e,Int[Log[c*(a+b*x)^n]^(p-1)*PolyLog[2,q]/(a+b*x),x]]] /; +FreeQ[{a,b,c,d,e,f,g,h,n},x] && RationalQ[p] && p>0 && ZeroQ[a*e-b*d] && ZeroQ[a*g*h-b*(f*h-1)] + + +Int[Log[c_.*(a_+b_.*x_)^n_.]^p_.*PolyLog[m_,h_.*(f_.+g_.*x_)]/(d_+e_.*x_),x_Symbol] := + Log[c*(a+b*x)^n]^p*PolyLog[m+1,h*(f+g*x)]/e - + Dist[b*n*p/e,Int[Log[c*(a+b*x)^n]^(p-1)*PolyLog[m+1,h*(f+g*x)]/(a+b*x),x]] /; +FreeQ[{a,b,c,d,e,f,g,h,m,n},x] && RationalQ[p] && p>0 && ZeroQ[a*e-b*d] && ZeroQ[a*g-b*f] + + +(* ::Item:: *) +(*Note: Reduces binomial to a linear, even for fractional and symbolic m, n and p.*) + + +(* Int[Log[c_.*(a_+b_.*x_^m_)^n_.]^p_./x_,x_Symbol] := + Dist[1/m,Subst[Int[Log[c*(a+b*x)^n]^p/x,x],x,x^m]] /; +FreeQ[{a,b,c,m,n,p},x] *) + + +(* ::Subsection::Closed:: *) +(*x^m Log[c (a+b x)^n]^p Products of monomials and powers of logarithms of monomials*) +(**) + + +Int[x_^m_.*Log[c_.*(a_+b_.*x_)^n_.]^p_,x_Symbol] := + x^m*(a+b*x)*Log[c*(a+b*x)^n]^p/(b*(m+1)) - + Dist[a*m/(b*(m+1)),Int[x^(m-1)*Log[c*(a+b*x)^n]^p,x]] - + Dist[n*p/(m+1),Int[x^m*Log[c*(a+b*x)^n]^(p-1),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[{m,p}] && m>0 && p>0 + + +Int[Log[c_.*(a_+b_.*x_)^n_.]^p_/x_^2,x_Symbol] := + -(a+b*x)*Log[c*(a+b*x)^n]^p/(a*x) + + Dist[b*n*p/a,Int[Log[c*(a+b*x)^n]^(p-1)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>0 + + +Int[x_^m_.*Log[c_.*(a_+b_.*x_)^n_.]^p_,x_Symbol] := + x^(m+1)*(a+b*x)*Log[c*(a+b*x)^n]^p/(a*(m+1)) - + Dist[(b*(m+2))/(a*(m+1)),Int[x^(m+1)*Log[c*(a+b*x)^n]^p,x]] - + Dist[b*n*p/(a*(m+1)),Int[x^(m+1)*Log[c*(a+b*x)^n]^(p-1),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[{m,p}] && m<-1 && m!=-2 && p>0 + + +Int[x_^m_.*Log[c_.*(a_+b_.*x_)^n_.]^p_,x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*Log[c*x^n]^p,x],x,a+b*x]] /; +FreeQ[{a,b,c,n,p},x] && IntegerQ[m] && m>0 && Not[RationalQ[p] && p>0] + + +(* ::Subsection::Closed:: *) +(*Log[c (a+b x^m)^n]^p Powers of logarithms of binomials*) +(**) + + +(* Way kool rule! Note that the b/x in the resulting integrand will be transformed to b*x + by the rule Int[f[x^n]/x,x] -> Subst[Int[f[x]/x,x],x,x^n]/n *) +Int[Log[c_.*(a_+b_./x_)^n_.]^p_, x_Symbol] := + (b+a*x)*Log[c*(a+b/x)^n]^p/a + + Dist[b/a*n*p,Int[Log[c*(a+b/x)^n]^(p-1)/x,x]] /; +FreeQ[{a,b,c,n},x] && IntegerQ[p] && p>0 + + +Int[Log[c_.*(a_+b_.*x_^2)^n_.]^2, x_Symbol] := + x*Log[c*(a+b*x^2)^n]^2 + + 8*n^2*x - + 4*n*x*Log[c*(a+b*x^2)^n] + + (n*Sqrt[a]/Sqrt[-b])*( + 4*n*Log[(-Sqrt[a]+Sqrt[-b]*x)/(Sqrt[a]+Sqrt[-b]*x)] - + 4*n*ArcTanh[Sqrt[-b]*x/Sqrt[a]]*(Log[-Sqrt[a]/Sqrt[-b]+x] + Log[Sqrt[a]/Sqrt[-b]+x]) - + n*Log[-Sqrt[a]/Sqrt[-b]+x]^2 + + n*Log[Sqrt[a]/Sqrt[-b]+x]^2 - + 2*n*Log[Sqrt[a]/Sqrt[-b]+x]*Log[1/2-Sqrt[-b]*x/(2*Sqrt[a])] + + 2*n*Log[-Sqrt[a]/Sqrt[-b]+x]*Log[(1+Sqrt[-b]*x/Sqrt[a])/2] + + 4*ArcTanh[Sqrt[-b]*x/Sqrt[a]]*Log[c*(a+b*x^2)^n] + + 2*n*PolyLog[2,1/2-Sqrt[-b]*x/(2*Sqrt[a])] - + 2*n*PolyLog[2,(1+Sqrt[-b]*x/Sqrt[a])/2]) /; +FreeQ[{a,b,c,n},x] + + +(* ::Subsection::Closed:: *) +(*Log[d (a+b x+c x^2)^n]^p Powers of logarithms of powers of quadratics*) +(**) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[d_.*(a_.+b_.*x_+c_.*x_^2)^n_.]^2,x_Symbol] := + x*Log[d*(a+b*x+c*x^2)^n]^2 - + Dist[2*b*n,Int[x*Log[d*(a+b*x+c*x^2)^n]/(a+b*x+c*x^2),x]] - + Dist[4*c*n,Int[x^2*Log[d*(a+b*x+c*x^2)^n]/(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,n},x] + + +(* ::Subsection::Closed:: *) +(*x^m Log[a Log[b x^n]^m] Logarithms of logarithms*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[a_.*Log[b_.*x_^n_.]^p_.],x_Symbol] := + x*Log[a*Log[b*x^n]^p] - + Dist[n*p,Int[1/Log[b*x^n],x]] /; +FreeQ[{a,b,n,p},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[a_.*Log[b_.*x_^n_.]^p_.]/x_,x_Symbol] := + Log[b*x^n]*(-p+Log[a*Log[b*x^n]^p])/n /; +FreeQ[{a,b,n,p},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Log[a_.*Log[b_.*x_^n_.]^p_.],x_Symbol] := + x^(m+1)*Log[a*Log[b*x^n]^p]/(m+1) - + Dist[n*p/(m+1),Int[x^m/Log[b*x^n],x]] /; +FreeQ[{a,b,m,n,p},x] && NonzeroQ[m+1] + + +(* ::Subsection::Closed:: *) +(*Log[u] / x Quotients of logarithms by x*) + + +(* Int[Log[b_.*x_^n_.+c_.*x_^p_.]/x_,x_Symbol] := + -Log[x^n]*(Log[x^n]/2-Log[b*x^n+c*x^p]+Log[1+c*x^n/b])/n - + PolyLog[2,-c*x^n/b]/n /; +FreeQ[{b,c,n,p},x] && p===2*n *) + + +(* Int[Log[a_+b_.*x_^n_.+c_.*x_^p_.]/x_,x_Symbol] := + Module[{q=Sqrt[b^2-4*a*c]}, + -Log[x]*(Log[1+2*c*x^n/(b-q)]+Log[1+2*c*x^n/(b+q)]-Log[a+b*x^n+c*x^p]) - + PolyLog[2,-2*c*x^n/(b-q)]/n - + PolyLog[2,-2*c*x^n/(b+q)]/n] /; +FreeQ[{a,b,c,n,p},x] && p===2*n *) + + +(* Way kool rule! More generally valid for any integrand of the form f ((a+b*x)/(c+d*x))/x. *) +Int[Log[(a_.+b_.*x_)/(c_+d_.*x_)]^m_./x_,x_Symbol] := + Subst[Int[Log[a/c+x/c]^m/x,x],x,(b*c-a*d)*x/(c+d*x)] - + Subst[Int[Log[b/d+x/d]^m/x,x],x,-(b*c-a*d)/(c+d*x)] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 && NonzeroQ[b*c-a*d] + + +(* ::Subsection::Closed:: *) +(*Log[u]^n / (a+b x+...) Quotients of powers of logarithms by polynomials*) + + +(* Int[Log[u_]^n_./(a_+b_.*x_),x_Symbol] := + Dist[1/b,Subst[Int[Regularize[Log[Subst[u,x,-a/b+x/b]]^n/x,x],x],x,a+b*x]] /; +FreeQ[{a,b,n},x] && NonzeroQ[u-a-b*x] && InverseFunctionFreeQ[u,x] *) + + +(* ::Subsection::Closed:: *) +(*(A+B Log[d+e x]) / Sqrt[a+b Log[d+e x]] Quotients of linear binomials of logarithms*) + + +(* ::Item:: *) +(*Basis: (A+B*z)/Sqrt[a+b*z] == (b*A-a*B)/(b*Sqrt[a+b*z]) + B/b*Sqrt[a+b*z]*) + + +Int[(A_.+B_.*Log[c_.+d_.*x_])/Sqrt[a_+b_.*Log[c_.+d_.*x_]],x_Symbol] := + Dist[(b*A-a*B)/b,Int[1/Sqrt[a+b*Log[c+d*x]],x]] + + Dist[B/b,Int[Sqrt[a+b*Log[c+d*x]],x]] /; +FreeQ[{a,b,c,d,A,B},x] && NonzeroQ[b*A-a*B] + + +(* ::Subsection::Closed:: *) +(*(a+b x)^m Log[c+d x]^n*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[(a_.+b_.*x_)^m_.*Log[c_.+d_.*x_]^n_,x_Symbol] := + (a+b*x)^(m+1)*Log[c+d*x]^n/(b*(m+1)) - + Dist[d*n/(b*(m+1)),Int[Regularize[(a+b*x)^(m+1)*Log[c+d*x]^(n-1)/(c+d*x),x],x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[{m,n}] && m<-1 && n>0 + + +(* ::Subsection::Closed:: *) +(*f^(a Log[u]) Exponentials of logarithms*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: f^(a*Log[g]) == g^(a*Log[f])*) + + +Int[f_^(a_.*Log[u_]),x_Symbol] := + Int[u^(a*Log[f]),x] /; +FreeQ[{a,f},x] + + +(* ::Subsection::Closed:: *) +(*Integration by substitution*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/z == Log'[z]*) + + +Int[1/(a_.*x_+b_.*x_*Log[c_.*x_^n_.]^m_.),x_Symbol] := + Dist[1/n,Subst[Int[1/(a+b*x^m),x],x,Log[c*x^n]]] /; +FreeQ[{a,b,c,m,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/z == Log'[z]*) + + +If[ShowSteps, + +Int[u_/x_,x_Symbol] := + Module[{lst=FunctionOfLog[u,x]}, + ShowStep["","Int[f[Log[a*x^n]]/x,x]","Subst[Int[f[x],x],x,Log[a*x^n]]/n",Hold[ + Dist[1/lst[[3]],Subst[Int[lst[[1]],x],x,Log[lst[[2]]]]]]] /; + Not[FalseQ[lst]]] /; +SimplifyFlag && NonsumQ[u], + +Int[u_/x_,x_Symbol] := + Module[{lst=FunctionOfLog[u,x]}, + Dist[1/lst[[3]],Subst[Int[lst[[1]],x],x,Log[lst[[2]]]]] /; + Not[FalseQ[lst]]] /; +NonsumQ[u]] + + +(* ::Subsection::Closed:: *) +(*Integration by parts*) + + +(* ::Item::Closed:: *) +(*Reference: A&S 4.1.53*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: D[Log[f[x]], x] == D[f[x],x] / f[x]*) + + +Int[Log[u_],x_Symbol] := + x*Log[u] - + Int[Regularize[x*D[u,x]/u,x],x] /; +AlgebraicFunctionQ[u,x] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/RationalFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/RationalFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/RationalFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/RationalFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,2165 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Rational Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*a u Products having constant factors*) + + +(* ::Item:: *) +(*Reference: CRC 1*) + + +Int[a_,x_Symbol] := + a*x /; +IndependentQ[a,x] + + +(* ::Item:: *) +(*Derivation: Power rule for integration*) + + +Int[c_*(a_+b_.*x_),x_Symbol] := + c*(a+b*x)^2/(2*b) /; +FreeQ[{a,b,c},x] + + +(* ::Item:: *) +(*Reference: G&R 2.02.1, CRC 2*) + + +If[ShowSteps, + +Int[c_*(a_+b_.*x_)^n_,x_Symbol] := + ShowStep["","Int[a*u,x]","a*Int[u,x]",Hold[ + Dist[c,Int[(a+b*x)^n,x]]]] /; +SimplifyFlag && FreeQ[{a,b,c,n},x] && NonzeroQ[n+1], + +Int[c_*(a_+b_.*x_)^n_,x_Symbol] := + Dist[c,Int[(a+b*x)^n,x]] /; +FreeQ[{a,b,c,n},x] && NonzeroQ[n+1]] + + +(* ::Item:: *) +(*Reference: G&R 2.02.1, CRC 2*) + + +If[ShowSteps, + +Int[a_*u_,x_Symbol] := + Module[{lst=ConstantFactor[u,x]}, + ShowStep["","Int[a*u,x]","a*Int[u,x]",Hold[ + Dist[a*lst[[1]],Int[lst[[2]],x]]]]] /; +SimplifyFlag && FreeQ[a,x] && Not[MatchQ[u,b_*v_ /; FreeQ[b,x]]], + +Int[a_*u_,x_Symbol] := + Module[{lst=ConstantFactor[u,x]}, + Dist[a*lst[[1]],Int[lst[[2]],x]]] /; +FreeQ[a,x] && Not[MatchQ[u,b_*v_ /; FreeQ[b,x]]]] + + +(* Note: Constant factors in denominators are aggressively factored out to prevent them occurring + unnecessarily in logarithm terms of antiderivatives! *) +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=ConstantFactor[Simplify[Denominator[u]],x]}, + ShowStep["","Int[a*u,x]","a*Int[u,x]",Hold[ + Dist[1/lst[[1]],Int[Numerator[u]/lst[[2]],x]]]] /; + lst[[1]]=!=1] /; +SimplifyFlag && ( + MatchQ[u,1/(a_+b_.*x) /; FreeQ[{a,b},x]] || + MatchQ[u,x^m_./(a_+b_.*x^n_) /; FreeQ[{a,b,m,n},x] && ZeroQ[m-n+1]] || + MatchQ[u,1/((a_.+b_.*x)*(c_+d_.*x)) /; FreeQ[{a,b,c,d},x]] || + MatchQ[u,(d_.+e_.*x)/(a_+b_.*x+c_.*x^2) /; FreeQ[{a,b,c,d,e},x]] || + MatchQ[u,(c_.*(a_.+b_.*x)^n_)^m_ /; FreeQ[{a,b,c,m,n},x] && ZeroQ[m*n+1]]), + +Int[u_,x_Symbol] := + Module[{lst=ConstantFactor[Simplify[Denominator[u]],x]}, + Dist[1/lst[[1]],Int[Numerator[u]/lst[[2]],x]] /; + lst[[1]]=!=1] /; + MatchQ[u,1/(a_+b_.*x) /; FreeQ[{a,b},x]] || + MatchQ[u,x^m_./(a_+b_.*x^n_) /; FreeQ[{a,b,m,n},x] && ZeroQ[m-n+1]] || + MatchQ[u,1/((a_.+b_.*x)*(c_+d_.*x)) /; FreeQ[{a,b,c,d},x]] || + MatchQ[u,(d_.+e_.*x)/(a_+b_.*x+c_.*x^2) /; FreeQ[{a,b,c,d,e},x]] || + MatchQ[u,(c_.*(a_.+b_.*x)^n_)^m_ /; FreeQ[{a,b,c,m,n},x] && ZeroQ[m*n+1]]] + + +(* Note: Constant factors in denominators are aggressively factored out to prevent them occurring + unnecessarily in logarithm terms of antiderivatives! *) +If[ShowSteps, + +Int[u_/v_,x_Symbol] := + Module[{lst=ConstantFactor[v,x]}, + ShowStep["","Int[a*u,x]","a*Int[u,x]",Hold[ + Dist[1/lst[[1]],Int[u/lst[[2]],x]]]] /; + lst[[1]]=!=1] /; +SimplifyFlag && Not[FalseQ[DerivativeDivides[v,u,x]]], + +Int[u_/v_,x_Symbol] := + Module[{lst=ConstantFactor[v,x]}, + Dist[1/lst[[1]],Int[u/lst[[2]],x]] /; + lst[[1]]=!=1] /; +Not[FalseQ[DerivativeDivides[v,u,x]]]] + + +(* ::Item:: *) +(*Basis: D[f[x]^p*(a*x^n/f[x])^p/x^(n*p),x] == 0*) + + +(* ??? *) + + +(* ::Item:: *) +(*Basis: D[x^(n*p)*f[x]^p/(a*x^n*f[x])^p,x] == 0*) + + +(* ??? *) + + +(* ::Item:: *) +(*Basis: D[f[x]^m/(-f[x])^m,x] == 0*) + + +Int[u_.*v_^m_*w_^n_,x_Symbol] := + (v^m*w^n)*Int[u,x] /; +FreeQ[{m,n},x] && ZeroQ[m+n] && ZeroQ[v+w] + + +(* ::Item:: *) +(*Basis: D[(a+b*x^m)^p/(x^(m*p)*(-b-a/x^m)^p),x] == 0*) + + +Int[u_.*(a_.+b_.*x_^m_.)^p_.*(c_.+d_.*x_^n_.)^q_., x_Symbol] := + (a+b*x^m)^p*(c+d*x^n)^q/x^(m*p)*Int[u*x^(m*p),x] /; +FreeQ[{a,b,c,d,m,n,p,q},x] && ZeroQ[a+d] && ZeroQ[b+c] && ZeroQ[m+n] && ZeroQ[p+q] + + +(* ::Subsection::Closed:: *) +(*(a + b x)^n Powers of linear binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.2, CRC 27, A&S 3.3.15*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule for integration*) + + +Int[1/(a_+b_.*x_),x_Symbol] := + Log[-a-b*x]/b /; +FreeQ[{a,b},x] && NegativeCoefficientQ[a] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.2, CRC 27, A&S 3.3.15*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule for integration*) + + +Int[1/(a_.+b_.*x_),x_Symbol] := + Log[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.1, CRC 7*) + + +(* ::Item:: *) +(*Derivation: Power rule for integration*) + + +Int[x_^n_.,x_Symbol] := + x^(n+1)/(n+1) /; +IndependentQ[n,x] && NonzeroQ[n+1] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.1, CRC 23, A&S 3.3.14*) + + +(* ::Item:: *) +(*Derivation: Power rule for integration*) + + +Int[(a_.+b_.*x_)^n_,x_Symbol] := + (a+b*x)^(n+1)/(b*(n+1)) /; +FreeQ[{a,b,n},x] && NonzeroQ[n+1] + + +(* ::Subsection::Closed:: *) +(*a x^m + b x^n + \[CenterEllipsis] Integrands involving sums of monomials*) + + +(* ::Item:: *) +(*Reference: CRC 1,2,4,7,9*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + If[PolynomialQ[u,x], + ShowStep["","Int[a+b*x+c*x^2+\[CenterEllipsis],x]","a*x+b*x^2/2+c*x^3/3+\[CenterEllipsis]",Hold[ + IntegrateMonomialSum[u,x]]], + ShowStep["","Int[a+b/x+c*x^m+\[CenterEllipsis],x]","a*x+b*Log[x]+c*x^(m+1)/(m+1)+\[CenterEllipsis]",Hold[ + IntegrateMonomialSum[u,x]]]] /; +SimplifyFlag && MonomialSumQ[u,x], + +Int[u_,x_Symbol] := + IntegrateMonomialSum[u,x] /; +MonomialSumQ[u,x]] + + +(* u is a monomial sum in x. IntegrateMonomialSum[u,x] returns the antiderivative of u wrt x + with the antiderivative of the constants terms of u collected into a single term times x. *) +IntegrateMonomialSum[u_,x_Symbol] := + Module[{lst=Map[Function[If[FreeQ[#,x],{#,0},{0,#*x*If[Exponent[#,x]===-1,Log[x],1/(Exponent[#,x]+1)]}]],u]}, + lst[[1]]*x + lst[[2]]] + + +(* ::Item:: *) +(*Reference: G&R 2.02.2, CRC 2,4*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{lst=SplitMonomialTerms[u,x]}, + ShowStep["","Int[a*u+b*v+\[CenterEllipsis],x]","a*Int[u,x]+b*Int[v,x]+\[CenterEllipsis]",Hold[ + Int[lst[[1]],x] + SplitFreeIntegrate[lst[[2]],x]]] /; + SumQ[lst[[1]]] && Not[FreeQ[lst[[1]],x]] && lst[[2]]=!=0] /; +SimplifyFlag && SumQ[u], + +Int[u_,x_Symbol] := + Module[{lst=SplitMonomialTerms[u,x]}, + Int[lst[[1]],x] + SplitFreeIntegrate[lst[[2]],x] /; + SumQ[lst[[1]]] && Not[FreeQ[lst[[1]],x]] && lst[[2]]=!=0] /; +SumQ[u]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: z*(u+v) == z*u+z*v*) + + +If[ShowSteps, + +Int[x_^m_.*u_,x_Symbol] := + ShowStep["","Int[z*(u+v+\[CenterEllipsis]),x]","Int[z*u+z*v+\[CenterEllipsis],x]",Hold[ + Int[Map[Function[x^m*#],u],x]]] /; +SimplifyFlag && IntegerQ[m] && SumQ[u], + +Int[x_^m_.*u_,x_Symbol] := + Int[Map[Function[x^m*#],u],x] /; +IntegerQ[m] && SumQ[u]] + + +(* ::Subsection::Closed:: *) +(*a + b x Integrands involving linear binomials*) + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x)^n Products of monomials and powers of linear binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification and integration by substitution*) + + +(* ::Item:: *) +(*Basis: x*(a+b*x) == -a^2/(4*b)*(1-(1+2*b*x/a)^2)*) + + +(* ::Item:: *) +(*Substitution: u = 1+2*b*x^n/a*) + + +Int[1/(x_*(a_+b_.*x_^n_.)),x_Symbol] := + -2*ArcTanh[1+2*b*x^n/a]/(a*n) /; +FreeQ[{a,b,n},x] && PosQ[n] && RationalQ[b/a] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.118.1, CRC 84*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule for integration*) + + +(* ::Item:: *) +(*Basis: 1/(x*(a+b*x^n)) == 1/(x^(n+1)*(b+a/x^n))*) + + +Int[1/(x_*(a_+b_.*x_^n_.)),x_Symbol] := +(* -Log[(a+b*x^n)/x^n]/(a*n) /; *) + Log[x]/a - Log[a+b*x^n]/(a*n) /; +FreeQ[{a,b,n},x] && PosQ[n] && Not[RationalQ[b/a]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.118.1, CRC 84*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule for integration*) + + +(* ::Item:: *) +(*Basis: 1/(x*(a+b*x^n)) == 1/(x^(n+1)*(b+a/x^n))*) + + +Int[1/(x_*(a_+b_.*x_^n_.)),x_Symbol] := + -Log[b+a*x^(-n)]/(a*n) /; +FreeQ[{a,b,n},x] && NegQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a*x+b*x^n == x*(a+b*x^(n-1))*) + + +Int[1/(a_.*x_+b_.*x_^n_),x_Symbol] := + Int[1/(x*(a+b*x^(n-1))),x] /; +FreeQ[{a,b,n},x] + + +(* ::Item:: *) +(*Reference: G&R 2.110.2, CRC 26b special case*) + + +Int[x_^m_.*(a_+b_.*x_)^n_,x_Symbol] := + -x^(m+1)*(a+b*x)^(n+1)/(a*(n+1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+2] && NonzeroQ[n+1] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.2, CRC 26b*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m (a+b*x)^n == x^(m+n+2) ((a+b*x)^n / x^(n+2))*) + + +Int[x_^m_.*(a_+b_.*x_)^n_,x_Symbol] := + -x^(m+1)*(a+b*x)^(n+1)/(a*(n+1)) + + Dist[(m+n+2)/(a*(n+1)),Int[x^m*(a+b*x)^(n+1),x]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && 00 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.1, CRC 26a*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_*(a_.+b_.*x_)^n_.,x_Symbol] := + x^(m+1)*(a+b*x)^n/(m+n+1) + + Dist[a*n/(m+n+1),Int[x^m*(a+b*x)^(n-1),x]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && 00 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.5, CRC 26c*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*(a_.+b_.*x_)^n_,x_Symbol] := + x^m*(a+b*x)^(n+1)/(b*(m+n+1)) - + Dist[a*m/(b*(m+n+1)),Int[x^(m-1)*(a+b*x)^n,x]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && 00 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.151, CRC 59b*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[(a_+b_.*x_)^m_*(c_+d_.*x_)^n_.,x_Symbol] := + (a+b*x)^(m+1)*(c+d*x)^n/(b*(m+n+1)) + + Dist[n*(b*c-a*d)/(b*(m+n+1)),Int[(a+b*x)^m*(c+d*x)^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[{m,n}] && NonzeroQ[b*c-a*d] && 05 + + +Int[x_^m_*(a_+b_.*x_)^n_.*(c_+d_.*x_)^p_.,x_Symbol] := + x^(m-1)*(a+b*x)^(n+1)*(c+d*x)^(p+1)/(b*d*(1+m+n+p)) - + Dist[a*c*(m-1)/(b*d*(1+m+n+p)), Int[x^(m-2)*(a+b*x)^n*(c+d*x)^p, x]] - + Dist[(b*c*(m+n)+a*d*(m+p))/(b*d*(1+m+n+p)), Int[x^(m-1)*(a+b*x)^n*(c+d*x)^p, x]] /; +FreeQ[{a,b,c,d,n,p},x] && IntegerQ[{m,n,p}] && 05 + + +(* ::Subsection::Closed:: *) +(*a + b x^n Integrands involving nonlinear binomials*) + + +(* ::Subsubsection::Closed:: *) +(*1 / (a+b x^n) Reciprocals of binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.124.1a, CRC 60, A&S 3.3.21*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: ArcTan'[z] == 1/(1+z^2)*) + + +Int[1/(a_+b_.*x_^2),x_Symbol] := + Rt[b/a,2]*ArcTan[Rt[b/a,2]*x]/b /; +FreeQ[{a,b},x] && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.124.1b', CRC 61b, A&S 3.3.23*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: ArcTanh'[z] == 1/(1-z^2)*) + + +Int[1/(a_+b_.*x_^2),x_Symbol] := + -Rt[-b/a,2]*ArcTanh[Rt[-b/a,2]*x]/b /; +FreeQ[{a,b},x] && NegQ[a/b] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.126.1.2, CRC 74*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=(a/b)^(1/3), 1/(a+b*z^3) == q/(3*a*(q+z)) + q/(3*a)*(2*q-z)/(q^2-q*z+z^2)*) + + +Int[1/(a_+b_.*x_^3),x_Symbol] := + Module[{r=Numerator[Rt[a/b,3]], s=Denominator[Rt[a/b,3]]}, + Dist[r/(3*a),Int[1/(r+s*x),x]] + + Dist[r/(3*a),Int[(2*r-s*x)/(r^2-r*s*x+s^2*x^2),x]]] /; +FreeQ[{a,b},x] && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=(-a/b)^(1/3), 1/(a+b*z^3) == q/(3*a*(q-z)) + q/(3*a)*(2*q+z)/(q^2+q*z+z^2)*) + + +Int[1/(a_+b_.*x_^3),x_Symbol] := + Module[{r=Numerator[Rt[-a/b,3]], s=Denominator[Rt[-a/b,3]]}, + Dist[r/(3*a),Int[1/(r-s*x),x]] + + Dist[r/(3*a),Int[(2*r+s*x)/(r^2+r*s*x+s^2*x^2),x]]] /; +FreeQ[{a,b},x] && NegQ[a/b] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.132.1.1', CRC 77'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=(a/b)^(1/4), 1/(a+b*z^4) == *) +(* q/(2*Sqrt[2]*a)*(Sqrt[2]*q-z)/(q^2-Sqrt[2]*q*z+z^2) + q/(2*Sqrt[2]*a)*(Sqrt[2]*q+z)/(q^2+Sqrt[2]*q*z+z^2)*) + + +Int[1/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[a/b,4]], s=Denominator[Rt[a/b,4]]}, + Dist[r/(2*Sqrt[2]*a),Int[(Sqrt[2]*r-s*x^(n/4))/(r^2-Sqrt[2]*r*s*x^(n/4)+s^2*x^(n/2)),x]] + + Dist[r/(2*Sqrt[2]*a),Int[(Sqrt[2]*r+s*x^(n/4))/(r^2+Sqrt[2]*r*s*x^(n/4)+s^2*x^(n/2)),x]]] /; +FreeQ[{a,b},x] && EvenQ[n/2] && n>2 && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.132.1.2', CRC 78'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[-a/b], 1/(a+b*z^2) == q/(2*a*(q-z)) + q/(2*a*(q+z))*) + + +Int[1/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[-a/b,2]], s=Denominator[Rt[-a/b,2]]}, + Dist[r/(2*a),Int[1/(r-s*x^(n/2)),x]] + + Dist[r/(2*a),Int[1/(r+s*x^(n/2)),x]]] /; +FreeQ[{a,b},x] && EvenQ[n/2] && n>2 && NegQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is even and q=(a/b)^(1/n), 1/(a+b*x^n) == Sum[2 q (q-Cos[(2 k-1) Pi/n] x)/(a n (q^2-2 q Cos[(2 k-1) Pi/n] x+x^2)), {k,1,n/2}]*) + + +(* ::Item:: *) +(*Basis: If n/2>0 is odd and q=(a/b)^(2/n), 1/(a+b*x^n) == 2*q/(a*n*(q+x^2)) +*) +(* 4*q/(a*n)*Sum[(q-Cos[2*(2*k-1)*Pi/n]*x^2)/(q^2-2*q*Cos[2*(2*k-1)*Pi/n]*x^2+x^4), {k, 1, (n/2-1)/2}]*) + + +Int[1/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[a/b,n/2]], s=Denominator[Rt[a/b,n/2]]}, + Dist[2*r/(a*n),Int[1/(r+s*x^2),x]] + + Dist[4*r/(a*n),Int[Sum[(r-s*Cos[2*(2*k-1)*Pi/n]*x^2)/(r^2-2*r*s*Cos[2*(2*k-1)*Pi/n]*x^2+s^2*x^4),{k,1,(n/2-1)/2}],x]]] /; +FreeQ[{a,b},x] && OddQ[n/2] && n>2 && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is even and q=(-a/b)^(1/n), 1/(a+b*x^n) == 2 q^2/(n a (q^2-x^2)) + Sum[2 q (q-Cos[2 k Pi/n] x)/(a n (q^2-2 q Cos[2 k Pi/n] x+x^2)), {k,1,n/2-1}]*) + + +(* ::Item:: *) +(*Basis: If n/2>0 is odd and q=(-a/b)^(2/n), 1/(a+b*x^n) == 2*q/(a*n*(q-x^2)) +*) +(* 4*q/(a*n)*Sum[(q-Cos[4*k*Pi/n]*x^2)/(q^2-2*q*Cos[4*k*Pi/n]*x^2+x^4), {k, 1, (n/2-1)/2}]*) + + +Int[1/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[-a/b,n/2]], s=Denominator[Rt[-a/b,n/2]]}, + Dist[2*r/(a*n),Int[1/(r-s*x^2),x]] + + Dist[4*r/(a*n),Int[Sum[(r-s*Cos[4*k*Pi/n]*x^2)/(r^2-2*r*s*Cos[4*k*Pi/n]*x^2+s^2*x^4),{k,1,(n/2-1)/2}],x]]] /; +FreeQ[{a,b},x] && OddQ[n/2] && n>2 && NegQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is odd and q=(a/b)^(1/n), 1/(a+b*x^n) == q/(a n (q+x)) + Sum[2 q (q-Cos[(2 k-1) Pi/n] x)/(a n (q^2-2 q Cos[(2 k-1) Pi/n] x+x^2)), {k,1,(n-1)/2}]*) + + +Int[1/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[a/b,n]], s=Denominator[Rt[a/b,n]]}, + Int[r/(a*n*(r+s*x)) + + Sum[2*r*(r-s*Cos[(2*k-1)*Pi/n]*x)/(a*n*(r^2-2*r*s*Cos[(2*k-1)*Pi/n]*x+s^2*x^2)), {k,1,(n-1)/2}],x]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is odd and q=(-a/b)^(1/n), 1/(a+b*x^n) == q/(a n (q-x)) + Sum[2 q (q+Cos[(2 k-1) Pi/n] x)/(a n (q^2+2 q Cos[(2 k-1) Pi/n] x+x^2)), {k,1,(n-1)/2}]*) + + +Int[1/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[-a/b,n]], s=Denominator[Rt[-a/b,n]]}, + Int[r/(a*n*(r-s*x)) + + Sum[2*r*(r+s*Cos[(2*k-1)*Pi/n]*x)/(a*n*(r^2+2*r*s*Cos[(2*k-1)*Pi/n]*x+s^2*x^2)), {k,1,(n-1)/2}],x]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 && NegQ[a/b] + + +(* ::Subsubsection::Closed:: *) +(*x^m / (a+b x^n) Quotients of monomials by binomials*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.126.2, CRC 75*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Let q=(a/b)^(1/3), then x/(a+b*x^3) == -q^2/(3*a*(q+x)) + q^2/(3*a)*(q+x)/(q^2-q*x+x^2)*) + + +Int[x_/(a_+b_.*x_^3),x_Symbol] := + Module[{r=Numerator[Rt[a/b,3]], s=Denominator[Rt[a/b,3]]}, + Dist[-r^2/(3*a*s),Int[1/(r+s*x),x]] + + Dist[r^2/(3*a*s),Int[(r+s*x)/(r^2-r*s*x+s^2*x^2),x]]] /; +FreeQ[{a,b},x] && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Let q=(-a/b)^(1/3), then x/(a+b*x^3) == q^2/(3*a*(q-x)) - q^2/(3*a)*(q-x)/(q^2+q*x+x^2)*) + + +Int[x_/(a_+b_.*x_^3),x_Symbol] := + Module[{r=Numerator[Rt[-a/b,3]], s=Denominator[Rt[-a/b,3]]}, + Dist[r^2/(3*a*s),Int[1/(r-s*x),x]] - + Dist[r^2/(3*a*s),Int[(r-s*x)/(r^2+r*s*x+s^2*x^2),x]]] /; +FreeQ[{a,b},x] && NegQ[a/b] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[x_^m_./(a_+b_.*x_^n_),x_Symbol] := + Module[{g=GCD[m+1,n]}, + Dist[1/g,Subst[Int[x^((m+1)/g-1)/(a+b*x^(n/g)),x],x,x^g]] /; + g>1] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && 00 && n===2*m && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.132.3.2', CRC 82'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Let q=Sqrt[-a/b], then z/(a+b*z^2) == 1/(2*b*(q+z)) - 1/(2*b*(q-z))*) + + +(* ::Item:: *) +(*Basis: Let q=Sqrt[-a/b], then x^m/(a+b*x^(2*m)) == 1/(2*b*(q+x^m)) - 1/(2*b*(q-x^m))*) + + +Int[x_^m_/(a_+b_.*x_^n_),x_Symbol] := + Module[{r=Numerator[Rt[-a/b,2]], s=Denominator[Rt[-a/b,2]]}, + Dist[s/(2*b),Int[1/(r+s*x^m),x]] - + Dist[s/(2*b),Int[1/(r-s*x^m),x]]] /; +FreeQ[{a,b},x] && EvenQ[m] && m>0 && n===2*m && NegQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If n>0 is even and 0<=m0 is odd, m is even and 0<=m0 is odd, m is even and 0<=m0 is odd and 0<=m0 is odd and 0<=m1 when m is odd and n even:*) + + +(* ::Item:: *) +(*Basis: If m is odd and n is even and 0<=m0 && n===2*m && PosQ[a/b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Let q=Sqrt[-a/b], then (c+d*x^m)/(a+b*x^(2*m)) == (c+d*q)/(2*(a+b*q*x^m)) + (c-d*q)/(2*(a-b*q*x^m))*) + + +Int[(c_.+d_.*x_^m_)/(a_+b_.*x_^n_),x_Symbol] := + Module[{q=Rt[-a/b,2]}, + Dist[(c+d*q)/2, Int[1/(a+b*q*x^m),x]] + + Dist[(c-d*q)/2, Int[1/(a-b*q*x^m),x]]] /; +FreeQ[{a,b,c,d},x] && EvenQ[m] && m>0 && n===2*m && NegQ[a/b] && NonzeroQ[b*c^2+a*d^2] + + +(* ::Subsubsection::Closed:: *) +(*(a+b x^n)^p Powers of binomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.110.2, CRC 88d special case*) + + +Int[(a_+b_.*x_^n_)^p_,x_Symbol] := + x*(a+b*x^n)^(p+1)/a /; +FreeQ[{a,b,n,p},x] && ZeroQ[n*(p+1)+1] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.2, CRC 88d*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: (a+b*x^n)^p == x^(n*(p+1)+1) * ((a+b*x^n)^p/x^(n*(p+1)+1))*) + + +(* ::Item:: *) +(*Basis: Int[(a+b*x^n)^p/x^(n*(p+1)+1),x] == -((a+b*x^n)^(p+1)/(x^(n*(p+1))*(a*n*(p+1))))*) + + +(* ::Item:: *) +(*Note: Requirement that n>1 ensures new term is a proper fraction.*) + + +Int[(a_+b_.*x_^n_)^p_,x_Symbol] := + -x*(a+b*x^n)^(p+1)/(a*n*(p+1)) + + Dist[(n*(p+1)+1)/(a*n*(p+1)),Int[(a+b*x^n)^(p+1),x]] /; +FreeQ[{a,b},x] && IntegerQ[{n,p}] && n>1 && p<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x^n)^p Products of monomials and powers of binomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.110.6, CRC 88c special case*) + + +Int[x_^m_.*(a_+b_.*x_^n_)^p_,x_Symbol] := + x^(m+1)*(a+b*x^n)^(p+1)/(a*(m+1)) /; +FreeQ[{a,b,m,n,p},x] && ZeroQ[m+n*(p+1)+1] && NonzeroQ[m+1] && NonzeroQ[p+2] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.4*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m (a+b*x^n)^p == x^(m-n+1) * ((a+b*x^n)^p*x^(n-1))*) + + +(* ::Item:: *) +(*Basis: Int[(a+b*x^n)^p*x^(n-1),x] == (a+b*x^n)^(p+1)/(b*n*(p+1))*) + + +(* ::Item:: *) +(*Note: Requirement that m<2 n-1 ensures new term is a proper fraction.*) + + +Int[x_^m_.*(a_+b_.*x_^n_)^p_,x_Symbol] := + x^(m-n+1)*(a+b*x^n)^(p+1)/(b*n*(p+1)) - + Dist[(m-n+1)/(b*n*(p+1)),Int[x^(m-n)*(a+b*x^n)^(p+1),x]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n,p}] && n>1 && p<-1 && n<=m<2*n-1 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.2, CRC 88d*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m (a+b*x^n)^p == x^(m+n*(p+1)+1) ((a+b*x^n)^p/x^(n*(p+1)+1))*) + + +(* ::Item:: *) +(*Basis: Int[(a+b*x^n)^p/x^(n*(p+1)+1),x] == -((a+b*x^n)^(p+1)/(x^(n*(p+1))*(a*n*(p+1))))*) + + +(* ::Item:: *) +(*Note: Requirement that m+11 && 00 && +IntegerQ[(m+n*(p+1)+1)/n] && 00 && ExpandIntegrandQ[m,n,p] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.110.4*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m (a+b*x^n)^p == x^(m-n+1) ((a+b*x^n)^p x^(n-1))*) + + +(* ::Item:: *) +(*Note: Requirement that m<2 n-1 ensures new term is a proper fraction.*) + + +(* ::Item:: *) +(*Note: Unfortunately this rule is necessary to prevent the Ostrogradskiy-Hermite method from being applied instead of substituting for c+d x.*) + + +Int[(c_+d_.*x_)^m_.*(a_+b_.*(c_+d_.*x_)^n_)^p_,x_Symbol] := + (c+d*x)^(m-n+1)*(a+b*(c+d*x)^n)^(p+1)/(b*d*n*(p+1)) - + Dist[(m-n+1)/(b*n*(p+1)),Int[(c+d*x)^(m-n)*(a+b*(c+d*x)^n)^(p+1),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[{m,n,p}] && n>1 && p<-1 && n<=m<2*n-1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b x^n)^m / (b+a/x^n) Quotients of powers of monomials and monomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: (a+b*x^n)/(b+a/x^n) == x^n*) + + +Int[(a_+b_.*x_^n_.)^m_/(b_+a_.*x_^p_.),x_Symbol] := + Int[x^n*(a+b*x^n)^(m-1), x] /; +FreeQ[{a,b,m,n,p},x] && ZeroQ[n+p] + + +(* ::Subsection::Closed:: *) +(*a + b x + c x^2 Integrands involving quadratic trinomials*) + + +(* ::Subsubsection::Closed:: *) +(*(a+b x+c x^2)^n Powers of quadratic trinomials*) + + +(* ::Item::Closed:: *) +(*Reference: A&S 3.3.18*) + + +(* ::Item:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If b^2-4*a*c=0, a+b*z+c*z^2 == (b/2+c*z)^2/c*) + + +Int[(a_+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + Int[(b/2+c*x)^(2*n),x]/c^n /; +FreeQ[{a,b,c},x] && IntegerQ[n] && ZeroQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.172.2, CRC 110a, A&S 3.3.17*) + + +(* ::Item:: *) +(*Derivation: Algebraic simplification and integration by substitution*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4 a c], a+b x+c x^2 == -q^2/(4 c) (1-((b+2 c x)/q)^2)*) + + +(* ::Item:: *) +(*Substitution: u = (b+2 c x)/q where q = Sqrt[b^2-4 a c]*) + + +Int[1/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + -2*ArcTanh[b/q+2*c*x/q]/q /; + SqrtNumberQ[q] && RationalQ[b/q]] /; +FreeQ[{a,b,c},x] && PosQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.172.2, CRC 110a, A&S 3.3.17*) + + +(* ::Item:: *) +(*Derivation: Algebraic simplification and integration by substitution*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[b^2-4 a c], a+b x+c x^2 == -q^2/(4 c) (1-((b+2 c x)/q)^2)*) + + +(* ::Item:: *) +(*Substitution: u = (b+2 c x)/q where q = Sqrt[b^2-4 a c]*) + + +Int[1/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + -2*ArcTanh[(b+2*c*x)/Rt[b^2-4*a*c,2]]/Rt[b^2-4*a*c,2] /; +FreeQ[{a,b,c},x] && PosQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.172.4, CRC 109, A&S 3.3.16*) + + +(* ::Item:: *) +(*Derivation: Algebraic simplification and integration by substitution*) + + +(* ::Item:: *) +(*Basis: If q = Sqrt[4 a c-b^2], a+b x+c x^2 == q^2/(4 c) (1+((b+2 c x)/q)^2)*) + + +(* ::Item:: *) +(*Substitution: u = (b+2 c x)/q where q = Sqrt[4 a c-b^2]*) + + +Int[1/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + Module[{q=Rt[4*a*c-b^2,2]}, + 2*ArcTan[b/q+2*c*x/q]/q /; + SqrtNumberQ[q] && RationalQ[b/q]] /; +FreeQ[{a,b,c},x] && NegQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.172.4, CRC 109, A&S 3.3.16*) + + +(* ::Item:: *) +(*Derivation: Algebraic simplification and integration by substitution*) + + +(* ::Item:: *) +(*Basis: If q = Sqrt[4 a c-b^2], a+b x+c x^2 == q^2/(4 c) (1+((b+2 c x)/q)^2)*) + + +(* ::Item:: *) +(*Substitution: u = (b+2 c x)/q where q = Sqrt[4 a c-b^2]*) + + +Int[1/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + 2*ArcTan[(b+2*c*x)/Rt[4*a*c-b^2,2]]/Rt[4*a*c-b^2,2] /; +FreeQ[{a,b,c},x] && NegQ[b^2-4*a*c] + + +(* ::Item:: *) +(*Reference: G&R 2.264.5, CRC 239*) + + +Int[1/(a_.+b_.*x_+c_.*x_^2)^(3/2),x_Symbol] := + -2*(b+2*c*x)/((b^2-4*a*c)*Sqrt[a+b*x+c*x^2]) /; +FreeQ[{a,b,c},x] && NonzeroQ[b^2-4*a*c] + + +(* ::Item:: *) +(*Reference: G&R 2.171.3, GR5 2.263.3, CRC 113,241*) + + +Int[(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + (b+2*c*x)*(a+b*x+c*x^2)^(n+1)/((n+1)*(b^2-4*a*c)) - + Dist[2*c*(2*n+3)/((n+1)*(b^2-4*a*c)),Int[(a+b*x+c*x^2)^(n+1),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*(d+e x) / (a+b x+c x^2) Quotients of linears by quadratic trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.175.1, CRC 114*) + + +Int[(d_.+e_.*x_)/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + e*Log[-a-b*x-c*x^2]/(2*c) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[2*c*d-b*e] && NegativeCoefficientQ[a] + + +(* ::Item:: *) +(*Reference: G&R 2.175.1, CRC 114*) + + +Int[(d_.+e_.*x_)/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + e*Log[a+b*x+c*x^2]/(2*c) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[2*c*d-b*e] + + +(* ::Item:: *) +(*Reference: A&S 3.3.19*) + + +Int[(d_.+e_.*x_)/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + e*Log[-a-b*x-c*x^2]/(2*c) + + Dist[Simplify[(2*c*d-b*e)/(2*c)],Int[1/(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e},x] && Not[RationalQ[Rt[b^2-4*a*c,2]]] && NonzeroQ[a*e^2+c*d^2-b*d*e] && +NegativeCoefficientQ[a] + + +(* ::Item:: *) +(*Reference: A&S 3.3.19*) + + +Int[(d_.+e_.*x_)/(a_+b_.*x_+c_.*x_^2),x_Symbol] := + e*Log[a+b*x+c*x^2]/(2*c) + + Dist[Simplify[(2*c*d-b*e)/(2*c)],Int[1/(a+b*x+c*x^2),x]] /; +FreeQ[{a,b,c,d,e},x] && Not[RationalQ[Rt[b^2-4*a*c,2]]] && NonzeroQ[a*e^2+c*d^2-b*d*e] + + +(* ::Subsubsection::Closed:: *) +(*(d+e x)^m (a+c x^2)^n Products of powers of linears and powers of quadratic binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If a*e^2+c*d^2==0, a+c*x^2 == (d+e*x)*(a/d+c/e*x)*) + + +Int[(d_+e_.*x_)^m_.*(a_+c_.*x_^2)^n_.,x_Symbol] := + Int[(d+e*x)^(m+n)*(a/d+c/e*x)^n,x] /; +FreeQ[{a,c,d,e,m},x] && IntegerQ[n] && ZeroQ[a*e^2+c*d^2] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[(d_+e_.*x_)*(a_.+c_.*x_^2)^n_,x_Symbol] := + e*(a+c*x^2)^(n+1)/(2*c*(n+1)) + + Dist[d,Int[(a+c*x^2)^n,x]] /; +FreeQ[{a,c,d,e,n},x] && NonzeroQ[n+1] && Not[IntegerQ[n] && n>0] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[(d_+e_.*x_)^m_*(a_.+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m-1)*(a+c*x^2)^(n+1)/(c*(m+2*n+1)) - + Dist[(a*e^2+c*d^2)*(m-1)/(c*(m+2*n+1)),Int[(d+e*x)^(m-2)*(a+c*x^2)^n,x]] /; +FreeQ[{a,c,d,e},x] && RationalQ[{m,n}] && m>1 && ZeroQ[m+n] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[(d_+e_.*x_)^m_.*(a_.+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m-1)*(a+c*x^2)^(n+1)/(c*(m+2*n+1)) + + Dist[2*c*d*(m+n)/(c*(m+2*n+1)),Int[(d+e*x)^(m-1)*(a+c*x^2)^n,x]] /; +FreeQ[{a,c,d,e,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+2*n+1] && Not[IntegerQ[n] && n>=-1] && +ZeroQ[a*e^2+c*d^2] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +(* Int[(d_+e_.*x_)^m_*(a_.+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m-1)*(a+c*x^2)^(n+1)/(c*(m+2*n+1)) + + Dist[2*c*d*(m+n)/(c*(m+2*n+1)),Int[(d+e*x)^(m-1)*(a+c*x^2)^n,x]] - + Dist[(a*e^2+c*d^2)*(m-1)/(c*(m+2*n+1)),Int[(d+e*x)^(m-2)*(a+c*x^2)^n,x]] /; +FreeQ[{a,c,d,e,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+2*n+1] && Not[IntegerQ[n] && n>=-1] *) + + +Int[(d_+e_.*x_)^m_*(a_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^m*(a+c*x^2)^(n+1)/(2*c*d*(n+1)) /; +FreeQ[{a,c,d,e,n},x] && ZeroQ[c*d^2+a*e^2] && ZeroQ[m+2*(n+1)] && NonzeroQ[n+1] + + +Int[(d_+e_.*x_)^m_*(a_+c_.*x_^2)^n_,x_Symbol] := + -e*(d+e*x)^m*(a+c*x^2)^(n+1)/(2*c*d*(m+n+1)) + + Dist[(m+2*(n+1))/(2*d*(m+n+1)),Int[(d+e*x)^(m+1)*(a+c*x^2)^n,x]] /; +FreeQ[{a,c,d,e,n},x] && RationalQ[m] && m<-1 && ZeroQ[c*d^2+a*e^2] && NonzeroQ[m+n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.176, CRC 123*) + + +Int[(d_+e_.*x_)^m_*(a_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m+1)*(a+c*x^2)^(n+1)/((m+1)*(c*d^2+a*e^2)) + + Dist[2*c*d*(m+n+2)/((m+1)*(c*d^2+a*e^2)),Int[(d+e*x)^(m+1)*(a+c*x^2)^n,x]] /; +FreeQ[{a,c,d,e,n},x] && RationalQ[m] && m<-1 && NonzeroQ[c*d^2+a*e^2] && +Not[IntegerQ[n] && n>=-1] && ZeroQ[m+2*n+3] + + +(* ::Item:: *) +(*Reference: G&R 2.176, CRC 123*) + + +(* Int[(d_+e_.*x_)^m_*(a_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m+1)*(a+c*x^2)^(n+1)/((m+1)*(c*d^2+a*e^2)) + + Dist[2*c*d*(m+n+2)/((m+1)*(c*d^2+a*e^2)),Int[(d+e*x)^(m+1)*(a+c*x^2)^n,x]] - + Dist[c*(m+2*n+3)/((m+1)*(c*d^2+a*e^2)),Int[(d+e*x)^(m+2)*(a+c*x^2)^n,x]] /; +FreeQ[{a,c,d,e,n},x] && RationalQ[m] && m<-1 && NonzeroQ[c*d^2+a*e^2] && +Not[IntegerQ[n] && n>=-1] && NonzeroQ[m+2*n+3] *) + + +(* ::Subsubsection::Closed:: *) +(*(d+e x)^m (a+b x+c x^2)^n Products of powers of linears and powers of quadratic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If a*e^2+c*d^2==b*d*e, a+b*x+c*x^2 == (d+e*x)*(a/d+c/e*x)*) + + +Int[(d_+e_.*x_)^m_.*(a_.+b_.*x_+c_.*x_^2)^n_.,x_Symbol] := + Int[(d+e*x)^(m+n)*(a/d+c/e*x)^n,x] /; +FreeQ[{a,b,c,d,e,m},x] && IntegerQ[n] && ZeroQ[a*e^2+c*d^2-b*d*e] + + +(* ::Item:: *) +(*Reference: G&R 2.174.2*) + + +Int[(d_.+e_.*x_)^m_*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + -e*(d+e*x)^(m-1)*(a+b*x+c*x^2)^(n+1)/(c*(m-1)) + + Dist[e^2/c,Int[(d+e*x)^(m-2)*(a+b*x+c*x^2)^(n+1),x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[{m,n}] && n<-1 && ZeroQ[m+2*n+1] && ZeroQ[2*c*d-b*e] + + +(* ::Item:: *) +(*Reference: G&R 2.174.2*) + + +(* Int[(d_.+e_.*x_)^m_*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + -e*(d+e*x)^(m-1)*(a+b*x+c*x^2)^(n+1)/(c*(m-1)) + + Dist[(2*c*d-b*e)/(2*c),Int[(d+e*x)^(m-1)*(a+b*x+c*x^2)^n,x]] + + Dist[e^2/c,Int[(d+e*x)^(m-2)*(a+b*x+c*x^2)^(n+1),x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[{m,n}] && n<-1 && ZeroQ[m+2*n+1] *) + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[(d_.+e_.*x_)*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(a+b*x+c*x^2)^(n+1)/(2*c*(n+1)) /; +FreeQ[{a,b,c,d,e,n},x] && ZeroQ[2*c*d-b*e] && NonzeroQ[n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[(d_.+e_.*x_)*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(a+b*x+c*x^2)^(n+1)/(2*c*(n+1)) + + Dist[(2*c*d-b*e)/(2*c),Int[(a+b*x+c*x^2)^n,x]] /; +FreeQ[{a,b,c,d,e,n},x] && NonzeroQ[n+1] && Not[IntegerQ[n] && n>0] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +(* Int[(d_.+e_.*x_)^m_.*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m-1)*(a+b*x+c*x^2)^(n+1)/(c*(2*n+m+1)) /; +FreeQ[{a,b,c,d,e,m,n},x] && ZeroQ[2*c*d-b*e] && NonzeroQ[2*n+m+1] && ZeroQ[b^2-4*a*c] *) + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[(d_.+e_.*x_)^m_*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m-1)*(a+b*x+c*x^2)^(n+1)/(c*(m+2*n+1)) - + Dist[(e*(a*e-b*d)+c*d^2)*(m-1)/(c*(m+2*n+1)),Int[(d+e*x)^(m-2)*(a+b*x+c*x^2)^n,x]] /; +FreeQ[{a,b,c,d,e,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+2*n+1] && Not[IntegerQ[n] && n>=-1] && +(ZeroQ[m+n] || ZeroQ[2*c*d-b*e]) + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +Int[(d_.+e_.*x_)^m_.*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m-1)*(a+b*x+c*x^2)^(n+1)/(c*(m+2*n+1)) + + Dist[(2*c*d-b*e)*(m+n)/(c*(m+2*n+1)),Int[(d+e*x)^(m-1)*(a+b*x+c*x^2)^n,x]] /; +FreeQ[{a,b,c,d,e,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+2*n+1] && Not[IntegerQ[n] && n>=-1] && +ZeroQ[e*(a*e-b*d)/c+d^2] + + +(* ::Item:: *) +(*Reference: G&R 2.174.1, CRC 119*) + + +(* Int[(d_.+e_.*x_)^m_*(a_.+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m-1)*(a+b*x+c*x^2)^(n+1)/(c*(m+2*n+1)) + + Dist[(2*c*d-b*e)*(m+n)/(c*(m+2*n+1)),Int[(d+e*x)^(m-1)*(a+b*x+c*x^2)^n,x]] - + Dist[(e*(a*e-b*d)/c+d^2)*(m-1)/(m+2*n+1),Int[(d+e*x)^(m-2)*(a+b*x+c*x^2)^n,x]] /; +FreeQ[{a,b,c,d,e,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+2*n+1] && Not[IntegerQ[n] && n>=-1] *) + + +(* ::Item:: *) +(*Reference: G&R 2.265c*) + + +Int[x_^m_*(b_.*x_+c_.*x_^2)^n_,x_Symbol] := + x^m*(b*x+c*x^2)^(n+1)/(b*(m+n+1)) /; +FreeQ[{b,c,m,n},x] && NonzeroQ[m+n+1] && ZeroQ[m+2*(n+1)] + + +(* ::Item:: *) +(*Reference: G&R 2.265c*) + + +Int[x_^m_*(b_.*x_+c_.*x_^2)^n_,x_Symbol] := + x^m*(b*x+c*x^2)^(n+1)/(b*(m+n+1)) - + Dist[c*(m+2*(n+1))/(b*(m+n+1)),Int[x^(m+1)*(b*x+c*x^2)^n,x]] /; +FreeQ[{b,c,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n+1] && Not[IntegerQ[n] && n>=-1] + + +(* ::Item:: *) +(*Reference: G&R 2.176, CRC 123*) + + +Int[(d_.+e_.*x_)^m_*(a_+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m+1)*(a+b*x+c*x^2)^(n+1)/((m+1)*(c*d^2+a*e^2-b*d*e)) + + Dist[(2*c*d-b*e)*(m+n+2)/((m+1)*(c*d^2+a*e^2-b*d*e)),Int[(d+e*x)^(m+1)*(a+b*x+c*x^2)^n,x]] /; +FreeQ[{a,b,c,d,e,n},x] && RationalQ[m] && m<-1 && NonzeroQ[c*d^2+a*e^2-b*d*e] && +Not[IntegerQ[n] && n>=-1] && ZeroQ[m+2*n+3] + + +(* ::Item:: *) +(*Reference: G&R 2.176, CRC 123*) + + +(* Int[(d_.+e_.*x_)^m_*(a_+b_.*x_+c_.*x_^2)^n_,x_Symbol] := + e*(d+e*x)^(m+1)*(a+b*x+c*x^2)^(n+1)/((m+1)*(c*d^2+a*e^2-b*d*e)) + + Dist[(2*c*d-b*e)*(m+n+2)/((m+1)*(c*d^2+a*e^2-b*d*e)),Int[(d+e*x)^(m+1)*(a+b*x+c*x^2)^n,x]] - + Dist[c*(m+2*n+3)/((m+1)*(c*d^2+a*e^2-b*d*e)),Int[(d+e*x)^(m+2)*(a+b*x+c*x^2)^n,x]] /; +FreeQ[{a,b,c,d,e,n},x] && RationalQ[m] && m<-1 && NonzeroQ[c*d^2+a*e^2-b*d*e] && +Not[IntegerQ[n] && n>=-1] && NonzeroQ[m+2*n+3] *) + + +(* ::Subsection::Closed:: *) +(*a + b x^k + c x^(2k) Integrands involving symmetric trinomials*) + + +(* ::Subsubsection::Closed:: *) +(*(d+e x^2)/(a+b x^2+c x^4) Quotients of binomials by quartic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If b^2-4*a*c=0, a+b*z^2+c*z^4 == (b/2+c*z^2)^2/c*) + + +Int[u_./(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + Dist[c,Int[u/(b/2+c*x^2)^2,x]] /; +FreeQ[{a,b,c},x] && ZeroQ[b^2-4*a*c] && PolynomialQ[u,x] + + +(* Previously undiscovered rules ??? *) + + +Int[(d_+e_.*x_^2)/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + d/(a*Rt[(d*b+2*e*a)/(d*a),2])*ArcTan[d*Rt[(d*b+2*e*a)/(d*a),2]*x/(d-e*x^2)] /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[d^2*c-e^2*a] && PosQ[(d*b+2*e*a)/(d*a)] + + +Int[(d_+e_.*x_^2)/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + d/(a*Rt[-(d*b+2*e*a)/(d*a),2])*ArcTanh[d*Rt[-(d*b+2*e*a)/(d*a),2]*x/(d-e*x^2)] /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[d^2*c-e^2*a] && NegQ[(d*b+2*e*a)/(d*a)] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[a/c], then 1/(a+b*x^2+c*x^4) == c*q*(q+x^2)/(2*a*(a+b*x^2+c*x^4)) + c*q*(q-x^2)/(2*a*(a+b*x^2+c*x^4))*) + + +Int[1/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + Module[{q=Rt[a/c,2]}, + Dist[c*q/(2*a),Int[(q+x^2)/(a+b*x^2+c*x^4),x]] + + Dist[c*q/(2*a),Int[(q-x^2)/(a+b*x^2+c*x^4),x]]] /; +FreeQ[{a,b,c},x] && PosQ[a/c] && +(NegativeQ[b^2-4*a*c] || RationalQ[a/c] && Not[PositiveQ[b^2-4*a*c]]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[-a/c], then 1/(a+b*x^2+c*x^4) == -c*q/(2*a)*(q+x^2)/(a+b*x^2+c*x^4) - c*q/(2*a)*(q-x^2)/(a+b*x^2+c*x^4)*) + + +Int[1/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + Module[{q=Rt[-a/c,2]}, + -Dist[c*q/(2*a),Int[(q+x^2)/(a+b*x^2+c*x^4),x]] - + Dist[c*q/(2*a),Int[(q-x^2)/(a+b*x^2+c*x^4),x]]] /; +FreeQ[{a,b,c},x] && NegQ[a/c] && +(NegativeQ[b^2-4*a*c] || RationalQ[a/c] && Not[PositiveQ[b^2-4*a*c]]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[a/c], then x^2/(a+b*x^2+c*x^4) == (q+x^2)/(2*(a+b*x^2+c*x^4)) - (q-x^2)/(2*(a+b*x^2+c*x^4))*) + + +Int[x_^2/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + Module[{q=Rt[a/c,2]}, + Dist[1/2,Int[(q+x^2)/(a+b*x^2+c*x^4),x]] - + Dist[1/2,Int[(q-x^2)/(a+b*x^2+c*x^4),x]]] /; +FreeQ[{a,b,c},x] && PosQ[a/c] && +(NegativeQ[b^2-4*a*c] || RationalQ[a/c] && Not[PositiveQ[b^2-4*a*c]]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[-a/c], then x^2/(a+b*x^2+c*x^4) == (q+x^2)/(2*(a+b*x^2+c*x^4)) - (q-x^2)/(2*(a+b*x^2+c*x^4))*) + + +Int[x_^2/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + Module[{q=Rt[-a/c,2]}, + Dist[1/2,Int[(q+x^2)/(a+b*x^2+c*x^4),x]] - + Dist[1/2,Int[(q-x^2)/(a+b*x^2+c*x^4),x]]] /; +FreeQ[{a,b,c},x] && NegQ[a/c] && +(NegativeQ[b^2-4*a*c] || RationalQ[a/c] && Not[PositiveQ[b^2-4*a*c]]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[a/c], then (d+e*x^2)/(a+b*x^2+c*x^4) == *) +(* (q*c*d+a*e)/(2*a)*(q+x^2)/(a+b*x^2+c*x^4) + (q*c*d-a*e)/(2*a)*(q-x^2)/(a+b*x^2+c*x^4)*) + + +Int[(d_+e_.*x_^2)/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + Module[{q=Rt[a/c,2]}, + Dist[(q*c*d+a*e)/(2*a),Int[(q+x^2)/(a+b*x^2+c*x^4),x]] + + Dist[(q*c*d-a*e)/(2*a),Int[(q-x^2)/(a+b*x^2+c*x^4),x]]] /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[d^2*c-e^2*a] && PosQ[a/c] && +(NegativeQ[b^2-4*a*c] || RationalQ[a/c] && Not[PositiveQ[b^2-4*a*c]]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[-a/c], then (d+e*x^2)/(a+b*x^2+c*x^4) == *) +(* -(q*c*d-a*e)/(2*a)*(q+x^2)/(a+b*x^2+c*x^4) - (q*c*d+a*e)/(2*a)*(q-x^2)/(a+b*x^2+c*x^4)*) + + +Int[(d_+e_.*x_^2)/(a_+b_.*x_^2+c_.*x_^4), x_Symbol] := + Module[{q=Rt[-a/c,2]}, + Dist[-(q*c*d-a*e)/(2*a),Int[(q+x^2)/(a+b*x^2+c*x^4),x]] - + Dist[(q*c*d+a*e)/(2*a),Int[(q-x^2)/(a+b*x^2+c*x^4),x]]] /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[d^2*c-e^2*a] && NegQ[a/c] && +(NegativeQ[b^2-4*a*c] || RationalQ[a/c] && Not[PositiveQ[b^2-4*a*c]]) + + +(* ::Subsubsection::Closed:: *) +(*x^m (a + b x^2)/(c + d x^n + e x^k + f x^j) Quotients of binomials by quartic trinomials*) + + +Int[(a_+b_.*x_^k_)/(c_+d_.*x_^2+e_.*x_^k_+f_.*x_^j_), x_Symbol] := + a/Rt[c*d,2]*ArcTan[a*(k-1)*Rt[c*d,2]*x/(c*(a*(k-1)-b*x^k))] /; +FreeQ[{a,b,c,d,e,f},x] && IntegerQ[{j,k}] && k>0 && j==2*k && ZeroQ[(k-1)^2*a^2*f-b^2*c] && +ZeroQ[b*e+2*a*(k-1)*f] && PosQ[c*d] + + +Int[(a_+b_.*x_^k_)/(c_+d_.*x_^2+e_.*x_^k_+f_.*x_^j_), x_Symbol] := + a/Rt[-c*d,2]*ArcTanh[a*(k-1)*Rt[-c*d,2]*x/(c*(a*(k-1)-b*x^k))] /; +FreeQ[{a,b,c,d,e,f},x] && IntegerQ[{j,k}] && k>0 && j==2*k && ZeroQ[(k-1)^2*a^2*f-b^2*c] && +ZeroQ[b*e+2*a*(k-1)*f] && NegQ[c*d] + + +Int[x_^m_.*(a_+b_.*x_^k_.)/(c_+d_.*x_^n_.+e_.*x_^k_.+f_.*x_^j_), x_Symbol] := + a*ArcTan[a*(m-k+1)*Rt[c*d,2]*x^(m+1)/(c*(a*(m-k+1)+b*(m+1)*x^k))]/((m+1)*Rt[c*d,2]) /; +FreeQ[{a,b,c,d,e,f,j,k,m,n},x] && ZeroQ[n-2*(m+1)] && ZeroQ[j-2*k] && +ZeroQ[a^2*f*(m-k+1)^2-b^2*c*(m+1)^2] && ZeroQ[b*e*(m+1)-2*a*f*(m-k+1)] && PosQ[c*d] + + +Int[x_^m_.*(a_+b_.*x_^k_.)/(c_+d_.*x_^n_.+e_.*x_^k_.+f_.*x_^j_), x_Symbol] := + a*ArcTanh[a*(m-k+1)*Rt[-c*d,2]*x^(m+1)/(c*(a*(m-k+1)+b*(m+1)*x^k))]/((m+1)*Rt[-c*d,2]) /; +FreeQ[{a,b,c,d,e,f,j,k,m,n},x] && ZeroQ[n-2*(m+1)] && ZeroQ[j-2*k] && +ZeroQ[a^2*f*(m-k+1)^2-b^2*c*(m+1)^2] && ZeroQ[b*e*(m+1)-2*a*f*(m-k+1)] && NegQ[c*d] + + +(* ::Subsubsection::Closed:: *) +(*(a+b x^k+c x^(2k))^n Powers of symmetric trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.161.1b?*) + + +Int[1/(a_+b_.*x_^k_+c_.*x_^j_),x_Symbol] := + Module[{q=2*Rt[a/c,2]-b/c}, + Dist[1/(2*c*Rt[a/c,2]*Rt[q,2]),Int[(Rt[q,2]+x^(k/2))/(Rt[a/c,2]+Rt[q,2]*x^(k/2)+x^k),x]] + + Dist[1/(2*c*Rt[a/c,2]*Rt[q,2]),Int[(Rt[q,2]-x^(k/2))/(Rt[a/c,2]-Rt[q,2]*x^(k/2)+x^k),x]] /; + Not[NegativeQ[q]]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k}] && k>0 && j==2*k && EvenQ[k] && PosQ[a/c] && +NegativeQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.161.1a'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*z+c*z^2) == 2*c/(q*(b-q+2*c*z)) - 2*c/(q*(b+q+2*c*z)) where q=Sqrt[b^2-4*a*c]*) + + +Int[1/(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[2*c/q,Int[1/(b-q+2*c*x^k),x]] - + Dist[2*c/q,Int[1/(b+q+2*c*x^k),x]]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k}] && k>0 && j==2*k && NonzeroQ[b^2-4*a*c] && +(OddQ[k] || Not[NegativeQ[b^2-4*a*c]]) + + +(* ::Item:: *) +(*Reference: G&R 2.161.5' (GR5 2.161.4 is a special case.)*) + + +(* Previously undiscovered rule ??? *) +Int[(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + -x*(b^2-2*a*c+b*c*x^k)*(a+b*x^k+c*x^j)^(n+1)/(k*a*(n+1)*(b^2-4*a*c)) + + Dist[(k*(n+1)*(b^2-4*a*c)+b^2-2*a*c)/(k*a*(n+1)*(b^2-4*a*c)),Int[(a+b*x^k+c*x^j)^(n+1),x]] + + Dist[(k*(2*n+3)+1)*b*c/(k*a*(n+1)*(b^2-4*a*c)),Int[x^k*(a+b*x^k+c*x^j)^(n+1),x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,n}] && k>0 && j==2*k && NonzeroQ[b^2-4*a*c] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m / (a+b x^k+c x^(2k)) Quotients of monomials by symmetric trinomials*) + + +(* ::Item:: *) +(*Reference: G&R 2.177.1', CRC 120'*) + + +(* Note: This rule does not use the obvious substitution u=x^k on the whole integrand reducing + it to 1/(x*(a+b*x+c*x^2)) so that Log[x] instead of Log[x^k] appears in the result *) +Int[1/(x_*(a_+b_.*x_^k_+c_.*x_^j_.)),x_Symbol] := +(* Dist[1/a,Int[x^(k-1)*(b+c*x^k)/(a+b*x^k+c*x^j),x]] /; *) + Log[x]/a - + Dist[1/(a*k),Subst[Int[(b+c*x)/(a+b*x+c*x^2),x],x,x^k]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k}] && k>0 && j==2*k && NonzeroQ[b^2-4*a*c] + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +Int[x_^m_./(a_+b_.*x_^k_+c_.*x_^j_),x_Symbol] := + Module[{q=2*Rt[a/c,2]-b/c}, + Dist[1/(2*c*Rt[q,2]),Int[x^(m-k/2)/(Rt[a/c,2]-Rt[q,2]*x^(k/2)+x^k),x]] - + Dist[1/(2*c*Rt[q,2]),Int[x^(m-k/2)/(Rt[a/c,2]+Rt[q,2]*x^(k/2)+x^k),x]] /; + PosQ[q]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,m}] && k>0 && j==2*k && EvenQ[m] && EvenQ[k] && +00 && j==2*k && NonzeroQ[b^2-4*a*c] && +(OddQ[k] || Not[NegativeQ[b^2-4*a*c]]) + + +(* ::Item:: *) +(*Reference: G&R 2.174.1', CRC 119'*) + + +Int[x_^m_./(a_+b_.*x_^k_+c_.*x_^j_),x_Symbol] := + x^(m-j+1)/(c*(m-j+1))- + Dist[1/c,Int[x^(m-j)*(a+b*x^k)/(a+b*x^k+c*x^(2k)),x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,m}] && k>0 && j==2*k && NonzeroQ[b^2-4*a*c] && 00 && j==2*k && NonzeroQ[b^2-4*a*c] && m<-1 && k>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b x^k+c x^(2k))^n Products of monomials and powers of symmetric trinomials*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* Int[x_^m_./(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + Module[{g=GCD[m+1,k]}, + Dist[1/g,Subst[Int[x^((m+1)/g-1)/(a+b*x^(k/g)+c*x^(j/g)),x],x,x^g]] /; + g>1] /; +FreeQ[{a,b,c},x] && IntegerQ[{m,k,j}] && j==2*k && 00 && j==2*k && m>0 && n<0 && IntegerQ[(m+1)/k] && +NonzeroQ[b^2-4*a*c] + + +(* Int[(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + Int[(b/2+c*x^k)^(2*n),x]/c^n /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,n}] && k>0 && j==2*k && ZeroQ[b^2-4*a*c] *) + + +(* ::Item:: *) +(*Reference: G&R 2.160.4*) + + +Int[x_^m_*(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^n/(m+j*n+1) + + Dist[a*j*n/(m+j*n+1),Int[x^m*(a+b*x^k+c*x^j)^(n-1),x]] + + Dist[b*k*n/(m+j*n+1),Int[x^(m+k)*(a+b*x^k+c*x^j)^(n-1),x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,m,n}] && k>0 && j==2*k && m<-1 && n>1 && NonzeroQ[m+j*n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.160.3'*) + + +Int[x_^m_*(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + x^(m-j+1)*(a+b*x^k+c*x^j)^(n+1)/(c*k*(n+1)) + + Dist[a/c,Int[x^(m-j)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,m,n}] && k>0 && j==2*k && m-j>=0 && n<-1 && ZeroQ[m+k*(n-1)+1] + + +(* ::Item:: *) +(*Reference: G&R 2.160.3 (GR5 2.174.1 is a special case.)*) + + +Int[x_^m_*(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + x^(m-j+1)*(a+b*x^k+c*x^j)^(n+1)/(c*(m+j*n+1)) - + Dist[b*(m+k*(n-1)+1)/(c*(m+j*n+1)),Int[x^(m-k)*(a+b*x^k+c*x^j)^n,x]] - + Dist[a*(m-j+1)/(c*(m+j*n+1)),Int[x^(m-j)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,m,n}] && k>0 && j==2*k && m-j>=0 && n<-1 && NonzeroQ[m+j*n+1] && +NonzeroQ[m+k*(n-1)+1] + + +(* ::Item:: *) +(*Reference: G&R 2.160.2*) + + +Int[x_^m_*(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^n/(m+1) - + Dist[b*k*n/(m+1),Int[x^(m+k)*(a+b*x^k+c*x^j)^(n-1),x]] - + Dist[c*j*n/(m+1),Int[x^(m+j)*(a+b*x^k+c*x^j)^(n-1),x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,m,n}] && k>0 && j==2*k && m<-1 && n>1 + + +(* ::Item:: *) +(*Reference: G&R 2.160.1 (GR5 2.161.6 is a special case.)*) + + +Int[x_^m_*(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + x^(m+1)*(a+b*x^k+c*x^j)^(n+1)/(a*(m+1)) - + Dist[b*(m+1+k*(n+1))/(a*(m+1)),Int[x^(m+k)*(a+b*x^k+c*x^j)^n,x]] - + Dist[c*(m+1+j*(n+1))/(a*(m+1)),Int[x^(m+j)*(a+b*x^k+c*x^j)^n,x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,m,n}] && k>0 && j==2*k && m<-1 && n<=1 + + +(* Previously undiscovered rules ??? *) +Int[x_^k_*(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + x*(b+2*c*x^k)*(a+b*x^k+c*x^j)^n/(2*c*(k*(2*n+1)+1)) - + Dist[b/(2*c*(k*(2*n+1)+1)),Int[(a+b*x^k+c*x^j)^n, x]] - + Dist[k*n*(b^2-4*a*c)/(2*c*(k*(2*n+1)+1)),Int[x^k*(a+b*x^k+c*x^j)^(n-1), x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,n}] && k>0 && j==2*k && n>0 && NonzeroQ[b^2-4*a*c] && +NonzeroQ[k*(2*n+1)+1] + + +Int[x_^k_*(a_+b_.*x_^k_+c_.*x_^j_.)^n_,x_Symbol] := + x*(b+2*c*x^k)*(a+b*x^k+c*x^j)^(n+1)/(k*(n+1)*(b^2-4*a*c)) - + Dist[b/(k*(n+1)*(b^2-4*a*c)),Int[(a+b*x^k+c*x^j)^(n+1),x]] - + Dist[2*c*(k*(2*n+3)+1)/(k*(n+1)*(b^2-4*a*c)),Int[x^k*(a+b*x^k+c*x^j)^(n+1),x]] /; +FreeQ[{a,b,c},x] && IntegerQ[{j,k,n}] && k>0 && j==2*k && n<-1 && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*x^m (d+e x^k) / (a+b x^k+c x^(2k)) Products of monomials and quotients of binomials by symmetric trinomials*) + + +(* These way kool, and to my knowledge original, rules reduce the degree of monomial without + increasing the complexity of the integrands. *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: (d+e*z)/(a+b*z+c*z^2) == (e+(2*c*d-b*e)/q)/(b-q+2*c*z) + (e-(2*c*d-b*e)/q)/(b+q+2*c*z) where q=Sqrt[b^2-4*a*c]*) + + +Int[(d_+e_.*x_^k_)/(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + Module[{q=Rt[b^2-4*a*c,2]}, + Dist[(e+(2*c*d-b*e)/q),Int[1/(b-q+2*c*x^k),x]] + + Dist[(e-(2*c*d-b*e)/q),Int[1/(b+q+2*c*x^k),x]]] /; +FreeQ[{a,b,c,d,e},x] && IntegerQ[{j,k}] && k>0 && j==2*k && NonzeroQ[b^2-4*a*c] && +Not[NegativeQ[b^2-4*a*c]] + + +(* Note: This rule does not use the obvious substitution u=x^k on the whole integrand reducing + it to (d+e*x)/(x*(a+b*x+c*x^2)) so that Log[x] instead of Log[x^k] appears in the result *) +Int[(d_.+e_.*x_^k_)/(x_*(a_+b_.*x_^k_+c_.*x_^j_.)),x_Symbol] := +(* Dist[1/a,Int[x^(k-1)*(b*d-a*e+c*d*x^k)/(a+b*x^k+c*x^j),x]] /; *) + d*Log[x]/a - + Dist[1/(a*k),Subst[Int[(b*d-a*e+c*d*x)/(a+b*x+c*x^2),x],x,x^k]] /; +FreeQ[{a,b,c,d,e},x] && IntegerQ[{j,k}] && k>0 && j==2*k + + +Int[x_^m_.*(d_.+e_.*x_^k_)/(a_+b_.*x_^k_+c_.*x_^j_.),x_Symbol] := + e*x^(m-k+1)/(c*(m-k+1)) - + Dist[1/c,Int[x^(m-k)*(a*e+(b*e-c*d)*x^k)/(a+b*x^k+c*x^j),x]] /; +FreeQ[{a,b,c,d,e},x] && IntegerQ[{j,k,m}] && k>0 && j==2*k && k0 && j==2*k && m<-1 + + +(* ::Subsection::Closed:: *) +(*a + b x + c x^2 + b x^3 + a x^4 Integrands involving symmetric quartic polynomials*) + + +(* ::Subsubsection::Closed:: *) +(*(d+e x+f x^2+g x^3)/(a+b x+c x^2+b x^3+a x^4) Quotients of binomials by quartic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[8*a^2+b^2-4*a*c], then a+b*x+c*x^2+b*x^3+a*x^4 == a*(1+((b-q)*x)/(2*a)+x^2)*(1+((b+q)*x)/(2*a)+x^2)*) + + +(* ::Item:: *) +(*Basis: If q=Sqrt[8*a^2+b^2-4*a*c], then (d+e*x+f*x^2+g*x^3)/(a+b*x+c*x^2+b*x^3+a*x^4) == *) +(* (b*d-2*a*e+2*a*g+d*q+(2*a*d-2*a*f+b*g+g*q)*x)/(q*(2*a+(b+q)*x+2*a*x^2)) - *) +(* (b*d-2*a*e+2*a*g-d*q+(2*a*d-2*a*f+b*g-g*q)*x)/(q*(2*a+(b-q)*x+2*a*x^2))*) + + +Int[(d_.+e_.*x_+f_.*x_^2+g_.*x_^3)/(a_+b_.*x_+c_.*x_^2+b_.*x_^3+a_.*x_^4),x_Symbol] := + Module[{q=Sqrt[8*a^2+b^2-4*a*c]}, + Dist[1/q,Int[(b*d-2*a*e+2*a*g+d*q+(2*a*d-2*a*f+b*g+g*q)*x)/(2*a+(b+q)*x+2*a*x^2),x]] - + Dist[1/q,Int[(b*d-2*a*e+2*a*g-d*q+(2*a*d-2*a*f+b*g-g*q)*x)/(2*a+(b-q)*x+2*a*x^2),x]]] /; +FreeQ[{a,b,c,d,e,f,g},x] && PosQ[8*a^2+b^2-4*a*c] + + +Int[(d_.+e_.*x_+g_.*x_^3)/(a_+b_.*x_+c_.*x_^2+b_.*x_^3+a_.*x_^4),x_Symbol] := + Module[{q=Sqrt[8*a^2+b^2-4*a*c]}, + Dist[1/q,Int[(b*d-2*a*e+2*a*g+d*q+(2*a*d+b*g+g*q)*x)/(2*a+(b+q)*x+2*a*x^2),x]] - + Dist[1/q,Int[(b*d-2*a*e+2*a*g-d*q+(2*a*d+b*g-g*q)*x)/(2*a+(b-q)*x+2*a*x^2),x]]] /; +FreeQ[{a,b,c,d,e,g},x] && PosQ[8*a^2+b^2-4*a*c] + + +(* ::Subsection::Closed:: *) +(*a x^p + b x^q Integrands involving nonnormal binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a z^p+b z^q == z^p (a+b z^(q-p))*) + + +Int[(a_.*x_^p_.+b_.*x_^q_.)^n_,x_Symbol] := + Int[x^(n*p)*(a+b*x^(q-p))^n,x] /; +FreeQ[{a,b,p,q},x] && IntegerQ[n] && Not[FractionQ[p]] && Not[FractionQ[q]] && Not[NegativeQ[q-p]] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a z^p+b z^q == z^p (a+b z^(q-p))*) + + +Int[x_^m_.*(a_.*x_^p_.+b_.*x_^q_.)^n_,x_Symbol] := + Int[x^(m+n*p)*(a+b*x^(q-p))^n,x] /; +FreeQ[{a,b,m,p,q},x] && IntegerQ[n] && Not[FractionQ[p]] && Not[FractionQ[q]] && Not[FractionQ[m]] && Not[NegativeQ[q-p]] + + +(* ::Subsection::Closed:: *) +(*P(x)/Q(x)^n Quotients of polynomials and powers of polynomials*) + + +(* Note: Finds one term of the rational part of the antiderivative, thereby reducing the degree + of the polynomial in the numerator of the integrand. Equivalent to the Ostrogradskiy-Hermite + method (GR5 2.104) but without the need to solve a system of linear equations. *) +(* If m+1>=n and m+1-n*p!=0, let c=pm/(qn*(m+1-n*p)), then Int[Pm[x]/Qn[x]^p,x] --> + c*x^(m-n+1)/Qn[x]^(p-1)+ + Int[(Pm[x]-c*x^(m-n)*((m-n+1)*Qn[x]+(1-p)*x*D[Qn[x],x]))/Qn[x]^p,x] *) +(* Integrate[Sum[ai*(m+i-i*p)*x^(m+i-1),{i,0,n}]/Sum[ai*x^i,{i,0,n}]^p,x] == + x^m/Sum[ai*x^i,{i,0,n}]^(p-1) *) +(* Note: Requirement that m<2*n-1 ensures new term is a proper fraction. *) +If[ShowSteps, + +Int[u_*v_^p_,x_Symbol] := + Module[{m=Exponent[u,x],n=Exponent[v,x]}, + Module[{c=Coefficient[u,x,m]/(Coefficient[v,x,n]*(m+1+n*p)),w}, + w=Apart[u-c*x^(m-n)*((m-n+1)*v+(p+1)*x*D[v,x]),x]; + If[ZeroQ[w], + ShowStep["If p>1, m+1>=n>1, and m-n*p<-1, let c=pm/(qn*(m+1-n*p)), then if (Pm[x]-c*x^(m-n)*((m-n+1)*Qn[x]+(1-p)*x*D[Qn[x],x]))==0,", + "Int[Pm[x]/Qn[x]^p,x]", "c*x^(m-n+1)/Qn[x]^(p-1)", + Hold[c*x^(m-n+1)*v^(p+1)]], + ShowStep["If p>1, m+1>=n>1, and m-n*p<-1, let c=pm/(qn*(m+1-n*p)), then", + "Int[Pm[x]/Qn[x]^p,x]", + "c*x^(m-n+1)/Qn[x]^(p-1)+Int[(Pm[x]-c*x^(m-n)*((m-n+1)*Qn[x]+(1-p)*x*D[Qn[x],x]))/Qn[x]^p,x]", + Hold[c*x^(m-n+1)*v^(p+1) + Int[w*v^p,x]]]]] /; + m+1>=n>1 && m+n*p<-1 && FalseQ[DerivativeDivides[v,u,x]]] /; +SimplifyFlag && RationalQ[p] && p<-1 && PolynomialQ[{u,v},x] && SumQ[v] && +Not[MonomialQ[u,x] && BinomialQ[v,x]] && +Not[ZeroQ[Coefficient[u,x,0]] && ZeroQ[Coefficient[v,x,0]]], + +Int[u_*v_^p_,x_Symbol] := + Module[{m=Exponent[u,x],n=Exponent[v,x]}, + Module[{c=Coefficient[u,x,m]/(Coefficient[v,x,n]*(m+1+n*p)),w}, + c=Coefficient[u,x,m]/(Coefficient[v,x,n]*(m+1+n*p)); + w=Apart[u-c*x^(m-n)*((m-n+1)*v+(p+1)*x*D[v,x]),x]; + If[ZeroQ[w], + c*x^(m-n+1)*v^(p+1), + c*x^(m-n+1)*v^(p+1) + Int[w*v^p,x]]] /; + m+1>=n>1 && m+n*p<-1 && FalseQ[DerivativeDivides[v,u,x]]] /; +RationalQ[p] && p<-1 && PolynomialQ[{u,v},x] && SumQ[v] && +Not[MonomialQ[u,x] && BinomialQ[v,x]] && +Not[ZeroQ[Coefficient[u,x,0]] && ZeroQ[Coefficient[v,x,0]]]] + + +(* ::Subsection::Closed:: *) +(*u + v Sums*) + + +(* ::Item:: *) +(*Reference: G&R 2.02.5*) + + +Int[f_'[u_]*g_[v_]*w_. + f_[u_]*g_'[v_]*t_.,x_Symbol] := + f[u]*g[v] /; +FreeQ[{f,g},x] && ZeroQ[D[u,x]-w] && ZeroQ[D[v,x]-t] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.02.2, CRC 2,4*) + + +(* ::Item:: *) +(*Basis: Int[a*u+b*v+...,x] == a*Int[u,x]+b*Int[v,x]+...*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + If[SplitFreeTerms[u,x][[1]]===0, + ShowStep["","Int[a*u+b*v+\[CenterEllipsis],x]","a*Int[u,x]+b*Int[v,x]+\[CenterEllipsis]",Hold[ + SplitFreeIntegrate[u,x]]], + ShowStep["","Int[a+b*u+c*v+\[CenterEllipsis],x]","a*x+b*Int[u,x]+c*Int[v,x]+\[CenterEllipsis]",Hold[ + SplitFreeIntegrate[u,x]]]] /; +SimplifyFlag && SumQ[u], + +Int[u_,x_Symbol] := + SplitFreeIntegrate[u,x] /; +SumQ[u]] + + +(* ::Item:: *) +(*Basis: Int[a*u,x] == a*Int[u,x]*) + + +SplitFreeIntegrate[u_,x_Symbol] := + If[SumQ[u], + Map[Function[SplitFreeIntegrate[#,x]],u], + If[FreeQ[u,x], + u*x, + If[MatchQ[u,c_*(a_+b_.*x) /; FreeQ[{a,b,c},x]], + Int[u,x], + Module[{lst=SplitFreeFactors[u,x]}, + Dist[lst[[1]], Int[lst[[2]],x]]]]]] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/SpecialFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/SpecialFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/SpecialFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/SpecialFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,831 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Special Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Gamma Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Gamma[n,a+b x]*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Gamma[n_,a_.+b_.*x_],x_Symbol] := + (a+b*x)*Gamma[n,a+b*x]/b - + Gamma[n+1,a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m Gamma[n,a+b x]*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Gamma[n_,a_.*x_],x_Symbol] := + x^(m+1)*Gamma[n,a*x]/(m+1) - + Gamma[m+n+1,a*x]/((m+1)*a^(m+1)) /; +FreeQ[{a,n},x] && (IntegerQ[m] || PositiveQ[a]) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Gamma[n_,a_*x_],x_Symbol] := + x^(m+1)*Gamma[n,a*x]/(m+1) - + x^(m+1)*Gamma[m+n+1,a*x]/((m+1)*(a*x)^(m+1)) /; +FreeQ[{a,m,n},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Gamma[n_,a_+b_.*x_],x_Symbol] := + x^m*(a+b*x)*Gamma[n,a+b*x]/(b*(m+1)) - + x^m*Gamma[n+1,a+b*x]/(b*(m+1)) - + Dist[a*m/(b*(m+1)),Int[x^(m-1)*Gamma[n,a+b*x],x]] + + Dist[m/(b*(m+1)),Int[x^(m-1)*Gamma[n+1,a+b*x],x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>0 + + +(* ::Subsection::Closed:: *) +(*LogGamma Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*LogGamma[a+b x]*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[PolyGamma[-2,z],z] == LogGamma[z]*) + + +Int[LogGamma[a_.+b_.*x_],x_Symbol] := + PolyGamma[-2,a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m LogGamma[a+b x]*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*LogGamma[a_.+b_.*x_],x_Symbol] := + x^m*PolyGamma[-2,a+b*x]/b - + Dist[m/b,Int[x^(m-1)*PolyGamma[-2,a+b*x],x]] /; +FreeQ[{a,b},x] && RationalQ[m] && m>0 + + +(* ::Subsection::Closed:: *) +(*PolyGamma Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*PolyGamma[n, a+b x]*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[PolyGamma[n,z],z] == PolyGamma[n+1,z]*) + + +Int[PolyGamma[n_,a_.+b_.*x_],x_Symbol] := + PolyGamma[n-1,a+b*x]/b /; +FreeQ[{a,b,n},x] + + +(* ::Subsubsection::Closed:: *) +(*x^m PolyGamma[n, a+b x]*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*PolyGamma[n_,a_.+b_.*x_],x_Symbol] := + x^m*PolyGamma[n-1,a+b*x]/b - + Dist[m/b,Int[x^(m-1)*PolyGamma[n-1,a+b*x],x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*PolyGamma[n_,a_.+b_.*x_],x_Symbol] := + x^(m+1)*PolyGamma[n,a+b*x]/(m+1) - + Dist[b/(m+1),Int[x^(m+1)*PolyGamma[n+1,a+b*x],x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 + + +(* ::Subsubsection::Closed:: *) +(*Gamma[a+b x]^n PolyGamma[0, a+b x]*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[Gamma[z]^n, z] == n Gamma[z]^n PolyGamma[0, z]*) + + +Int[Gamma[a_.+b_.*x_]^n_.*PolyGamma[0,a_.+b_.*x_],x_Symbol] := + Gamma[a+b*x]^n/(b*n) /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[(z!)^n, z] == n (z!)^n PolyGamma[0, 1+z]*) + + +Int[((a_.+b_.*x_)!)^n_.*PolyGamma[0,c_.+b_.*x_],x_Symbol] := + ((a+b*x)!)^n/(b*n) /; +FreeQ[{a,b,c,n},x] && ZeroQ[a-c+1] + + +(* ::Subsection::Closed:: *) +(*Zeta Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Zeta[s, a+b x]*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Zeta[2,z] == PolyGamma[1,z]*) + + +Int[Zeta[2,a_.+b_.*x_],x_Symbol] := + Int[PolyGamma[1,a+b*x],x] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[Zeta[s,z],z] == -s*Zeta[s+1,z]*) + + +Int[Zeta[s_,a_.+b_.*x_],x_Symbol] := + -Zeta[s-1,a+b*x]/(b*(s-1)) /; +FreeQ[{a,b,s},x] && NonzeroQ[s-1] && NonzeroQ[s-2] + + +(* ::Subsubsection::Closed:: *) +(*x^m Zeta[s, a+b x]*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Zeta[2,z] == PolyGamma[1,z]*) + + +Int[x_^m_.*Zeta[2,a_.+b_.*x_],x_Symbol] := + Int[x^m*PolyGamma[1,a+b*x],x] /; +FreeQ[{a,b},x] && RationalQ[m] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Zeta[s_,a_.+b_.*x_],x_Symbol] := + -x^m*Zeta[s-1,a+b*x]/(b*(s-1)) + + Dist[m/(b*(s-1)),Int[x^(m-1)*Zeta[s-1,a+b*x],x]] /; +FreeQ[{a,b,s},x] && RationalQ[m] && m>0 && NonzeroQ[s-1] && NonzeroQ[s-2] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*Zeta[s_,a_.+b_.*x_],x_Symbol] := + x^(m+1)*Zeta[s,a+b*x]/(m+1) + + Dist[b*s/(m+1),Int[x^(m+1)*Zeta[s+1,a+b*x],x]] /; +FreeQ[{a,b,s},x] && RationalQ[m] && m<-1 && NonzeroQ[s-1] && NonzeroQ[s-2] + + +(* ::Subsection::Closed:: *) +(*Polylogarithm Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*PolyLog[n, a (b x^p)^q]*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[PolyLog[n_,a_.*(b_.*x_^p_.)^q_.],x_Symbol] := + x*PolyLog[n,a*(b*x^p)^q] - + Dist[p*q,Int[PolyLog[n-1,a*(b*x^p)^q],x]] /; +FreeQ[{a,b,p,q},x] && RationalQ[n] && n>0 + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[PolyLog[n_,a_.*(b_.*x_^p_.)^q_.],x_Symbol] := + x*PolyLog[n+1,a*(b*x^p)^q]/(p*q) - + Dist[1/(p*q),Int[PolyLog[n+1,a*(b*x^p)^q],x]] /; +FreeQ[{a,b,p,q},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m PolyLog[n, a (b x^p)^q]*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: D[PolyLog[n,z],z] == PolyLog[n-1,z]/z*) + + +Int[PolyLog[n_,a_.*(b_.*x_^p_.)^q_.]/x_,x_Symbol] := + PolyLog[n+1,a*(b*x^p)^q]/(p*q) /; +FreeQ[{a,b,n,p,q},x] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*PolyLog[n_,a_.*(b_.*x_^p_.)^q_.],x_Symbol] := + x^(m+1)*PolyLog[n,a*(b*x^p)^q]/(m+1) - + Dist[p*q/(m+1),Int[x^m*PolyLog[n-1,a*(b*x^p)^q],x]] /; +FreeQ[{a,b,m,p,q},x] && RationalQ[n] && n>0 && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts*) + + +Int[x_^m_.*PolyLog[n_,a_.*(b_.*x_^p_.)^q_.],x_Symbol] := + x^(m+1)*PolyLog[n+1,a*(b*x^p)^q]/(p*q) - + Dist[(m+1)/(p*q),Int[x^m*PolyLog[n+1,a*(b*x^p)^q],x]] /; +FreeQ[{a,b,m,p,q},x] && RationalQ[n] && n<-1 && NonzeroQ[m+1] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[PolyLog[n_,u_]/(a_+b_.*x_),x_Symbol] := + Dist[1/b,Subst[Int[PolyLog[n,Regularize[Subst[u,x,-a/b+x/b],x]]/x,x],x,a+b*x]] /; +FreeQ[{a,b,n},x] + + +(* ::Subsubsection::Closed:: *) +(*PolyLog[n, c (a+b x)^p]*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[PolyLog[n_,c_.*(a_.+b_.*x_)^p_.],x_Symbol] := + x*PolyLog[n,c*(a+b*x)^p] - + Dist[p,Int[PolyLog[n-1,c*(a+b*x)^p],x]] + + Dist[a*p,Int[PolyLog[n-1,c*(a+b*x)^p]/(a+b*x),x]] /; +FreeQ[{a,b,c,p},x] && RationalQ[n] && n>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m PolyLog[n, c (a+b x)^p]*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*PolyLog[n_,c_.*(a_.+b_.*x_)^p_.],x_Symbol] := + x^(m+1)*PolyLog[n,c*(a+b*x)^p]/(m+1) - + Dist[b*p/(m+1),Int[x^(m+1)*PolyLog[n-1,c*(a+b*x)^p]/(a+b*x),x]] /; +FreeQ[{a,b,c,m,p},x] && RationalQ[n] && n>0 && IntegerQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*Log[a x^n]^p PolyLog[q, b x^m]/x*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[Log[a_.*x_^n_.]^p_.*PolyLog[q_,b_.*x_^m_.]/x_,x_Symbol] := + Log[a*x^n]^p*PolyLog[q+1,b*x^m]/m - + Dist[n*p/m,Int[Log[a*x^n]^(p-1)*PolyLog[q+1,b*x^m]/x,x]] /; +FreeQ[{a,b,m,n,q},x] && RationalQ[p] && p>0 + + +(* ::Subsection::Closed:: *) +(*LambertW (ProductLog) Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*ProductLog[a+b x]^p*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ProductLog[a_.+b_.*x_]^p_.,x_Symbol] := + (a+b*x)*ProductLog[a+b*x]^p/b - + Dist[p,Int[ProductLog[a+b*x]^p/(1+ProductLog[a+b*x]),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p>=-1 + + +Int[ProductLog[a_.+b_.*x_]^p_,x_Symbol] := + (a+b*x)*ProductLog[a+b*x]^p/(b*(p+1)) + + Dist[p/(p+1),Int[ProductLog[a+b*x]^(p+1)/(1+ProductLog[a+b*x]),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p<-1 + + +Int[ProductLog[a_.+b_.*x_]^p_,x_Symbol] := + ProductLog[a+b*x]^p/(-ProductLog[a+b*x])^p*Int[(-ProductLog[a+b*x])^p,x] /; +FreeQ[{a,b,p},x] && Not[RationalQ[p]] + + +(* ::Subsubsection::Closed:: *) +(*ProductLog[a+b x]^p / (1+ProductLog[a+b x])*) + + +Int[1/(1+ProductLog[a_.+b_.*x_]),x_Symbol] := + (a+b*x)/(b*ProductLog[a+b*x]) /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: z/(1+z) == 1-1/(1+z)*) + + +Int[ProductLog[a_.+b_.*x_]/(1+ProductLog[a_.+b_.*x_]),x_Symbol] := + x - + Int[1/(1+ProductLog[a+b*x]),x] /; +FreeQ[{a,b},x] + + +Int[1/(ProductLog[a_.+b_.*x_]*(1+ProductLog[a_.+b_.*x_])),x_Symbol] := + ExpIntegralEi[ProductLog[a+b*x]]/b /; +FreeQ[{a,b},x] + + +Int[1/(Sqrt[ProductLog[a_.+b_.*x_]]*(1+ProductLog[a_.+b_.*x_])),x_Symbol] := + Sqrt[Pi]*Erfi[Sqrt[ProductLog[a+b*x]]]/b /; +FreeQ[{a,b},x] + + +Int[ProductLog[a_.+b_.*x_]^p_/(1+ProductLog[a_.+b_.*x_]),x_Symbol] := + (a+b*x)*ProductLog[a+b*x]^(p-1)/b - + Dist[p,Int[ProductLog[a+b*x]^(p-1)/(1+ProductLog[a+b*x]),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p>0 + + +Int[ProductLog[a_.+b_.*x_]^p_./(1+ProductLog[a_.+b_.*x_]),x_Symbol] := + (a+b*x)*ProductLog[a+b*x]^p/(b*(p+1)) - + Dist[1/(p+1),Int[ProductLog[a+b*x]^(p+1)/(1+ProductLog[a+b*x]),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m ProductLog[a+b x]^p*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ProductLog[a_.*x_]^p_.,x_Symbol] := + x^(m+1)*ProductLog[a*x]^p/(m+1) - + Dist[p/(m+1),Int[x^m*ProductLog[a*x]^p/(1+ProductLog[a*x]),x]] /; +FreeQ[a,x] && RationalQ[{m,p}] && NonzeroQ[m+1] && m+p+1>=0 + + +Int[x_^m_.*ProductLog[a_.*x_]^p_.,x_Symbol] := + x^(m+1)*ProductLog[a*x]^p/(m+p+1) + + Dist[p/(m+p+1),Int[x^m*ProductLog[a*x]^(p+1)/(1+ProductLog[a*x]),x]] /; +FreeQ[a,x] && RationalQ[{m,p}] && NonzeroQ[m+1] && m+p+1<0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 == 1/(1+z) + z/(1+z)*) + + +Int[x_^m_.*ProductLog[a_.*x_]^p_.,x_Symbol] := + Int[x^m*ProductLog[a*x]^p/(1+ProductLog[a*x]),x] + + Int[x^m*ProductLog[a*x]^(p+1)/(1+ProductLog[a*x]),x] /; +FreeQ[a,x] && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b*x,x], x] == Subst[Int[f[x,-a/b+x/b], x], x, a+b*x]/b*) + + +Int[x_^m_.*ProductLog[a_+b_.*x_]^p_.,x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m*ProductLog[x]^p,x],x,a+b*x]] /; +FreeQ[{a,b,p},x] && IntegerQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m / (1+ProductLog[a+b x])*) + + +Int[x_^m_./(1+ProductLog[a_.*x_]),x_Symbol] := + x^(m+1)/((m+1)*ProductLog[a*x]) - + Dist[m/(m+1),Int[x^m/(ProductLog[a*x]*(1+ProductLog[a*x])),x]] /; +FreeQ[a,x] && RationalQ[m] && m>0 + + +Int[x_^m_./(1+ProductLog[a_.*x_]),x_Symbol] := + x^(m+1)/(m+1) - + Int[x^m*ProductLog[a*x]/(1+ProductLog[a*x]),x] /; +FreeQ[a,x] && RationalQ[m] && m<-1 + + +Int[x_^m_./(1+ProductLog[a_.*x_]),x_Symbol] := + x^m*Gamma[m+1,-(m+1)*ProductLog[a*x]]/ + (a*(m+1)*E^(m*ProductLog[a*x])*(-(m+1)*ProductLog[a*x])^m) /; +FreeQ[a,x] && NonzeroQ[m+1] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b*x,x], x] == Subst[Int[f[x,-a/b+x/b], x], x, a+b*x]/b*) + + +Int[x_^m_./(1+ProductLog[a_+b_.*x_]),x_Symbol] := + Dist[1/b,Subst[Int[(-a/b+x/b)^m/(1+ProductLog[x]),x],x,a+b*x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m ProductLog[a x]^p / (1+ProductLog[a x])*) +(**) + + +Int[x_^m_.*ProductLog[a_.*x_]^p_./(1+ProductLog[a_.*x_]),x_Symbol] := + x^(m+1)*ProductLog[a*x]^(p-1)/(m+1) /; +FreeQ[{a,m,p},x] && ZeroQ[m+(p-1)+1] && NonzeroQ[m+1] + + +Int[x_^m_.*ProductLog[a_.*x_]^p_./(1+ProductLog[a_.*x_]),x_Symbol] := + a^p*ExpIntegralEi[-p*ProductLog[a*x]] /; +FreeQ[{a,m},x] && IntegerQ[p] && ZeroQ[m+p+1] + + +Int[x_^m_.*ProductLog[a_.*x_]^p_/(1+ProductLog[a_.*x_]),x_Symbol] := + a^(p-1/2)*Sqrt[Pi/(p-1/2)]*Erf[Sqrt[(p-1/2)*ProductLog[a*x]]] /; +FreeQ[{a,m},x] && IntegerQ[p-1/2] && p>1 && ZeroQ[m+(p-1/2)+1] + + +Int[x_^m_.*ProductLog[a_.*x_]^p_/(1+ProductLog[a_.*x_]),x_Symbol] := + a^(p-1/2)*Sqrt[-Pi/(p-1/2)]*Erfi[Sqrt[-(p-1/2)*ProductLog[a*x]]] /; +FreeQ[{a,m},x] && IntegerQ[p-1/2] && p<0 && ZeroQ[m+(p-1/2)+1] + + +Int[x_^m_.*ProductLog[a_.*x_]^p_./(1+ProductLog[a_.*x_]),x_Symbol] := + x^(m+1)*ProductLog[a*x]^(p-1)/(m+1) - + Dist[(m+(p-1)+1)/(m+1),Int[x^m*ProductLog[a*x]^(p-1)/(1+ProductLog[a*x]),x]] /; +FreeQ[a,x] && RationalQ[{m,p}] && NonzeroQ[m+1] && m+p>0 + + +Int[x_^m_.*ProductLog[a_.*x_]^p_./(1+ProductLog[a_.*x_]),x_Symbol] := + x^(m+1)*ProductLog[a*x]^p/(m+p+1) - + Dist[(m+1)/(m+p+1),Int[x^m*ProductLog[a*x]^(p+1)/(1+ProductLog[a*x]),x]] /; +FreeQ[a,x] && RationalQ[{m,p}] && NonzeroQ[m+1] && m+p<-1 + + +Int[x_^m_.*ProductLog[a_.*x_]^p_./(1+ProductLog[a_.*x_]),x_Symbol] := + x^m*Gamma[m+p+1,-(m+1)*ProductLog[a*x]]*ProductLog[a*x]^p/ + (a*(m+1)*E^(m*ProductLog[a*x])*(-(m+1)*ProductLog[a*x])^(m+p)) /; +FreeQ[a,x] && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*ProductLog[a x^n]^p*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[ProductLog[a_.*x_^n_]^p_.,x_Symbol] := + x*ProductLog[a*x^n]^p - + Dist[n*p,Int[ProductLog[a*x^n]^p/(1+ProductLog[a*x^n]),x]] /; +FreeQ[{a,n,p},x] && (ZeroQ[n*(p-1)+1] || IntegerQ[p-1/2] && ZeroQ[n*(p-1/2)+1]) + + +Int[ProductLog[a_.*x_^n_]^p_.,x_Symbol] := + x*ProductLog[a*x^n]^p/(n*p+1) + + Dist[n*p/(n*p+1),Int[ProductLog[a*x^n]^(p+1)/(1+ProductLog[a*x^n]),x]] /; +FreeQ[{a,n},x] && (IntegerQ[p] && ZeroQ[n*(p+1)+1] || IntegerQ[p-1/2] && ZeroQ[n*(p+1/2)+1]) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x], x] == -Subst[Int[f[1/x]/x^2, x], x, 1/x]*) + + +Int[ProductLog[a_.*x_^n_]^p_.,x_Symbol] := + -Subst[Int[ProductLog[a*x^(-n)]^p/x^2,x],x,1/x] /; +FreeQ[{a,p},x] && IntegerQ[n] && n<0 + + +(* ::Subsubsection::Closed:: *) +(*ProductLog[a x^n]^p / (1+ProductLog[a x^n])*) + + +Int[ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + x*ProductLog[a*x^n]^(p-1) /; +FreeQ[{a,n,p},x] && ZeroQ[n*(p-1)+1] + + +Int[ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + a^p*ExpIntegralEi[-p*ProductLog[a*x^n]]/n /; +FreeQ[{a,n},x] && IntegerQ[p] && ZeroQ[n*p+1] + + +Int[ProductLog[a_.*x_^n_]^p_/(1+ProductLog[a_.*x_^n_]),x_Symbol] := + a^(p-1/2)*Sqrt[Pi/(p-1/2)]*Erf[Sqrt[(p-1/2)*ProductLog[a*x^n]]]/n /; +FreeQ[{a,n},x] && IntegerQ[p-1/2] && p>1 && ZeroQ[n*(p-1/2)+1] + + +Int[ProductLog[a_.*x_^n_]^p_/(1+ProductLog[a_.*x_^n_]),x_Symbol] := + a^(p-1/2)*Sqrt[-Pi/(p-1/2)]*Erfi[Sqrt[-(p-1/2)*ProductLog[a*x^n]]]/n /; +FreeQ[{a,n},x] && IntegerQ[p-1/2] && p<0 && ZeroQ[n*(p-1/2)+1] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x], x] == -Subst[Int[f[1/x]/x^2, x], x, 1/x]*) + + +Int[ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + -Subst[Int[ProductLog[a*x^(-n)]^p/(x^2*(1+ProductLog[a*x^(-n)])),x],x,1/x] /; +FreeQ[{a,p},x] && IntegerQ[n] && n<0 + + +(* ::Subsubsection::Closed:: *) +(*x^m ProductLog[a x^n]^p*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_.,x_Symbol] := + x^(m+1)*ProductLog[a*x^n]^p/(m+1) - + Dist[n*p/(m+1),Int[x^m*ProductLog[a*x^n]^p/(1+ProductLog[a*x^n]),x]] /; +FreeQ[{a,m,n,p},x] && NonzeroQ[m+1] && + (ZeroQ[m+n*(p-1)+1] || + IntegerQ[p] && ZeroQ[m+n*p+1] || + IntegerQ[p-1/2] && ZeroQ[m+n*(p-1/2)+1]) + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_.,x_Symbol] := + x^(m+1)*ProductLog[a*x^n]^p/(m+n*p+1) + + Dist[n*p/(m+n*p+1),Int[x^m*ProductLog[a*x^n]^(p+1)/(1+ProductLog[a*x^n]),x]] /; +FreeQ[{a,m,n,p},x] && NonzeroQ[m+1] && + (IntegerQ[p] && ZeroQ[m+n*(p+1)+1] || IntegerQ[p-1/2] && ZeroQ[m+n*(p+1/2)+1]) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x], x] == -Subst[Int[f[1/x]/x^2, x], x, 1/x]*) + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_.,x_Symbol] := + -Subst[Int[ProductLog[a*x^(-n)]^p/x^(m+2),x],x,1/x] /; +FreeQ[{a,p},x] && IntegerQ[{m,n}] && n<0 && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m / (1+ProductLog[a x^n])*) + + +(* Int[x_^m_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + x^(m+1)/((m+1)*ProductLog[a*x^n]) - + Dist[(m-n+1)/(m+1),Int[x^m/(ProductLog[a*x^n]*(1+ProductLog[a*x^n])),x]] /; +FreeQ[a,x] && RationalQ[{m,n}] && m>0 && NonzeroQ[m-n+1] *) + + +(* Int[x_^m_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + x^(m+1)/(m+1) - + Int[x^m*ProductLog[a*x^n]/(1+ProductLog[a*x^n]),x] /; +FreeQ[a,x] && RationalQ[{m,n}] && m<-1 *) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x], x] == -Subst[Int[f[1/x]/x^2, x], x, 1/x]*) + + +Int[1/(1+ProductLog[a_.*x_^n_]),x_Symbol] := + -Subst[Int[1/(x^2*(1+ProductLog[a*x^(-n)])),x],x,1/x] /; +FreeQ[a,x] && IntegerQ[n] && n<0 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x], x] == -Subst[Int[f[1/x]/x^2, x], x, 1/x]*) + + +Int[x_^m_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + -Subst[Int[1/(x^(m+2)*(1+ProductLog[a*x^(-n)])),x],x,1/x] /; +FreeQ[a,x] && IntegerQ[{m,n}] && n<0 && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m ProductLog[a x^n]^p / (1+ProductLog[a x^n])*) +(**) + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + x^(m+1)*ProductLog[a*x^n]^(p-1)/(m+1) /; +FreeQ[{a,m,n,p},x] && ZeroQ[m+n*(p-1)+1] && NonzeroQ[m+1] + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + a^p*ExpIntegralEi[-p*ProductLog[a*x^n]]/n /; +FreeQ[{a,m,n},x] && IntegerQ[p] && ZeroQ[m+n*p+1] + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_/(1+ProductLog[a_.*x_^n_]),x_Symbol] := + a^(p-1/2)*Sqrt[Pi/(p-1/2)]*Erf[Sqrt[(p-1/2)*ProductLog[a*x^n]]]/n /; +FreeQ[{a,m,n},x] && IntegerQ[p-1/2] && p>1 && ZeroQ[m+n*(p-1/2)+1] + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_/(1+ProductLog[a_.*x_^n_]),x_Symbol] := + a^(p-1/2)*Sqrt[-Pi/(p-1/2)]*Erfi[Sqrt[-(p-1/2)*ProductLog[a*x^n]]]/n /; +FreeQ[{a,m,n},x] && IntegerQ[p-1/2] && p<0 && ZeroQ[m+n*(p-1/2)+1] + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + x^(m+1)*ProductLog[a*x^n]^(p-1)/(m+1) - + Dist[(m+n*(p-1)+1)/(m+1),Int[x^m*ProductLog[a*x^n]^(p-1)/(1+ProductLog[a*x^n]),x]] /; +FreeQ[a,x] && RationalQ[{m,n,p}] && n>0 && NonzeroQ[m+1] && m+n*(p-1)+1>0 + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + x^(m+1)*ProductLog[a*x^n]^p/(m+n*p+1) - + Dist[(m+1)/(m+n*p+1),Int[x^m*ProductLog[a*x^n]^(p+1)/(1+ProductLog[a*x^n]),x]] /; +FreeQ[a,x] && RationalQ[{m,n,p}] && n>0 && NonzeroQ[m+1] && m+n*p+1<0 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[x], x] == -Subst[Int[f[1/x]/x^2, x], x, 1/x]*) + + +Int[x_^m_.*ProductLog[a_.*x_^n_]^p_./(1+ProductLog[a_.*x_^n_]),x_Symbol] := + -Subst[Int[ProductLog[a*x^(-n)]^p/(x^(m+2)*(1+ProductLog[a*x^(-n)])),x],x,1/x] /; +FreeQ[{a,p},x] && IntegerQ[{m,n}] && n<0 && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*(-ProductLog[a+b x])^p / (1+ProductLog[a+b x])*) + + +Int[(-ProductLog[a_.+b_.*x_])^p_./(1+ProductLog[a_.+b_.*x_]),x_Symbol] := + Gamma[p+1,-ProductLog[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 == 1/(1+z) - -z/(1+z)*) + + +Int[(-ProductLog[a_.+b_.*x_])^p_,x_Symbol] := + Int[(-ProductLog[a+b*x])^p/(1+ProductLog[a+b*x]),x] - + Int[(-ProductLog[a+b*x])^(p+1)/(1+ProductLog[a+b*x]),x] /; +FreeQ[{a,b,p},x] + + +(* ::Subsubsection::Closed:: *) +(*f[ProductLog[a+b x]]*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: 1/z == (1 + ProductLog[z])/ProductLog[z]*ProductLog'[z]*) + + +If[ShowSteps, + +Int[u_/x_,x_Symbol] := + Module[{lst=FunctionOfProductLog[u,x]}, + ShowStep["","Int[f[ProductLog[a*x^n]]/x,x]","Subst[Int[f[x]*(1+x)/x,x],x,ProductLog[a*x^n]]/n",Hold[ + Dist[1/lst[[3]],Subst[Int[Regularize[lst[[1]]*(1+x)/x,x],x],x,ProductLog[lst[[2]]]]]]] /; + Not[FalseQ[lst]]] /; +SimplifyFlag && NonsumQ[u], + +Int[u_/x_,x_Symbol] := + Module[{lst=FunctionOfProductLog[u,x]}, + Dist[1/lst[[3]],Subst[Int[Regularize[lst[[1]]*(1+x)/x,x],x],x,ProductLog[lst[[2]]]]] /; + Not[FalseQ[lst]]] /; +NonsumQ[u]] + + +(* ::Item:: *) +(*Derivation: Integration by *) + + +(* Int[x_^m_.*ProductLog[a_.+b_.*x_],x_Symbol] := + Dist[1/b^(m+1),Subst[Int[Regularize[(x*E^x-a)^m*x*(x+1)*E^x,x],x],x,ProductLog[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 *) + + +(* ::Item::Closed:: *) +(*Author: Rob Corless 2009-07-10*) + + +(* ::Item:: *) +(*Derivation: Legendre substitution for inverse functions*) + + +(* ::Item:: *) +(*Basis: ProductLog[z]*E^ProductLog[z] == z*) + + +Int[u_,x_Symbol] := + Subst[Int[Regularize[(x+1)*E^x*SubstFor[ProductLog[x],u,x],x],x],x,ProductLog[x]] /; +FunctionOfQ[ProductLog[x],u,x] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/TrigFunctionIntegrationRules.m mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/TrigFunctionIntegrationRules.m --- mathpiper-0.0.svn2556/src/org/mathpiper/test/matheclipse/TrigFunctionIntegrationRules.m 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/matheclipse/TrigFunctionIntegrationRules.m 2010-09-22 01:38:37.000000000 +0000 @@ -0,0 +1,4364 @@ +(* ::Package:: *) + +(* ::Title:: *) +(*Trig Function Integration Rules*) + + +(* ::Subsection::Closed:: *) +(*Sine Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b x]^n Powers of sines of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.5, CRC 290, A&S 4.3.113*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Cos'[z] == -Sin[z]*) + + +Int[Sin[a_.+b_.*x_],x_Symbol] := + -Cos[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.513.5, CRC 296*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[Sin[a_.+b_.*x_]^2,x_Symbol] := + x/2 - Cos[a+b*x]*Sin[a+b*x]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, Sin[z]^n == -(1-Cos[z]^2)^((n-1)/2)*Cos'[z]*) + + +Int[Sin[a_.+b_.*x_]^n_,x_Symbol] := + Dist[-1/b,Subst[Int[Regularize[(1-x^2)^((n-1)/2),x],x],x,Cos[a+b*x]]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 + + +(* ::ItemParagraph::Closed:: *) +(**) + + +(* ::Item:: *) +(*Reference: G&R 2.510.2, CRC 299*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Sin[a_.+b_.*x_])^n_,x_Symbol] := + -c*Cos[a+b*x]*(c*Sin[a+b*x])^(n-1)/(b*n) + + Dist[(n-1)*c^2/n,Int[(c*Sin[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[OddQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.3, CRC 309*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Sin[a_.+b_.*x_])^n_,x_Symbol] := + Cos[a+b*x]*(c*Sin[a+b*x])^(n+1)/(c*b*(n+1)) + + Dist[(n+2)/((n+1)*c^2),Int[(c*Sin[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Sin[x])^n/Sin[x]^n,x] == 0*) + + +Int[(c_*Sin[a_.+b_.*x_])^n_,x_Symbol] := + (c*Sin[a+b*x])^n/Sin[a+b*x]^n*Int[Sin[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -11 && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.555.1'*) + + +Int[(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + b*Cos[c+d*x]*(a+b*Sin[c+d*x])^n/(a*d*(2*n+1)) + + Dist[(n+1)/(a*(2*n+1)),Int[(a+b*Sin[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.552.3 inverted*) + + +(* Note: This would result in an infinite loop!!! *) +(* Int[(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + b*Cos[c+d*x]*(a+b*Sin[c+d*x])^n/(a*d*n) + + Dist[(a^2-b^2)/a,Int[(a+b*Sin[c+d*x])^(n-1),x]] + + Dist[b*(n+1)/(a*n),Int[Sin[c+d*x]*(a+b*Sin[c+d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>0 && NonzeroQ[a^2-b^2] *) + + +(* ::Item:: *) +(*Reference: G&R 2.552.3*) + + +Int[1/(a_+b_.*Sin[c_.+d_.*x_])^2,x_Symbol] := + b*Cos[c+d*x]/(d*(a^2-b^2)*(a+b*Sin[c+d*x])) + + Dist[a/(a^2-b^2),Int[1/(a+b*Sin[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.552.3*) + + +Int[(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + -b*Cos[c+d*x]*(a+b*Sin[c+d*x])^(n+1)/(d*(n+1)*(a^2-b^2)) + + Dist[1/((n+1)*(a^2-b^2)),Int[(a*(n+1)-b*(n+2)*Sin[c+d*x])*(a+b*Sin[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Sin[c+d x])^n Products of monomials and powers of linear binomials of sines of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1+Sin[z]==2*Sin[z/2+Pi/4]^2==2*Cos[z/2-Pi/4]^2*) + + +Int[x_^m_.*(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := +(*Dist[(2*a)^n,Int[x^m*Sin[Pi/4+c/2+d*x/2]^(2*n),x]] /; *) + Dist[(2*a)^n,Int[x^m*Cos[-Pi/4+c/2+d*x/2]^(2*n),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && n<0 && ZeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1+Sin[z]==2*Sin[z/2+Pi/4]^2==2*Cos[z/2-Pi/4]^2*) + + +Int[x_^m_.*(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := +(*Dist[2^n,Int[x^m*(a*Sin[Pi/4+c/2+d*x/2]^2)^n,x]] /;*) + Dist[2^n,Int[x^m*(a*Cos[-Pi/4+c/2+d*x/2]^2)^n,x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[{m,n}] && ZeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1-Sin[z]==2*Sin[z/2-Pi/4]^2==2*Cos[z/2+Pi/4]^2*) + + +Int[x_^m_.*(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := +(*Dist[(2*a)^n,Int[x^m*Sin[-Pi/4+c/2+d*x/2]^(2*n),x]] /; *) + Dist[(2*a)^n,Int[x^m*Cos[Pi/4+c/2+d*x/2]^(2*n),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && n<0 && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1-Sin[z]==2*Sin[z/2-Pi/4]^2==2*Cos[z/2+Pi/4]^2*) + + +Int[x_^m_.*(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := +(*Dist[2^n,Int[x^m*(a*Sin[-Pi/4+c/2+d*x/2]^2)^n,x]] /; *) + Dist[2^n,Int[x^m*(a*Cos[Pi/4+c/2+d*x/2]^2)^n,x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[{m,n}] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b z)^2 == a/((a^2-b^2) (a+b z)) - b (b+a z)/((a^2-b^2) (a+b z)^2)*) + + +Int[x_/(a_+b_.*Sin[c_.+d_.*x_])^2,x_Symbol] := + Dist[a/(a^2-b^2),Int[x/(a+b*Sin[c+d*x]),x]] - + Dist[b/(a^2-b^2),Int[x*(b+a*Sin[c+d*x])/(a+b*Sin[c+d*x])^2,x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: a+b*Sin[z] == (I*b+2*a*E^(I*z)-I*b*E^(2*I*z))/(2*E^(I*z))*) + + +Int[x_^m_.*(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + Dist[1/2^n,Int[x^m*(I*b+2*a*E^(I*c+I*d*x)-I*b*E^(2*(I*c+I*d*x)))^n/E^(n*(I*c+I*d*x)),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && IntegerQ[n] && n<0 && RationalQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*(A+B Sin[c+d x]) (a+b Sin[c+d x])^n Products of powers of linear binomials of sines*) + + +(* ::Item:: *) +(*Basis: (A+B*z)/Sqrt[a+b*z] == (b*A-a*B)/(b*Sqrt[a+b*z]) + B/b*Sqrt[a+b*z]*) + + +Int[(A_.+B_.*Sin[c_.+d_.*x_])/Sqrt[a_+b_.*Sin[c_.+d_.*x_]],x_Symbol] := + Dist[(b*A-a*B)/b,Int[1/Sqrt[a+b*Sin[c+d*x]],x]] + + Dist[B/b,Int[Sqrt[a+b*Sin[c+d*x]],x]] /; +FreeQ[{a,b,c,d,A,B},x] && NonzeroQ[b*A-a*B] + + +(* ::Item:: *) +(*Reference: G&R 2.551.1 inverted*) + + +Int[(A_.+B_.*Sin[c_.+d_.*x_])*(a_+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + -B*Cos[c+d*x]*(a+b*Sin[c+d*x])^n/(d*(n+1)) + + Dist[1/(n+1),Int[(b*B*n+a*A*(n+1) + (a*B*n+b*A*(n+1))*Sin[c+d*x])*(a+b*Sin[c+d*x])^(n-1), x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n>1 && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.551.1 special case*) + + +Int[(A_+B_.*Sin[c_.+d_.*x_])/(a_+b_.*Sin[c_.+d_.*x_])^2,x_Symbol] := + -B*Cos[c+d*x]/(a*d*(a+b*Sin[c+d*x])) /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A-b*B] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*(A_+B_.*Sin[c_.+d_.*x_])/(a_+b_.*Sin[c_.+d_.*x_])^2,x_Symbol] := + -B*x*Cos[c+d*x]/(a*d*(a+b*Sin[c+d*x])) + + Dist[B/(a*d),Int[Cos[c+d*x]/(a+b*Sin[c+d*x]),x]] /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A-b*B] + + +(* ::Item:: *) +(*Reference: G&R 2.551.1*) + + +Int[(A_.+B_.*Sin[c_.+d_.*x_])*(a_.+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + (a*B-b*A)*Cos[c+d*x]*(a+b*Sin[c+d*x])^(n+1)/(d*(n+1)*(a^2-b^2)) + + Dist[1/((n+1)*(a^2-b^2)),Int[((n+1)*(a*A-b*B)+(n+2)*(a*B-b*A)*Sin[c+d*x])*(a+b*Sin[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Sin[c+d x]^2)^n Products of monomials and powers of quadratic binomials of sines of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sin[z]^2 == (1 - Cos[2*z])/2*) + + +Int[x_^m_./(a_+b_.*Sin[c_.+d_.*x_]^2),x_Symbol] := + Dist[2,Int[x^m/(2*a+b-b*Cos[2*c+2*d*x]),x]] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 && NonzeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a+b*Cos[z]^2+c*Sin[z]^2 == (2*a+b+c + (b-c)*Cos[2*z])/2*) + + +Int[x_^m_./(a_.+b_.*Cos[d_.+e_.*x_]^2+c_.*Sin[d_.+e_.*x_]^2),x_Symbol] := + Dist[2,Int[x^m/(2*a+b+c+(b-c)*Cos[2*d+2*e*x]),x]] /; +FreeQ[{a,b,c,d,e},x] && IntegerQ[m] && m>0 && NonzeroQ[a+b] && NonzeroQ[a+c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sin[z]^2 == (1 - Cos[2*z])/2*) + + +Int[(a_+b_.*Sin[c_.+d_.*x_]^2)^n_,x_Symbol] := + Dist[1/2^n,Int[(2*a+b-b*Cos[2*c+2*d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a+b] && HalfIntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Sin[c+d x] Cos[c+d x])^n Products of monomials and powers involving products of sines and cosines*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sin[z]*Cos[z] == Sin[2*z]/2*) + + +Int[x_^m_./(a_+b_.*Sin[c_.+d_.*x_]*Cos[c_.+d_.*x_]),x_Symbol] := + Int[x^m/(a+b*Sin[2*c+2*d*x]/2),x] /; +FreeQ[{a,b,c,d},x] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sin[z]*Cos[z] == Sin[2*z]/2*) + + +Int[(a_+b_.*Sin[c_.+d_.*x_]*Cos[c_.+d_.*x_])^n_,x_Symbol] := + Int[(a+b*Sin[2*c+2*d*x]/2)^n,x] /; +FreeQ[{a,b,c,d},x] && HalfIntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b x]^m Cos[a+b x]^n Products of powers of sines and cosines*) + + +Int[Sin[a_.+b_.*x_]^m_.*Cos[a_.+b_.*x_]^n_,x_Symbol] := + Sin[a+b*x]^(m+1)*Cos[a+b*x]^(n+1)/(b*(m+1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+2] && NonzeroQ[m+1] && PosQ[m] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, Cos[z]^n == (1-Sin[z]^2)^((n-1)/2)*Sin'[z]*) + + +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[x^m*(1-x^2)^((n-1)/2),x],x],x,Sin[a+b*x]]] /; +FreeQ[{a,b,m},x] && OddQ[n] && Not[OddQ[m] && 01 && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.510.2, CRC 323b, A&S 4.3.127b*) + + +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + -Sin[a+b*x]^(m-1)*Cos[a+b*x]^(n+1)/(b*(m+n)) + + Dist[(m-1)/(m+n),Int[Sin[a+b*x]^(m-2)*Cos[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[OddQ[m]] && NonzeroQ[m+n] && +Not[OddQ[n] && n>1] + + +(* ::Item:: *) +(*Reference: G&R 2.510.3, CRC 334a, A&S 4.3.128b*) + + +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + Sin[a+b*x]^(m+1)*Cos[a+b*x]^(n+1)/(b*(m+1)) + + Dist[(m+n+2)/(m+1),Int[Sin[a+b*x]^(m+2)*Cos[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n+2] + + +(* Note: Kool rule, but replace with a more general collect fractional power rule?! *) +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/(b*m),Subst[Int[x^(1/m)/(1+x^(2/m)),x],x,Sin[a+b*x]^m*Cos[a+b*x]^n]] /; +FreeQ[{a,b},x] && FractionQ[{m,n}] && ZeroQ[m+n] && IntegerQ[1/m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b x]^m Tan[a+b x]^n Products of powers of sines and tangents*) +(**) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.18', CRC 327'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[z]*Tan[z] == -Cos[z]+Sec[z]*) + + +Int[Sin[a_.+b_.*x_]*Tan[a_.+b_.*x_],x_Symbol] := + -Sin[a+b*x]/b + + Int[Sec[a+b*x],x] /; +FreeQ[{a,b},x] + + +Int[Sin[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + -Sin[a+b*x]^m*Tan[a+b*x]^(n-1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-1] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[Sin[a_.+b_.*x_]^m_.*Tan[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[-1/b,Subst[Int[Regularize[(1-x^2)^((m+n-1)/2)/x^n,x],x],x,Cos[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && OddQ[m+n] + + +(* ::Item:: *) +(*Reference: G&R 2.510.5, CRC 323a*) + + +Int[Sin[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + Sin[a+b*x]^m*Tan[a+b*x]^(n+1)/(b*m) - + Dist[(n+1)/m,Int[Sin[a+b*x]^(m-2)*Tan[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m>1 && n<-1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.6, CRC 334b*) + + +Int[Sin[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + Sin[a+b*x]^(m+2)*Tan[a+b*x]^(n-1)/(b*(n-1)) - + Dist[(m+2)/(n-1),Int[Sin[a+b*x]^(m+2)*Tan[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.2, CRC 323b*) + + +Int[Sin[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_.,x_Symbol]:= + -Sin[a+b*x]^m*Tan[a+b*x]^(n-1)/(b*m) + + Dist[(m+n-1)/m,Int[Sin[a+b*x]^(m-2)*Tan[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.1*) + + +Int[Sin[a_.+b_.*x_]^m_.*Tan[a_.+b_.*x_]^n_,x_Symbol] := + Sin[a+b*x]^m*Tan[a+b*x]^(n-1)/(b*(n-1)) - + Dist[(m+n-1)/(n-1),Int[Sin[a+b*x]^m*Tan[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.3, CRC 334a*) + + +Int[Sin[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_.,x_Symbol]:= + Sin[a+b*x]^(m+2)*Tan[a+b*x]^(n-1)/(b*(m+n+1)) + + Dist[(m+2)/(m+n+1),Int[Sin[a+b*x]^(m+2)*Tan[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.4*) + + +Int[Sin[a_.+b_.*x_]^m_.*Tan[a_.+b_.*x_]^n_,x_Symbol]:= + Sin[a+b*x]^m*Tan[a+b*x]^(n+1)/(b*(m+n+1)) - + Dist[(n+1)/(m+n+1),Int[Sin[a+b*x]^m*Tan[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b x^n] Sines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: FresnelS'[z] == Sin[Pi*z^2/2]*) + + +Int[Sin[b_.*x_^2],x_Symbol] := + Sqrt[Pi/2]*FresnelS[Rt[b,2]*x/Sqrt[Pi/2]]/Rt[b,2] /; +FreeQ[b,x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[w+z] == Sin[w]*Cos[z] + Cos[w]*Sin[z]*) + + +Int[Sin[a_+b_.*x_^2],x_Symbol] := + Dist[Sin[a],Int[Cos[b*x^2],x]] + + Dist[Cos[a],Int[Sin[b*x^2],x]] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[z] == I/2*E^(-I*z) - I/2*E^(I*z)*) + + +Int[Sin[a_.+b_.*x_^n_],x_Symbol] := + Dist[I/2,Int[E^(-a*I-b*I*x^n),x]] - + Dist[I/2,Int[E^(a*I+b*I*x^n),x]] /; +FreeQ[{a,b,n},x] && Not[FractionOrNegativeQ[n]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Note: Although resulting integrand looks more complicated than original one, rules for + improper binomials rectify it. *) +Int[Sin[a_.+b_.*x_^n_],x_Symbol] := + x*Sin[a+b*x^n] - + Dist[b*n,Int[x^n*Cos[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && n<0 + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[a+b x^n] Products of monomials and sines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: SinIntegral'[z] == Sin[z]/z*) + + +Int[Sin[a_.*x_^n_.]/x_,x_Symbol] := + SinIntegral[a*x^n]/n /; +FreeQ[{a,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[w+z] == Sin[w]*Cos[z] + Cos[w]*Sin[z]*) + + +Int[Sin[a_+b_.*x_^n_.]/x_,x_Symbol] := + Dist[Sin[a],Int[Cos[b*x^n]/x,x]] + + Dist[Cos[a],Int[Sin[b*x^n]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 392, A&S 4.3.119*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m*Sin[a+b*x^n] == x^(m-n+1)*(Sin[a+b*x^n]*x^(n-1))*) + + +Int[x_^m_.*Sin[a_.+b_.*x_^n_.],x_Symbol] := + -x^(m-n+1)*Cos[a+b*x^n]/(b*n) + + Dist[(m-n+1)/(b*n),Int[x^(m-n)*Cos[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[m] && 00 && m<-1 || 0<-n1 && ZeroQ[m-2*n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.631.2'*) + + +Int[x_^m_.*Sin[a_.+b_.*x_^n_.]^p_,x_Symbol] := + (m-n+1)*x^(m-2*n+1)*Sin[a+b*x^n]^p/(b^2*n^2*p^2) - + x^(m-n+1)*Cos[a+b*x^n]*Sin[a+b*x^n]^(p-1)/(b*n*p) + + Dist[(p-1)/p,Int[x^m*Sin[a+b*x^n]^(p-2),x]] - + Dist[(m-n+1)*(m-2*n+1)/(b^2*n^2*p^2),Int[x^(m-2*n)*Sin[a+b*x^n]^p,x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[{m,p}] && p>1 && 0<2*n1 && m<-1 && n>0 && NonzeroQ[m+n+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[a+b (c+d x)^n]^p Products of monomials and powers of sines of binomials of linears*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b x,x],x] == Subst[Int[f[x,-a/b+x/b],x],x,a+b x]/b*) + + +Int[x_^m_.*Sin[a_.+b_.*(c_+d_.*x_)^n_]^p_.,x_Symbol] := + Dist[1/d,Subst[Int[(-c/d+x/d)^m*Sin[a+b*x^n]^p,x],x,c+d*x]] /; +FreeQ[{a,b,c,d,n},x] && IntegerQ[m] && m>0 && RationalQ[p] + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b x+c x^2] Sines of quadratic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If b^2-4*a*c=0, a+b*x+c*x^2 == (b+2*c*x)^2/(4*c)*) + + +Int[Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Int[Sin[(b+2*c*x)^2/(4*c)],x] /; +FreeQ[{a,b,c},x] && ZeroQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: a+b*x+c*x^2 == (b+2*c*x)^2/(4*c) - (b^2-4*a*c)/(4*c)*) + + +(* ::Item:: *) +(*Basis: Sin[z-w] == Cos[w]*Sin[z] - Sin[w]*Cos[z]*) + + +Int[Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Cos[(b^2-4*a*c)/(4*c)]*Int[Sin[(b+2*c*x)^2/(4*c)],x] - + Sin[(b^2-4*a*c)/(4*c)]*Int[Cos[(b+2*c*x)^2/(4*c)],x] /; +FreeQ[{a,b,c},x] && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*(d+e x)^m Sin[a+b x+c x^2] Products of linears and sines of quadratic trinomials*) +(**) + + +Int[(d_.+e_.*x_)*Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + -e*Cos[a+b*x+c*x^2]/(2*c) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)*Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + -e*Cos[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[Sin[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + -e*(d+e*x)^(m-1)*Cos[a+b*x+c*x^2]/(2*c) + + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Cos[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + -e*(d+e*x)^(m-1)*Cos[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[(d+e*x)^(m-1)*Sin[a+b*x+c*x^2],x]] + + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Cos[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Sin[a+b*x+c*x^2]/(e*(m+1)) - + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Cos[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Sin[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Sin[a+b*x+c*x^2]/(e*(m+1)) - + Dist[(b*e-2*c*d)/(e^2*(m+1)),Int[(d+e*x)^(m+1)*Cos[a+b*x+c*x^2],x]] - + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Cos[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && NonzeroQ[b*e-2*c*d] + + +(* ::Subsubsection::Closed:: *) +(*Sin[a+b Log[c x^n]]^p Powers of sines of logarithms*) + + +Int[Sin[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + x*Sin[a+b*Log[c*x^n]]/(1+b^2*n^2) - + b*n*x*Cos[a+b*Log[c*x^n]]/(1+b^2*n^2) /; +FreeQ[{a,b,c,n},x] && NonzeroQ[1+b^2*n^2] + + +Int[Sin[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Sin[a+b*Log[c*x^n]]^p/(1+b^2*n^2*p^2) - + b*n*p*x*Cos[a+b*Log[c*x^n]]*Sin[a+b*Log[c*x^n]]^(p-1)/(1+b^2*n^2*p^2) + + Dist[b^2*n^2*p*(p-1)/(1+b^2*n^2*p^2),Int[Sin[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && NonzeroQ[1+b^2*n^2*p^2] + + +Int[Sin[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Cot[a+b*Log[c*x^n]]*Sin[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + x*Sin[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) + + Dist[(1+b^2*n^2*(p+2)^2)/(b^2*n^2*(p+1)*(p+2)),Int[Sin[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && p!=-2 + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[a+b Log[c x^n]]^p Products of monomials and powers of sines of logarithms*) + + +Int[x_^m_.*Sin[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + (m+1)*x^(m+1)*Sin[a+b*Log[c*x^n]]/(b^2*n^2+(m+1)^2) - + b*n*x^(m+1)*Cos[a+b*Log[c*x^n]]/(b^2*n^2+(m+1)^2) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[b^2*n^2+(m+1)^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Sin[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + (m+1)*x^(m+1)*Sin[a+b*Log[c*x^n]]^p/(b^2*n^2*p^2+(m+1)^2) - + b*n*p*x^(m+1)*Cos[a+b*Log[c*x^n]]*Sin[a+b*Log[c*x^n]]^(p-1)/(b^2*n^2*p^2+(m+1)^2) + + Dist[b^2*n^2*p*(p-1)/(b^2*n^2*p^2+(m+1)^2),Int[x^m*Sin[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && NonzeroQ[b^2*n^2*p^2+(m+1)^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Sin[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x^(m+1)*Cot[a+b*Log[c*x^n]]*Sin[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + (m+1)*x^(m+1)*Sin[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) + + Dist[(b^2*n^2*(p+2)^2+(m+1)^2)/(b^2*n^2*(p+1)*(p+2)),Int[x^m*Sin[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && p!=-2 && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sin[a x^n Log[b x]^p Log[b x]^p Products of sines and powers of logarithms*) +(**) + + +Int[Sin[a_.*x_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + -Cos[a*x*Log[b*x]^p]/a - + Dist[p,Int[Sin[a*x*Log[b*x]^p]*Log[b*x]^(p-1),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p>0 + + +Int[Sin[a_.*x_^n_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + -Cos[a*x^n*Log[b*x]^p]/(a*n*x^(n-1)) - + Dist[p/n,Int[Sin[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] - + Dist[(n-1)/(a*n),Int[Cos[a*x^n*Log[b*x]^p]/x^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{n,p}] && p>0 + + +Int[x_^m_*Sin[a_.*x_^n_.*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + -x^(m-n+1)*Cos[a*x^n*Log[b*x]^p]/(a*n) - + Dist[p/n,Int[x^m*Sin[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] + + Dist[(m-n+1)/(a*n),Int[x^(m-n)*Cos[a*x^n*Log[b*x]^p],x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>0 + + +(* ::Subsubsection::Closed:: *) +(*u Sin[v]^2 Products involving squares of sines*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[z]^2 == 1/2 - 1/2*Cos[2*z]*) + + +Int[u_*Sin[v_]^2,x_Symbol] := + Dist[1/2,Int[u,x]] - + Dist[1/2,Int[u*Cos[2*v],x]] /; +FunctionOfTrigQ[u,2*v,x] + + +(* ::Subsubsection::Closed:: *) +(*u Sin[v] Trig[w] Products of circular trig functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[v]*Cos[w] == Sin[v+w]/2 + Sin[v-w]/2*) + + +Int[u_.*Sin[v_]*Cos[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Sin[v+w],x],x]] + + Dist[1/2,Int[u*Regularize[Sin[v-w],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && PosQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[v]*Sin[w] == Cos[v-w]/2 - Cos[v+w]/2*) + + +Int[u_.*Sin[v_]*Sin[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Cos[v-w],x],x]] - + Dist[1/2,Int[u*Regularize[Cos[v+w],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[v]*Tan[w] == -Cos[v] + Cos[v-w]*Sec[w]*) + + +Int[u_.*Sin[v_]*Tan[w_]^n_.,x_Symbol] := + -Int[u*Cos[v]*Tan[w]^(n-1),x] + Cos[v-w]*Int[u*Sec[w]*Tan[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[v]*Cot[w] == Cos[v] + Sin[v-w]*Csc[w]*) + + +Int[u_.*Sin[v_]*Cot[w_]^n_.,x_Symbol] := + Int[u*Cos[v]*Cot[w]^(n-1),x] + Sin[v-w]*Int[u*Csc[w]*Cot[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[v]*Sec[w] == Cos[v-w]*Tan[w] + Sin[v-w]*) + + +Int[u_.*Sin[v_]*Sec[w_]^n_.,x_Symbol] := + Cos[v-w]*Int[u*Tan[w]*Sec[w]^(n-1),x] + Sin[v-w]*Int[u*Sec[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[v]*Csc[w] == Sin[v-w]*Cot[w] + Cos[v-w]*) + + +Int[u_.*Sin[v_]*Csc[w_]^n_.,x_Symbol] := + Sin[v-w]*Int[u*Cot[w]*Csc[w]^(n-1),x] + Cos[v-w]*Int[u*Csc[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Subsection::Closed:: *) +(*Cosine Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b x]^n Positive integer powers of cosines of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.01.6, CRC 291, A&S 4.3.114*) + + +(* ::Item:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: Sin'[z] == Cos[z]*) + + +Int[Cos[a_.+b_.*x_],x_Symbol] := + Sin[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.513.11, CRC 302*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[Cos[a_.+b_.*x_]^2,x_Symbol] := + x/2 + Cos[a+b*x]*Sin[a+b*x]/(2*b) /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, Cos[z]^n == (1-Sin[z]^2)^((n-1)/2)*Sin'[z]*) + + +Int[Cos[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(1-x^2)^((n-1)/2),x],x],x,Sin[a+b*x]]] /; +FreeQ[{a,b},x] && OddQ[n] && n>1 + + +(* ::ItemParagraph::Closed:: *) +(**) + + +(* ::Item:: *) +(*Reference: G&R 2.510.5, CRC 305*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Cos[a_.+b_.*x_])^n_,x_Symbol] := + c*Sin[a+b*x]*(c*Cos[a+b*x])^(n-1)/(b*n) + + Dist[(n-1)*c^2/n,Int[(c*Cos[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[OddQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.6, CRC 313*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Cos[a_.+b_.*x_])^n_,x_Symbol] := + -Sin[a+b*x]*(c*Cos[a+b*x])^(n+1)/(c*b*(n+1)) + + Dist[(n+2)/((n+1)*c^2),Int[(c*Cos[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Cos[x])^n/Cos[x]^n,x] == 0*) + + +Int[(c_*Cos[a_.+b_.*x_])^n_,x_Symbol] := + (c*Cos[a+b*x])^n/Cos[a+b*x]^n*Int[Cos[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -11 && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.555.2'*) + + +Int[(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + -b*Sin[c+d*x]*(a+b*Cos[c+d*x])^n/(a*d*(2*n+1)) + + Dist[(n+1)/(a*(2*n+1)),Int[(a+b*Cos[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && ZeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.554.3 inverted*) + + +(* Note: This would result in an infinite loop!!! *) +(* Int[(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + b*Sin[c+d*x]*(a+b*Cos[c+d*x])^n/(a*d*n) + + Dist[(a^2-b^2)/a,Int[(a+b*Cos[c+d*x])^(n-1),x]] + + Dist[b*(n+1)/(a*n),Int[Cos[c+d*x]*(a+b*Cos[c+d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>0 && NonzeroQ[a^2-b^2] *) + + +(* ::Item:: *) +(*Reference: G&R 2.554.3*) + + +Int[1/(a_+b_.*Cos[c_.+d_.*x_])^2,x_Symbol] := + -b*Sin[c+d*x]/(d*(a^2-b^2)*(a+b*Cos[c+d*x])) + + Dist[a/(a^2-b^2),Int[1/(a+b*Cos[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.554.3*) + + +Int[(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + b*Sin[c+d*x]*(a+b*Cos[c+d*x])^(n+1)/(d*(n+1)*(a^2-b^2)) + + Dist[1/((n+1)*(a^2-b^2)),Int[(a*(n+1)-b*(n+2)*Cos[c+d*x])*(a+b*Cos[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Cos[c+d x])^n Products of monomials and powers of linear binomials of cosines of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1+Cos[z] == 2*Cos[z/2]^2*) + + +Int[x_^m_.*(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + Dist[(2*a)^n,Int[x^m*Cos[c/2+d*x/2]^(2*n),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && n<0 && ZeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1+Cos[z] == 2*Cos[z/2]^2*) + + +Int[x_^m_.*(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + Dist[2^n,Int[x^m*(a*Cos[c/2+d*x/2]^2)^n,x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[{m,n}] && ZeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1-Cos[z] == 2*Sin[z/2]^2*) + + +Int[x_^m_.*(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + Dist[(2*a)^n,Int[x^m*Sin[c/2+d*x/2]^(2*n),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && n<0 && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1-Cos[z] == 2*Sin[z/2]^2*) + + +Int[x_^m_.*(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + Dist[2^n,Int[x^m*(a*Sin[c/2+d*x/2]^2)^n,x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[{m,n}] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b z)^2 == a/((a^2-b^2) (a+b z)) - b (b+a z)/((a^2-b^2) (a+b z)^2)*) + + +Int[x_/(a_+b_.*Cos[c_.+d_.*x_])^2,x_Symbol] := + Dist[a/(a^2-b^2),Int[x/(a+b*Cos[c+d*x]),x]] - + Dist[b/(a^2-b^2),Int[x*(b+a*Cos[c+d*x])/(a+b*Cos[c+d*x])^2,x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: a+b*Cos[z] == (b+2*a*E^(I*z)+b*E^(2*I*z))/(2*E^(I*z))*) + + +Int[x_^m_.*(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + Dist[1/2^n,Int[x^m*(b+2*a*E^(I*c+I*d*x)+b*E^(2*(I*c+I*d*x)))^n/E^(n*(I*c+I*d*x)),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2-b^2] && IntegerQ[n] && n<0 && RationalQ[m] && m>0 + + +(* ::Subsubsection::Closed:: *) +(*(A+B Cos[c+d x]) (a+b Cos[c+d x])^n Products of powers of linear binomials of cosines*) + + +(* ::Item:: *) +(*Basis: (A+B*z)/Sqrt[a+b*z] == (b*A-a*B)/(b*Sqrt[a+b*z]) + B/b*Sqrt[a+b*z]*) + + +Int[(A_.+B_.*Cos[c_.+d_.*x_])/Sqrt[a_+b_.*Cos[c_.+d_.*x_]],x_Symbol] := + Dist[(b*A-a*B)/b,Int[1/Sqrt[a+b*Cos[c+d*x]],x]] + + Dist[B/b,Int[Sqrt[a+b*Cos[c+d*x]],x]] /; +FreeQ[{a,b,c,d,A,B},x] && NonzeroQ[b*A-a*B] + + +(* ::Item:: *) +(*Reference: G&R 2.554.1 inverted*) + + +Int[(A_.+B_.*Cos[c_.+d_.*x_])*(a_+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + B*Sin[c+d*x]*(a+b*Cos[c+d*x])^n/(d*(n+1)) + + Dist[1/(n+1),Int[(b*B*n+a*A*(n+1) + (a*B*n+b*A*(n+1))*Cos[c+d*x])*(a+b*Cos[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n>1 && NonzeroQ[a^2-b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.554.1 special case*) + + +Int[(A_+B_.*Cos[c_.+d_.*x_])/(a_+b_.*Cos[c_.+d_.*x_])^2,x_Symbol] := + B*Sin[c+d*x]/(a*d*(a+b*Cos[c+d*x])) /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A-b*B] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_*(A_+B_.*Cos[c_.+d_.*x_])/(a_+b_.*Cos[c_.+d_.*x_])^2,x_Symbol] := + B*x*Sin[c+d*x]/(a*d*(a+b*Cos[c+d*x])) - + Dist[B/(a*d),Int[Sin[c+d*x]/(a+b*Cos[c+d*x]),x]] /; +FreeQ[{a,b,c,d,A,B},x] && ZeroQ[a*A-b*B] + + +(* ::Item:: *) +(*Reference: G&R 2.554.1*) + + +Int[(A_.+B_.*Cos[c_.+d_.*x_])*(a_.+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + -(a*B-b*A)*Sin[c+d*x]*(a+b*Cos[c+d*x])^(n+1)/(d*(n+1)*(a^2-b^2)) + + Dist[1/((n+1)*(a^2-b^2)),Int[((n+1)*(a*A-b*B)+(n+2)*(a*B-b*A)*Cos[c+d*x])*(a+b*Cos[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,A,B},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m (a+b Cos[c+d x]^2)^n Products of monomials and powers of quadratic binomials of sines of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Cos[z]^2 == (1 + Cos[2*z])/2*) + + +Int[x_^m_./(a_+b_.*Cos[c_.+d_.*x_]^2),x_Symbol] := + Dist[2,Int[x^m/(2*a+b+b*Cos[2*c+2*d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a+b] && IntegerQ[m] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Cos[z]^2 == (1 + Cos[2*z])/2*) + + +Int[(a_+b_.*Cos[c_.+d_.*x_]^2)^n_,x_Symbol] := + Dist[1/2^n,Int[(2*a+b+b*Cos[2*c+2*d*x])^n,x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a+b] && HalfIntegerQ[n] + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b x]^n Sin[a+b x]^m Products of powers of cosines and sines*) + + +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_.,x_Symbol] := + -Sin[a+b*x]^(m+1)*Cos[a+b*x]^(n+1)/(b*(n+1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+2] && NonzeroQ[n+1] && PosQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m is odd, Sin[z]^m == -(1-Cos[z]^2)^((m-1)/2)*Cos'[z]*) + + +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + Dist[-1/b,Subst[Int[Regularize[x^n*(1-x^2)^((m-1)/2),x],x],x,Cos[a+b*x]]] /; +FreeQ[{a,b,n},x] && OddQ[m] && Not[OddQ[n] && 01 + + +(* ::Item:: *) +(*Reference: G&R 2.510.5, CRC 323a, A&S 4.3.127a*) + + +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + Sin[a+b*x]^(m+1)*Cos[a+b*x]^(n-1)/(b*(m+n)) + + Dist[(n-1)/(m+n),Int[Sin[a+b*x]^m*Cos[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[OddQ[n]] && NonzeroQ[m+n] && +Not[OddQ[m] && m>1] + + +(* ::Item:: *) +(*Reference: G&R 2.510.6, CRC 334b, A&S 4.3.128a*) + + +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + -Sin[a+b*x]^(m+1)*Cos[a+b*x]^(n+1)/(b*(n+1)) + + Dist[(m+n+2)/(n+1),Int[Sin[a+b*x]^m*Cos[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n+2] + + +(* Kool rule, but replace with a more general collect fractional power rule?! *) +Int[Sin[a_.+b_.*x_]^m_*Cos[a_.+b_.*x_]^n_,x_Symbol] := + Dist[-1/(b*n),Subst[Int[x^(1/n)/(1+x^(2/n)),x],x,Sin[a+b*x]^m*Cos[a+b*x]^n]] /; +FreeQ[{a,b},x] && FractionQ[{m,n}] && ZeroQ[m+n] && IntegerQ[1/n] && n>0 + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b x]^m Cot[a+b x]^n Products of powers of cosines and cotangents*) +(**) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.34'*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[z]*Cot[z] == -Sin[z]+Csc[z]*) + + +Int[Cos[a_.+b_.*x_]*Cot[a_.+b_.*x_],x_Symbol] := + Cos[a+b*x]/b + + Int[Csc[a+b*x],x] /; +FreeQ[{a,b},x] + + +Int[Cos[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_,x_Symbol] := + Cos[a+b*x]^m*Cot[a+b*x]^(n-1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-1] + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +Int[Cos[a_.+b_.*x_]^m_.*Cot[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(1-x^2)^((m+n-1)/2)/x^n,x],x],x,Sin[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && OddQ[m+n] + + +(* ::Item:: *) +(*Reference: G&R 2.510.2, CRC 323b*) + + +Int[Cos[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Cos[a+b*x]^m*Cot[a+b*x]^(n+1)/(b*m) - + Dist[(n+1)/m,Int[Cos[a+b*x]^(m-2)*Cot[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m>1 && n<-1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.3, CRC 334a*) + + +Int[Cos[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Cos[a+b*x]^(m+2)*Cot[a+b*x]^(n-1)/(b*(n-1)) - + Dist[(m+2)/(n-1),Int[Cos[a+b*x]^(m+2)*Cot[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.5, CRC 323a*) + + +Int[Cos[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_.,x_Symbol] := + Cos[a+b*x]^m*Cot[a+b*x]^(n-1)/(b*m) + + Dist[(m+n-1)/m,Int[Cos[a+b*x]^(m-2)*Cot[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.4*) + + +Int[Cos[a_.+b_.*x_]^m_.*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Cos[a+b*x]^m*Cot[a+b*x]^(n-1)/(b*(n-1)) - + Dist[(m+n-1)/(n-1),Int[Cos[a+b*x]^m*Cot[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.6, CRC 334b*) + + +Int[Cos[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_.,x_Symbol] := + -Cos[a+b*x]^(m+2)*Cot[a+b*x]^(n-1)/(b*(m+n+1)) + + Dist[(m+2)/(m+n+1),Int[Cos[a+b*x]^(m+2)*Cot[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.1*) + + +Int[Cos[a_.+b_.*x_]^m_.*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Cos[a+b*x]^m*Cot[a+b*x]^(n+1)/(b*(m+n+1)) - + Dist[(n+1)/(m+n+1),Int[Cos[a+b*x]^m*Cot[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n+1] && Not[OddQ[m] && EvenQ[n]] + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b x^n] Cosines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: FresnelC'[z] == Cos[Pi*z^2/2]*) + + +Int[Cos[b_.*x_^2],x_Symbol] := + Sqrt[Pi/2]*FresnelC[Rt[b,2]*x/Sqrt[Pi/2]]/Rt[b,2] /; +FreeQ[b,x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[w+z] == Cos[w]*Cos[z] - Sin[w]*Sin[z]*) + + +Int[Cos[a_+b_.*x_^2],x_Symbol] := + Dist[Cos[a],Int[Cos[b*x^2],x]] - + Dist[Sin[a],Int[Sin[b*x^2],x]] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[z] == E^(-I*z)/2 + E^(I*z)/2*) + + +Int[Cos[a_.+b_.*x_^n_],x_Symbol] := + Dist[1/2,Int[E^(-a*I-b*I*x^n),x]] + + Dist[1/2,Int[E^(a*I+b*I*x^n),x]] /; +FreeQ[{a,b,n},x] && Not[FractionOrNegativeQ[n]] + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* Note: Although resulting integrand looks more complicated than original one, rules for + improper binomials rectify it. *) +Int[Cos[a_.+b_.*x_^n_],x_Symbol] := + x*Cos[a+b*x^n] + + Dist[b*n,Int[x^n*Sin[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && n<0 + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[a+b x^n] Products of monomials and cosines of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Primitive rule*) + + +(* ::Item:: *) +(*Basis: CosIntegral'[z] == Cos[z]/z*) + + +Int[Cos[a_.*x_^n_.]/x_,x_Symbol] := + CosIntegral[a*x^n]/n /; +FreeQ[{a,n},x] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[w+z] == Cos[w]*Cos[z] - Sin[w]*Sin[z]*) + + +Int[Cos[a_+b_.*x_^n_.]/x_,x_Symbol] := + Dist[Cos[a],Int[Cos[b*x^n]/x,x]] - + Dist[Sin[a],Int[Sin[b*x^n]/x,x]] /; +FreeQ[{a,b,n},x] + + +(* ::Item::Closed:: *) +(*Reference: CRC 396, A&S 4.3.123*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +(* ::Item:: *) +(*Basis: x^m*Cos[a+b*x^n] == x^(m-n+1)*(Cos[a+b*x^n]*x^(n-1))*) + + +Int[x_^m_.*Cos[a_.+b_.*x_^n_.],x_Symbol] := + x^(m-n+1)*Sin[a+b*x^n]/(b*n) - + Dist[(m-n+1)/(b*n),Int[x^(m-n)*Sin[a+b*x^n],x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[m] && 00 && m<-1 || 0<-n1 && ZeroQ[m-2*n+1] + + +(* ::Item:: *) +(*Reference: G&R 2.631.3'*) + + +Int[x_^m_.*Cos[a_.+b_.*x_^n_.]^p_,x_Symbol] := + (m-n+1)*x^(m-2*n+1)*Cos[a+b*x^n]^p/(b^2*n^2*p^2) + + x^(m-n+1)*Sin[a+b*x^n]*Cos[a+b*x^n]^(p-1)/(b*n*p) + + Dist[(p-1)/p,Int[x^m*Cos[a+b*x^n]^(p-2),x]] - + Dist[(m-n+1)*(m-2*n+1)/(b^2*n^2*p^2),Int[x^(m-2*n)*Cos[a+b*x^n]^p,x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && RationalQ[{m,p}] && p>1 && 0<2*n1 && m<-1 && n>0 && NonzeroQ[m+n+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[a+b (c+d x)^n]^p Products of monomials and powers of cosines of binomials of linears*) +(**) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Int[f[a+b x,x],x] == Subst[Int[f[x,-a/b+x/b],x],x,a+b x]/b*) + + +Int[x_^m_.*Cos[a_.+b_.*(c_+d_.*x_)^n_]^p_.,x_Symbol] := + Dist[1/d,Subst[Int[(-c/d+x/d)^m*Cos[a+b*x^n]^p,x],x,c+d*x]] /; +FreeQ[{a,b,c,d,n},x] && IntegerQ[m] && m>0 && RationalQ[p] + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b x+c x^2] Cosines of quadratic trinomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: If b^2-4*a*c=0, a+b*x+c*x^2 == (b+2*c*x)^2/(4*c)*) + + +Int[Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Int[Cos[(b+2*c*x)^2/(4*c)],x] /; +FreeQ[{a,b,c},x] && ZeroQ[b^2-4*a*c] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: a+b*x+c*x^2 == (b+2*c*x)^2/(4*c) - (b^2-4*a*c)/(4*c)*) + + +(* ::Item:: *) +(*Basis: Cos[z-w] == Cos[w]*Cos[z] + Sin[w]*Sin[z]*) + + +Int[Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + Cos[(b^2-4*a*c)/(4*c)]*Int[Cos[(b+2*c*x)^2/(4*c)],x] + + Sin[(b^2-4*a*c)/(4*c)]*Int[Sin[(b+2*c*x)^2/(4*c)],x] /; +FreeQ[{a,b,c},x] && NonzeroQ[b^2-4*a*c] + + +(* ::Subsubsection::Closed:: *) +(*(d+e x)^m Cos[a+b x+c x^2] Products of linears and cosines of quadratic trinomials*) +(**) + + +Int[(d_.+e_.*x_)*Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*Sin[a+b*x+c*x^2]/(2*c) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)*Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*Sin[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[Cos[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*(d+e*x)^(m-1)*Sin[a+b*x+c*x^2]/(2*c) - + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Sin[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + e*(d+e*x)^(m-1)*Sin[a+b*x+c*x^2]/(2*c) - + Dist[(b*e-2*c*d)/(2*c),Int[(d+e*x)^(m-1)*Cos[a+b*x+c*x^2],x]] - + Dist[e^2*(m-1)/(2*c),Int[(d+e*x)^(m-2)*Sin[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m>1 && NonzeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Cos[a+b*x+c*x^2]/(e*(m+1)) + + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Sin[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && ZeroQ[b*e-2*c*d] + + +Int[(d_.+e_.*x_)^m_*Cos[a_.+b_.*x_+c_.*x_^2],x_Symbol] := + (d+e*x)^(m+1)*Cos[a+b*x+c*x^2]/(e*(m+1)) + + Dist[(b*e-2*c*d)/(e^2*(m+1)),Int[(d+e*x)^(m+1)*Sin[a+b*x+c*x^2],x]] + + Dist[2*c/(e^2*(m+1)),Int[(d+e*x)^(m+2)*Sin[a+b*x+c*x^2],x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[m] && m<-1 && NonzeroQ[b*e-2*c*d] + + +(* ::Subsubsection::Closed:: *) +(*Cos[a+b Log[c x^n]]^p Powers of cosines of logarithms*) + + +Int[Cos[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + x*Cos[a+b*Log[c*x^n]]/(1+b^2*n^2) + + b*n*x*Sin[a+b*Log[c*x^n]]/(1+b^2*n^2) /; +FreeQ[{a,b,c,n},x] && NonzeroQ[1+b^2*n^2] + + +Int[Cos[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Cos[a+b*Log[c*x^n]]^p/(1+b^2*n^2*p^2) + + b*n*p*x*Cos[a+b*Log[c*x^n]]^(p-1)*Sin[a+b*Log[c*x^n]]/(1+b^2*n^2*p^2) + + Dist[b^2*n^2*p*(p-1)/(1+b^2*n^2*p^2),Int[Cos[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && NonzeroQ[1+b^2*n^2*p^2] + + +Int[Cos[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x*Tan[a+b*Log[c*x^n]]*Cos[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + x*Cos[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) + + Dist[(1+b^2*n^2*(p+2)^2)/(b^2*n^2*(p+1)*(p+2)),Int[Cos[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && p!=-2 + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[a+b Log[c x^n]]^p Products of monomials and powers of cosines of logarithms*) + + +Int[x_^m_.*Cos[a_.+b_.*Log[c_.*x_^n_.]],x_Symbol] := + (m+1)*x^(m+1)*Cos[a+b*Log[c*x^n]]/(b^2*n^2+(m+1)^2) + + b*n*x^(m+1)*Sin[a+b*Log[c*x^n]]/(b^2*n^2+(m+1)^2) /; +FreeQ[{a,b,c,m,n},x] && NonzeroQ[b^2*n^2+(m+1)^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Cos[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + (m+1)*x^(m+1)*Cos[a+b*Log[c*x^n]]^p/(b^2*n^2*p^2+(m+1)^2) + + b*n*p*x^(m+1)*Cos[a+b*Log[c*x^n]]^(p-1)*Sin[a+b*Log[c*x^n]]/(b^2*n^2*p^2+(m+1)^2) + + Dist[b^2*n^2*p*(p-1)/(b^2*n^2*p^2+(m+1)^2),Int[x^m*Cos[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && NonzeroQ[b^2*n^2*p^2+(m+1)^2] && NonzeroQ[m+1] + + +Int[x_^m_.*Cos[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x^(m+1)*Tan[a+b*Log[c*x^n]]*Cos[a+b*Log[c*x^n]]^(p+2)/(b*n*(p+1)) - + (m+1)*x^(m+1)*Cos[a+b*Log[c*x^n]]^(p+2)/(b^2*n^2*(p+1)*(p+2)) + + Dist[(b^2*n^2*(p+2)^2+(m+1)^2)/(b^2*n^2*(p+1)*(p+2)),Int[x^m*Cos[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && p!=-2 && NonzeroQ[m+1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cos[a x^n Log[b x]^p Log[b x]^p Products of cosines and powers of logarithms*) +(**) + + +Int[Cos[a_.*x_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + Sin[a*x*Log[b*x]^p]/a - + Dist[p,Int[Cos[a*x*Log[b*x]^p]*Log[b*x]^(p-1),x]] /; +FreeQ[{a,b},x] && RationalQ[p] && p>0 + + +Int[Cos[a_.*x_^n_*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + Sin[a*x^n*Log[b*x]^p]/(a*n*x^(n-1)) - + Dist[p/n,Int[Cos[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] + + Dist[(n-1)/(a*n),Int[Sin[a*x^n*Log[b*x]^p]/x^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{n,p}] && p>0 + + +Int[x_^m_*Cos[a_.*x_^n_.*Log[b_.*x_]^p_.]*Log[b_.*x_]^p_.,x_Symbol] := + x^(m-n+1)*Sin[a*x^n*Log[b*x]^p]/(a*n) - + Dist[p/n,Int[x^m*Cos[a*x^n*Log[b*x]^p]*Log[b*x]^(p-1),x]] - + Dist[(m-n+1)/(a*n),Int[x^(m-n)*Sin[a*x^n*Log[b*x]^p],x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>0 + + +(* ::Subsubsection::Closed:: *) +(*u Cos[v]^2 Products involving squares of cosines*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[z]^2 == 1/2 + 1/2*Cos[2*z]*) + + +Int[u_*Cos[v_]^2,x_Symbol] := + Dist[1/2,Int[u,x]] + + Dist[1/2,Int[u*Cos[2*v],x]] /; +FunctionOfTrigQ[u,2*v,x] + + +(* ::Subsubsection::Closed:: *) +(*u Cos[v] Trig[w] Products of circular trig functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[v]*Cos[w] == Sin[w+v]/2 - Sin[w-v]/2*) + + +Int[u_.*Sin[v_]*Cos[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Sin[w+v],x],x]] - + Dist[1/2,Int[u*Regularize[Sin[w-v],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && PosQ[w-v] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[v]*Cos[w] == Cos[v-w]/2 + Cos[v+w]/2*) + + +Int[u_.*Cos[v_]*Cos[w_],x_Symbol] := + Dist[1/2,Int[u*Regularize[Cos[v-w],x],x]] + + Dist[1/2,Int[u*Regularize[Cos[v+w],x],x]] /; +(PolynomialQ[v,x] && PolynomialQ[w,x] || IndependentQ[Cancel[v/w],x]) && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[v]*Tan[w] == Sin[v] - Sin[v-w]*Sec[w]*) + + +Int[u_.*Cos[v_]*Tan[w_]^n_.,x_Symbol] := + Int[u*Sin[v]*Tan[w]^(n-1),x] - Sin[v-w]*Int[u*Sec[w]*Tan[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[v]*Cot[w] == -Sin[v] + Cos[v-w]*Csc[w]*) + + +Int[u_.*Cos[v_]*Cot[w_]^n_.,x_Symbol] := + -Int[u*Sin[v]*Cot[w]^(n-1),x] + Cos[v-w]*Int[u*Csc[w]*Cot[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[v]*Sec[w] == -Sin[v-w]*Tan[w] + Cos[v-w]*) + + +Int[u_.*Cos[v_]*Sec[w_]^n_.,x_Symbol] := + -Sin[v-w]*Int[u*Tan[w]*Sec[w]^(n-1),x] + Cos[v-w]*Int[u*Sec[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[v]*Csc[w] == Cos[v-w]*Cot[w] - Sin[v-w]*) + + +Int[u_.*Cos[v_]*Csc[w_]^n_.,x_Symbol] := + Cos[v-w]*Int[u*Cot[w]*Csc[w]^(n-1),x] - Sin[v-w]*Int[u*Csc[w]^(n-1),x] /; +RationalQ[n] && n>0 && FreeQ[v-w,x] && NonzeroQ[v-w] + + +(* ::Subsection::Closed:: *) +(*Tangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*(c Tan[a+b x])^n Powers of tangents of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.17, CRC 292, A&S 4.3.115*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule*) + + +(* ::Item:: *) +(*Basis: Tan[z] == Sin[z]/Cos[z]*) + + +Int[Tan[a_.+b_.*x_],x_Symbol] := + -Log[Cos[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.22, CRC 420*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Tan[z]^2 == -1+Sec[z]^2*) + + +Int[Tan[a_.+b_.*x_]^2,x_Symbol] := + -x + Tan[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.1, CRC 423, A&S 4.3.129*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +(* ::Item:: *) +(*Basis: Tan[z]^n == Tan[z]^(n-1)/Cos[z]*Sin[z]*) + + +Int[(c_.*Tan[a_.+b_.*x_])^n_,x_Symbol] := + c*(c*Tan[a+b*x])^(n-1)/(b*(n-1)) - + Dist[c^2,Int[(c*Tan[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.4, CRC 427'*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Tan[a_.+b_.*x_])^n_,x_Symbol] := + (c*Tan[a+b*x])^(n+1)/(b*c*(n+1)) - + Dist[1/c^2,Int[(c*Tan[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Tan[c+d x])^n Powers of binomials of tangents where a^2+b^2 is zero*) + + +Int[Sqrt[a_+b_.*Tan[c_.+d_.*x_]],x_Symbol] := + -(Sqrt[2]*b*ArcTanh[Sqrt[a+b*Tan[c+d*x]]/(Sqrt[2]*Rt[a,2])])/(d*Rt[a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] && PosQ[a] + + +Int[Sqrt[a_+b_.*Tan[c_.+d_.*x_]],x_Symbol] := + (Sqrt[2]*b*ArcTan[Sqrt[a+b*Tan[c+d*x]]/(Sqrt[2]*Rt[-a,2])])/(d*Rt[-a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] && NegQ[a] + + +Int[(a_+b_.*Tan[c_.+d_.*x_])^n_,x_Symbol] := + -a^2*(a+b*Tan[c+d*x])^(n-1)/(b*d*(n-1)) + + Dist[2*a,Int[(a+b*Tan[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && ZeroQ[a^2+b^2] + + +Int[1/(a_+b_.*Tan[c_.+d_.*x_]),x_Symbol] := + x/(2*a) - a/(2*b*d*(a+b*Tan[c+d*x])) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] + + +Int[(a_+b_.*Tan[c_.+d_.*x_])^n_,x_Symbol] := + a*(a+b*Tan[c+d*x])^n/(2*b*d*n) + + Dist[1/(2*a),Int[(a+b*Tan[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<0 && ZeroQ[a^2+b^2] + + +(* ::Subsubsection::Closed:: *) +(*1 / (a+b Tan[c+d x]^n) Reciprocals of binomials of tangents*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*Tan[z]) == Cos[z]/(a*Cos[z]+b*Sin[z])*) + + +Int[1/(a_+b_.*Tan[c_.+d_.*x_]),x_Symbol] := + a*x/(a^2+b^2) + b*Log[a*Cos[c+d*x]+b*Sin[c+d*x]]/(d*(a^2+b^2)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] + + +Int[1/(a_+b_.*Tan[c_.+d_.*x_]^2),x_Symbol] := + x/(a-b) - Sqrt[b]*ArcTan[(Sqrt[b]*Tan[c+d*x])/Sqrt[a]]/(Sqrt[a]*d*(a-b)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a-b] + + +(* ::Subsubsection::Closed:: *) +(*x^m Tan[a+b x^n]^p Products of monomials and powers of tangents of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Tan[z] == -I + 2*I/(1+E^(2*I*z))*) + + +Int[x_^m_.*Tan[a_.+b_.*x_^n_.],x_Symbol] := + -I*x^(m+1)/(m+1) + + Dist[2*I,Int[x^m/(1+E^(2*I*a+2*I*b*x^n)),x]] /; +FreeQ[{a,b,m,n},x] && NonzeroQ[m-n+1] && IntegerQ[m] && m>0 + + +(* Note: Rule not in literature ??? *) +Int[x_^m_.*Tan[a_.+b_.*x_^n_.]^p_,x_Symbol] := + x^(m-n+1)*Tan[a+b*x^n]^(p-1)/(b*n*(p-1)) - + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Tan[a+b*x^n]^(p-1),x]] - + Int[x^m*Tan[a+b*x^n]^(p-2),x] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>1 && NonzeroQ[m-n+1] && 01 *) + + +(* ::Subsection::Closed:: *) +(*Cotangent Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*(c Cot[a+b x])^n Powers of cotangents of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.33, CRC 293, A&S 4.3.118*) + + +(* ::Item:: *) +(*Derivation: Reciprocal rule*) + + +(* ::Item:: *) +(*Basis: Cot[z] == Cos[z]/Sin[z]*) + + +Int[Cot[a_.+b_.*x_],x_Symbol] := + Log[Sin[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.38, CRC 424*) + + +(* ::Item:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cot[z]^2 == -1+Csc[z]^2*) + + +Int[Cot[a_.+b_.*x_]^2,x_Symbol] := + -x - Cot[a+b*x]/b /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.4, CRC 427, A&S 4.3.130*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +(* ::Item:: *) +(*Basis: Cot[z]^n == Cot[z]^(n-1)/Sin[z]*Cos[z]*) + + +Int[(c_.*Cot[a_.+b_.*x_])^n_,x_Symbol] := + -c*(c*Cot[a+b*x])^(n-1)/(b*(n-1)) - + Dist[c^2,Int[(c*Cot[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.1, CRC 423'*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Cot[a_.+b_.*x_])^n_,x_Symbol] := + -(c*Cot[a+b*x])^(n+1)/(b*c*(n+1)) - + Dist[1/c^2,Int[(c*Cot[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Cot[c+d x])^n Powers of binomials of cotangents where a^2+b^2 is zero*) + + +Int[Sqrt[a_+b_.*Cot[c_.+d_.*x_]],x_Symbol] := + (Sqrt[2]*b*ArcCoth[Sqrt[a+b*Cot[c+d*x]]/(Sqrt[2]*Rt[a,2])])/(d*Rt[a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] && PosQ[a] + + +Int[Sqrt[a_+b_.*Cot[c_.+d_.*x_]],x_Symbol] := + (Sqrt[2]*b*ArcCot[Sqrt[a+b*Cot[c+d*x]]/(Sqrt[2]*Rt[-a,2])])/(d*Rt[-a,2]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] && NegQ[a] + + +Int[(a_+b_.*Cot[c_.+d_.*x_])^n_,x_Symbol] := + a^2*(a+b*Cot[c+d*x])^(n-1)/(b*d*(n-1)) + + Dist[2*a,Int[(a+b*Cot[c+d*x])^(n-1),x]] /; +FreeQ[{a,b,c,d},x] && FractionQ[n] && n>1 && ZeroQ[a^2+b^2] + + +Int[1/(a_+b_.*Cot[c_.+d_.*x_]),x_Symbol] := + x/(2*a) + a/(2*b*d*(a+b*Cot[c+d*x])) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2+b^2] + + +Int[(a_+b_.*Cot[c_.+d_.*x_])^n_,x_Symbol] := + -a*(a+b*Cot[c+d*x])^n/(2*b*d*n) + + Dist[1/(2*a),Int[(a+b*Cot[c+d*x])^(n+1),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<0 && ZeroQ[a^2+b^2] + + +(* ::Subsubsection::Closed:: *) +(*1 / (a+b Cot[c+d x]^n) Reciprocals of binomials of cotangents*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: 1/(a+b*Cot[z]) == Sin[z]/(a*Sin[z]+b*Cos[z])*) + + +Int[1/(a_+b_.*Cot[c_.+d_.*x_]),x_Symbol] := + a*x/(a^2+b^2) - b*Log[b*Cos[c+d*x]+a*Sin[c+d*x]]/(d*(a^2+b^2)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] + + +Int[1/(a_+b_.*Cot[c_.+d_.*x_]^2),x_Symbol] := + x/(a-b) + Sqrt[b]*ArcTan[(Sqrt[b]*Cot[c+d*x])/Sqrt[a]]/(Sqrt[a]*d*(a-b)) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a-b] + + +(* ::Subsubsection::Closed:: *) +(*x^m Cot[a+b x^n]^p Products of monomials and powers of cotangents of binomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cot[z] == I - 2*I/(1-E^(2*I*z))*) + + +Int[x_^m_.*Cot[a_.+b_.*x_^n_.],x_Symbol] := + I*x^(m+1)/(m+1) - + Dist[2*I,Int[x^m/(1-E^(2*I*a+2*I*b*x^n)),x]] /; +FreeQ[{a,b,m,n},x] && NonzeroQ[m-n+1] && IntegerQ[m] && m>0 + + +(* Note: Rule not in literature ??? *) +Int[x_^m_.*Cot[a_.+b_.*x_^n_.]^p_,x_Symbol] := + -x^(m-n+1)*Cot[a+b*x^n]^(p-1)/(b*n*(p-1)) + + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Cot[a+b*x^n]^(p-1),x]] - + Int[x^m*Cot[a+b*x^n]^(p-2),x] /; +FreeQ[{a,b},x] && RationalQ[{m,n,p}] && p>1 && NonzeroQ[m-n+1] && 01*) + + +(* ::Subsection::Closed:: *) +(*Secant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Sec[a+b x]^n Powers of secants of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.9', CRC 294', A&S 4.3.117'*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Sec[z] == 1/(1-Sin[z]^2)*Sin'[z]*) + + +Int[Sec[a_.+b_.*x_],x_Symbol] := + ArcTanh[Sin[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* Note: This entirely redundant is required due to idem potent problem in Mathematica 6 & 7. *) +Int[1/Sqrt[Sec[a_.+b_.*x_]],x_Symbol] := + Sqrt[Cos[a+b*x]]*Sqrt[Sec[a+b*x]]*Int[Sqrt[Cos[a+b*x]],x] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Sec[x])^n*Cos[x]^n,x] == 0*) + + +Int[(c_.*Sec[a_.+b_.*x_])^n_,x_Symbol] := + (c*Sec[a+b*x])^n*Cos[a+b*x]^n*Int[1/Cos[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -11 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.6, CRC 313*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Sec[a_.+b_.*x_])^n_,x_Symbol] := + c*Sin[a+b*x]*(c*Sec[a+b*x])^(n-1)/(b*(n-1)) + + Dist[(n-2)*c^2/(n-1),Int[(c*Sec[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[EvenQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.5, CRC 305*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Sec[a_.+b_.*x_])^n_,x_Symbol] := + -Sin[a+b*x]*(c*Sec[a+b*x])^(n+1)/(b*c*n) + + Dist[(n+1)/(c^2*n),Int[(c*Sec[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m Sec[a+b x]^n Products of monomials and powers of secants of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sec[a_.+b_.*x_],x_Symbol] := + -2*I*x^m*ArcTan[E^(I*a+I*b*x)]/b + + Dist[2*I*m/b,Int[x^(m-1)*ArcTan[E^(I*a+I*b*x)],x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: CRC 430, A&S 4.3.125*) + + +Int[x_^m_.*Sec[a_.+b_.*x_]^2,x_Symbol] := + x^m*Tan[a+b*x]/b - + Dist[m/b,Int[x^(m-1)*Tan[a+b*x],x]] /; +FreeQ[{a,b},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: G&R 2.643.2, CRC 431, A&S 4.3.126*) + + +Int[x_*Sec[a_.+b_.*x_]^n_,x_Symbol] := + x*Tan[a+b*x]*Sec[a+b*x]^(n-2)/(b*(n-1)) - + Sec[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) + + Dist[(n-2)/(n-1),Int[x*Sec[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 && n!=2 + + +(* ::Item:: *) +(*Reference: G&R 2.643.2*) + + +Int[x_^m_*Sec[a_.+b_.*x_]^n_,x_Symbol] := + x^m*Tan[a+b*x]*Sec[a+b*x]^(n-2)/(b*(n-1)) - + m*x^(m-1)*Sec[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) + + Dist[(n-2)/(n-1),Int[x^m*Sec[a+b*x]^(n-2),x]] + + Dist[m*(m-1)/(b^2*(n-1)*(n-2)),Int[x^(m-2)*Sec[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n>1 && n!=2 && m>1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.3*) + + +Int[x_*Sec[a_.+b_.*x_]^n_,x_Symbol] := + Sec[a+b*x]^n/(b^2*n^2) - + x*Sin[a+b*x]*Sec[a+b*x]^(n+1)/(b*n) + + Dist[(n+1)/n,Int[x*Sec[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.3*) + + +Int[x_^m_*Sec[a_.+b_.*x_]^n_,x_Symbol] := + m*x^(m-1)*Sec[a+b*x]^n/(b^2*n^2) - + x^m*Sin[a+b*x]*Sec[a+b*x]^(n+1)/(b*n) + + Dist[(n+1)/n,Int[x^m*Sec[a+b*x]^(n+2),x]] - + Dist[m*(m-1)/(b^2*n^2),Int[x^(m-2)*Sec[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n<-1 && m>1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Sec[c+d x])^n Powers of constant plus secants of linears where a^2-b^2 is zero*) + + +Int[Sqrt[a_+b_.*Sec[c_.+d_.*x_]],x_Symbol] := + 2*a*ArcTan[Sqrt[-1+a/b*Sec[c+d*x]]]*Tan[c+d*x]/ + (d*Sqrt[-1+a/b*Sec[c+d*x]]*Sqrt[a+b*Sec[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* Note: There should be a simpler antiderivative! *) +Int[1/Sqrt[a_+b_.*Sec[c_.+d_.*x_]],x_Symbol] := + (Sqrt[2]*ArcTan[(Sqrt[2]*Sqrt[a])/Sqrt[-a+b*Sec[x]]]+2*ArcTan[Sqrt[-a+b*Sec[x]]/Sqrt[a]])* + Sqrt[-a+b*Sec[x]]*Sqrt[a+b*Sec[x]]*Cot[x]/a^(3/2) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*(a+b Sec[c+d x]^n)^m Powers of constant plus powers of secants of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Sec[z]^n == (b+a*Cos[z]^n)/Cos[z]^n*) + + +Int[(a_+b_.*Sec[v_]^n_.)^m_,x_Symbol] := + Int[(b+a*Cos[v]^n)^m/Cos[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m<0 && n>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Sec[z]^n == (b+a*Cos[z]^n)/Cos[z]^n*) + + +Int[Cos[v_]^p_.*(a_+b_.*Sec[v_]^n_.)^m_,x_Symbol] := + Int[Cos[v]^(p-m*n)*(b+a*Cos[v]^n)^m,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n,p}] && m<0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*Sec[a+b x]^n Csc[a+b x]^m Products of powers of secants and cosecants*) + + +(* ::Item:: *) +(*Reference: G&R 2.526.49, CRC 329*) + + +Int[Csc[a_.+b_.*x_]*Sec[a_.+b_.*x_],x_Symbol] := + Log[Tan[a+b*x]]/b /; +FreeQ[{a,b},x] && PosQ[b] + + +Int[Csc[a_.+b_.*x_]^m_*Sec[a_.+b_.*x_]^n_,x_Symbol] := + Csc[a+b*x]^(m-1)*Sec[a+b*x]^(n-1)/(b*(n-1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-2] && NonzeroQ[n-1] && PosQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m and n are integers and m+n is even, Csc[z]^m*Sec[z]^n == (1+Tan[z]^2)^((m+n)/2-1)/Tan[z]^m*Tan'[z]*) + + +Int[Csc[a_.+b_.*x_]^m_.*Sec[a_.+b_.*x_]^n_,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[(1+x^2)^((m+n)/2-1)/x^m,x],x],x,Tan[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && EvenQ[m+n] && 01 + + +(* ::Item:: *) +(*Reference: G&R 2.510.6, CRC 334b, A&S 4.3.128a*) + + +Int[Csc[a_.+b_.*x_]^m_.*Sec[a_.+b_.*x_]^n_,x_Symbol] := + Csc[a+b*x]^(m-1)*Sec[a+b*x]^(n-1)/(b*(n-1)) + + Dist[(m+n-2)/(n-1),Int[Csc[a+b*x]^m*Sec[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && Not[EvenQ[m+n]] && Not[EvenQ[n] && OddQ[m] && m>1] + + +(* ::Item:: *) +(*Reference: G&R 2.510.5, CRC 323a, A&S 4.3.127a*) + + +Int[Csc[a_.+b_.*x_]^m_.*Sec[a_.+b_.*x_]^n_,x_Symbol] := + -Csc[a+b*x]^(m-1)*Sec[a+b*x]^(n+1)/(b*(m+n)) + + Dist[(n+1)/(m+n),Int[Csc[a+b*x]^m*Sec[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && NonzeroQ[m+n] + + +(* ::Subsubsection::Closed:: *) +(*Sec[a+b x]^m Tan[a+b x]^n Products of powers of secants and tangents*) +(**) + + +(* ::Item:: *) +(*Derivation: Power rule for integration*) + + +Int[Sec[a_.+b_.*x_]^m_.*Tan[a_.+b_.*x_]^n_.,x_Symbol] := + Sec[a+b*x]^m/(b*m) /; +FreeQ[{a,b,m},x] && n===1 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m is even, Sec[z]^m == (1+Tan[z]^2)^((m-2)/2)*Tan'[z]*) + + +Int[Sec[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[1/b,Subst[Int[Regularize[x^n*(1+x^2)^((m-2)/2),x],x],x,Tan[a+b*x]]] /; +FreeQ[{a,b,n},x] && EvenQ[m] && m>2 && Not[OddQ[n] && 01 && n<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.2, CRC 323b*) + + +Int[Sec[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + Sec[a+b*x]^m*Tan[a+b*x]^(n-1)/(b*m) - + Dist[(n-1)/m,Int[Sec[a+b*x]^(m+2)*Tan[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.5, CRC 323a*) + + +Int[Sec[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + -Sec[a+b*x]^m*Tan[a+b*x]^(n+1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+1] + + +Int[Sec[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + -Sec[a+b*x]^m*Tan[a+b*x]^(n+1)/(b*m) + + Dist[(m+n+1)/m,Int[Sec[a+b*x]^(m+2)*Tan[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.6, CRC 334b*) + + +Int[Sec[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + Sec[a+b*x]^(m-2)*Tan[a+b*x]^(n+1)/(b*(m+n-1)) + + Dist[(m-2)/(m+n-1),Int[Sec[a+b*x]^(m-2)*Tan[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.1*) + + +Int[Sec[a_.+b_.*x_]^m_.*Tan[a_.+b_.*x_]^n_,x_Symbol] := + Sec[a+b*x]^m*Tan[a+b*x]^(n-1)/(b*(m+n-1)) - + Dist[(n-1)/(m+n-1),Int[Sec[a+b*x]^m*Tan[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.4*) + + +Int[Sec[a_.+b_.*x_]^m_*Tan[a_.+b_.*x_]^n_,x_Symbol] := + Sec[a+b*x]^m*Tan[a+b*x]^(n+1)/(b*(n+1)) - + Dist[(m+n+1)/(n+1),Int[Sec[a+b*x]^m*Tan[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && Not[EvenQ[m]] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sec[a+b x^n]^p Sin[a+b x^n] Products of monomials, sines and powers of secants of binomials*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sec[a_.+b_.*x_^n_.]^p_*Sin[a_.+b_.*x_^n_.],x_Symbol] := + x^(m-n+1)*Sec[a+b*x^n]^(p-1)/(b*n*(p-1)) - + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Sec[a+b*x^n]^(p-1),x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && NonzeroQ[p-1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sec[a+b x^n]^p Tan[a+b x^n] Products of monomials, tangents and powers of secants of binomials*) +(**) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Sec[a_.+b_.*x_^n_.]^p_.*Tan[a_.+b_.*x_^n_.]^q_.,x_Symbol] := + x^(m-n+1)*Sec[a+b*x^n]^p/(b*n*p) - + Dist[(m-n+1)/(b*n*p),Int[x^(m-n)*Sec[a+b*x^n]^p,x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && q===1 (* Required so InputForm is matchable *) + + +(* ::Subsubsection::Closed:: *) +(*Sec[a+b Log[c x^n]]^p Powers of secants of logarithms*) + + +Int[Sec[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Tan[a+b*Log[c*x^n]]*Sec[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) - + x*Sec[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) + + Dist[(1+b^2*n^2*(p-2)^2)/(b^2*n^2*(p-1)*(p-2)),Int[Sec[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[Sec[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Sec[a+b*Log[c*x^n]]^p/(1+b^2*n^2*p^2) - + b*n*p*x*Sec[a+b*Log[c*x^n]]^(p+1)*Sin[a+b*Log[c*x^n]]/(1+b^2*n^2*p^2) + + Dist[b^2*n^2*p*(p+1)/(1+b^2*n^2*p^2),Int[Sec[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && NonzeroQ[1+b^2*n^2*p^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m Sec[a+b Log[c x^n]]^p Products of monomials and powers of secants of logarithms*) + + +Int[Sec[a_.+b_.*Log[c_.*x_^n_.]]^2/x_,x_Symbol] := + Tan[a+b*Log[c*x^n]]/(b*n) /; +FreeQ[{a,b,c,n},x] + + +Int[Sec[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + Tan[a+b*Log[c*x^n]]*Sec[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) + + Dist[(p-2)/(p-1),Int[Sec[a+b*Log[c*x^n]]^(p-2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 + + +Int[Sec[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + -Sec[a+b*Log[c*x^n]]^(p+1)*Sin[a+b*Log[c*x^n]]/(b*n*p) + + Dist[(p+1)/p,Int[Sec[a+b*Log[c*x^n]]^(p+2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 + + +Int[x_^m_.*Sec[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x^(m+1)*Tan[a+b*Log[c*x^n]]*Sec[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) - + (m+1)*x^(m+1)*Sec[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) + + Dist[(b^2*n^2*(p-2)^2+(m+1)^2)/(b^2*n^2*(p-1)*(p-2)),Int[x^m*Sec[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[x_^m_.*Sec[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + (m+1)*x^(m+1)*Sec[a+b*Log[c*x^n]]^p/(b^2*n^2*p^2+(m+1)^2) - + b*n*p*x^(m+1)*Sec[a+b*Log[c*x^n]]^(p+1)*Sin[a+b*Log[c*x^n]]/(b^2*n^2*p^2+(m+1)^2) + + Dist[b^2*n^2*p*(p+1)/(b^2*n^2*p^2+(m+1)^2),Int[x^m*Sec[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && NonzeroQ[b^2*n^2*p^2+(m+1)^2] + + +(* ::Subsection::Closed:: *) +(*Cosecant Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Csc[a+b x]^n Powers of cosecants of linears*) + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.526.1, CRC 295, A&S 4.3.116'*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: Csc[z] == -1/(1-Cos[z]^2)*Cos'[z]*) + + +Int[Csc[a_.+b_.*x_],x_Symbol] := + -ArcTanh[Cos[a+b*x]]/b /; +FreeQ[{a,b},x] + + +(* Note: This entirely redundant is required due to idem potent problem in Mathematica 6 & 7. *) +Int[1/Sqrt[Csc[a_.+b_.*x_]],x_Symbol] := + Sqrt[Csc[a+b*x]]*Sqrt[Sin[a+b*x]]*Int[Sqrt[Sin[a+b*x]],x] /; +FreeQ[{a,b},x] + + +(* ::Item::Closed:: *) +(*Derivation: Extract constant factor*) + + +(* ::Item:: *) +(*Basis: D[(c*Csc[x])^n*Sin[x]^n,x] == 0*) + + +Int[(c_.*Csc[a_.+b_.*x_])^n_,x_Symbol] := + (c*Csc[a+b*x])^n*Sin[a+b*x]^n*Int[1/Sin[a+b*x]^n,x] /; +FreeQ[{a,b,c},x] && RationalQ[n] && -11 + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.3, CRC 309*) + + +(* ::Item:: *) +(*Derivation: Inverted integration by parts with a double-back flip*) + + +Int[(c_.*Csc[a_.+b_.*x_])^n_,x_Symbol] := + -c*Cos[a+b*x]*(c*Csc[a+b*x])^(n-1)/(b*(n-1)) + + Dist[(n-2)*c^2/(n-1),Int[(c*Csc[a+b*x])^(n-2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n>1 && Not[EvenQ[n]] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.510.2, CRC 299*) + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(c_.*Csc[a_.+b_.*x_])^n_,x_Symbol] := + Cos[a+b*x]*(c*Csc[a+b*x])^(n+1)/(b*c*n) + + Dist[(n+1)/(c^2*n),Int[(c*Csc[a+b*x])^(n+2),x]] /; +FreeQ[{a,b,c},x] && RationalQ[n] && n<-1 + + +(* ::Subsubsection::Closed:: *) +(*x^m Csc[a+b x]^n Products of monomials and powers of cosecants of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Csc[a_.+b_.*x_],x_Symbol] := + -2*x^m*ArcTanh[E^(I*a+I*b*x)]/b + + Dist[2*m/b,Int[x^(m-1)*ArcTanh[E^(I*a+I*b*x)],x]] /; +FreeQ[{a,b},x] && IntegerQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: CRC 428, A&S 4.3.121*) + + +Int[x_^m_.*Csc[a_.+b_.*x_]^2,x_Symbol] := + -x^m*Cot[a+b*x]/b + + Dist[m/b,Int[x^(m-1)*Cot[a+b*x],x]] /; +FreeQ[{a,b},x] && RationalQ[m] && m>0 + + +(* ::Item:: *) +(*Reference: G&R 2.643.1, CRC 429', A&S 4.3.122*) + + +Int[x_*Csc[a_.+b_.*x_]^n_,x_Symbol] := + -x*Cot[a+b*x]*Csc[a+b*x]^(n-2)/(b*(n-1)) - + Csc[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) + + Dist[(n-2)/(n-1),Int[x*Csc[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n>1 && n!=2 + + +(* ::Item:: *) +(*Reference: G&R 2.643.1*) + + +Int[x_^m_*Csc[a_.+b_.*x_]^n_,x_Symbol] := + -x^m*Cot[a+b*x]*Csc[a+b*x]^(n-2)/(b*(n-1)) - + m*x^(m-1)*Csc[a+b*x]^(n-2)/(b^2*(n-1)*(n-2)) + + Dist[(n-2)/(n-1),Int[x^m*Csc[a+b*x]^(n-2),x]] + + Dist[m*(m-1)/(b^2*(n-1)*(n-2)),Int[x^(m-2)*Csc[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n>1 && n!=2 && m>1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.2'*) + + +Int[x_*Csc[a_.+b_.*x_]^n_,x_Symbol] := + Csc[a+b*x]^n/(b^2*n^2) + + x*Cos[a+b*x]*Csc[a+b*x]^(n+1)/(b*n) + + Dist[(n+1)/n,Int[x*Csc[a+b*x]^(n+2),x]] /; +FreeQ[{a,b},x] && RationalQ[n] && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.631.2*) + + +Int[x_^m_*Csc[a_.+b_.*x_]^n_,x_Symbol] := + m*x^(m-1)*Csc[a+b*x]^n/(b^2*n^2) + + x^m*Cos[a+b*x]*Csc[a+b*x]^(n+1)/(b*n) + + Dist[(n+1)/n,Int[x^m*Csc[a+b*x]^(n+2),x]] - + Dist[m*(m-1)/(b^2*n^2),Int[x^(m-2)*Csc[a+b*x]^n,x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && n<-1 && m>1 + + +(* ::Subsubsection::Closed:: *) +(*(a+b Csc[c+d x])^n Powers of constant plus cosecants of linears where a^2-b^2 is zero*) + + +Int[Sqrt[a_+b_.*Csc[c_.+d_.*x_]],x_Symbol] := + -2*a*ArcTan[Sqrt[-1+a/b*Csc[c+d*x]]]*Cot[c+d*x]/ + (d*Sqrt[-1+a/b*Csc[c+d*x]]*Sqrt[a+b*Csc[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* Note: There should be a simpler antiderivative! *) +Int[1/Sqrt[a_+b_.*Csc[c_.+d_.*x_]],x_Symbol] := + -(Sqrt[2]*ArcTan[(Sqrt[2]*Sqrt[a])/Sqrt[-a+b*Csc[x]]]+2*ArcTan[Sqrt[-a+b*Csc[x]]/Sqrt[a]])* + Sqrt[-a+b*Csc[x]]*Sqrt[a+b*Csc[x]]*Tan[x]/a^(3/2) /; +FreeQ[{a,b,c,d},x] && ZeroQ[a^2-b^2] + + +(* ::Subsubsection::Closed:: *) +(*(a+b Csc[c+d x]^n)^m Powers of constant plus powers of cosecants of linears*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Csc[z]^n == (b+a*Sin[z]^n)/Sin[z]^n*) + + +Int[(a_+b_.*Csc[v_]^n_.)^m_,x_Symbol] := + Int[(b+a*Sin[v]^n)^m/Sin[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m<0 && n>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If n is an integer, a+b*Csc[z]^n == (b+a*Sin[z]^n)/Sin[z]^n*) + + +Int[Sin[v_]^p_.*(a_+b_.*Csc[v_]^n_.)^m_,x_Symbol] := + Int[Sin[v]^(p-m*n)*(b+a*Sin[v]^n)^m,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n,p}] && m<0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*Csc[a+b x]^m Sec[a+b x]^n Products of powers of cosecants and secants*) + + +(* ::Item:: *) +(*Reference: G&R 2.526.49', CRC 329'*) + + +Int[Csc[a_.+b_.*x_]*Sec[a_.+b_.*x_],x_Symbol] := + -Log[Cot[a+b*x]]/b /; +FreeQ[{a,b},x] && NegQ[b] + + +Int[Csc[a_.+b_.*x_]^m_*Sec[a_.+b_.*x_]^n_,x_Symbol] := + -Csc[a+b*x]^(m-1)*Sec[a+b*x]^(n-1)/(b*(m-1)) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n-2] && NonzeroQ[m-1] && PosQ[m] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m and n are integers and m+n is even, Csc[z]^m*Sec[z]^n == -(1+Cot[z]^2)^((m+n)/2-1)/Cot[z]^n*Cot'[z]*) + + +Int[Csc[a_.+b_.*x_]^m_*Sec[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[-1/b,Subst[Int[Regularize[(1+x^2)^((m+n)/2-1)/x^n,x],x],x,Cot[a+b*x]]] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && EvenQ[m+n] && 01 && n<-1 + + +(* ::Item:: *) +(*Reference: G&R 2.510.3, CRC 334a, A&S 4.3.128b*) + + +Int[Csc[a_.+b_.*x_]^m_*Sec[a_.+b_.*x_]^n_.,x_Symbol] := + -Csc[a+b*x]^(m-1)*Sec[a+b*x]^(n-1)/(b*(m-1)) + + Dist[(m+n-2)/(m-1),Int[Csc[a+b*x]^(m-2)*Sec[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && Not[EvenQ[m+n]] && Not[EvenQ[m] && OddQ[n] && n>1] + + +(* ::Item:: *) +(*Reference: G&R 2.510.2, CRC 323b, A&S 4.3.127b*) + + +Int[Csc[a_.+b_.*x_]^m_*Sec[a_.+b_.*x_]^n_.,x_Symbol] := + Csc[a+b*x]^(m+1)*Sec[a+b*x]^(n-1)/(b*(m+n)) + + Dist[(m+1)/(m+n),Int[Csc[a+b*x]^(m+2)*Sec[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && NonzeroQ[m+n] + + +(* ::Subsubsection::Closed:: *) +(*Csc[a+b x]^m Cot[a+b x]^n Products of powers of cosecants and cotangents*) +(**) + + +(* ::Item:: *) +(*Derivation: Power rule for integration*) + + +Int[Csc[a_.+b_.*x_]^m_.*Cot[a_.+b_.*x_]^n_.,x_Symbol] := + -Csc[a+b*x]^m/(b*m) /; +FreeQ[{a,b,m},x] && n===1 + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If m is even, Csc[z]^m == -(1+Cot[z]^2)^((m-2)/2)*Cot'[z]*) + + +Int[Csc[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_.,x_Symbol] := + Dist[-1/b,Subst[Int[Regularize[x^n*(1+x^2)^((m-2)/2),x],x],x,Cot[a+b*x]]] /; +FreeQ[{a,b,n},x] && EvenQ[m] && m>2 && Not[OddQ[n] && 01 && n<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.5, CRC 323a*) + + +Int[Csc[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Csc[a+b*x]^m*Cot[a+b*x]^(n-1)/(b*m) - + Dist[(n-1)/m,Int[Csc[a+b*x]^(m+2)*Cot[a+b*x]^(n-2),x]] /; +FreeQ[{a,b},x] && RationalQ[{m,n}] && m<-1 && n>1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.2, CRC 323b*) + + +Int[Csc[a_.+b_.*x_]^m_.*Cot[a_.+b_.*x_]^n_,x_Symbol] := + Csc[a+b*x]^m*Cot[a+b*x]^(n+1)/(b*m) /; +FreeQ[{a,b,m,n},x] && ZeroQ[m+n+1] + + +Int[Csc[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_,x_Symbol] := + Csc[a+b*x]^m*Cot[a+b*x]^(n+1)/(b*m) + + Dist[(m+n+1)/m,Int[Csc[a+b*x]^(m+2)*Cot[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m<-1 && Not[EvenQ[m]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.3, CRC 334a*) + + +Int[Csc[a_.+b_.*x_]^m_*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Csc[a+b*x]^(m-2)*Cot[a+b*x]^(n+1)/(b*(m+n-1)) + + Dist[(m-2)/(m+n-1),Int[Csc[a+b*x]^(m-2)*Cot[a+b*x]^n,x]] /; +FreeQ[{a,b,n},x] && RationalQ[m] && m>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.4*) + + +Int[Csc[a_.+b_.*x_]^m_.*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Csc[a+b*x]^m*Cot[a+b*x]^(n-1)/(b*(m+n-1)) - + Dist[(n-1)/(m+n-1),Int[Csc[a+b*x]^m*Cot[a+b*x]^(n-2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n>1 && NonzeroQ[m+n-1] && Not[EvenQ[m]] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Reference: G&R 2.510.1*) + + +Int[Csc[a_.+b_.*x_]^m_.*Cot[a_.+b_.*x_]^n_,x_Symbol] := + -Csc[a+b*x]^m*Cot[a+b*x]^(n+1)/(b*(n+1)) - + Dist[(m+n+1)/(n+1),Int[Csc[a+b*x]^m*Cot[a+b*x]^(n+2),x]] /; +FreeQ[{a,b,m},x] && RationalQ[n] && n<-1 && Not[EvenQ[m]] + + +(* ::Subsubsection::Closed:: *) +(*x^m Csc[a+b x^n]^p Cos[a+b x^n] Products of monomials, cosines and powers of cosecants of binomials*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Csc[a_.+b_.*x_^n_.]^p_*Cos[a_.+b_.*x_^n_.],x_Symbol] := + -x^(m-n+1)*Csc[a+b*x^n]^(p-1)/(b*n*(p-1)) + + Dist[(m-n+1)/(b*n*(p-1)),Int[x^(m-n)*Csc[a+b*x^n]^(p-1),x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && NonzeroQ[p-1] + + +(* ::Subsubsection::Closed:: *) +(*x^m Csc[a+b x^n]^p Cot[a+b x^n] Products of monomials, cotangents and powers of cosecants of binomials*) +(**) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*Csc[a_.+b_.*x_^n_.]^p_.*Cot[a_.+b_.*x_^n_.]^q_.,x_Symbol] := + -x^(m-n+1)*Csc[a+b*x^n]^p/(b*n*p) + + Dist[(m-n+1)/(b*n*p),Int[x^(m-n)*Csc[a+b*x^n]^p,x]] /; +FreeQ[{a,b,p},x] && RationalQ[m] && IntegerQ[n] && m-n>=0 && q===1 (* Required so InputForm is matchable *) + + +(* ::Subsubsection::Closed:: *) +(*Csc[a+b Log[c x^n]]^p Powers of cosecants of logarithms*) + + +Int[Csc[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x*Cot[a+b*Log[c*x^n]]*Csc[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) - + x*Csc[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) + + Dist[(1+b^2*n^2*(p-2)^2)/(b^2*n^2*(p-1)*(p-2)),Int[Csc[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[Csc[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + x*Csc[a+b*Log[c*x^n]]^p/(1+b^2*n^2*p^2) + + b*n*p*x*Cos[a+b*Log[c*x^n]]*Csc[a+b*Log[c*x^n]]^(p+1)/(1+b^2*n^2*p^2) + + Dist[b^2*n^2*p*(p+1)/(1+b^2*n^2*p^2),Int[Csc[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 && NonzeroQ[1+b^2*n^2*p^2] + + +(* ::Subsubsection::Closed:: *) +(*x^m Csc[a+b Log[c x^n]]^p Products of monomials and powers of cosecants of logarithms*) + + +Int[Csc[a_.+b_.*Log[c_.*x_^n_.]]^2/x_,x_Symbol] := + -Cot[a+b*Log[c*x^n]]/(b*n) /; +FreeQ[{a,b,c,n},x] + + +Int[Csc[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + -Cot[a+b*Log[c*x^n]]*Csc[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) + + Dist[(p-2)/(p-1),Int[Csc[a+b*Log[c*x^n]]^(p-2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p>1 + + +Int[Csc[a_.+b_.*Log[c_.*x_^n_.]]^p_/x_,x_Symbol] := + Cos[a+b*Log[c*x^n]]*Csc[a+b*Log[c*x^n]]^(p+1)/(b*n*p) + + Dist[(p+1)/p,Int[Csc[a+b*Log[c*x^n]]^(p+2)/x,x]] /; +FreeQ[{a,b,c,n},x] && RationalQ[p] && p<-1 + + +Int[x_^m_.*Csc[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + -x^(m+1)*Cot[a+b*Log[c*x^n]]*Csc[a+b*Log[c*x^n]]^(p-2)/(b*n*(p-1)) - + (m+1)*x^(m+1)*Csc[a+b*Log[c*x^n]]^(p-2)/(b^2*n^2*(p-1)*(p-2)) + + Dist[(b^2*n^2*(p-2)^2+(m+1)^2)/(b^2*n^2*(p-1)*(p-2)),Int[x^m*Csc[a+b*Log[c*x^n]]^(p-2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p>1 && p!=2 + + +Int[x_^m_.*Csc[a_.+b_.*Log[c_.*x_^n_.]]^p_,x_Symbol] := + (m+1)*x^(m+1)*Csc[a+b*Log[c*x^n]]^p/(b^2*n^2*p^2+(m+1)^2) + + b*n*p*x^(m+1)*Cos[a+b*Log[c*x^n]]*Csc[a+b*Log[c*x^n]]^(p+1)/(b^2*n^2*p^2+(m+1)^2) + + Dist[b^2*n^2*p*(p+1)/(b^2*n^2*p^2+(m+1)^2),Int[x^m*Csc[a+b*Log[c*x^n]]^(p+2),x]] /; +FreeQ[{a,b,c,m,n},x] && RationalQ[p] && p<-1 && NonzeroQ[b^2*n^2*p^2+(m+1)^2] + + +(* ::Subsection::Closed:: *) +(*Powers of sums of Trig Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*(a Cos[c+d x] + b Sin[c+d x])^n Powers of sums of sines and cosines*) + + +Int[(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + a*(a*Cos[c+d*x]+b*Sin[c+d*x])^n/(b*d*n) /; +FreeQ[{a,b,c,d,n},x] && ZeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Reference: G&R 2.557.5b'*) + + +Int[1/(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_])^2,x_Symbol] := + Sin[c+d*x]/(a*d*(a*Cos[c+d*x]+b*Sin[c+d*x])) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Basis: a*Cos[z]+b*Sin[z] == Sqrt[a^2+b^2]*Cos[z-ArcTan[a,b]]*) + + +Int[Sqrt[a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_]],x_Symbol] := + 2*EllipticE[(c+d*x-ArcTan[a,b])/2,2]*Sqrt[a*Cos[c+d*x]+b*Sin[c+d*x]]/ + (d*Sqrt[(a*Cos[c+d*x]+b*Sin[c+d*x])/Sqrt[a^2+b^2]]) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Basis: a*Cos[z]+b*Sin[z] == Sqrt[a^2+b^2]*Cos[z-ArcTan[a,b]]*) + + +Int[1/Sqrt[a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_]],x_Symbol] := + 2*EllipticF[(c+d*x-ArcTan[a,b])/2,2]*Sqrt[(a*Cos[c+d*x]+b*Sin[c+d*x])/Sqrt[a^2+b^2]]/ + (d*Sqrt[a*Cos[c+d*x]+b*Sin[c+d*x]]) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] + + +(* ::Item::Closed:: *) +(*Reference: G&R 2.557'*) + + +(* ::Item:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is odd, (a*Cos[z]+b*Sin[z])^n == (a^2+b^2-u^2)^((n-1)/2)*D[u,z] where u = -b*Cos[z]+a*Sin[z]*) + + +(* Note: For odd n<-1, better to stay in the trig world using 2nd rule below ??? *) +Int[(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + Dist[1/d,Subst[Int[Regularize[(a^2+b^2-x^2)^((n-1)/2),x],x],x,-b*Cos[c+d*x]+a*Sin[c+d*x]]] /; +FreeQ[{a,b},x] && OddQ[n] && n>=-1 && NonzeroQ[a^2+b^2] + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + -(b*Cos[c+d*x]-a*Sin[c+d*x])*(a*Cos[c+d*x]+b*Sin[c+d*x])^(n-1)/(d*n) + + Dist[(n-1)*(a^2+b^2)/n,Int[(a*Cos[c+d*x]+b*Sin[c+d*x])^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n>1 && NonzeroQ[a^2+b^2] && Not[OddQ[n]] + + +(* ::Item:: *) +(*Derivation: Integration by parts with a double-back flip*) + + +Int[(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + (b*Cos[c+d*x]-a*Sin[c+d*x])*(a*Cos[c+d*x]+b*Sin[c+d*x])^(n+1)/(d*(n+1)*(a^2+b^2)) + + Dist[(n+2)/((n+1)*(a^2+b^2)),Int[(a*Cos[c+d*x]+b*Sin[c+d*x])^(n+2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2+b^2] + + +(* ::Subsubsection::Closed:: *) +(*(a Csc[c+d x] - a Sin[c+d x])^n where a+b is zero*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Csc[z]-Sin[z] == Cos[z]*Cot[z]*) + + +Int[(a_.*Csc[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_])^n_,x_Symbol] := + Int[(a*Cos[c+d*x]*Cot[c+d*x])^n,x] /; +FreeQ[{a,b,c,d,n},x] && ZeroQ[a+b] + + +(* ::Subsubsection::Closed:: *) +(*(a Sec[c+d x] - a Cos[c+d x])^n where a+b is zero*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sec[z]-Cos[z] == Sin[z]*Tan[z]*) + + +Int[(a_.*Sec[c_.+d_.*x_]+b_.*Cos[c_.+d_.*x_])^n_,x_Symbol] := + Int[(a*Sin[c+d*x]*Tan[c+d*x])^n,x] /; +FreeQ[{a,b,c,d,n},x] && ZeroQ[a+b] + + +(* ::Subsection::Closed:: *) +(*Rational functions of Trig Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*u Trig[c+d x]^m / (a Cos[c+d x]+b Sin[c+d x]) where a^2+b^2 is nonzero*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[z]^2/(a*Cos[z]+b*Sin[z]) == b/(a^2+b^2)*Sin[z] - a/(a^2+b^2)*Cos[z] + a^2/((a^2+b^2)*(a*Cos[z]+b*Sin[z]))*) + + +Int[u_.*Sin[c_.+d_.*x_]^n_./(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_]),x_Symbol] := + Dist[b/(a^2+b^2),Int[u*Sin[c+d*x]^(n-1),x]] - + Dist[a/(a^2+b^2),Int[u*Sin[c+d*x]^(n-2)*Cos[c+d*x],x]] + + Dist[a^2/(a^2+b^2),Int[u*Sin[c+d*x]^(n-2)/(a*Cos[c+d*x]+b*Sin[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] && IntegerQ[n] && n>0 && +(n>1 || MatchQ[u,v_.*Tan[c+d*x]^m_. /; IntegerQ[m] && m>0]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[z]^2/(a*Cos[z]+b*Sin[z]) == a/(a^2+b^2)*Cos[z] - b/(a^2+b^2)*Sin[z] + b^2/(a^2+b^2)/(a*Cos[z]+b*Sin[z])*) + + +Int[u_.*Cos[c_.+d_.*x_]^n_./(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_]),x_Symbol] := + Dist[a/(a^2+b^2),Int[u*Cos[c+d*x]^(n-1),x]] - + Dist[b/(a^2+b^2),Int[u*Cos[c+d*x]^(n-2)*Sin[c+d*x],x]] + + Dist[b^2/(a^2+b^2),Int[u*Cos[c+d*x]^(n-2)/(a*Cos[c+d*x]+b*Sin[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] && IntegerQ[n] && n>0 && +(n>1 || MatchQ[u,v_.*Cot[c+d*x]^m_. /; IntegerQ[m] && m>0]) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[z]*Sin[z]/(a*Cos[z]+b*Sin[z]) == b/(a^2+b^2)*Cos[z] + a/(a^2+b^2)*Sin[z] - a*b/((a^2+b^2)*(a*Cos[z]+b*Sin[z]))*) + + +(* Int[u_.*Cos[c_.+d_.*x_]^m_.*Sin[c_.+d_.*x_]^n_./(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_]),x_Symbol] := + Dist[b/(a^2+b^2),Int[u*Cos[c+d*x]^m*Sin[c+d*x]^(n-1),x]] + + Dist[a/(a^2+b^2),Int[u*Cos[c+d*x]^(m-1)*Sin[c+d*x]^n,x]] - + Dist[a*b/(a^2+b^2),Int[u*Cos[c+d*x]^(m-1)*Sin[c+d*x]^(n-1)/(a*Cos[c+d*x]+b*Sin[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] && NonzeroQ[a^2+b^2] && IntegerQ[{m,n}] && m>0 && n>0 *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sec[z]/(a*Cos[z]+b*Sin[z]) == Tan[z]/b + (b*Cos[z]-a*Sin[z])/(b*(a*Cos[z]+b*Sin[z]))*) + + +(* Int[u_.*Sec[c_.+d_.*x_]/(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_]),x_Symbol] := + Dist[1/b,Int[u*Tan[c+d*x],x]] + + Dist[1/b,Int[u*(b*Cos[c+d*x]-a*Sin[c+d*x])/(a*Cos[c+d*x]+b*Sin[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Csc[z]/(a*Cos[z]+b*Sin[z]) == Cot[z]/a - (b*Cos[z]-a*Sin[z])/(a*(a*Cos[z]+b*Sin[z]))*) + + +(* Int[u_.*Csc[c_.+d_.*x_]/(a_.*Cos[c_.+d_.*x_]+b_.*Sin[c_.+d_.*x_]),x_Symbol] := + Dist[1/a,Int[u*Cot[c+d*x],x]] - + Dist[1/a,Int[u*(b*Cos[c+d*x]-a*Sin[c+d*x])/(a*Cos[c+d*x]+b*Sin[c+d*x]),x]] /; +FreeQ[{a,b,c,d},x] *) + + +(* ::Subsubsection::Closed:: *) +(*(a+b Cos[d+e x]+c Sin[d+e x])^n where a^2-b^2-c^2 is zero*) + + +(* ::Item:: *) +(*Reference: G&R 2.558.4d*) + + +Int[1/(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := +(* (-c*Cos[d+e*x]+b*Sin[d+e*x])/(a*e*(a+b*Cos[d+e*x]+c*Sin[d+e*x])) *) + -2/(e*(c+(a-b)*Tan[(d+e*x)/2])) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a^2-b^2-c^2] + + +Int[Sqrt[a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]],x_Symbol] := + -2*(c*Cos[d+e*x]-b*Sin[d+e*x])/(e*Sqrt[a+b*Cos[d+e*x]+c*Sin[d+e*x]]) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a^2-b^2-c^2] + + +(* Int[1/Sqrt[a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]],x_Symbol] := + -2*ArcTanh[Sin[z/2]]*Cos[z/2]/(e*Sqrt[a+b*Cos[d+e*x]+c*Sin[d+e*x]]) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a^2-b^2-c^2] *) + + +(* Int[1/Sqrt[a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]],x_Symbol] := + 2*ArcTanh[Sin[z/2]]*Cos[z/2]/(e*Sqrt[a+b*Cos[d+e*x]+c*Sin[d+e*x]]) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a^2-b^2-c^2] *) + + +Int[(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_])^n_,x_Symbol] := + (-c*Cos[d+e*x]+b*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n-1)/(e*n) + + Dist[a*(2*n-1)/n,Int[(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n-1),x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[n] && n>1 && ZeroQ[a^2-b^2-c^2] + + +Int[(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_])^n_,x_Symbol] := + (c*Cos[d+e*x]-b*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^n/(a*e*(2*n+1)) + + Dist[(n+1)/(a*(2*n+1)),Int[(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[n] && n<-1 && ZeroQ[a^2-b^2-c^2] + + +(* ::Subsubsection::Closed:: *) +(*(a+b Cos[d+e x]+c Sin[d+e x])^n where a^2-b^2-c^2 is nonzero*) + + +(* ::Item:: *) +(*Reference: G&R 2.558.4c*) + + +(* The following two rules should be unified?! *) +Int[1/(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := + Log[a+c*Tan[(d+e*x)/2]]/(c*e) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a-b] + + +Int[1/(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := + -Log[a+c*Cot[(d+e*x)/2]]/(c*e) /; +FreeQ[{a,b,c,d,e},x] && ZeroQ[a+b] + + +(* ::Item:: *) +(*Reference: G&R 2.558.4a, CRC 342b*) + + +Int[1/(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := + 2*ArcTan[(c+(a-b)*Tan[(d+e*x)/2])/Rt[a^2-b^2-c^2,2]]/(e*Rt[a^2-b^2-c^2,2]) /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[a^2-b^2] && PosQ[a^2-b^2-c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.558.4b', CRC 342b'*) + + +Int[1/(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := + -2*ArcTanh[(c+(a-b)*Tan[(d+e*x)/2])/Rt[-a^2+b^2+c^2,2]]/(e*Rt[-a^2+b^2+c^2,2]) /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[a^2-b^2] && NegQ[a^2-b^2-c^2] + + +(* ::Item:: *) +(*Basis: a+b*Cos[z]+c*Sin[z] == a+Sqrt[b^2+c^2]*Cos[z-ArcTan[b,c]]*) + + +Int[Sqrt[a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]],x_Symbol] := + 2*EllipticE[(d+e*x-ArcTan[b,c])/2,2/(1+a/Sqrt[b^2+c^2])]*Sqrt[a+b*Cos[d+e*x]+c*Sin[d+e*x]]/ + (e*Sqrt[(a+b*Cos[d+e*x]+c*Sin[d+e*x])/(a+Sqrt[b^2+c^2])]) /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[a^2-b^2-c^2] + + +(* ::Item:: *) +(*Basis: a+b*Cos[z]+c*Sin[z] == a+Sqrt[b^2+c^2]*Cos[z-ArcTan[b,c]]*) + + +Int[1/Sqrt[a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]],x_Symbol] := + 2*EllipticF[(d+e*x-ArcTan[b,c])/2,2/(1+a/Sqrt[b^2+c^2])]* + Sqrt[(a+b*Cos[d+e*x]+c*Sin[d+e*x])/(a+Sqrt[b^2+c^2])]/ + (e*Sqrt[a+b*Cos[d+e*x]+c*Sin[d+e*x]]) /; +FreeQ[{a,b,c,d,e},x] && NonzeroQ[a^2-b^2-c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.558.1*) + + +Int[(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_])^n_,x_Symbol] := + (-c*Cos[d+e*x]+b*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1)/(e*(n+1)*(a^2-b^2-c^2)) + + Dist[1/((n+1)*(a^2-b^2-c^2)), + Int[((n+1)*a-(n+2)*b*Cos[d+e*x]-(n+2)*c*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2-c^2] + + +(* ::Subsubsection::Closed:: *) +(*(A+B Cos[d+e x]+C Sin[d+e x]) (a+b Cos[d+e x]+c Sin[d+e x])^n where a^2-b^2-c^2 is nonzero*) +(**) + + +(* ::Item:: *) +(*Reference: G&R 2.558.2*) + + +Int[(A_.+C_.*Sin[d_.+e_.*x_])/(a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := + -b*C*Log[a+b*Cos[d+e*x]+c*Sin[d+e*x]]/(e*(b^2+c^2)) + + c*C*(d+e*x)/(e*(b^2+c^2)) + + Dist[(A-a*c*C/(b^2+c^2)),Int[1/(a+b*Cos[d+e*x]+c*Sin[d+e*x]),x]] /; +FreeQ[{a,b,c,d,e,A,C},x] && NonzeroQ[b^2+c^2] && NonzeroQ[A-a*c*C/(b^2+c^2)] + + +(* ::Item:: *) +(*Reference: G&R 2.558.2*) + + +Int[(A_.+B_.*Cos[d_.+e_.*x_])/(a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := + c*B*Log[a+b*Cos[d+e*x]+c*Sin[d+e*x]]/(e*(b^2+c^2)) + + b*B*(d+e*x)/(e*(b^2+c^2)) + + Dist[(A-a*b*B/(b^2+c^2)),Int[1/(a+b*Cos[d+e*x]+c*Sin[d+e*x]),x]] /; +FreeQ[{a,b,c,d,e,A,B},x] && NonzeroQ[b^2+c^2] && NonzeroQ[A-a*b*B/(b^2+c^2)] + + +(* ::Item:: *) +(*Reference: G&R 2.558.2*) + + +Int[(A_.+B_.*Cos[d_.+e_.*x_]+C_.*Sin[d_.+e_.*x_])/(a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_]),x_Symbol] := + (c*B-b*C)*Log[a+b*Cos[d+e*x]+c*Sin[d+e*x]]/(e*(b^2+c^2)) + + (b*B+c*C)*(d+e*x)/(e*(b^2+c^2)) + + Dist[(A-a*(b*B+c*C)/(b^2+c^2)),Int[1/(a+b*Cos[d+e*x]+c*Sin[d+e*x]),x]] /; +FreeQ[{a,b,c,d,e,A,B,C},x] && NonzeroQ[b^2+c^2] && NonzeroQ[A-a*(b*B+c*C)/(b^2+c^2)] + + +(* ::Item:: *) +(*Reference: G&R 2.558.1 inverted*) + + +(* Int[(A_.+B_.*Cos[d_.+e_.*x_]+C_.*Sin[d_.+e_.*x_])*(a_+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_])^n_,x_Symbol] := + (B*c-b*C-a*C*Cos[d+e*x]+a*B*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^n/(a*e*(n+1)) + + Dist[1/(a*(n+1)),Int[(a*(b*B+c*C)*n + a^2*A*(n+1) + + (a^2*B*n + c*(b*C-c*B)*n + a*b*A*(n+1))*Cos[d+e*x] + + (a^2*C*n - b*(b*C-c*B)*n + a*c*A*(n+1))*Sin[d+e*x])* + (a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n-1), x]] /; +FreeQ[{a,b,c,d,e,A,B,C},x] && RationalQ[n] && n>1 && NonzeroQ[a^2-b^2-c^2] *) + + +(* ::Item:: *) +(*Reference: G&R 2.558.1*) + + +Int[(A_.+C_.*Sin[d_.+e_.*x_])*(a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_])^n_,x_Symbol] := + (b*C+(a*C-c*A)*Cos[d+e*x]+b*A*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1)/ + (e*(n+1)*(a^2-b^2-c^2)) + + Dist[1/((n+1)*(a^2-b^2-c^2)), + Int[((n+1)*(a*A-c*C)-(n+2)*b*A*Cos[d+e*x]+(n+2)*(a*C-c*A)*Sin[d+e*x])* + (a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e,A,C},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2-c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.558.1*) + + +Int[(A_.+B_.*Cos[d_.+e_.*x_])*(a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_])^n_,x_Symbol] := + -(c*B+c*A*Cos[d+e*x]+(a*B-b*A)*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1)/ + (e*(n+1)*(a^2-b^2-c^2)) + + Dist[1/((n+1)*(a^2-b^2-c^2)), + Int[((n+1)*(a*A-b*B)+(n+2)*(a*B-b*A)*Cos[d+e*x]-(n+2)*c*A*Sin[d+e*x])* + (a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e,A,B},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2-c^2] + + +(* ::Item:: *) +(*Reference: G&R 2.558.1*) + + +Int[(A_.+B_.*Cos[d_.+e_.*x_]+C_.*Sin[d_.+e_.*x_])*(a_.+b_.*Cos[d_.+e_.*x_]+c_.*Sin[d_.+e_.*x_])^n_,x_Symbol] := + -(c*B-b*C-(a*C-c*A)*Cos[d+e*x]+(a*B-b*A)*Sin[d+e*x])*(a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1)/ + (e*(n+1)*(a^2-b^2-c^2)) + + Dist[1/((n+1)*(a^2-b^2-c^2)), + Int[((n+1)*(a*A-b*B-c*C)+(n+2)*(a*B-b*A)*Cos[d+e*x]+(n+2)*(a*C-c*A)*Sin[d+e*x])* + (a+b*Cos[d+e*x]+c*Sin[d+e*x])^(n+1),x]] /; +FreeQ[{a,b,c,d,e,A,B,C},x] && RationalQ[n] && n<-1 && NonzeroQ[a^2-b^2-c^2] + + +(* ::Subsubsection::Closed:: *) +(*Trig[v] (a+b Tan[v])^n*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: (a+b*Tan[z])/Sec[z] == a*Cos[z] + b*Sin[z]*) + + +Int[Sec[v_]^m_.*(a_+b_.*Tan[v_])^n_., x_Symbol] := + Int[(a*Cos[v]+b*Sin[v])^n,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m+n==0 + + +(* ::Subsubsection::Closed:: *) +(*Trig[v] (a+b Cot[v])^n*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: (a+b*Cot[z])/Csc[z] == b*Cos[z] + a*Sin[z]*) + + +Int[Csc[v_]^m_.*(a_+b_.*Cot[v_])^n_., x_Symbol] := + Int[(b*Cos[v]+a*Sin[v])^n,x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && m+n==0 + + +(* ::Subsection::Closed:: *) +(*Exponential and Trig Function Integration Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Sin[c + d x]^n Products of exponentials and powers of sines of linears*) + + +(* ::Item:: *) +(*Reference: CRC 533, A&S 4.3.136*) + + +Int[E^(a_.+b_.*x_)*Sin[c_.+d_.*x_],x_Symbol] := + -d*E^(a+b*x)*Cos[c+d*x]/(b^2+d^2) + b*E^(a+b*x)*Sin[c+d*x]/(b^2+d^2) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[b^2+d^2] + + +(* ::Item:: *) +(*Reference: CRC 542, A&S 4.3.138*) + + +Int[E^(a_.+b_.*x_)*Sin[c_.+d_.*x_]^n_,x_Symbol] := + b*E^(a+b*x)*Sin[c+d*x]^n/(b^2+d^2*n^2) - + d*n*E^(a+b*x)*Cos[c+d*x]*Sin[c+d*x]^(n-1)/(b^2+d^2*n^2) + + Dist[n*(n-1)*d^2/(b^2+d^2*n^2),Int[E^(a+b*x)*Sin[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Cos[c + d x]^n Products of exponentials and powers of cosines of linears*) + + +(* ::Item:: *) +(*Reference: CRC 538, A&S 4.3.137*) + + +Int[E^(a_.+b_.*x_)*Cos[c_.+d_.*x_],x_Symbol] := + b*E^(a+b*x)*Cos[c+d*x]/(b^2+d^2) + d*E^(a+b*x)*Sin[c+d*x]/(b^2+d^2) /; +FreeQ[{a,b,c,d},x] && NonzeroQ[b^2+d^2] + + +(* ::Item:: *) +(*Reference: CRC 543, A&S 4.3.139*) + + +Int[E^(a_.+b_.*x_)*Cos[c_.+d_.*x_]^n_,x_Symbol] := + b*E^(a+b*x)*Cos[c+d*x]^n/(b^2+d^2*n^2) + + d*n*E^(a+b*x)*Cos[c+d*x]^(n-1)*Sin[c+d*x]/(b^2+d^2*n^2) + + Dist[n*(n-1)*d^2/(b^2+d^2*n^2),Int[E^(a+b*x)*Cos[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n>1 + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Sec[c + d x]^n Products of exponentials and powers of secants of linears*) + + +(* ::Item:: *) +(*Reference: CRC 552*) + + +Int[E^(a_.+b_.*x_)*Sec[c_.+d_.*x_]^n_,x_Symbol] := + -b*E^(a+b*x)*Sec[c+d*x]^(n-2)/(d^2*(n-1)*(n-2)) + + E^(a+b*x)*Sec[c+d*x]^(n-1)*Sin[c+d*x]/(d*(n-1)) + + Dist[(b^2+d^2*(n-2)^2)/(d^2*(n-1)*(n-2)),Int[E^(a+b*x)*Sec[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n>1 && n!=2 + + +(* ::Subsubsection::Closed:: *) +(*Exp[a + b x] Csc[c + d x]^n Products of exponentials and powers of cosecants of linears*) +(**) + + +(* ::Item:: *) +(*Reference: CRC 551*) + + +Int[E^(a_.+b_.*x_)*Csc[c_.+d_.*x_]^n_,x_Symbol] := + -b*E^(a+b*x)*Csc[c+d*x]^(n-2)/(d^2*(n-1)*(n-2)) - + E^(a+b*x)*Cos[c+d*x]*Csc[c+d*x]^(n-1)/(d*(n-1)) + + Dist[(b^2+d^2*(n-2)^2)/(d^2*(n-1)*(n-2)),Int[E^(a+b*x)*Csc[c+d*x]^(n-2),x]] /; +FreeQ[{a,b,c,d},x] && RationalQ[n] && n>1 && n!=2 + + +(* ::Subsubsection::Closed:: *) +(*x^m Exp[a + b x] Sin[c + d x]^n Products of monomials, exponentials and powers of sines of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*E^(a_.+b_.*x_)*Sin[c_.+d_.*x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[E^(a+b*x)*Sin[c+d*x]^n,x]]}, + x^m*u - Dist[m,Int[x^(m-1)*u,x]]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && m>0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*x^m Exp[a + b x] Cos[c + d x]^n Products of exponentials and powers of cosines of linears*) + + +(* ::Item:: *) +(*Derivation: Integration by parts*) + + +Int[x_^m_.*E^(a_.+b_.*x_)*Cos[c_.+d_.*x_]^n_.,x_Symbol] := + Module[{u=Block[{ShowSteps=False,StepCounter=Null}, Int[E^(a+b*x)*Cos[c+d*x]^n,x]]}, + x^m*u - Dist[m,Int[x^(m-1)*u,x]]] /; +FreeQ[{a,b,c,d},x] && RationalQ[m] && IntegerQ[n] && m>0 && n>0 + + +(* ::Subsubsection::Closed:: *) +(*u f^v Trig[w] Products of exponentials and trig functions of polynomials*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[z] == I/2*(1/E^(I*z) - E^(I*z)) *) + + +Int[f_^v_*Sin[w_],x_Symbol] := + Dist[I/2,Int[f^v/E^(I*w),x]] - + Dist[I/2,Int[f^v*E^(I*w),x]] /; +FreeQ[f,x] && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Sin[z] == I/2*(1/E^(I*z) - E^(I*z)) *) + + +Int[f_^v_*Sin[w_]^n_,x_Symbol] := + Dist[(I/2)^n,Int[f^v*(1/E^(I*w)-E^(I*w))^n,x]] /; +FreeQ[f,x] && IntegerQ[n] && n>0 && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[z] == 1/2*(E^(I*z) + 1/E^(I*z))*) + + +Int[f_^v_*Cos[w_],x_Symbol] := + Dist[1/2,Int[f^v*E^(I*w),x]] + + Dist[1/2,Int[f^v/E^(I*w),x]] /; +FreeQ[f,x] && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic expansion*) + + +(* ::Item:: *) +(*Basis: Cos[z] == 1/2*(E^(I*z) + 1/E^(I*z))*) + + +Int[f_^v_*Cos[w_]^n_,x_Symbol] := + Dist[1/2^n,Int[f^v*(E^(I*w)+1/E^(I*w))^n,x]] /; +FreeQ[f,x] && IntegerQ[n] && n>0 && PolynomialQ[v,x] && Exponent[v,x]<=2 && PolynomialQ[w,x] && Exponent[w,x]<=2 + + +(* ::Subsection::Closed:: *) +(*Trig Function Simplification Rules*) + + +(* ::Subsubsection::Closed:: *) +(*u (a-a Trig[v]^2)^n*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1-Sin[z]^2 == Cos[z]^2*) + + +Int[u_.*(a_+b_.*Sin[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Cos[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 - Cos[z]^2 == Sin[z]^2*) + + +Int[u_.*(a_+b_.*Cos[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Sin[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 + Tan[z]^2 == Sec[z]^2*) + + +Int[u_.*(a_+b_.*Tan[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Sec[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: 1 + Cot[z]^2 == Csc[z]^2*) + + +Int[u_.*(a_+b_.*Cot[v_]^2)^n_.,x_Symbol] := + Dist[a^n,Int[u*Csc[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a-b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: -1 + Sec[z]^2 == Tan[z]^2*) + + +Int[u_.*(a_+b_.*Sec[v_]^2)^n_.,x_Symbol] := + Dist[b^n,Int[u*Tan[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: -1 + Csc[z]^2 == Cot[z]^2*) + + +Int[u_.*(a_+b_.*Csc[v_]^2)^n_.,x_Symbol] := + Dist[b^n,Int[u*Cot[v]^(2*n),x]] /; +FreeQ[{a,b},x] && IntegerQ[n] && ZeroQ[a+b] + + +(* ::Subsubsection::Closed:: *) +(*u (a Tan[v]^m+b Sec[v]^m)^n Simplify sum of powers of trig functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If a^2-b^2=0, then a*Tan[z]+b*Sec[z] == a*Tan[z/2+a/b*Pi/4]*) + + +Int[(a_.*Tan[v_]+b_.*Sec[v_])^n_,x_Symbol] := + Dist[a^n,Int[Tan[v/2+a/b*Pi/4]^n,x]] /; +FreeQ[{a,b},x] && ZeroQ[a^2-b^2] && EvenQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a*Sec[z]+b*Tan[z] == (a+b*Sin[z])/Cos[z]*) + + +Int[u_.*(a_.*Sec[v_]^m_.+b_.*Tan[v_]^m_.)^n_.,x_Symbol] := + Int[u*(a+b*Sin[v]^m)^n/Cos[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && (OddQ[m*n] || m*n<0) && Not[m==2 && ZeroQ[a+b]] + + +(* ::Subsubsection::Closed:: *) +(*u (a Cot[v]^m+b Csc[v]^m)^n Simplify sum of powers of trig functions*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: If a^2-b^2=0, then a*Cot[z]+b*Csc[z] == a*Cot[z/2+(a/b-1)*Pi/4]*) + + +Int[(a_.*Cot[v_]+b_.*Csc[v_])^n_,x_Symbol] := + Dist[a^n,Int[Cot[v/2+(a/b-1)*Pi/4]^n,x]] /; +FreeQ[{a,b},x] && ZeroQ[a^2-b^2] && EvenQ[n] + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: a*Csc[z]+b*Cot[z] == (a+b*Cos[z])/Sin[z]*) + + +Int[u_.*(a_.*Csc[v_]^m_.+b_.*Cot[v_]^m_.)^n_.,x_Symbol] := + Int[u*(a+b*Cos[v]^m)^n/Sin[v]^(m*n),x] /; +FreeQ[{a,b},x] && IntegerQ[{m,n}] && (OddQ[m*n] || m*n<0) && Not[m==2 && ZeroQ[a+b]] + + +(* ::Subsubsection::Closed:: *) +(*x^m Trig[u]^n Trig[v]^p*) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sin[z]*Cos[z] == Sin[2*z]/2*) + + +(* Int[x_^m_.*Sin[v_]^n_.*Cos[v_]^n_.,x_Symbol] := + Dist[1/2^n,Int[x^m*Sin[Dist[2,v]]^n,x]] /; +IntegerQ[n] *) + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Sec[z]*Csc[z] == 2*Csc[2*z]*) + + +Int[x_^m_.*Sec[v_]^n_.*Csc[v_]^n_.,x_Symbol] := + Dist[2^n,Int[x^m*Csc[Dist[2,v]]^n,x]] /; +IntegerQ[{m,n}] && m>0 + + +(* ::Item::Closed:: *) +(*Derivation: Algebraic simplification*) + + +(* ::Item:: *) +(*Basis: Convert trig function to complex exponentials*) + + +(* Got to improve x^m*f[e^x] integration before doing this! *) +(* Int[x_^m_.*f_[u_]^n_.*g_[v_]^p_.,x_Symbol] := + Int[x^m*TrigToExp[f[u]]^n*TrigToExp[g[v]]^p,x] /; +IntegerQ[{m,n,p}] && TrigQ[f] && TrigQ[g] *) + + +(* ::Subsection::Closed:: *) +(*Trig Function Substitution Rules*) + + +(* ::Subsubsection::Closed:: *) +(*Pure sine function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sin[z]]*Cos[z] == f[Sin[z]] * Sin'[z]*) + + +Int[u_*Cos[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Sin[c*(a+b*x)],u,x],x],x],x,Sin[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sin[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sin[z]]*Cot[z] == f[Sin[z]]/Sin[z] * Sin'[z]*) + + +Int[u_*Cot[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Sin[c*(a+b*x)],u,x]/x,x],x],x,Sin[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sin[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Sin[z]]*Sin[2*z] == 2*f[Sin[z]]*Sin[z] * Sin'[z]*) + + +Int[u_*Sin[c_.*(a_.+b_.*x_)],x_Symbol] := + Dist[4/(b*c),Subst[Int[Regularize[x*SubstFor[Sin[c*(a+b*x)/2],u,x],x],x],x,Sin[c*(a+b*x)/2]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Sin[c*(a+b*x)/2],u,x,True] + + +(* ::Subsubsection::Closed:: *) +(*Pure cosine function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cos[z]]*Sin[z] == -f[Cos[z]] * Cos'[z]*) + + +Int[u_*Sin[c_.*(a_.+b_.*x_)],x_Symbol] := + -Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Cos[c*(a+b*x)],u,x],x],x],x,Cos[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cos[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cos[z]]*Tan[z] == -f[Cos[z]]/Cos[z] * Cos'[z]*) + + +Int[u_*Tan[c_.*(a_.+b_.*x_)],x_Symbol] := + -Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Cos[c*(a+b*x)],u,x]/x,x],x],x,Cos[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cos[c*(a+b*x)],u,x,True] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cos[z]]*Sin[2*z] == -2*f[Cos[z]]*Cos[z] * Cos'[z]*) + + +Int[u_*Sin[c_.*(a_.+b_.*x_)],x_Symbol] := + -Dist[4/(b*c),Subst[Int[Regularize[x*SubstFor[Cos[c*(a+b*x)/2],u,x],x],x],x,Cos[c*(a+b*x)/2]]] /; +FreeQ[{a,b,c},x] && FunctionOfQ[Cos[c*(a+b*x)/2],u,x,True] + + +(* ::Subsubsection::Closed:: *) +(*Pure cotangent function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is an integer, f[Cot[z]]*Tan[z]^n == -f[Cot[z]]/(Cot[z]^n*(1+Cot[z]^2)) * Cot'[z]*) + + +Int[u_*Tan[c_.*(a_.+b_.*x_)]^n_.,x_Symbol] := + -Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Cot[c*(a+b*x)],u,x]/(x^n*(1+x^2)),x],x],x,Cot[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && IntegerQ[n] && FunctionOfQ[Cot[c*(a+b*x)],u,x,True] && TryPureTanSubst[u*Tan[c*(a+b*x)]^n,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Cot[z]] == -f[Cot[z]]/(1+Cot[z]^2) * Cot'[z]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + ShowStep["","Int[f[Cot[a+b*x]],x]","Subst[Int[f[x]/(1+x^2),x],x,Cot[a+b*x]]/b",Hold[ + Dist[-1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cot[v],u,x]/(1+x^2),x],x],x,Cot[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Cot[v],u,x,True] && TryPureTanSubst[u,x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + Dist[-1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Cot[v],u,x]/(1+x^2),x],x],x,Cot[v]]] /; + NotFalseQ[v] && FunctionOfQ[Cot[v],u,x,True] && TryPureTanSubst[u,x]]] + + +(* ::Subsubsection::Closed:: *) +(*Pure tangent function substitution rules*) + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: If n is an integer, f[Tan[z]]*Cot[z]^n == f[Tan[z]]/(Tan[z]^n*(1+Tan[z]^2)) * Tan'[z]*) + + +Int[u_*Cot[c_.*(a_.+b_.*x_)]^n_.,x_Symbol] := + Dist[1/(b*c),Subst[Int[Regularize[SubstFor[Tan[c*(a+b*x)],u,x]/(x^n*(1+x^2)),x],x],x,Tan[c*(a+b*x)]]] /; +FreeQ[{a,b,c},x] && IntegerQ[n] && FunctionOfQ[Tan[c*(a+b*x)],u,x,True] && TryPureTanSubst[u*Cot[c*(a+b*x)]^n,x] + + +(* ::Item::Closed:: *) +(*Derivation: Integration by substitution*) + + +(* ::Item:: *) +(*Basis: f[Tan[z]] == f[Tan[z]]/(1+Tan[z]^2) * Tan'[z]*) + + +If[ShowSteps, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + ShowStep["","Int[f[Tan[a+b*x]],x]","Subst[Int[f[x]/(1+x^2),x],x,Tan[a+b*x]]/b",Hold[ + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Tan[v],u,x]/(1+x^2),x],x],x,Tan[v]]]]] /; + NotFalseQ[v] && FunctionOfQ[Tan[v],u,x,True] && TryPureTanSubst[u,x]] /; +SimplifyFlag, + +Int[u_,x_Symbol] := + Module[{v=FunctionOfTrig[u,x]}, + Dist[1/Coefficient[v,x,1],Subst[Int[Regularize[SubstFor[Tan[v],u,x]/(1+x^2),x],x],x,Tan[v]]] /; + NotFalseQ[v] && FunctionOfQ[Tan[v],u,x,True] && TryPureTanSubst[u,x]]] + + +TryPureTanSubst[u_,x_Symbol] := + Not[MatchQ[u,ArcTan[a_.*Tan[v_]] /; FreeQ[a,x]]] && + Not[MatchQ[u,ArcTan[a_.*Cot[v_]] /; FreeQ[a,x]]] && + Not[MatchQ[u,ArcCot[a_.*Tan[v_]] /; FreeQ[a,x]]] && + Not[MatchQ[u,ArcCot[a_.*Cot[v_]] /; FreeQ[a,x]]] && + u===ExpnExpand[u,x] diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/RunTestSuite.java mathpiper-0.81f+dfsg1/src/org/mathpiper/test/RunTestSuite.java --- mathpiper-0.0.svn2556/src/org/mathpiper/test/RunTestSuite.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/RunTestSuite.java 2010-07-18 16:36:18.000000000 +0000 @@ -13,7 +13,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - //}}} // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.test; @@ -30,6 +29,8 @@ private java.io.File testDirectory; private EvaluationResponse evaluationResponse; private java.io.FileWriter logFile; + private String scriptsDirectory = "scripts4"; + private int exceptionCount = 0; public RunTestSuite() { super(); @@ -40,34 +41,31 @@ try { logFile = new java.io.FileWriter("./tests/mathpiper_tests.log"); - int exceptionCount = 0; + - BufferedReader scriptNames = new BufferedReader(new InputStreamReader(java.lang.ClassLoader.getSystemResource("tests/scripts/test_index.txt").openStream())); + BufferedReader scriptNames = new BufferedReader(new InputStreamReader(RunTestSuite.class.getClassLoader().getSystemResource("tests/" + scriptsDirectory + "/test_index.txt").openStream())); if (scriptNames != null) //File is on the classpath. { String output; mathPiper = Interpreters.newSynchronousInterpreter(); - - //Optional initialization code. - /* - evaluationResponse = mathPiper.evaluate("10 # Factors(p_IsRational)_(Denom(p) != 1) <-- {{Factor(Numer(p)) / Factor(Denom(p)) , 1}};"); - output = "Result: " + evaluationResponse.getResult() + "\n\nSide Effects:\n" + evaluationResponse.getSideEffects() + "\nException:" + evaluationResponse.getExceptionMessage(); - if (evaluationResponse.isExceptionThrown()) { - output = output + " Source file: " + evaluationResponse.getSourceFileName() + " Line number: " + evaluationResponse.getLineNumber(); - } - System.out.println("Initialization response: " + output); - */ - output = "\n***** Beginning of tests. *****\n"; + //Initialization code. + evaluationResponse = mathPiper.evaluate("StackTraceOn();"); + output = evaluationResponse(evaluationResponse); + System.out.println("Turning stack tracing on: " + output); + logFile.write("Turning stack tracing on: " + output); + + + output = "\n\n***** Beginning of tests. *****\n"; output = "\n***** " + new java.util.Date() + " *****\n"; - output += "***** Using a new interpreter instance for each test file. *****\n"; + //output += "***** Using a new interpreter instance for each test file. *****\n"; output += "***** MathPiper version: " + org.mathpiper.Version.version + " *****\n"; System.out.print(output); logFile.write(output); - + while (scriptNames.ready()) { @@ -79,15 +77,13 @@ System.out.print(output); logFile.write(output); - evaluationResponse = mathPiper.evaluate("Load(\"tests/scripts/" + scriptName + "\");"); - output = "Result: " + evaluationResponse.getResult() + "\n\nSide Effects:\n" + evaluationResponse.getSideEffects() + "\nException:" + evaluationResponse.getExceptionMessage(); - if (evaluationResponse.isExceptionThrown()) { - output = output + " Source file: " + evaluationResponse.getSourceFileName() + " Line number: " + evaluationResponse.getLineNumber(); - exceptionCount++; - } - System.out.println(output); + evaluationResponse = mathPiper.evaluate("LoadScript(\"tests/" + scriptsDirectory + "/" + scriptName + "\");"); + output = evaluationResponse(evaluationResponse); + + + System.out.println(output); logFile.write(output); } else { output = "\n===========================\n" + scriptName + ": is not a MathPiper test file.\n"; @@ -107,6 +103,12 @@ logFile.write(output); + //Check the global variables. + evaluationResponse = mathPiper.evaluate("Echo(GlobalVariablesGet());"); + output = evaluationResponse(evaluationResponse); + System.out.println("Global variables: " + output); + logFile.write("GlobalVariables: " + output); + logFile.close(); } catch (java.io.IOException e) { @@ -116,6 +118,23 @@ }//end method. + private String evaluationResponse(EvaluationResponse evaluationResponse) { + + String result = "Result: " + evaluationResponse.getResult() + "\n"; + + if (!evaluationResponse.getSideEffects().equals("")) { + result = result + "\nSide Effects:\n" + evaluationResponse.getSideEffects(); + } + + + if (evaluationResponse.isExceptionThrown()) { + result = result + "\nException:" + evaluationResponse.getExceptionMessage() + " Source file: " + evaluationResponse.getSourceFileName() + " Line number: " + evaluationResponse.getLineNumber(); + exceptionCount++; + } + + return result; + } + public static void main(String[] args) { RunTestSuite pt = new RunTestSuite(); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/test/test.mpi mathpiper-0.81f+dfsg1/src/org/mathpiper/test/test.mpi --- mathpiper-0.0.svn2556/src/org/mathpiper/test/test.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/test/test.mpi 2011-02-02 08:38:37.000000000 +0000 @@ -1,121 +1,25 @@ -Import("org/mathpiper/builtin/functions/plugins/jfreechart/"); +// Check the rare case where the bounds finder lands on +// exactly a root +/*[ + Local(p); + p:=FindRealRoots((x+4)*(x-6),1,7)-{-4.,6.}; + Verify(VerifyZero(Dot(p, p)),True); +];*/ +Retract("Dx", *); -//Histogram({1.0, 1.1, 1.1, 1.2, 1.7, 2.2, 2.5, 4.0}, cumulative -> True); +Rulebase("Dx", {u,v}); +10 # Dx(X) <-- 1; -//a := {5,2,3,3,4,4,2,4,3,1,1,1,6,4,2,4,1,1,5,3,1,6,5,4,3,1,5,5,4,5,2,6,2,3,3,6,5,1,1,2,1,5,1,1,2,4,5,2,1,1,3,1,4,5,6,2,3,4,6,5,6,1,2,6,5,5,6,6,5,6,6,4,1,1,4,6,6,3,4,6,1,3,5,3,3,4,6,2,5,5,3,2,3,5,6,3,4,3,4,6}; -//Histogram(a, binMinimum -> .5, binMaximum -> 6.5, numberOfBins -> 6); +11 # Dx(Y) <-- 0; -/* -samples := { -438,413,444,468,445,472,474,454,455,449, -450,450,450,459,466,470,457,441,450,445, -487,430,446,450,456,433,455,459,423,455, -451,437,444,453,434,454,448,435,432,441, -452,465,466,473,471,464,478,446,459,464, -441,444,458,454,437,443,465,435,444,457, -444,471,471,458,459,449,462,460,445,437, -461,453,452,438,445,435,454,428,454,434, -432,431,455,447,454,435,425,449,449,452, -471,458,445,463,423,451,440,442,441,439}; +12 # Dx(_u + _v) <-- Dx(u) + Dx(v); +13 # Dx(_u * _v) <-- (u * Dx(v)) + (Dx(u) * v); -//samples := {1,1,2,2,2,3,3}; -//CumulativePlot(samples); +ViewGraphicConsole(); -//Use("/home/tkosan/NetBeansProjects/mathpiper/tests/scripts/solve.mpt"); -*/ +//Dx(Hold(X * X)); -/* -claim := 1 .. 40; -days1 := {48,41,35,36,37,26,36,46,35,47,35,34,36,42,43,36,56,32,46,30,37,43,17,26,28,27,45,33,22,27,16,22,33,30,24,23,22,30,31,17}; -days2 := RandomIntegerVector(Length(claim), 20, 50); -BarChart({claim, days1, claim, days2}, title -> "Bar Chart", series1Title -> "Series 1", series2Title -> "Series 2", xAxisLabel -> "Claim", yAxisLabel -> "Days", orientation -> "horizontal"); -*/ - - - - -/* -domain := 0 .. 15; - -sample1 := {}; -ForEach(x, 0 .. 15) -[ - probability := ProbabilityDensityFunction(BinomialDistribution(.1,15),x); - sample1 := Append(sample1, probability); -]; - - -sample2 := {}; -ForEach(x, 0 .. 15) -[ - probability := ProbabilityDensityFunction(BinomialDistribution(.5,15),x); - sample2 := Append(sample2, probability); -]; - -sample3 := {}; -ForEach(x, 0 .. 15) -[ - probability := ProbabilityDensityFunction(BinomialDistribution(.9,15),x); - sample3 := Append(sample3, probability); -]; - -LineChart({domain, sample1, domain, sample2, domain, sample3}); - -*/ - - -/* -Retract("Test",*); - -Function() Test(x, ...); - -Test(_x, _options ) <-- -[ - Echo(x); - Echo(options); - -]; - -Test(2); - -*/ - - -/* -rooms := {}; - -kitchen := {}; -kitchen["name"] := "kitchen"; -rooms := Append(rooms,kitchen); - - -livingRoom := {}; -livingRoom["name"] := "living room"; -rooms := Append(rooms,livingRoom); - -kitchen["n"] := livingRoom; - -livingRoom["s"] := kitchen; - -Write(rooms); -NewLine(); -Write(kitchen); -NewLine(); -Write(livingRoom,Nl()); -Write(rooms, Nl()); - -*/ - - -//10 # SetTag(_x,_tag) <-- [ Meta(x)["Tags"] := tag; ]; - -//SetTag(y,3); - - -a := MetaSet(3,"x",42); -a := MetaSet(a,"y",43); -MetaEntries(a); \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ColorConsole.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ColorConsole.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ColorConsole.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ColorConsole.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,969 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.ui.gui.consoles; - - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Stack; -import javax.swing.text.Element; -import javax.swing.text.AttributeSet; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JSplitPane; -import javax.swing.JTextArea; -import javax.swing.JTextPane; -import javax.swing.SwingUtilities; -import javax.swing.text.BadLocationException; -import javax.swing.text.DefaultEditorKit; -import javax.swing.text.Document; -import javax.swing.text.MutableAttributeSet; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyleContext; -import javax.swing.text.StyledDocument; -import org.mathpiper.interpreters.EvaluationResponse; -import org.mathpiper.interpreters.Interpreter; -import org.mathpiper.interpreters.Interpreters; -import org.mathpiper.interpreters.ResponseListener; -import org.mathpiper.io.MathPiperOutputStream; -import org.mathpiper.lisp.Environment; - - -public class ColorConsole extends javax.swing.JPanel implements ActionListener, KeyListener, ResponseListener, ItemListener, MathPiperOutputStream { - - private final Color green = new Color(0, 130, 0); - private final Color purple = new Color(153, 0, 153); - private Interpreter interpreter = Interpreters.getAsynchronousInterpreter(); - private StringBuilder input = new StringBuilder(); - private JButton haltButton, clearConsoleButton, clearRawButton, helpButton, button2, button3; - private JCheckBox rawOutputCheckBox; - private JCheckBox showRawOutputCheckBox; - private JTextArea rawOutputTextArea; - private ColorPane textPane; - private MathPiperOutputStream currentOutput; - private JScrollPane typePane; - private char[] typedKey = new char[1]; - private JPanel consoleButtons; - private JPanel rawButtons; - private boolean deleteFlag = false; - private int fontSize = 12; - private Font bitstreamVera; - private StringBuilder inputLines; - private int responseInsertionOffset = -1; - private boolean encounteredIn = false; - private boolean noLinesBetweenInAndEndOfTextArea = false; - private JSplitPane splitPane; - private int splitPaneDividerLocation = 400; - private JScrollPane rawOutputScrollPane; - private JPanel rawOutputPanel; - private JPopupMenu Pmenu; - private Stack history = new java.util.Stack(); - private boolean controlKeyDown = false; - private int historyIndex = -1; - private String helpMessage = - "Press after an expression to create an additional input line and to append a hidden ;.\n\n" + - "Press after any input line in a group of input lines to execute them all.\n\n" + - "Type In> on the left edge of any line to create your own input prompt.\n\n" + - "Press after an empty In> to erase the In>.\n" + - "Any line in a group that ends with a \\ will not have a ; appended to it.\n\n" + - "Pressing at the end of a line automatically appends a \\ to the line.\n\n" + - "Use and to navigate through the command line history.\n\n" + - "The console window is an editable text area, so you can add text to it and remove text from \n" + - "it as needed.\n\n" + - "The Raw Output checkbox sends all side effects output to the raw output text area."; - - - public ColorConsole() { - - inputLines = new StringBuilder(); - - - this.setLayout(new BorderLayout()); - - //keySendQueue = new java.util.concurrent.ArrayBlockingQueue(30); - - consoleButtons = new JPanel(); - consoleButtons.setLayout(new BoxLayout(consoleButtons, BoxLayout.X_AXIS)); - - - rawOutputPanel = new JPanel(); - rawOutputPanel.setLayout(new BorderLayout()); - rawButtons = new JPanel(); - rawButtons.setLayout(new BoxLayout(rawButtons, BoxLayout.X_AXIS)); - - - - //textArea = new JTextArea(30, 20); - textPane = new ColorPane(); - - textPane.append(purple, "MathPiper version " + org.mathpiper.Version.version + ".\n"); - textPane.append(purple, "Enter an expression after any In> prompt and press to evaluate it.\n"); - - - textPane.append(Color.BLACK, "\nIn> "); - textPane.setCaretPosition(textPane.getDocument().getLength()); - - //java.io.InputStream inputStream = org.gjt.sp.jedit.jEdit.getPlugin("org.mathrider.u6502plugin.U6502Plugin").getPluginJAR().getClassLoader().getResourceAsStream( "resources/ttf-bitstream-vera-1.10/VeraMono.ttf" ); - - //bitstreamVera = Font.createFont (Font.TRUETYPE_FONT, inputStream); - //bitstreamVera = bitstreamVera.deriveFont(fontSize); - //typeArea.setFont(bitstreamVera); - - - textPane.addKeyListener(this); - typePane = new JScrollPane(textPane); - //guiBox.add(typePane); - - - - haltButton = new JButton("Halt Calculation"); - haltButton.setEnabled(false); - haltButton.setForeground(Color.RED); - haltButton.addActionListener(this); - consoleButtons.add(haltButton); - - button2 = new JButton("Font-"); - button2.addActionListener(this); - consoleButtons.add(button2); - button3 = new JButton("Font+"); - button3.addActionListener(this); - consoleButtons.add(button3); - - rawOutputCheckBox = new JCheckBox("Raw Side Effects"); - rawOutputCheckBox.addItemListener(this); - rawButtons.add(rawOutputCheckBox); - this.rawOutputTextArea = new JTextArea(); - rawOutputTextArea.setEditable(false); - rawOutputTextArea.setText("Raw output text area.\n\n"); - - - showRawOutputCheckBox = new JCheckBox("Show Raw"); - showRawOutputCheckBox.addItemListener(this); - consoleButtons.add(showRawOutputCheckBox); - - consoleButtons.add(Box.createGlue()); - - - clearConsoleButton = new JButton("Clear"); - clearConsoleButton.addActionListener(this); - consoleButtons.add(clearConsoleButton); - - - clearRawButton = new JButton("Clear Raw"); - clearRawButton.addActionListener(this); - rawButtons.add(clearRawButton); - - - helpButton = new JButton("Help"); - helpButton.addActionListener(this); - consoleButtons.add(helpButton); - - - - this.add(consoleButtons, BorderLayout.NORTH); - - this.rawOutputPanel.add(rawButtons, BorderLayout.NORTH); - - //this.add(guiBox, BorderLayout.CENTER); - - - rawOutputScrollPane = new JScrollPane(rawOutputTextArea); - rawOutputPanel.add(rawOutputScrollPane); - - - splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, typePane, null); - splitPane.setOneTouchExpandable(true); - splitPane.setDividerLocation(splitPaneDividerLocation); - - this.add(splitPane); - - - - this.addPopupMenu(); - - - }//Constructor. - - - public void actionPerformed(ActionEvent event) { - Object src = event.getSource(); - - if (src == haltButton) { - interpreter.haltEvaluation(); - } else if (src == button2) { - this.fontSize -= 2; - - //bitstreamVera = bitstreamVera.deriveFont(fontSize); - //typeArea.setFont(bitstreamVera); - this.setJTextPaneFont(textPane, fontSize); - } else if (src == button3) { - this.fontSize += 2; - //bitstreamVera = bitstreamVera.deriveFont(fontSize); - //typeArea.setFont(bitstreamVera); - this.setJTextPaneFont(textPane, fontSize); - } else if (src == helpButton) { - JOptionPane.showMessageDialog(this, this.helpMessage); - } else if (src == clearConsoleButton) { - this.textPane.setText(""); - this.textPane.append(Color.BLACK, "In> "); - } else if (src == clearRawButton) { - this.rawOutputTextArea.setText(""); - } - - }//end method. - - - public void itemStateChanged(ItemEvent ie) { - Object source = ie.getSource(); - - if (source == rawOutputCheckBox) { - if (ie.getStateChange() == ItemEvent.SELECTED) { - Environment environment = interpreter.getEnvironment(); - this.currentOutput = environment.iCurrentOutput; - environment.iCurrentOutput = this; - } else { - Environment environment = interpreter.getEnvironment(); - environment.iCurrentOutput = this.currentOutput; - }//end if/else. - } else if (source == showRawOutputCheckBox) { - if (ie.getStateChange() == ItemEvent.SELECTED) { - splitPane.add(rawOutputPanel); - splitPane.setDividerLocation(splitPaneDividerLocation); - splitPane.revalidate(); - } else { - splitPane.remove(2); - splitPane.revalidate(); - }//end if/else. - } - }//end method. - - - public void putChar(char aChar) throws Exception { - if (rawOutputTextArea != null && currentOutput != null) { - this.rawOutputTextArea.append("" + aChar); - this.rawOutputTextArea.setCaretPosition(this.rawOutputTextArea.getDocument().getLength()); - this.currentOutput.putChar(aChar); - }//end if. - }//end method. - - - public void write(String aString) throws Exception { - int i; - for (i = 0; i < aString.length(); i++) { - putChar(aString.charAt(i)); - } - }//end method. - - - public void keyPressed(KeyEvent e) { - int keyCode = (int) e.getKeyCode(); - - if (keyCode == KeyEvent.VK_CONTROL) { - this.controlKeyDown = true; - }//end if. - - - if (keyCode == KeyEvent.VK_UP && this.controlKeyDown) { - //System.out.println("up"); - - if (!history.empty() && historyIndex != history.size() - 1) { - - - historyIndex++; - //System.out.println(history.get((history.size()-1) - historyIndex)); - - try { - int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); - int lineStartOffset = textPane.getLineStartOffset(lineNumber); - int lineEndOffset = textPane.getLineEndOffset(lineNumber); - - textPane.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex), lineStartOffset, lineEndOffset); - - } catch (BadLocationException ble) { - //Eat exception. - } - - - }//end if. - - }//end if. - - - }//end method. - - - public void keyReleased(KeyEvent e) { - int keyCode = (int) e.getKeyCode(); - - if (keyCode == KeyEvent.VK_CONTROL) { - this.controlKeyDown = false; - }//end if. - - - if (keyCode == KeyEvent.VK_DOWN && this.controlKeyDown) { - //System.out.println("down"); - - if (!history.empty() && (!(historyIndex < 1))) { - - - historyIndex--; - //System.out.println(history.get((history.size()-1) - historyIndex)); - - try { - int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); - int lineStartOffset = textPane.getLineStartOffset(lineNumber); - int lineEndOffset = textPane.getLineEndOffset(lineNumber); - - textPane.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex), lineStartOffset, lineEndOffset); - - } catch (BadLocationException ble) { - //Eat exception. - } - - } else if (!history.empty() && historyIndex == 0) { - try { - int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); - int lineStartOffset = textPane.getLineStartOffset(lineNumber); - int lineEndOffset = textPane.getLineEndOffset(lineNumber); - - textPane.replaceRange("In> ", lineStartOffset, lineEndOffset); - - this.historyIndex = -1; - - } catch (BadLocationException ble) { - //Eat exception.; - } - - }//end else. - }//end if. - - }//end method. - - - public void keyTyped(KeyEvent e) { - - char key = e.getKeyChar(); - - //System.out.println((int)key); - - if ((int) key == e.VK_ENTER || (int) key == 13) { //== 10) { - try { - int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); - String line = ""; - //System.out.println("key pressed"); //TODO remove. - - //System.out.println("LN: " + lineNumber + " LSO: " + lineStartOffset + " LEO: " + lineEndOffset ); - if (e.isShiftDown()) { - - captureInputLines(lineNumber); - - clearPreviousResponse(); - - - String code = inputLines.toString().replaceAll(";;", ";").trim(); - - code = code.replaceAll("\\\\", ""); - - //System.out.println(code); - - history.push(code.substring(0, code.length() - 1)); - this.historyIndex = -1; - - if (code.length() > 0) { - interpreter.addResponseListener(this); - interpreter.evaluate("[" + code + "];", true); - haltButton.setEnabled(true); - - }//end if. - } else { - int relativeLineOffset = -1; - int cursorInsert = 0; - String eol = ""; - if (e.isControlDown()) { - relativeLineOffset = 0; - int textAreaLineCount = textPane.getLineCount(); - if (lineNumber + 1 == textAreaLineCount) { - eol = " \\\n"; - cursorInsert = 3; - } - - } - int lineStartOffset = textPane.getLineStartOffset(lineNumber + relativeLineOffset); - int lineEndOffset = textPane.getLineEndOffset(lineNumber + relativeLineOffset); - line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); - if (line.startsWith("In> \n") || line.startsWith("In>\n")) { - textPane.replaceRange("", lineStartOffset, lineEndOffset); - } else if (line.startsWith("In>")) { - textPane.insert(Color.BLACK, eol + "In> ", lineEndOffset); - textPane.setCaretPosition(lineEndOffset + 4 + cursorInsert); - } - - } - - - - //input.delete(0, input.length()); - // typeArea.append(response.getResult()); - - } catch (BadLocationException ex) { - System.out.println(ex.getMessage() + " , " + ex.offsetRequested()); - } - - //typeArea.append(new String(typedKey)); - //typeArea.setCaretPosition( typeArea.getDocument().getLength() ); - /* } else if ((int) key == 22) { - try { - String clipBoard = (String) java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().getData(java.awt.datatransfer.DataFlavor.stringFlavor); - - if (clipBoard.length() != 0) { - char[] chars = clipBoard.toCharArray(); - for (int x = 0; x < chars.length; x++) { - //buffer.put((int) chars[x]); - }//end for. - //setReceiveDataRegisterFull(true); - }//end if. - - } catch (NullPointerException ev) { - ev.printStackTrace(); - } catch (IllegalStateException ev) { - ev.printStackTrace(); - } catch (java.awt.datatransfer.UnsupportedFlavorException ev) { - ev.printStackTrace(); - } catch (java.io.IOException ev) { - ev.printStackTrace(); - }//*/ - } else { - //System.out.println(key); - //registers[0] = (int) key; - if ((int) key == e.VK_BACK_SPACE) { //== 8) { - deleteFlag = true; - } - - input.append(key); - //typeArea.append(Character.toString(key)); - //buffer.put((int) key); - //setReceiveDataRegisterFull(true); - } - }//end method. - - - public void response(EvaluationResponse response) { - - final int caretPosition = responseInsertionOffset; - - int offsetIndex = responseInsertionOffset; - - final int initialOffset = offsetIndex; - - String extraNewline = ""; - if (!encounteredIn) { - - if (noLinesBetweenInAndEndOfTextArea == true) { - extraNewline = "\n";// + result + "\n\nIn> "; - offsetIndex++; - } - - }//end if.*/ - - final int responseOffset = offsetIndex; - String result = "Result: " + response.getResult().trim(); - - - String sideEffects = null; - int sideEffectsOffset = 0; - int sideEffectsLength = 0; - if (!response.getSideEffects().equalsIgnoreCase("")) { - sideEffectsOffset = responseOffset + result.length(); - sideEffects = "\nSide Effects:\n" + response.getSideEffects(); - sideEffectsLength = sideEffects.length(); - } - - - String exception = null; - int exceptionOffset = 0; - int exceptionLength = 0; - if (response.isExceptionThrown()) { - exceptionOffset = responseOffset + result.length() + sideEffectsOffset; - exception = "\nException: " + response.getExceptionMessage(); - exceptionLength = exception.length(); - } - - - - - - final String finalExtraNewline = extraNewline; - final String finalResult = result; - final String finalSideEffects = sideEffects; - final String finalException = exception; - - final int finalSideEffectsOffset = sideEffectsOffset; - final int finalExceptionOffset = exceptionOffset; - final int insertInOffset = responseOffset + result.length() + sideEffectsLength + exceptionLength; - - - - /* if (insertionPointLine == lineCount - 1) { - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - haltButton.setEnabled(false); - textArea.append(Color.BLACK, finalOutput); - } - - - }); - - //textArea.setCaretPosition( textArea.getDocument().getLength() ); - } else {*/ - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - haltButton.setEnabled(false); - - - textPane.insert(Color.BLACK, finalExtraNewline, initialOffset); //finalExtraNewline - - textPane.insert(Color.BLUE, finalResult, responseOffset); - - if (finalSideEffects != null) { - textPane.insert(green, finalSideEffects, finalSideEffectsOffset); - } - - if (finalException != null) { - textPane.insert(Color.RED, finalException, finalExceptionOffset); - } - - - if (!encounteredIn) { - - textPane.insert(Color.BLACK, "\n\nIn> ", insertInOffset); - - } else { - textPane.setCaretPosition(caretPosition - 1); - } - - - }//end method. - - - }); - - //}//end if/else. - - }//end method. - - - public boolean remove() { - return true; - } - - - private void clearPreviousResponse() { - - try { - int lineNumber = textPane.getLineOfOffset(responseInsertionOffset - 1); - - if (responseInsertionOffset == -1 || lineNumber == textPane.getLineCount()) { - encounteredIn = false; - return; - } - - String line = ""; - int lineStartOffset = 0; - int lineEndOffset = 0; - - do { - - lineNumber++; - lineStartOffset = textPane.getLineStartOffset(lineNumber); - lineEndOffset = textPane.getLineEndOffset(lineNumber); - line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); - - } while (!line.startsWith("In>") && lineNumber < textPane.getLineCount()); - - textPane.replaceRange("\n\n\n", responseInsertionOffset - 1, lineStartOffset); - encounteredIn = line.startsWith("In>"); - return; - - } catch (BadLocationException ex) { - encounteredIn = false; - textPane.replaceRange("\n\n\n", responseInsertionOffset, textPane.getDocument().getLength()); - return; - } - }//end method. - - - private void captureInputLines(int lineNumber) { - - inputLines.delete(0, inputLines.length()); - - try { - int lineStartOffset = textPane.getLineStartOffset(lineNumber); - int lineEndOffset = textPane.getLineEndOffset(lineNumber); - String line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); - - if (line.startsWith("In>")) { - //Scan backwards to first line that does not start with In>. - do { - lineStartOffset = textPane.getLineStartOffset(lineNumber); - lineEndOffset = textPane.getLineEndOffset(lineNumber); - line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); - lineNumber--; - - } while (line.startsWith("In>") && lineNumber != -1);//end do/while. - - if (lineNumber != -1) { - lineNumber++; - } - - - //Scan forwards to first line that does not start with In>. - boolean pastInputLines = false; - noLinesBetweenInAndEndOfTextArea = false; - do { - lineNumber++; - lineStartOffset = textPane.getLineStartOffset(lineNumber); - lineEndOffset = textPane.getLineEndOffset(lineNumber); - line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); - if (line.startsWith("In>")) { - String eol = new String(line); - inputLines.append(line.substring(3, line.length()).trim()); - responseInsertionOffset = lineEndOffset; - if (!eol.endsWith(";") && !eol.endsWith("\\\n")) { - inputLines.append(";"); - }//end if. - } else { - pastInputLines = true; - } - - - } while (!pastInputLines && lineNumber < textPane.getLineCount());//end while. - - }//end if. - - } catch (BadLocationException ex) { - noLinesBetweenInAndEndOfTextArea = true; - } - - - }//end method. - - - public void setHaltButtonEnabledState(boolean state) { - this.haltButton.setEnabled(state); - - }//end method. - - - public class ColorPane extends JTextPane { - - public void append(Color c, String s) { // better implementation--uses - // StyleContext - StyleContext sc = StyleContext.getDefaultStyleContext(); - AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, - StyleConstants.Foreground, c); - - int len = getDocument().getLength(); // same value as - // getText().length(); - setCaretPosition(len); // place caret at the end (with no selection) - setCharacterAttributes(aset, false); - replaceSelection(s); // there is no selection, so inserts at caret - }//end method. - - - public void insert(Color c, String str, int pos) { - - Font font = getFont(); - - MutableAttributeSet attrs = getInputAttributes(); - - - StyleConstants.setFontFamily(attrs, font.getFamily()); - StyleConstants.setFontSize(attrs, fontSize); - StyleConstants.setForeground(attrs, c); - - //StyleContext sc = StyleContext.getDefaultStyleContext(); - //MutableAttributeSet aset = this.getInputAttributes(); - //AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c); - setCaretPosition(pos); // place caret at the end (with no selection) - setCharacterAttributes(attrs, false); - replaceSelection(str); - - - - } - - - /** - * Translates an offset into the components text to a - * line number. - * - * @param offset the offset >= 0 - * @return the line number >= 0 - * @exception BadLocationException thrown if the offset is - * less than zero or greater than the document length. - */ - public int getLineOfOffset(int offset) throws BadLocationException { - Document doc = getDocument(); - if (offset < 0) { - throw new BadLocationException("Can't translate offset to line", -1); - } else if (offset > doc.getLength()) { - throw new BadLocationException("Can't translate offset to line", doc.getLength() + 1); - } else { - Element map = getDocument().getDefaultRootElement(); - return map.getElementIndex(offset); - } - } - - - /** - * Determines the number of lines contained in the area. - * - * @return the number of lines > 0 - */ - public int getLineCount() { - Element map = getDocument().getDefaultRootElement(); - return map.getElementCount(); - } - - - /** - * Determines the offset of the start of the given line. - * - * @param line the line number to translate >= 0 - * @return the offset >= 0 - * @exception BadLocationException thrown if the line is - * less than zero or greater or equal to the number of - * lines contained in the document (as reported by - * getLineCount). - */ - public int getLineStartOffset(int line) throws BadLocationException { - int lineCount = getLineCount(); - if (line < 0) { - throw new BadLocationException("Negative line", -1); - } else if (line >= lineCount) { - throw new BadLocationException("No such line", getDocument().getLength() + 1); - } else { - Element map = getDocument().getDefaultRootElement(); - Element lineElem = map.getElement(line); - return lineElem.getStartOffset(); - } - } - - - /** - * Determines the offset of the end of the given line. - * - * @param line the line >= 0 - * @return the offset >= 0 - * @exception BadLocationException Thrown if the line is - * less than zero or greater or equal to the number of - * lines contained in the document (as reported by - * getLineCount). - */ - public int getLineEndOffset(int line) throws BadLocationException { - int lineCount = getLineCount(); - if (line < 0) { - throw new BadLocationException("Negative line", -1); - } else if (line >= lineCount) { - throw new BadLocationException("No such line", getDocument().getLength() + 1); - } else { - Element map = getDocument().getDefaultRootElement(); - Element lineElem = map.getElement(line); - int endOffset = lineElem.getEndOffset(); - // hide the implicit break at the end of the document - return ((line == lineCount - 1) ? (endOffset - 1) : endOffset); - } - } - - - /** - * Replaces text from the indicated start to end position with the - * new text specified. Does nothing if the model is null. Simply - * does a delete if the new string is null or empty. - *

    - * This method is thread safe, although most Swing methods - * are not. - * - * @param str the text to use as the replacement - * @param start the start position >= 0 - * @param end the end position >= start - * @exception IllegalArgumentException if part of the range is an - * invalid position in the model - * @see #insert - * @see #replaceRange - */ - public void replaceRange(String str, int start, int end) { - if (end < start) { - throw new IllegalArgumentException("end before start"); - } - - - Font font = getFont(); - - MutableAttributeSet attrs = getInputAttributes(); - - - StyleConstants.setFontFamily(attrs, font.getFamily()); - StyleConstants.setFontSize(attrs, fontSize); - - - setCharacterAttributes(attrs, false); - this.select(start, end); - replaceSelection(str); - - }//end method. - - - }//end class - - - public void setJTextPaneFont(JTextPane textPane, int fontSize) { - - Font font = textPane.getFont(); - - MutableAttributeSet attrs = textPane.getInputAttributes(); - - StyleConstants.setFontFamily(attrs, font.getFamily()); - StyleConstants.setFontSize(attrs, fontSize); - - StyledDocument doc = textPane.getStyledDocument(); - - - doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, false); - }//end method. - - - - public static class PopupTriggerMouseListener extends MouseAdapter { - - private JPopupMenu popup; - private JComponent component; - - - public PopupTriggerMouseListener(JPopupMenu popup, JComponent component) { - this.popup = popup; - this.component = component; - } - - //some systems trigger popup on mouse press, others on mouse release, we want to cater for both - - private void showMenuIfPopupTrigger(MouseEvent e) { - if (e.isPopupTrigger()) { - popup.show(component, e.getX() + 3, e.getY() + 3); - } - } - - //according to the javadocs on isPopupTrigger, checking for popup trigger on mousePressed and mouseReleased - //should be all that is required - //public void mouseClicked(MouseEvent e) - - - public void mousePressed(MouseEvent e) { - showMenuIfPopupTrigger(e); - } - - - public void mouseReleased(MouseEvent e) { - showMenuIfPopupTrigger(e); - } - - - }//end method. - - - private void addPopupMenu() { - final JPopupMenu menu = new JPopupMenu(); - final JMenuItem copyItem = new JMenuItem(); - copyItem.setAction(textPane.getActionMap().get(DefaultEditorKit.copyAction)); - copyItem.setText("Copy"); - - final JMenuItem cutItem = new JMenuItem(); - cutItem.setAction(textPane.getActionMap().get(DefaultEditorKit.cutAction)); - cutItem.setText("Cut"); - - final JMenuItem pasteItem = new JMenuItem("Paste"); - pasteItem.setAction(textPane.getActionMap().get(DefaultEditorKit.pasteAction)); - pasteItem.setText("Paste"); - - final JMenuItem selectAllItem = new JMenuItem("Select All"); - selectAllItem.setAction(textPane.getActionMap().get(DefaultEditorKit.selectAllAction)); - selectAllItem.setText("Select All"); - - final JMenuItem insertPrompt = new JMenuItem("Insert In>"); - insertPrompt.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e) - { - textPane.insert(Color.BLACK, "In> ", textPane.getCaretPosition()); - } - }); - insertPrompt.setText("Insert In>"); - - menu.add(copyItem); - menu.add(cutItem); - menu.add(pasteItem); - menu.add(new JSeparator()); - menu.add(selectAllItem); - menu.add(new JSeparator()); - menu.add(insertPrompt); - - - textPane.add(menu); - textPane.addMouseListener(new PopupTriggerMouseListener(menu, textPane)); - }//end method. - - - public static void main(String[] args) { - ColorConsole console = new ColorConsole(); - - JFrame frame = new javax.swing.JFrame(); - Container contentPane = frame.getContentPane(); - contentPane.add(console, BorderLayout.CENTER); - //frame.setAlwaysOnTop(true); - frame.setSize(new Dimension(700, 600)); - frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE); - //frame.setResizable(false); - frame.setPreferredSize(new Dimension(700, 600)); - frame.setLocationRelativeTo(null); // added - frame.pack(); - frame.setVisible(true); - }//end main. -}//end class. - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/Console.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/Console.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/Console.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/Console.java 2010-04-21 05:05:28.000000000 +0000 @@ -16,7 +16,6 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.ui.gui.consoles; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; @@ -28,42 +27,67 @@ import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.Stack; +import javax.swing.text.Element; +import javax.swing.text.AttributeSet; import javax.swing.Box; import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; +import javax.swing.JComponent; import javax.swing.JFrame; +import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButton; import javax.swing.JScrollPane; +import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTextArea; +import javax.swing.JTextPane; import javax.swing.SwingUtilities; import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Document; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.StyledDocument; import org.mathpiper.interpreters.EvaluationResponse; import org.mathpiper.interpreters.Interpreter; import org.mathpiper.interpreters.Interpreters; import org.mathpiper.interpreters.ResponseListener; import org.mathpiper.io.MathPiperOutputStream; import org.mathpiper.lisp.Environment; - +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.SublistCons; public class Console extends javax.swing.JPanel implements ActionListener, KeyListener, ResponseListener, ItemListener, MathPiperOutputStream { + private boolean suppressOutput = false; + private final Color green = new Color(0, 130, 0); + private final Color purple = new Color(153, 0, 153); private Interpreter interpreter = Interpreters.getAsynchronousInterpreter(); private StringBuilder input = new StringBuilder(); private JButton haltButton, clearConsoleButton, clearRawButton, helpButton, button2, button3; private JCheckBox rawOutputCheckBox; private JCheckBox showRawOutputCheckBox; private JTextArea rawOutputTextArea; - private JTextArea textArea; + private ColorPane textPane; private MathPiperOutputStream currentOutput; private JScrollPane typePane; private char[] typedKey = new char[1]; - private JPanel buttons; + private JPanel consoleButtons; + private JPanel rawButtons; private boolean deleteFlag = false; - private float fontSize = 12; + private int fontSize = 12; private Font bitstreamVera; private StringBuilder inputLines; private int responseInsertionOffset = -1; @@ -71,23 +95,27 @@ private boolean noLinesBetweenInAndEndOfTextArea = false; private JSplitPane splitPane; private int splitPaneDividerLocation = 400; - private JScrollPane rawOutputCheckBoxScrollPane; + private JScrollPane rawOutputScrollPane; + private JPanel rawOutputPanel; + private JPopupMenu Pmenu; private Stack history = new java.util.Stack(); private boolean controlKeyDown = false; private int historyIndex = -1; + private int caretPositionWhenEnterWasPressed = -1; + private JRadioButton numericModeButton; + private JRadioButton symbolicModeButton; + private ButtonGroup resultModeGroup; + private boolean numericResultMode = false; + private String helpMessage = - "Press after an expression to create an additional input line and to append a hidden ;.\n\n" + - "Press after any input line in a group of input lines to execute them all.\n\n" + - "Type In> on the left edge of any line to create your own input prompt.\n\n" + - "Press after an empty In> to erase the In>.\n" + - "Any line in a group that ends with a \\ will not have a ; appended to it.\n\n" + - "Pressing at the end of a line automatically appends a \\ to the line.\n\n" + + "Enter an expression after any In> prompt and press or to evaluate it.\n\n" + + "Type In> on the left end of any line to create your own input prompt.\n\n" + "Use and to navigate through the command line history.\n\n" + "The console window is an editable text area, so you can add text to it and remove text from \n" + "it as needed.\n\n" + + "Placing ;; after the end of the line of input will suppress the output.\n\n" + "The Raw Output checkbox sends all side effects output to the raw output text area."; - public Console() { inputLines = new StringBuilder(); @@ -97,84 +125,115 @@ //keySendQueue = new java.util.concurrent.ArrayBlockingQueue(30); - buttons = new JPanel(); - buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS)); + consoleButtons = new JPanel(); + consoleButtons.setLayout(new BoxLayout(consoleButtons, BoxLayout.X_AXIS)); + + + rawOutputPanel = new JPanel(); + rawOutputPanel.setLayout(new BorderLayout()); + rawButtons = new JPanel(); + rawButtons.setLayout(new BoxLayout(rawButtons, BoxLayout.X_AXIS)); - Box guiBox = new Box(BoxLayout.Y_AXIS); - textArea = new JTextArea(30, 20); - textArea.append("MathPiper version " + org.mathpiper.Version.version + ".\n"); - textArea.append("Enter an expression after any In> prompt and press to evaluate it.\n"); + //textArea = new JTextArea(30, 20); + textPane = new ColorPane(); - textArea.append("\nIn> "); - textArea.setCaretPosition(textArea.getDocument().getLength()); + textPane.append(purple, "MathPiper version " + org.mathpiper.Version.version + ".\n"); + textPane.append(purple, "Enter an expression after any In> prompt and press or to evaluate it.\n"); - //java.io.InputStream inputStream = org.gjt.sp.jedit.jEdit.getPlugin("org.mathrider.u6502plugin.U6502Plugin").getPluginJAR().getClassLoader().getResourceAsStream( "resources/ttf-bitstream-vera-1.10/VeraMono.ttf" ); + + textPane.append(Color.BLACK, "\nIn> "); + textPane.setCaretPosition(textPane.getDocument().getLength()); + + //java.io.InputStream inputStream = org.gjt.sp.jedit.jEdit.getPlugin("org.mathpiper.ide.u6502plugin.U6502Plugin").getPluginJAR().getClassLoader().getResourceAsStream( "resources/ttf-bitstream-vera-1.10/VeraMono.ttf" ); //bitstreamVera = Font.createFont (Font.TRUETYPE_FONT, inputStream); //bitstreamVera = bitstreamVera.deriveFont(fontSize); //typeArea.setFont(bitstreamVera); - textArea.addKeyListener(this); - typePane = new JScrollPane(textArea); + textPane.addKeyListener(this); + typePane = new JScrollPane(textPane); //guiBox.add(typePane); - Box ioBox = new Box(BoxLayout.Y_AXIS); + haltButton = new JButton("Halt Calculation"); haltButton.setEnabled(false); haltButton.setForeground(Color.RED); haltButton.addActionListener(this); - buttons.add(haltButton); + consoleButtons.add(haltButton); - /*button2 = new JButton("Font--"); +/* + numericModeButton = new JRadioButton("Numeric Mode"); + numericModeButton.addItemListener(this); + symbolicModeButton = new JRadioButton("Symbolic Mode"); + symbolicModeButton.addItemListener(this); + if(numericResultMode) + { + numericModeButton.setSelected(true); + } + else + { + symbolicModeButton.setSelected(true); + } + resultModeGroup = new ButtonGroup(); + resultModeGroup.add(numericModeButton); + resultModeGroup.add(symbolicModeButton); + consoleButtons.add(numericModeButton); + consoleButtons.add(symbolicModeButton); +*/ + + button2 = new JButton("Font-"); button2.addActionListener(this); - buttons.add(button2); - button3 = new JButton("Font++"); + consoleButtons.add(button2); + button3 = new JButton("Font+"); button3.addActionListener(this); - buttons.add(button3);*/ + consoleButtons.add(button3); - rawOutputCheckBox = new JCheckBox("Raw Output"); + rawOutputCheckBox = new JCheckBox("Raw Side Effects"); rawOutputCheckBox.addItemListener(this); - buttons.add(rawOutputCheckBox); + rawButtons.add(rawOutputCheckBox); this.rawOutputTextArea = new JTextArea(); rawOutputTextArea.setEditable(false); rawOutputTextArea.setText("Raw output text area.\n\n"); - showRawOutputCheckBox = new JCheckBox("Show Raw Output"); + showRawOutputCheckBox = new JCheckBox("Show Raw"); showRawOutputCheckBox.addItemListener(this); - buttons.add(showRawOutputCheckBox); + consoleButtons.add(showRawOutputCheckBox); - buttons.add(Box.createGlue()); + consoleButtons.add(Box.createGlue()); clearConsoleButton = new JButton("Clear"); clearConsoleButton.addActionListener(this); - buttons.add(clearConsoleButton); + consoleButtons.add(clearConsoleButton); clearRawButton = new JButton("Clear Raw"); clearRawButton.addActionListener(this); - buttons.add(clearRawButton); + rawButtons.add(clearRawButton); helpButton = new JButton("Help"); helpButton.addActionListener(this); - buttons.add(helpButton); + consoleButtons.add(helpButton); - ioBox.add(buttons); + this.add(consoleButtons, BorderLayout.NORTH); - this.add(ioBox, BorderLayout.NORTH); + this.rawOutputPanel.add(rawButtons, BorderLayout.NORTH); //this.add(guiBox, BorderLayout.CENTER); - rawOutputCheckBoxScrollPane = new JScrollPane(rawOutputTextArea); + rawOutputScrollPane = new JScrollPane(rawOutputTextArea); + rawOutputPanel.add(rawOutputScrollPane); + + splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, typePane, null); splitPane.setOneTouchExpandable(true); splitPane.setDividerLocation(splitPaneDividerLocation); @@ -182,15 +241,11 @@ this.add(splitPane); - }//Constructor. + this.addPopupMenu(); - public void setFontSize(float fontSize) { - this.fontSize = fontSize; - //bitstreamVera = bitstreamVera.deriveFont(fontSize); - //typeArea.setFont(bitstreamVera); - }//end method. + }//Constructor. public void actionPerformed(ActionEvent event) { Object src = event.getSource(); @@ -199,24 +254,26 @@ interpreter.haltEvaluation(); } else if (src == button2) { this.fontSize -= 2; + //bitstreamVera = bitstreamVera.deriveFont(fontSize); //typeArea.setFont(bitstreamVera); + this.setJTextPaneFont(textPane, fontSize); } else if (src == button3) { this.fontSize += 2; //bitstreamVera = bitstreamVera.deriveFont(fontSize); //typeArea.setFont(bitstreamVera); + this.setJTextPaneFont(textPane, fontSize); } else if (src == helpButton) { JOptionPane.showMessageDialog(this, this.helpMessage); } else if (src == clearConsoleButton) { - this.textArea.setText(""); - this.textArea.append("In> "); + this.textPane.setText(""); + this.textPane.append(Color.BLACK, "In> "); } else if (src == clearRawButton) { this.rawOutputTextArea.setText(""); } }//end method. - public void itemStateChanged(ItemEvent ie) { Object source = ie.getSource(); @@ -231,16 +288,28 @@ }//end if/else. } else if (source == showRawOutputCheckBox) { if (ie.getStateChange() == ItemEvent.SELECTED) { - splitPane.add(rawOutputCheckBoxScrollPane); + splitPane.add(rawOutputPanel); splitPane.setDividerLocation(splitPaneDividerLocation); splitPane.revalidate(); } else { splitPane.remove(2); splitPane.revalidate(); }//end if/else. - } - }//end method. + } else if (source == numericModeButton) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + this.numericResultMode = true; + } else { + this.numericResultMode = false; + }//end if/else. + } else if (source == symbolicModeButton) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + this.numericResultMode = false; + } else { + this.numericResultMode = true; + }//end if/else. + }//end if/else. + }//end method. public void putChar(char aChar) throws Exception { if (rawOutputTextArea != null && currentOutput != null) { @@ -250,7 +319,6 @@ }//end if. }//end method. - public void write(String aString) throws Exception { int i; for (i = 0; i < aString.length(); i++) { @@ -258,7 +326,6 @@ } }//end method. - public void keyPressed(KeyEvent e) { int keyCode = (int) e.getKeyCode(); @@ -277,11 +344,11 @@ //System.out.println(history.get((history.size()-1) - historyIndex)); try { - int lineNumber = textArea.getLineOfOffset(textArea.getCaretPosition()); - int lineStartOffset = textArea.getLineStartOffset(lineNumber); - int lineEndOffset = textArea.getLineEndOffset(lineNumber); + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); - textArea.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex), lineStartOffset, lineEndOffset); + textPane.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex), lineStartOffset, lineEndOffset); } catch (BadLocationException ble) { //Eat exception. @@ -295,7 +362,6 @@ }//end method. - public void keyReleased(KeyEvent e) { int keyCode = (int) e.getKeyCode(); @@ -314,11 +380,11 @@ //System.out.println(history.get((history.size()-1) - historyIndex)); try { - int lineNumber = textArea.getLineOfOffset(textArea.getCaretPosition()); - int lineStartOffset = textArea.getLineStartOffset(lineNumber); - int lineEndOffset = textArea.getLineEndOffset(lineNumber); + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); - textArea.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex), lineStartOffset, lineEndOffset); + textPane.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex), lineStartOffset, lineEndOffset); } catch (BadLocationException ble) { //Eat exception. @@ -326,11 +392,11 @@ } else if (!history.empty() && historyIndex == 0) { try { - int lineNumber = textArea.getLineOfOffset(textArea.getCaretPosition()); - int lineStartOffset = textArea.getLineStartOffset(lineNumber); - int lineEndOffset = textArea.getLineEndOffset(lineNumber); + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); - textArea.replaceRange("In> ", lineStartOffset, lineEndOffset); + textPane.replaceRange("In> ", lineStartOffset, lineEndOffset); this.historyIndex = -1; @@ -343,32 +409,58 @@ }//end method. - public void keyTyped(KeyEvent e) { char key = e.getKeyChar(); //System.out.println((int)key); - if ((int) key == 10) { + if ((int) key == e.VK_ENTER || (int) key == 13) { //== 10) { try { - int lineNumber = textArea.getLineOfOffset(textArea.getCaretPosition()); - String line = ""; + //System.out.println("key pressed"); //TODO remove. //System.out.println("LN: " + lineNumber + " LSO: " + lineStartOffset + " LEO: " + lineEndOffset ); - if (e.isShiftDown()) { + if (!e.isShiftDown()) { + textPane.replaceRange("", textPane.getCaretPosition() - 1, textPane.getCaretPosition()); + }//end if. + + caretPositionWhenEnterWasPressed = textPane.getCaretPosition(); + + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + //lineNumber--; + String line = ""; + + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + + int lineEndOffset = textPane.getLineEndOffset(lineNumber); + + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); + + if (line.startsWith("In> \n") || line.startsWith("In>\n")) { + //textPane.replaceRange("In> \n", lineStartOffset, lineEndOffset); //Just leave the In> there. + //textPane.setCaretPosition(lineEndOffset- 1); + } else if (line.startsWith("In>")) { captureInputLines(lineNumber); clearPreviousResponse(); - String code = inputLines.toString().replaceAll(";;", ";").trim(); + String code = inputLines.toString().trim(); + + // System.out.println("1: " + code); + + if (code.endsWith(";;")) { + this.suppressOutput = true; + } - code = code.replaceAll("\\\\", ""); + code = code.replaceAll(";;;", ";"); + code = code.replaceAll(";;", ";"); - //System.out.println(code); + //code = code.replaceAll("\\\\", ""); + + //System.out.println("2: " + code); history.push(code.substring(0, code.length() - 1)); this.historyIndex = -1; @@ -379,29 +471,10 @@ haltButton.setEnabled(true); }//end if. - } else { - int relativeLineOffset = -1; - int cursorInsert = 0; - String eol = ""; - if (e.isControlDown()) { - relativeLineOffset = 0; - int textAreaLineCount = textArea.getLineCount(); - if (lineNumber + 1 == textAreaLineCount) { - eol = " \\\n"; - cursorInsert = 3; - } - } - int lineStartOffset = textArea.getLineStartOffset(lineNumber + relativeLineOffset); - int lineEndOffset = textArea.getLineEndOffset(lineNumber + relativeLineOffset); - line = textArea.getText(lineStartOffset, lineEndOffset - lineStartOffset); - if (line.startsWith("In> \n") || line.startsWith("In>\n")) { - textArea.replaceRange("", lineStartOffset, lineEndOffset); - } else if (line.startsWith("In>")) { - textArea.insert(eol + "In> ", lineEndOffset); - textArea.setCaretPosition(lineEndOffset + 4 + cursorInsert); - } + } else { + textPane.insert(Color.BLACK, "\n", caretPositionWhenEnterWasPressed); } @@ -415,31 +488,31 @@ //typeArea.append(new String(typedKey)); //typeArea.setCaretPosition( typeArea.getDocument().getLength() ); - } else if ((int) key == 22) { + /* } else if ((int) key == 22) { try { - String clipBoard = (String) java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().getData(java.awt.datatransfer.DataFlavor.stringFlavor); + String clipBoard = (String) java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().getData(java.awt.datatransfer.DataFlavor.stringFlavor); - if (clipBoard.length() != 0) { - char[] chars = clipBoard.toCharArray(); - for (int x = 0; x < chars.length; x++) { - //buffer.put((int) chars[x]); - }//end for. - //setReceiveDataRegisterFull(true); - }//end if. + if (clipBoard.length() != 0) { + char[] chars = clipBoard.toCharArray(); + for (int x = 0; x < chars.length; x++) { + //buffer.put((int) chars[x]); + }//end for. + //setReceiveDataRegisterFull(true); + }//end if. } catch (NullPointerException ev) { - ev.printStackTrace(); + ev.printStackTrace(); } catch (IllegalStateException ev) { - ev.printStackTrace(); + ev.printStackTrace(); } catch (java.awt.datatransfer.UnsupportedFlavorException ev) { - ev.printStackTrace(); + ev.printStackTrace(); } catch (java.io.IOException ev) { - ev.printStackTrace(); - } + ev.printStackTrace(); + }//*/ } else { //System.out.println(key); //registers[0] = (int) key; - if ((int) key == 8) { + if ((int) key == e.VK_BACK_SPACE) { //== 8) { deleteFlag = true; } @@ -450,121 +523,198 @@ } }//end method. + public void response(EvaluationResponse response) + { +/* + if(this.numericResultMode) + { + try{ + Interpreter syncronousInterpreter = Interpreters.getSynchronousInterpreter(); - public void response(EvaluationResponse response) { + Cons atomCons = AtomCons.getInstance(syncronousInterpreter.getEnvironment(), -1, "N"); - String output = "Result: " + response.getResult().trim(); + atomCons.cdr().setCons(response.getResultList().getCons()); + Cons subListCons = SublistCons.getInstance(syncronousInterpreter.getEnvironment(), atomCons); + + ConsPointer inputExpressionPointer = new ConsPointer(subListCons); + + response = syncronousInterpreter.evaluate(inputExpressionPointer); + } + catch(Exception e) + { + e.printStackTrace(); + } + }//end if. +*/ + + + + //final int caretPosition = responseInsertionOffset; + + int offsetIndex = responseInsertionOffset; + + final int initialOffset = offsetIndex; + + String extraNewline = ""; + if (!encounteredIn) { + + if (noLinesBetweenInAndEndOfTextArea == true) { + extraNewline = "\n";// + result + "\n\nIn> "; + offsetIndex++; + } + + }//end if.*/ + + final int responseOffset = offsetIndex; + String result; + if (this.suppressOutput == false) { + result = "Result: " + response.getResult().trim(); + } else { + result = "Result: " + "OUTPUT SUPPRESSED"; + + this.suppressOutput = false; + } + + + String sideEffects = null; + int sideEffectsOffset = 0; + int sideEffectsLength = 0; if (!response.getSideEffects().equalsIgnoreCase("")) { - output += "\nSide Effects:\n" + response.getSideEffects(); + sideEffectsOffset = responseOffset + result.length(); + sideEffects = "\nSide Effects:\n" + response.getSideEffects(); + sideEffectsLength = sideEffects.length(); } + + String exception = null; + int exceptionOffset = 0; + int exceptionLength = 0; if (response.isExceptionThrown()) { - output += "\nException: " + response.getExceptionMessage(); + exceptionOffset = responseOffset + result.length() + sideEffectsOffset; + exception = "\nException: " + response.getExceptionMessage(); + exceptionLength = exception.length(); } - //try { - //int insertionPointLine = textArea.getLineOfOffset(responseInsertionOffset); - //int lineCount = textArea.getLineCount(); - if (!encounteredIn) { - if (noLinesBetweenInAndEndOfTextArea == true) { - output = "\n" + output + "\n\nIn> "; - } else { - output = output + "\n\nIn> "; - }//end if/else. + final String finalExtraNewline = extraNewline; + final String finalResult = result; + final String finalSideEffects = sideEffects; + final String finalException = exception; - }//end if. + final int finalSideEffectsOffset = sideEffectsOffset; + final int finalExceptionOffset = exceptionOffset; + final int insertInOffset = responseOffset + result.length() + sideEffectsLength + exceptionLength; + final int finalCaretPositionWhenEnterWasPressed = caretPositionWhenEnterWasPressed; - final String finalOutput = output; - /*if (insertionPointLine == lineCount - 1) { - SwingUtilities.invokeLater(new Runnable() { + /* if (insertionPointLine == lineCount - 1) { + SwingUtilities.invokeLater(new Runnable() { - public void run() { - haltButton.setEnabled(false); - textArea.append(finalOutput); - } + public void run() { + haltButton.setEnabled(false); + textArea.append(Color.BLACK, finalOutput); + } - }); + }); - //textArea.setCaretPosition( textArea.getDocument().getLength() ); - } else {*/ - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - haltButton.setEnabled(false); - textArea.insert(finalOutput, responseInsertionOffset); - } + //textArea.setCaretPosition( textArea.getDocument().getLength() ); + } else {*/ + SwingUtilities.invokeLater(new Runnable() { + public void run() { + haltButton.setEnabled(false); - }); - // }//end if/else. - //} catch (BadLocationException ex) { - // System.out.println(ex); - //} - }//end method. + textPane.insert(Color.BLACK, finalExtraNewline, initialOffset); //finalExtraNewline + + textPane.insert(Color.BLUE, finalResult, responseOffset); + + if (finalSideEffects != null) { + textPane.insert(green, finalSideEffects, finalSideEffectsOffset); + } + + if (finalException != null) { + textPane.insert(Color.RED, finalException, finalExceptionOffset); + } + + + if (!encounteredIn) { + + textPane.insert(Color.BLACK, "\n\nIn> ", insertInOffset); + + } else { + //textPane.setCaretPosition(caretPosition - 1); + textPane.setCaretPosition(finalCaretPositionWhenEnterWasPressed); + + } + + }//end method. + }); + + //}//end if/else. + + }//end method. public boolean remove() { return true; } - private void clearPreviousResponse() { try { - int lineNumber = textArea.getLineOfOffset(responseInsertionOffset); + int lineNumber = textPane.getLineOfOffset(responseInsertionOffset - 1); - if (responseInsertionOffset == -1 || lineNumber == textArea.getLineCount()) { + if (responseInsertionOffset == -1 || lineNumber == textPane.getLineCount()) { encounteredIn = false; return; } String line = ""; int lineStartOffset = 0; + int lineEndOffset = 0; do { lineNumber++; - lineStartOffset = textArea.getLineStartOffset(lineNumber); - int lineEndOffset = textArea.getLineEndOffset(lineNumber); - line = textArea.getText(lineStartOffset, lineEndOffset - lineStartOffset); + lineStartOffset = textPane.getLineStartOffset(lineNumber); + lineEndOffset = textPane.getLineEndOffset(lineNumber); + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); - } while (!line.startsWith("In>") && lineNumber < textArea.getLineCount()); + } while (!line.startsWith("In>") && lineNumber < textPane.getLineCount()); - textArea.replaceRange("\n\n", responseInsertionOffset, lineStartOffset); + textPane.replaceRange("\n\n\n", responseInsertionOffset - 1, lineStartOffset); encounteredIn = line.startsWith("In>"); return; } catch (BadLocationException ex) { encounteredIn = false; + textPane.replaceRange("\n\n\n", responseInsertionOffset, textPane.getDocument().getLength()); return; } }//end method. - private void captureInputLines(int lineNumber) { inputLines.delete(0, inputLines.length()); try { - int lineStartOffset = textArea.getLineStartOffset(lineNumber); - int lineEndOffset = textArea.getLineEndOffset(lineNumber); - String line = textArea.getText(lineStartOffset, lineEndOffset - lineStartOffset); + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); + String line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); if (line.startsWith("In>")) { //Scan backwards to first line that does not start with In>. do { - lineStartOffset = textArea.getLineStartOffset(lineNumber); - lineEndOffset = textArea.getLineEndOffset(lineNumber); - line = textArea.getText(lineStartOffset, lineEndOffset - lineStartOffset); + lineStartOffset = textPane.getLineStartOffset(lineNumber); + lineEndOffset = textPane.getLineEndOffset(lineNumber); + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); lineNumber--; } while (line.startsWith("In>") && lineNumber != -1);//end do/while. @@ -579,9 +729,9 @@ noLinesBetweenInAndEndOfTextArea = false; do { lineNumber++; - lineStartOffset = textArea.getLineStartOffset(lineNumber); - lineEndOffset = textArea.getLineEndOffset(lineNumber); - line = textArea.getText(lineStartOffset, lineEndOffset - lineStartOffset); + lineStartOffset = textPane.getLineStartOffset(lineNumber); + lineEndOffset = textPane.getLineEndOffset(lineNumber); + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset).trim(); if (line.startsWith("In>")) { String eol = new String(line); inputLines.append(line.substring(3, line.length()).trim()); @@ -594,7 +744,7 @@ } - } while (!pastInputLines && lineNumber < textArea.getLineCount());//end while. + } while (!pastInputLines && lineNumber < textPane.getLineCount());//end while. }//end if. @@ -605,14 +755,248 @@ }//end method. - public void setHaltButtonEnabledState(boolean state) { this.haltButton.setEnabled(state); + }//end method. + + public class ColorPane extends JTextPane { + + public void append(Color c, String s) { // better implementation--uses + // StyleContext + StyleContext sc = StyleContext.getDefaultStyleContext(); + AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, + StyleConstants.Foreground, c); + + int len = getDocument().getLength(); // same value as + // getText().length(); + setCaretPosition(len); // place caret at the end (with no selection) + setCharacterAttributes(aset, false); + replaceSelection(s); // there is no selection, so inserts at caret + }//end method. + + public void insert(Color c, String str, int pos) { + + Font font = getFont(); + + MutableAttributeSet attrs = getInputAttributes(); + + + StyleConstants.setFontFamily(attrs, font.getFamily()); + StyleConstants.setFontSize(attrs, fontSize); + StyleConstants.setForeground(attrs, c); + + //StyleContext sc = StyleContext.getDefaultStyleContext(); + //MutableAttributeSet aset = this.getInputAttributes(); + //AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c); + setCaretPosition(pos); // place caret at the end (with no selection) + setCharacterAttributes(attrs, false); + replaceSelection(str); + + + + } + + /** + * Translates an offset into the components text to a + * line number. + * + * @param offset the offset >= 0 + * @return the line number >= 0 + * @exception BadLocationException thrown if the offset is + * less than zero or greater than the document length. + */ + public int getLineOfOffset(int offset) throws BadLocationException { + Document doc = getDocument(); + if (offset < 0) { + throw new BadLocationException("Can't translate offset to line", -1); + } else if (offset > doc.getLength()) { + throw new BadLocationException("Can't translate offset to line", doc.getLength() + 1); + } else { + Element map = getDocument().getDefaultRootElement(); + return map.getElementIndex(offset); + } + } + + /** + * Determines the number of lines contained in the area. + * + * @return the number of lines > 0 + */ + public int getLineCount() { + Element map = getDocument().getDefaultRootElement(); + return map.getElementCount(); + } + + /** + * Determines the offset of the start of the given line. + * + * @param line the line number to translate >= 0 + * @return the offset >= 0 + * @exception BadLocationException thrown if the line is + * less than zero or greater or equal to the number of + * lines contained in the document (as reported by + * getLineCount). + */ + public int getLineStartOffset(int line) throws BadLocationException { + int lineCount = getLineCount(); + if (line < 0) { + throw new BadLocationException("Negative line", -1); + } else if (line >= lineCount) { + throw new BadLocationException("No such line", getDocument().getLength() + 1); + } else { + Element map = getDocument().getDefaultRootElement(); + Element lineElem = map.getElement(line); + return lineElem.getStartOffset(); + } + } + + /** + * Determines the offset of the end of the given line. + * + * @param line the line >= 0 + * @return the offset >= 0 + * @exception BadLocationException Thrown if the line is + * less than zero or greater or equal to the number of + * lines contained in the document (as reported by + * getLineCount). + */ + public int getLineEndOffset(int line) throws BadLocationException { + int lineCount = getLineCount(); + if (line < 0) { + throw new BadLocationException("Negative line", -1); + } else if (line >= lineCount) { + throw new BadLocationException("No such line", getDocument().getLength() + 1); + } else { + Element map = getDocument().getDefaultRootElement(); + Element lineElem = map.getElement(line); + int endOffset = lineElem.getEndOffset(); + // hide the implicit break at the end of the document + return ((line == lineCount - 1) ? (endOffset - 1) : endOffset); + } + } + + /** + * Replaces text from the indicated start to end position with the + * new text specified. Does nothing if the model is null. Simply + * does a delete if the new string is null or empty. + *

    + * This method is thread safe, although most Swing methods + * are not. + * + * @param str the text to use as the replacement + * @param start the start position >= 0 + * @param end the end position >= start + * @exception IllegalArgumentException if part of the range is an + * invalid position in the model + * @see #insert + * @see #replaceRange + */ + public void replaceRange(String str, int start, int end) { + if (end < start) { + throw new IllegalArgumentException("end before start"); + } + + + Font font = getFont(); + + MutableAttributeSet attrs = getInputAttributes(); + + + StyleConstants.setFontFamily(attrs, font.getFamily()); + StyleConstants.setFontSize(attrs, fontSize); + + + setCharacterAttributes(attrs, false); + this.select(start, end); + replaceSelection(str); + + }//end method. + }//end class + + public void setJTextPaneFont(JTextPane textPane, int fontSize) { + + Font font = textPane.getFont(); + + MutableAttributeSet attrs = textPane.getInputAttributes(); + + StyleConstants.setFontFamily(attrs, font.getFamily()); + StyleConstants.setFontSize(attrs, fontSize); + StyledDocument doc = textPane.getStyledDocument(); + + doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, false); + }//end method. + + public static class PopupTriggerMouseListener extends MouseAdapter { + + private JPopupMenu popup; + private JComponent component; + + public PopupTriggerMouseListener(JPopupMenu popup, JComponent component) { + this.popup = popup; + this.component = component; + } + + //some systems trigger popup on mouse press, others on mouse release, we want to cater for both + private void showMenuIfPopupTrigger(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(component, e.getX() + 3, e.getY() + 3); + } + } + + //according to the javadocs on isPopupTrigger, checking for popup trigger on mousePressed and mouseReleased + //should be all that is required + //public void mouseClicked(MouseEvent e) + public void mousePressed(MouseEvent e) { + showMenuIfPopupTrigger(e); + } + + public void mouseReleased(MouseEvent e) { + showMenuIfPopupTrigger(e); + } }//end method. + private void addPopupMenu() { + final JPopupMenu menu = new JPopupMenu(); + final JMenuItem copyItem = new JMenuItem(); + copyItem.setAction(textPane.getActionMap().get(DefaultEditorKit.copyAction)); + copyItem.setText("Copy"); + + final JMenuItem cutItem = new JMenuItem(); + cutItem.setAction(textPane.getActionMap().get(DefaultEditorKit.cutAction)); + cutItem.setText("Cut"); + + final JMenuItem pasteItem = new JMenuItem("Paste"); + pasteItem.setAction(textPane.getActionMap().get(DefaultEditorKit.pasteAction)); + pasteItem.setText("Paste"); + + final JMenuItem selectAllItem = new JMenuItem("Select All"); + selectAllItem.setAction(textPane.getActionMap().get(DefaultEditorKit.selectAllAction)); + selectAllItem.setText("Select All"); + + final JMenuItem insertPrompt = new JMenuItem("Insert In>"); + insertPrompt.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + textPane.insert(Color.BLACK, "In> ", textPane.getCaretPosition()); + } + }); + insertPrompt.setText("Insert In>"); + + menu.add(copyItem); + menu.add(cutItem); + menu.add(pasteItem); + menu.add(new JSeparator()); + menu.add(selectAllItem); + menu.add(new JSeparator()); + menu.add(insertPrompt); + + + textPane.add(menu); + textPane.addMouseListener(new PopupTriggerMouseListener(menu, textPane)); + }//end method. public static void main(String[] args) { Console console = new Console(); @@ -621,10 +1005,10 @@ Container contentPane = frame.getContentPane(); contentPane.add(console, BorderLayout.CENTER); //frame.setAlwaysOnTop(true); - frame.setSize(new Dimension(700, 600)); - frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE); + frame.setSize(new Dimension(800, 600)); + frame.setDefaultCloseOperation(frame.DISPOSE_ON_CLOSE); //frame.setResizable(false); - frame.setPreferredSize(new Dimension(700, 600)); + frame.setPreferredSize(new Dimension(800, 600)); frame.setLocationRelativeTo(null); // added frame.pack(); frame.setVisible(true); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/EditorPaneStructure.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/EditorPaneStructure.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/EditorPaneStructure.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/EditorPaneStructure.java 2010-07-22 17:07:40.000000000 +0000 @@ -0,0 +1,284 @@ +package org.mathpiper.ui.gui.consoles; + +import javax.swing.*; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.tree.*; +import javax.swing.text.*; +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.Field; +import java.util.Enumeration; + +public class EditorPaneStructure extends JPanel { + + JEditorPane sourcePane; + JLabel lblViewBounds = new JLabel() { + + public void paint(Graphics g) { + super.paint(g); + g.setColor(new Color(200, 200, 255, 128)); + g.fillRect(0, 0, getWidth(), getHeight()); + } + + }; + JTree trDocument = new JTree() { + + public String getToolTipText(MouseEvent event) { + return processDocumentTooltip(event); + } + + }; + JTree trView = new JTree() { + + public String getToolTipText(MouseEvent event) { + return processViewTooltip(event); + } + + }; + JButton btnRefresh = new JButton("Refresh"); + + + public EditorPaneStructure(JEditorPane source) { + this.sourcePane = source; + + init(); + initListeners(); + } + + + protected void init() { + + setLayout(new BorderLayout()); + + JPanel treePanel = new JPanel(); + + treePanel.setLayout(new GridBagLayout()); + + treePanel.add(new JLabel("Document structure"), new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + JScrollPane scroll = new JScrollPane(trDocument); + scroll.setPreferredSize(new Dimension(300, 200)); + treePanel.add(scroll, new GridBagConstraints(0, 1, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + treePanel.add(new JLabel("Views structure (Select node to highlight the view's bounds)"), new GridBagConstraints(0, 2, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + + scroll = new JScrollPane(trView); + scroll.setPreferredSize(new Dimension(300, 200)); + treePanel.add(scroll, new GridBagConstraints(0, 3, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); + + treePanel.add(btnRefresh, new GridBagConstraints(0, 5, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); + btnRefresh.setToolTipText("Press here to refresh trees"); + + this.add(treePanel); + + + JPanel buttonPanel = new JPanel(); + + JButton refreshButton = new javax.swing.JButton("Refresh"); + refreshButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + EditorPaneStructure.this.refresh(); + }//end method. + + }); + refreshButton.setEnabled(true); + buttonPanel.add(refreshButton); + + this.add(buttonPanel, BorderLayout.NORTH); + } + + + protected void initListeners() { + btnRefresh.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + refresh(); + } + + }); + + trView.addTreeSelectionListener(new TreeSelectionListener() { + + public void valueChanged(TreeSelectionEvent e) { + if (e.getNewLeadSelectionPath() != null) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.getNewLeadSelectionPath().getLastPathComponent(); + View v = (View) node.getUserObject(); + if (v.getParent() == null) { + View vParent = (View) ((DefaultMutableTreeNode) node.getParent()).getUserObject(); + v = vParent.getView(vParent.getViewIndex(v.getStartOffset(), Position.Bias.Forward)); + } + Rectangle r = getAllocation(v, sourcePane).getBounds(); + lblViewBounds.setBounds(r); + sourcePane.add(lblViewBounds); + sourcePane.repaint(); + } + } + + }); + } + + + public void refresh() { + if (sourcePane != null) { + Document doc = sourcePane.getDocument(); + + Element elem = doc.getDefaultRootElement(); + if (elem instanceof TreeNode) { + trDocument.setModel(new DefaultTreeModel((TreeNode) elem)); + } else { + DefaultMutableTreeNode node1 = new DefaultMutableTreeNode(elem); + buildElementsTree(node1, elem); + trDocument.setModel(new DefaultTreeModel(node1)); + } + int row = 0; + while (row < trDocument.getRowCount()) { + trDocument.expandRow(row); + row++; + } + trDocument.setToolTipText(" "); + + View v = sourcePane.getUI().getRootView(sourcePane); + DefaultMutableTreeNode node = new DefaultMutableTreeNode(v); + buildViewTree(node, v); + trView.setModel(new DefaultTreeModel(node)); + row = 0; + while (row < trView.getRowCount()) { + trView.expandRow(row); + row++; + } + trView.setToolTipText(" "); + } + } + + + public void buildElementsTree(DefaultMutableTreeNode root, Element elem) { + for (int i = 0; i < elem.getElementCount(); i++) { + AttributeSet attrs = getAttributes(elem.getElement(i)); + String str = elem.getElement(i).toString() + " " + attrs.getClass().getName() + "@" + Integer.toHexString(attrs.hashCode()); + DefaultMutableTreeNode node = new DefaultMutableTreeNode(str); + root.add(node); + buildElementsTree(node, elem.getElement(i)); + } + } + + + public void buildViewTree(DefaultMutableTreeNode root, View v) { + for (int i = 0; i < v.getViewCount(); i++) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(v.getView(i)); + root.add(node); + buildViewTree(node, v.getView(i)); + } + } + + + protected AttributeSet getAttributes(Element elem) { + if (elem instanceof AbstractDocument.AbstractElement) { + try { + Field f = AbstractDocument.AbstractElement.class.getDeclaredField("attributes"); + f.setAccessible(true); + AttributeSet res = (AttributeSet) f.get(elem); + return res; + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + return null; + } + + + protected String processDocumentTooltip(MouseEvent e) { + int rn = trDocument.getRowForLocation(e.getX(), e.getY()); + if (trDocument.getPathForRow(rn) != null) { + Element tn = (Element) trDocument.getPathForRow(rn).getLastPathComponent(); + StringBuffer buff = new StringBuffer(); + buff.append(""); + buff.append("Start offset: ").append(tn.getStartOffset()).append("
    "); + buff.append("End offset: ").append(tn.getEndOffset()).append("
    "); + buff.append("Child count: ").append(tn.getElementCount()).append("
    "); + buff.append("Text: \"").append(getText(tn.getDocument(), tn.getStartOffset(), tn.getEndOffset())).append("\"
    "); + buff.append("Attributes: ").append("
    "); + Enumeration names = tn.getAttributes().getAttributeNames(); + while (names.hasMoreElements()) { + Object name = names.nextElement(); + Object value = tn.getAttributes().getAttribute(name); + buff.append("  ").append(name).append(":").append(value).append("
    "); + } + buff.append(""); + return buff.toString(); + } + + return null; + } + + + protected String getText(Document doc, int startOffset, int endOffset) { + try { + String text = doc.getText(startOffset, endOffset - startOffset); + text = text.replaceAll("\n", "\\\\n"); + text = text.replaceAll("\t", "\\\\t"); + text = text.replaceAll("\r", "\\\\r"); + + return text; + } catch (BadLocationException e1) { + e1.printStackTrace(); + } + + return null; + } + + + protected String processViewTooltip(MouseEvent e) { + int rn = trView.getRowForLocation(e.getX(), e.getY()); + if (trView.getPathForRow(rn) != null) { + View tn = (View) ((DefaultMutableTreeNode) trView.getPathForRow(rn).getLastPathComponent()).getUserObject(); + StringBuffer buff = new StringBuffer(); + buff.append(""); + buff.append("Start offset: ").append(tn.getStartOffset()).append("
    "); + buff.append("End offset: ").append(tn.getEndOffset()).append("
    "); + buff.append("Child count: ").append(tn.getViewCount()).append("
    "); + buff.append("Text: \"").append(getText(tn.getDocument(), tn.getStartOffset(), tn.getEndOffset())).append("\"
    "); + if (tn.getAttributes() != null) { + buff.append("Attributes: ").append("
    "); + Enumeration names = tn.getAttributes().getAttributeNames(); + while (names.hasMoreElements()) { + Object name = names.nextElement(); + Object value = tn.getAttributes().getAttribute(name); + buff.append("  ").append(name).append(":").append(value).append("
    "); + } + } + buff.append(""); + return buff.toString(); + } + + return null; + } + + + protected static Shape getAllocation(View v, JEditorPane edit) { + Insets ins = edit.getInsets(); + View vParent = v.getParent(); + int x = ins.left; + int y = ins.top; + while (vParent != null) { + int i = vParent.getViewIndex(v.getStartOffset(), Position.Bias.Forward); + Shape alloc = vParent.getChildAllocation(i, new Rectangle(0, 0, Short.MAX_VALUE, Short.MAX_VALUE)); + x += alloc.getBounds().x; + y += alloc.getBounds().y; + + vParent = vParent.getParent(); + } + + if (v instanceof BoxView) { + int ind = v.getParent().getViewIndex(v.getStartOffset(), Position.Bias.Forward); + Rectangle r2 = v.getParent().getChildAllocation(ind, new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)).getBounds(); + + return new Rectangle(x, y, r2.width, r2.height); + } + + return new Rectangle(x, y, (int) v.getPreferredSpan(View.X_AXIS), (int) v.getPreferredSpan(View.Y_AXIS)); + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/GoAwayButton.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/GoAwayButton.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/GoAwayButton.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/GoAwayButton.java 2010-07-25 20:35:48.000000000 +0000 @@ -0,0 +1,129 @@ +package org.mathpiper.ui.gui.consoles; + +import java.awt.BasicStroke; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Color; + +import java.awt.Cursor; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import javax.swing.*; +import javax.swing.plaf.UIResource; + + +public class GoAwayButton extends JButton implements SwingConstants +{ + + private Color shadow; + private Color darkShadow; + private Color highlight; + + private BasicStroke redXStroke = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + + public GoAwayButton() { + super(); + + this.setBackground(UIManager.getColor("control")); + this.shadow = UIManager.getColor("controlShadow"); + this.darkShadow = UIManager.getColor("controlDkShadow"); + this.highlight = UIManager.getColor("controlLtHighlight"); + + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + + this.setToolTipText("Go back to the traditional math view of this expression."); + } + + + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + Color origColor; + boolean isPressed, isEnabled; + int w, h, size; + + w = getSize().width; + h = getSize().height; + origColor = g2d.getColor(); + isPressed = getModel().isPressed(); + isEnabled = isEnabled(); + + g2d.setColor(getBackground()); + g2d.fillRect(1, 1, w-2, h-2); + + /// Draw the border + if (getBorder() != null && !(getBorder() instanceof UIResource)) { + paintBorder(g2d); + } else if (isPressed) { + g2d.setColor(shadow); + g2d.drawRect(0, 0, w-1, h-1); + } else { + //Use the background color set above + g2d.drawLine(0, 0, 0, h-1); + g2d.drawLine(1, 0, w-2, 0); + + g2d.setColor(highlight); //Inner 3D border. + g2d.drawLine(1, 1, 1, h-3); + g2d.drawLine(2, 1, w-3, 1); + + g2d.setColor(shadow); //Inner 3D border. + g2d.drawLine(1, h-2, w-2, h-2); + g2d.drawLine(w-2, 1, w-2, h-3); + + g2d.setColor(darkShadow); //Backdrop shadow. + g2d.drawLine(0, h-1, w-1, h-1); + g2d.drawLine(w-1, h-1, w-1, 0); + } + + + if(h < 6 || w < 6) { + g2d.setColor(origColor); + return; + } + + if (isPressed) { + g2d.translate(1, 1); + } + + + g2d.setColor(Color.RED); + g2d.setStroke(redXStroke); + + g2d.drawLine(3, 4, 10, 11); + g2d.drawLine(10, 4, 3, 11); + + + + + + + if (isPressed) { + g2d.translate(-1, -1); + } + + + g2d.setColor(origColor); + + } + + + public Dimension getPreferredSize() { + return new Dimension(16, 16); + } + + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/GraphicConsole.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/GraphicConsole.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/GraphicConsole.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/GraphicConsole.java 2010-12-20 20:11:34.000000000 +0000 @@ -0,0 +1,1536 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.consoles; + + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Stack; +import javax.swing.BorderFactory; +import javax.swing.text.Element; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSplitPane; +import javax.swing.JTextArea; +import javax.swing.JTextPane; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Document; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import org.mathpiper.interpreters.EvaluationResponse; +import org.mathpiper.interpreters.Interpreter; +import org.mathpiper.interpreters.Interpreters; +import org.mathpiper.interpreters.ResponseListener; +import org.mathpiper.io.MathPiperOutputStream; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.Utility; +import org.mathpiper.lisp.cons.AtomCons; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.SublistCons; + +public class GraphicConsole extends javax.swing.JPanel implements ActionListener, KeyListener, ResponseListener, ItemListener, FocusListener, MathPiperOutputStream { + + ResultHolder resultHolder; + private boolean suppressOutput = false; + private final Color green = new Color(0, 130, 0); + private final Color purple = new Color(153, 0, 153); + private Interpreter interpreter = Interpreters.getAsynchronousInterpreter(); + private StringBuilder input = new StringBuilder(); + private JButton haltButton, clearConsoleButton, clearRawButton, helpButton, smallerFontButton, largerFontButton; + private JCheckBox rawOutputCheckBox; + private boolean isCodeResult = false; + private JCheckBox codeResultCheckBox; + private JCheckBox showRawOutputCheckBox; + private JTextArea rawOutputTextArea; + private ColorPane textPane; + private MathPiperOutputStream currentOutput; + private JScrollPane typePane; + private JPanel consoleButtons; + private JPanel rawButtons; + private int fontSize = 12; + private int resultHolderAdjustment = 3; + private StringBuilder inputLines; + private int responseInsertionOffset = -1; + private boolean encounteredIn = false; + private boolean noLinesBetweenInAndEndOfTextArea = false; + private JSplitPane splitPane; + private int splitPaneDividerLocation = 400; + private JScrollPane rawOutputScrollPane; + private JPanel rawOutputPanel; + private JPopupMenu Pmenu; + private Stack history = new java.util.Stack(); + private boolean controlKeyDown = false; + private int historyIndex = -1; + private int caretPositionWhenEnterWasPressed = -1; + private boolean deleteFlag = false; + private JRadioButton numericModeButton; + private JRadioButton symbolicModeButton; + private ButtonGroup resultModeGroup; + private boolean numericResultMode = false; + private JMenuBar menuBar; + private JFileChooser fileChooser; + private String helpMessage = + "Enter an expression after any In> prompt and press or to evaluate it.\n\n" + + "Type In> on the left end of any line to create your own input prompt.\n\n" + + "Use and to navigate through the command line history.\n\n" + + "Click on any result to obtain a code or a LaTeX version of it.\n\n" + + "The console window is an editable text area, so you can add text to it and remove text from \n" + + "it as needed.\n\n" + + "Placing ;; after the end of the line of input will suppress the output.\n\n" + + "The Raw Output checkbox sends all side effects output to the raw output text area."; + + + public GraphicConsole() { + + inputLines = new StringBuilder(); + + + this.setLayout(new BorderLayout()); + + //keySendQueue = new java.util.concurrent.ArrayBlockingQueue(30); + + + + consoleButtons = new JPanel(); + consoleButtons.setLayout(new BoxLayout(consoleButtons, BoxLayout.X_AXIS)); + + + rawOutputPanel = new JPanel(); + rawOutputPanel.setLayout(new BorderLayout()); + rawButtons = new JPanel(); + rawButtons.setLayout(new BoxLayout(rawButtons, BoxLayout.X_AXIS)); + + + + //textArea = new JTextArea(30, 20); + textPane = new ColorPane(); + + textPane.append(purple, "MathPiper version " + org.mathpiper.Version.version + ".\n"); + textPane.append(purple, "Enter an expression after any In> prompt and press or to evaluate it.\n"); + + + textPane.append(Color.BLACK, "\nIn> \n"); + textPane.setCaretPosition(textPane.getDocument().getLength() - 1); + + //java.io.InputStream inputStream = org.gjt.sp.jedit.jEdit.getPlugin("org.mathpiper.ide.u6502plugin.U6502Plugin").getPluginJAR().getClassLoader().getResourceAsStream( "resources/ttf-bitstream-vera-1.10/VeraMono.ttf" ); + + //bitstreamVera = Font.createFont (Font.TRUETYPE_FONT, inputStream); + //bitstreamVera = bitstreamVera.deriveFont(fontSize); + //typeArea.setFont(bitstreamVera); + + + textPane.addKeyListener(this); + typePane = new JScrollPane(textPane); + //guiBox.add(typePane); + + StyledDocument document = textPane.getStyledDocument(); + SimpleAttributeSet attrs = new SimpleAttributeSet(); + StyleConstants.setFontSize(attrs, fontSize); + document.setCharacterAttributes(0, document.getLength() + 1, attrs, false); + document.setParagraphAttributes(0, document.getLength() + 1, attrs, true); + + + + haltButton = new JButton("Halt Calculation"); + haltButton.setEnabled(false); + haltButton.setForeground(Color.RED); + haltButton.addActionListener(this); + consoleButtons.add(haltButton); + + + + smallerFontButton = new JButton("Font-"); + smallerFontButton.addActionListener(this); + consoleButtons.add(smallerFontButton); + largerFontButton = new JButton("Font+"); + largerFontButton.addActionListener(this); + consoleButtons.add(largerFontButton); + + rawOutputCheckBox = new JCheckBox("Raw Side Effects"); + rawOutputCheckBox.addItemListener(this); + rawButtons.add(rawOutputCheckBox); + this.rawOutputTextArea = new JTextArea(); + rawOutputTextArea.setEditable(false); + rawOutputTextArea.setText("Raw output text area.\n\n"); + + codeResultCheckBox = new JCheckBox("Code Result"); + codeResultCheckBox.setToolTipText("Show results in code format instead of traditional mathematics format."); + codeResultCheckBox.addItemListener(this); + consoleButtons.add(codeResultCheckBox); + + showRawOutputCheckBox = new JCheckBox("Show Raw"); + showRawOutputCheckBox.addItemListener(this); + consoleButtons.add(showRawOutputCheckBox); + + consoleButtons.add(Box.createGlue()); + + + clearConsoleButton = new JButton("Clear"); + clearConsoleButton.addActionListener(this); + consoleButtons.add(clearConsoleButton); + + + clearRawButton = new JButton("Clear Raw"); + clearRawButton.addActionListener(this); + rawButtons.add(clearRawButton); + + + helpButton = new JButton("Help"); + helpButton.addActionListener(this); + consoleButtons.add(helpButton); + + + + JButton structureButton = new javax.swing.JButton("Structure"); + structureButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + + new StructureDialog(textPane).setVisible(true); + + }//end method. + + }); + structureButton.setEnabled(true); + //consoleButtons.add(structureButton); + + + + JButton testButton = new javax.swing.JButton("Test"); + testButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + MathPiperDocument document = (MathPiperDocument) textPane.getDocument(); + + /*SimpleAttributeSet attrs = new SimpleAttributeSet(); + StyleConstants.setFontSize(attrs, fontSize + 5); + document.setCharacterAttributes(0, document.getLength() + 1, attrs, false);*/ + + //document.scanTree(fontSize); + + document.scanViews(textPane, fontSize); + + }//end method. + + }); + testButton.setEnabled(true); + //consoleButtons.add(testButton); + + + + + this.rawOutputPanel.add(rawButtons, BorderLayout.NORTH); + + //this.add(guiBox, BorderLayout.CENTER); + + + rawOutputScrollPane = new JScrollPane(rawOutputTextArea); + rawOutputPanel.add(rawOutputScrollPane); + + + splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, typePane, null); + splitPane.setOneTouchExpandable(true); + splitPane.setDividerLocation(splitPaneDividerLocation); + + this.add(splitPane); + + + this.addPopupMenu(); + + this.fileChooser = new JFileChooser(); + + + JPanel menuAndToolPanel = new JPanel(); + + menuAndToolPanel.setLayout(new BoxLayout(menuAndToolPanel, BoxLayout.Y_AXIS)); + + + this.menuBar = new MenuBar(); + + + //menuBar.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(Color.red), menuBar.getBorder())); //For testing. + + menuAndToolPanel.add(menuBar); + + menuAndToolPanel.add(consoleButtons); + + this.add(menuAndToolPanel, BorderLayout.NORTH); + + + }//Constructor. + + + public void actionPerformed(ActionEvent event) { + Object src = event.getSource(); + + if (src == haltButton) { + interpreter.haltEvaluation(); + } else if (src == smallerFontButton) { + this.fontSize -= 2; + + MathPiperDocument document = (MathPiperDocument) textPane.getDocument(); + /* + document.putProperty("ZOOM_FACTOR", new Double(zoomScale)); + document.refresh();*/ + + this.setJTextPaneFont(textPane, fontSize); + document.scanViews(textPane, fontSize + resultHolderAdjustment); + } else if (src == largerFontButton) { + this.fontSize += 2; + + MathPiperDocument document = (MathPiperDocument) textPane.getDocument(); + /*document.putProperty("ZOOM_FACTOR", new Double(zoomScale)); + document.refresh();*/ + + this.setJTextPaneFont(textPane, fontSize); + document.scanViews(textPane, fontSize + resultHolderAdjustment); + + + } else if (src == helpButton) { + JOptionPane.showMessageDialog(this, this.helpMessage); + } else if (src == clearConsoleButton) { + this.textPane.setText(""); + this.textPane.append(Color.BLACK, "In> \n"); + textPane.setCaretPosition(textPane.getDocument().getLength() - 1); + } else if (src == clearRawButton) { + this.rawOutputTextArea.setText(""); + } + + textPane.requestFocusInWindow(); + + }//end method. + + + public void itemStateChanged(ItemEvent ie) { + Object source = ie.getSource(); + + if (source == codeResultCheckBox) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + isCodeResult = true; + } else { + isCodeResult = false; + }//end if/else. + } + if (source == rawOutputCheckBox) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + Environment environment = interpreter.getEnvironment(); + this.currentOutput = environment.iCurrentOutput; + environment.iCurrentOutput = this; + } else { + Environment environment = interpreter.getEnvironment(); + environment.iCurrentOutput = this.currentOutput; + }//end if/else. + } else if (source == showRawOutputCheckBox) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + splitPane.add(rawOutputPanel); + splitPane.setDividerLocation(splitPaneDividerLocation); + splitPane.revalidate(); + } else { + splitPane.remove(2); + splitPane.revalidate(); + }//end if/else. + } else if (source == numericModeButton) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + this.numericResultMode = true; + } else { + this.numericResultMode = false; + }//end if/else. + } else if (source == symbolicModeButton) { + if (ie.getStateChange() == ItemEvent.SELECTED) { + this.numericResultMode = false; + } else { + this.numericResultMode = true; + }//end if/else. + + }//end if/else. + + textPane.requestFocusInWindow(); + }//end method. + + + public void putChar(char aChar) throws Exception { + if (rawOutputTextArea != null && currentOutput != null) { + this.rawOutputTextArea.append("" + aChar); + this.rawOutputTextArea.setCaretPosition(this.rawOutputTextArea.getDocument().getLength()); + this.currentOutput.putChar(aChar); + }//end if. + }//end method. + + + public void write(String aString) throws Exception { + int i; + for (i = 0; i < aString.length(); i++) { + putChar(aString.charAt(i)); + } + }//end method. + + + public void keyPressed(KeyEvent e) { + int keyCode = (int) e.getKeyCode(); + + if (keyCode == KeyEvent.VK_CONTROL) { + this.controlKeyDown = true; + }//end if. + + + if (keyCode == KeyEvent.VK_UP && this.controlKeyDown) { + //System.out.println("up"); + + if (!history.empty() && historyIndex != history.size() - 1) { + + + historyIndex++; + //System.out.println(history.get((history.size()-1) - historyIndex)); + + try { + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); + + textPane.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex) + "\n", lineStartOffset, lineEndOffset); + + textPane.setCaretPosition(textPane.getLineEndOffset(lineNumber) - 1); + + } catch (BadLocationException ble) { + //Eat exception. + } + + + }//end if. + + }//end if. + + + }//end method. + + + public void keyReleased(KeyEvent e) { + int keyCode = (int) e.getKeyCode(); + + if (keyCode == KeyEvent.VK_CONTROL) { + this.controlKeyDown = false; + }//end if. + + + if (keyCode == KeyEvent.VK_DOWN && this.controlKeyDown) { + //System.out.println("down"); + + if (!history.empty() && (!(historyIndex < 1))) { + + + historyIndex--; + //System.out.println(history.get((history.size()-1) - historyIndex)); + + try { + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); + + textPane.replaceRange("In> " + (String) history.get((history.size() - 1) - historyIndex) + "\n", lineStartOffset, lineEndOffset); + + textPane.setCaretPosition(textPane.getLineEndOffset(lineNumber) - 1); + + } catch (BadLocationException ble) { + //Eat exception. + } + + } else if (!history.empty() && historyIndex == 0) { + try { + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); + + textPane.replaceRange("In> \n", lineStartOffset, lineEndOffset); + + textPane.setCaretPosition(textPane.getLineEndOffset(lineNumber) - 1); + + this.historyIndex = -1; + + } catch (BadLocationException ble) { + //Eat exception.; + } + + }//end else. + }//end if. + + }//end method. + + + public void keyTyped(KeyEvent e) { + + char key = e.getKeyChar(); + + //System.out.println((int)key); + + if ((int) key == e.VK_ENTER || (int) key == 13) { //== 10) { + try { + + //System.out.println("key pressed"); //TODO remove. + + //System.out.println("LN: " + lineNumber + " LSO: " + lineStartOffset + " LEO: " + lineEndOffset ); + if (!e.isShiftDown()) { + textPane.replaceRange("", textPane.getCaretPosition() - 1, textPane.getCaretPosition()); + }//end if. + + caretPositionWhenEnterWasPressed = textPane.getCaretPosition(); + + int lineNumber = textPane.getLineOfOffset(textPane.getCaretPosition()); + //lineNumber--; + String line = ""; + + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + + int lineEndOffset = textPane.getLineEndOffset(lineNumber); + + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); + + + if (line.startsWith("In>")) { + //Check for a RenderingComponent in the input line. + int lineIndex = 3; + for (int lineOffsetIndex = lineStartOffset + 3; lineOffsetIndex < lineEndOffset; lineOffsetIndex++) { + Element element = textPane.getStyledDocument().getCharacterElement(lineOffsetIndex); + if (element.isLeaf()) { + Object object = element.getAttributes().getAttribute(StyleConstants.ComponentAttribute); + + if (object instanceof LatexComponent) { + line = line.subSequence(0, lineIndex) + " " + object.toString() + " " + line.substring(lineIndex); + + System.out.println(line); + } + } + lineIndex++; + }//end for + } + + + if (line.startsWith("In>") && line.substring(3).trim().equals("")) { + } else if (line.startsWith("In>")) { + + //String eol = new String(line); + String code = line.substring(3, line.length()).trim(); + responseInsertionOffset = lineEndOffset; + + /*if (!eol.endsWith(";") && !eol.endsWith("\\\n")) { + code = code + ";"; + }//end if.*/ + + if (!code.endsWith(";")) { + code = code + ";"; + } + + clearPreviousResponse(); + + + // System.out.println("1: " + code); + + if (code.endsWith(";;")) { + this.suppressOutput = true; + } + + code = code.replaceAll(";;;", ";"); + code = code.replaceAll(";;", ";"); + + //code = code.replaceAll("\\\\", ""); + + //System.out.println("2: " + code); + + history.push(code.substring(0, code.length() - 1)); + this.historyIndex = -1; + + if (code.length() > 0) { + interpreter.addResponseListener(this); + interpreter.evaluate("[" + code + "];", true); + haltButton.setEnabled(true); + + }//end if. + + + } else { + textPane.insert(Color.BLACK, "\n", caretPositionWhenEnterWasPressed); + } + + + + //input.delete(0, input.length()); + // typeArea.append(response.getResult()); + + } catch (BadLocationException ex) { + System.out.println(ex.getMessage() + " , " + ex.offsetRequested()); + } + + //typeArea.append(new String(typedKey)); + //typeArea.setCaretPosition( typeArea.getDocument().getLength() ); + /* } else if ((int) key == 22) { + try { + String clipBoard = (String) java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().getData(java.awt.datatransfer.DataFlavor.stringFlavor); + + if (clipBoard.length() != 0) { + char[] chars = clipBoard.toCharArray(); + for (int x = 0; x < chars.length; x++) { + //buffer.put((int) chars[x]); + }//end for. + //setReceiveDataRegisterFull(true); + }//end if. + + } catch (NullPointerException ev) { + ev.printStackTrace(); + } catch (IllegalStateException ev) { + ev.printStackTrace(); + } catch (java.awt.datatransfer.UnsupportedFlavorException ev) { + ev.printStackTrace(); + } catch (java.io.IOException ev) { + ev.printStackTrace(); + }//*/ + } else { + //System.out.println(key); + //registers[0] = (int) key; + if ((int) key == e.VK_BACK_SPACE) { //== 8) { + deleteFlag = true; + } + + input.append(key); + //typeArea.append(Character.toString(key)); + //buffer.put((int) key); + //setReceiveDataRegisterFull(true); + } + }//end method. + + + public void response(EvaluationResponse response) { + + if (response.isExceptionThrown()) { + resultHolder = new ResultHolder("Exception", "Exception", fontSize + resultHolderAdjustment); + } else { + + Object responseObject = response.getObject(); + if (responseObject == null && response.getResultList() != null) { + + + if (!isCodeResult) { + try { + Interpreter syncronousInterpreter = Interpreters.getSynchronousInterpreter(); + + //Evaluate Hold function. + Cons holdAtomCons = AtomCons.getInstance(syncronousInterpreter.getEnvironment(), -1, "Hold"); + holdAtomCons.cdr().setCons(response.getResultList().getCons()); + Cons holdSubListCons = SublistCons.getInstance(syncronousInterpreter.getEnvironment(), holdAtomCons); + ConsPointer holdInputExpressionPointer = new ConsPointer(holdSubListCons); + + + //Evaluate TeXForm function. + Cons texFormAtomCons = AtomCons.getInstance(syncronousInterpreter.getEnvironment(), -1, "TeXForm"); + texFormAtomCons.cdr().setCons(holdInputExpressionPointer.getCons()); + Cons texFormSubListCons = SublistCons.getInstance(syncronousInterpreter.getEnvironment(), texFormAtomCons); + ConsPointer texFormInputExpressionPointer = new ConsPointer(texFormSubListCons); + EvaluationResponse latexResponse = syncronousInterpreter.evaluate(texFormInputExpressionPointer); + + String latexString = latexResponse.getResult(); + + latexString = Utility.stripEndQuotesIfPresent(null, -1, latexString); + + latexString = Utility.stripEndDollarSigns(latexString); + + resultHolder = new ResultHolder(latexString, response.getResult(), fontSize + resultHolderAdjustment); + + + //Set the % variable to the original result. + Environment iEnvironment = syncronousInterpreter.getEnvironment(); + String percent = (String) iEnvironment.getTokenHash().lookUp("%"); + iEnvironment.setGlobalVariable(-1, percent, response.getResultList(), true); + + + } catch (Exception e) { + e.printStackTrace(); + } + } else { + resultHolder = new ResultHolder(response.getResult(), response.getResult(), fontSize + resultHolderAdjustment); + } + + }//end if + + }//end if. + + + //final int caretPosition = responseInsertionOffset; + + int offsetIndex = responseInsertionOffset; + + final int initialOffset = offsetIndex; + + String extraNewline = ""; + if (!encounteredIn) { + + if (noLinesBetweenInAndEndOfTextArea == true) { + extraNewline = "\n";// + result + "\n\nIn> "; + offsetIndex++; + } + + }//end if.*/ + + final int responseOffset = offsetIndex; + String result; + if (this.suppressOutput == false) { + result = "Result: ";// + response.getResult().trim(); + if (isCodeResult) { + result = result + response.getResult().trim(); + } + } else { + result = "Result: " + "OUTPUT SUPPRESSED"; + } + + + String sideEffects = null; + int sideEffectsOffset = 0; + int sideEffectsLength = 0; + if (!response.getSideEffects().equalsIgnoreCase("")) { + sideEffectsOffset = responseOffset + result.length(); + sideEffects = "\nSide Effects:\n" + response.getSideEffects(); + sideEffectsLength = sideEffects.length(); + } + + + String exception = null; + int exceptionOffset = 0; + int exceptionLength = 0; + if (response.isExceptionThrown()) { + exceptionOffset = responseOffset + result.length() + sideEffectsOffset; + exception = "\nException: " + response.getExceptionMessage(); + exceptionLength = exception.length(); + } + + + + + + final String finalExtraNewline = extraNewline; + final String finalResult = result; + final String finalSideEffects = sideEffects; + final String finalException = exception; + + final int finalSideEffectsOffset = sideEffectsOffset; + final int finalExceptionOffset = exceptionOffset; + final int insertInOffset = responseOffset + result.length() + sideEffectsLength + exceptionLength; + final int finalCaretPositionWhenEnterWasPressed = caretPositionWhenEnterWasPressed; + final ResultHolder resultHolderFinal = resultHolder; + final EvaluationResponse responseFinal = response; + final boolean isCodeResultFinal = isCodeResult; + final boolean suppressOutputFinal = suppressOutput; + + this.suppressOutput = false; + + /* if (insertionPointLine == lineCount - 1) { + SwingUtilities.invokeLater(new Runnable() { + + public void run() { + haltButton.setEnabled(false); + textArea.append(Color.BLACK, finalOutput); + } + + + }); + + //textArea.setCaretPosition( textArea.getDocument().getLength() ); + } else {*/ + SwingUtilities.invokeLater(new Runnable() { + + public void run() { + haltButton.setEnabled(false); + + + textPane.insert(Color.BLACK, finalExtraNewline, initialOffset); //finalExtraNewline + + textPane.insert(Color.BLUE, finalResult, responseOffset); + + if (finalSideEffects != null) { + textPane.insert(green, finalSideEffects, finalSideEffectsOffset); + } + + if (finalException != null) { + textPane.insert(Color.RED, finalException, finalExceptionOffset); + } + + + if (!encounteredIn) { + + textPane.insert(Color.BLACK, "\n\nIn> ", insertInOffset); + + } else { + //textPane.setCaretPosition(caretPosition - 1); + textPane.setCaretPosition(finalCaretPositionWhenEnterWasPressed); + + } + + + if (!suppressOutputFinal && !isCodeResultFinal) { + + try { + + StyledDocument doc = (StyledDocument) textPane.getDocument(); + + Style style = doc.addStyle("RenderingComponent", null); + + + + Object responseObject = responseFinal.getObject(); + + if (false) {//responseObject instanceof JPanel) { + //Histogram({3,4,3,2,2,3,3,4,5,5,6,5,4,3,2,1,2,3,3,4,5,4,5,6}) + JPanel responseObjectJPanel = (JPanel) responseObject; + Resizable resizer = new Resizable(responseObjectJPanel); + + //resizer.setBounds(50, 50, 200, 150); + StyleConstants.setComponent(style, resizer); + doc.insertString(responseOffset + 8, responseObject.getClass().toString(), style); + } else { + StyleConstants.setComponent(style, resultHolderFinal); + doc.insertString(responseOffset + 8, resultHolderFinal.getCodeResult(), style); + } + + + + + + } catch (BadLocationException e) { + e.printStackTrace(); + } + + }//end if. + + + }//end method. + + }); + + //}//end if/else. + + }//end method. + + + public boolean remove() { + return true; + } + + + private void clearPreviousResponse() { + + try { + int lineNumber = textPane.getLineOfOffset(responseInsertionOffset - 1); + + if (responseInsertionOffset == -1 || lineNumber == textPane.getLineCount()) { + encounteredIn = false; + return; + } + + String line = ""; + int lineStartOffset = 0; + int lineEndOffset = 0; + + do { + + lineNumber++; + lineStartOffset = textPane.getLineStartOffset(lineNumber); + lineEndOffset = textPane.getLineEndOffset(lineNumber); + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); + + } while (!line.startsWith("In>") && lineNumber < textPane.getLineCount()); + + textPane.replaceRange("\n\n\n", responseInsertionOffset - 1, lineStartOffset); + encounteredIn = line.startsWith("In>"); + return; + + } catch (BadLocationException ex) { + encounteredIn = false; + textPane.replaceRange("\n\n\n", responseInsertionOffset, textPane.getDocument().getLength()); + return; + } + }//end method. + + + private void captureInputLines(int lineNumber) { + + inputLines.delete(0, inputLines.length()); + + try { + int lineStartOffset = textPane.getLineStartOffset(lineNumber); + int lineEndOffset = textPane.getLineEndOffset(lineNumber); + String line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); + + if (line.startsWith("In>")) { + + //Scan backwards to first line that does not start with In>. + do { + lineStartOffset = textPane.getLineStartOffset(lineNumber); + lineEndOffset = textPane.getLineEndOffset(lineNumber); + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset); + lineNumber--; + + } while (line.startsWith("In>") && lineNumber != -1);//end do/while. + + if (lineNumber != -1) { + lineNumber++; + } + + + //Scan forwards to first line that does not start with In>. + boolean pastInputLines = false; + noLinesBetweenInAndEndOfTextArea = false; + do { + lineNumber++; + lineStartOffset = textPane.getLineStartOffset(lineNumber); + lineEndOffset = textPane.getLineEndOffset(lineNumber); + line = textPane.getText(lineStartOffset, lineEndOffset - lineStartOffset).trim(); + if (line.startsWith("In>")) { + String eol = new String(line); + inputLines.append(line.substring(3, line.length()).trim()); + responseInsertionOffset = lineEndOffset; + if (!eol.endsWith(";") && !eol.endsWith("\\\n")) { + inputLines.append(";"); + }//end if. + } else { + pastInputLines = true; + } + + + } while (!pastInputLines && lineNumber < textPane.getLineCount());//end while. + + }//end if.*/ + + } catch (BadLocationException ex) { + noLinesBetweenInAndEndOfTextArea = true; + } + + + }//end method. + + + public void setHaltButtonEnabledState(boolean state) { + this.haltButton.setEnabled(state); + + }//end method. + + class ColorPane extends JTextPane { + + public ColorPane() { + super(); + //this.getDocument().putProperty("i18n", Boolean.FALSE); + //this.getDocument().putProperty("ZOOM_FACTOR", new Double(zoomScale)); + this.setDocument(new MathPiperDocument()); + + } + + + public void append(Color c, String s) { // better implementation--uses // StyleContext. + MutableAttributeSet attrs = getInputAttributes(); + //attrs.removeAttribute("size"); + //SimpleAttributeSet attrs = new SimpleAttributeSet(); + //StyleConstants.setFontSize(attrs, fontSize); + + + //StyleConstants.setFontSize(attrs, fontSize); + + + StyleConstants.setForeground(attrs, c); + + int len = getDocument().getLength(); // same value as // getText().length(); + setCaretPosition(len); // place caret at the end (with no selection). + setCharacterAttributes(attrs, false); + + + /*try { + this.getDocument().insertString(this.getCaretPosition(), s, attrs); + } catch (BadLocationException e) { + }*/ + + replaceSelection(s); // there is no selection, so inserts at caret. + }//end method. + + + public void insert(Color c, String str, int pos) { + + + + MutableAttributeSet attrs = getInputAttributes(); + //attrs.removeAttribute(StyleConstants.FontSize); + //SimpleAttributeSet attrs = new SimpleAttributeSet(); + + //StyleConstants.setFontSize(attrs, fontSize); + + + //StyleConstants.setFontFamily(attrs, font.getFamily()); + //StyleConstants.setFontSize(attrs, fontSize); + StyleConstants.setForeground(attrs, c); + + //StyleContext sc = StyleContext.getDefaultStyleContext(); + //MutableAttributeSet aset = this.getInputAttributes(); + //AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c); + setCaretPosition(pos); // place caret at the end (with no selection) + setCharacterAttributes(attrs, false); + + /*try { + this.getDocument().insertString(this.getCaretPosition(), str, attrs); + } catch (BadLocationException e) { + }*/ + + + + replaceSelection(str); // there is no selection, so inserts at caret. + + } + + + /** + * Translates an offset into the components text to a + * line number. + * + * @param offset the offset >= 0 + * @return the line number >= 0 + * @exception BadLocationException thrown if the offset is + * less than zero or greater than the document length. + */ + public int getLineOfOffset(int offset) throws BadLocationException { + Document doc = getDocument(); + if (offset < 0) { + throw new BadLocationException("Can't translate offset to line", -1); + } else if (offset > doc.getLength()) { + throw new BadLocationException("Can't translate offset to line", doc.getLength() + 1); + } else { + Element map = getDocument().getDefaultRootElement(); + return map.getElementIndex(offset); + } + } + + + /** + * Determines the number of lines contained in the area. + * + * @return the number of lines > 0 + */ + public int getLineCount() { + Element map = getDocument().getDefaultRootElement(); + return map.getElementCount(); + } + + + /** + * Determines the offset of the start of the given line. + * + * @param line the line number to translate >= 0 + * @return the offset >= 0 + * @exception BadLocationException thrown if the line is + * less than zero or greater or equal to the number of + * lines contained in the document (as reported by + * getLineCount). + */ + public int getLineStartOffset(int line) throws BadLocationException { + int lineCount = getLineCount(); + if (line < 0) { + throw new BadLocationException("Negative line", -1); + } else if (line >= lineCount) { + throw new BadLocationException("No such line", getDocument().getLength() + 1); + } else { + Element map = getDocument().getDefaultRootElement(); + Element lineElem = map.getElement(line); + return lineElem.getStartOffset(); + } + } + + + /** + * Determines the offset of the end of the given line. + * + * @param line the line >= 0 + * @return the offset >= 0 + * @exception BadLocationException Thrown if the line is + * less than zero or greater or equal to the number of + * lines contained in the document (as reported by + * getLineCount). + */ + public int getLineEndOffset(int line) throws BadLocationException { + int lineCount = getLineCount(); + if (line < 0) { + throw new BadLocationException("Negative line", -1); + } else if (line >= lineCount) { + throw new BadLocationException("No such line", getDocument().getLength() + 1); + } else { + Element map = getDocument().getDefaultRootElement(); + Element lineElem = map.getElement(line); + int endOffset = lineElem.getEndOffset(); + // hide the implicit break at the end of the document + return ((line == lineCount - 1) ? (endOffset - 1) : endOffset); + } + } + + + /** + * Replaces text from the indicated start to end position with the + * new text specified. Does nothing if the model is null. Simply + * does a delete if the new string is null or empty. + *

    + * This method is thread safe, although most Swing methods + * are not. + * + * @param str the text to use as the replacement + * @param start the start position >= 0 + * @param end the end position >= start + * @exception IllegalArgumentException if part of the range is an + * invalid position in the model + * @see #insert + * @see #replaceRange + */ + public void replaceRange(String str, int start, int end) { + if (end < start) { + throw new IllegalArgumentException("end before start"); + } + + + Font font = getFont(); + + MutableAttributeSet attrs = getInputAttributes(); + + + StyleConstants.setFontFamily(attrs, font.getFamily()); + StyleConstants.setFontSize(attrs, fontSize); + + + setCharacterAttributes(attrs, false); + this.select(start, end); + replaceSelection(str); + + }//end method. + + }//end class + + + public void setJTextPaneFont(JTextPane textPane, int fontSize) { + + StyledDocument document = textPane.getStyledDocument(); + SimpleAttributeSet attrs = new SimpleAttributeSet(); + StyleConstants.setFontSize(attrs, fontSize); + document.setCharacterAttributes(0, document.getLength() + 1, attrs, false); + document.setParagraphAttributes(0, document.getLength() + 1, attrs, true); + + MutableAttributeSet attrs2 = textPane.getInputAttributes(); + StyleConstants.setFontSize(attrs2, fontSize); + + }//end method. + + public static class PopupTriggerMouseListener extends MouseAdapter { + + private JPopupMenu popup; + private JComponent component; + + + public PopupTriggerMouseListener(JPopupMenu popup, JComponent component) { + this.popup = popup; + this.component = component; + } + + //some systems trigger popup on mouse press, others on mouse release, we want to cater for both + + private void showMenuIfPopupTrigger(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(component, e.getX() + 3, e.getY() + 3); + } + } + + //according to the javadocs on isPopupTrigger, checking for popup trigger on mousePressed and mouseReleased + //should be all that is required + //public void mouseClicked(MouseEvent e) + + public void mousePressed(MouseEvent e) { + showMenuIfPopupTrigger(e); + } + + + public void mouseReleased(MouseEvent e) { + showMenuIfPopupTrigger(e); + } + + }//end method. + + + public JMenuBar getMenuBar() { + return menuBar; + } + + + private void addPopupMenu() { + final JPopupMenu menu = new JPopupMenu(); + + final JMenuItem copyItem = new JMenuItem(); + copyItem.setAction(textPane.getActionMap().get(DefaultEditorKit.copyAction)); + copyItem.setText("Copy"); + menu.add(copyItem); + + final JMenuItem cutItem = new JMenuItem(); + cutItem.setAction(textPane.getActionMap().get(DefaultEditorKit.cutAction)); + cutItem.setText("Cut"); + menu.add(cutItem); + + final JMenuItem pasteItem = new JMenuItem("Paste"); + pasteItem.setAction(textPane.getActionMap().get(DefaultEditorKit.pasteAction)); + pasteItem.setText("Paste"); + menu.add(pasteItem); + + menu.add(new JSeparator()); + + final JMenuItem selectAllItem = new JMenuItem("Select All"); + selectAllItem.setAction(textPane.getActionMap().get(DefaultEditorKit.selectAllAction)); + selectAllItem.setText("Select All"); + menu.add(selectAllItem); + + menu.add(new JSeparator()); + + final JMenuItem insertPrompt = new JMenuItem("Insert In>"); + insertPrompt.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + textPane.insert(Color.BLACK, "In> ", textPane.getCaretPosition()); + } + + }); + insertPrompt.setText("Insert In>"); + menu.add(insertPrompt); + + final JMenuItem insertLatex = new JMenuItem("Insert LaTeX"); + insertLatex.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + textPane.insertComponent(new LatexComponent(GraphicConsole.this.fontSize + GraphicConsole.this.resultHolderAdjustment, GraphicConsole.this)); + } + + }); + insertLatex.setText("Insert LaTeX"); + //menu.add(insertLatex); + + + + final JMenuItem insertMathPiperCode = new JMenuItem("Insert MathPiper Code Renderer"); + insertMathPiperCode.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + + LatexComponent codeComponent = new LatexComponent(GraphicConsole.this.fontSize + GraphicConsole.this.resultHolderAdjustment, GraphicConsole.this); + + codeComponent.setLatexMode(false); + + textPane.insertComponent(codeComponent); + + codeComponent.giveFocus(); + + } + + }); + insertMathPiperCode.setText("Insert MathPiper Code Renderer"); + menu.add(insertMathPiperCode); + + + + + textPane.add(menu); + textPane.addMouseListener(new PopupTriggerMouseListener(menu, textPane)); + }//end method. + + + public void giveFocus() { + textPane.requestFocusInWindow(); + } + + + public void focusGained(FocusEvent e) { + } + + + public void focusLost(FocusEvent e) { + if (e.getSource() instanceof RenderingComponent) { + giveFocus(); + } + } + + + public static void main(String[] args) { + final GraphicConsole console = new GraphicConsole(); + + JFrame frame = new javax.swing.JFrame(); + Container contentPane = frame.getContentPane(); + contentPane.add(console, BorderLayout.CENTER); + //frame.setAlwaysOnTop(true); + frame.setSize(new Dimension(800, 600)); + frame.setDefaultCloseOperation(frame.DISPOSE_ON_CLOSE); + frame.setTitle("Graphic Console"); + //frame.setResizable(false); + + //frame.setJMenuBar(console.getMenuBar()); + + + //Make textField get the focus whenever frame is activated. + frame.addWindowFocusListener(new WindowAdapter() { + + public void windowGainedFocus(WindowEvent e) { + console.giveFocus(); + } + + }); + + frame.setPreferredSize(new Dimension(800, 600)); + frame.setLocationRelativeTo(null); // added + frame.pack(); + frame.setVisible(true); + }//end main. + + class MenuBar extends JMenuBar { + + public MenuBar() { + + //setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + FlowLayout layout = new FlowLayout(); + + layout.setAlignment(FlowLayout.LEFT); + + layout.setVgap(0); + + this.setLayout(layout); + + + + JMenu fileMenu = new JMenu("File"); + JMenu editMenu = new JMenu("Edit"); + add(fileMenu); + add(editMenu); + + + JMenuItem newAction = new JMenuItem("New"); + newAction.setText("New"); + newAction.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent ae) { + } + + }); + + + JMenuItem openAction = new JMenuItem(); + openAction.setText("Open"); + openAction.addActionListener(new FileOperationListener()); + fileMenu.add(openAction); + + JMenuItem saveAction = new JMenuItem(); + saveAction.setText("Save"); + saveAction.addActionListener(new FileOperationListener()); + fileMenu.add(saveAction); + + //JMenuItem exitAction = new JMenuItem("Exit"); + //fileMenu.add(exitAction); + + JMenuItem copyAction = new JMenuItem(); + copyAction.setAction(textPane.getActionMap().get(DefaultEditorKit.copyAction)); + copyAction.setText("Copy"); + editMenu.add(copyAction); + + JMenuItem cutAction = new JMenuItem(); + cutAction.setAction(textPane.getActionMap().get(DefaultEditorKit.cutAction)); + cutAction.setText("Cut"); + editMenu.add(cutAction); + + JMenuItem pasteAction = new JMenuItem(); + pasteAction.setAction(textPane.getActionMap().get(DefaultEditorKit.pasteAction)); + pasteAction.setText("Paste"); + editMenu.add(pasteAction); + + + + /* + JCheckBoxMenuItem checkAction = new JCheckBoxMenuItem("Check Action"); + + JRadioButtonMenuItem radioAction1 = new JRadioButtonMenuItem( + "Radio Button1"); + JRadioButtonMenuItem radioAction2 = new JRadioButtonMenuItem( + "Radio Button2"); + + ButtonGroup bg = new ButtonGroup(); + bg.add(radioAction1); + bg.add(radioAction2); + fileMenu.add(newAction); + fileMenu.add(checkAction); + fileMenu.addSeparator(); + editMenu.addSeparator(); + editMenu.add(radioAction1); + editMenu.add(radioAction2); + */ + + + + }//end constructor. + + + }//end class. + + class FileOperationListener implements ActionListener { + + public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); + int retVal; + boolean exists; + + //set the current directory to the application's current directory + try { + //create a file object containing the cannonical path of the desired file + File f = new File(new File("untitled.txt").getCanonicalPath()); + //set the selected file + fileChooser.setSelectedFile(f); + } catch (IOException ex3) { + ex3.printStackTrace(); + } + + + + if (command.equals("Save")) { + //show the dialog; wait until dialog is closed + retVal = fileChooser.showSaveDialog(null); + //Approve(Save was clicked) + if (retVal == JFileChooser.APPROVE_OPTION) { + //get the currently selected file + File thefile = fileChooser.getSelectedFile(); + String nameOfFile = ""; + nameOfFile = thefile.getPath(); + //check if the file exists + exists = (new File(nameOfFile)).exists(); + if (!exists) { + System.out.println("Does not exist"); + //If the file does not already exist, it is automatically created. + try { + BufferedWriter out = new BufferedWriter(new FileWriter(nameOfFile)); + out.write(textPane.getText()); + out.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } else { + //System.out.println(" Exists"); + //Save over a file. + try { + BufferedWriter out = new BufferedWriter(new FileWriter(nameOfFile, false)); + out.write(textPane.getText()); + out.close(); + } catch (IOException ex2) { + } + }//end else. + /* + if (thefile != null) { + if (thefile.isDirectory()) { + JOptionPane.showMessageDialog(null, "You chose this directory: " + thefile.getPath()); + } else { + JOptionPane.showMessageDialog(null, "You chose this file: " + thefile.getPath()); + + //to append to the existing file + //out = new FileOutputStream(theFile, true); + } + }*/ + } else if (retVal == JFileChooser.CANCEL_OPTION) { + //Cancel or the close dialog icon was clicked + JOptionPane.showMessageDialog(null, "User cancelled operation. No file was chosen."); + } else if (retVal == JFileChooser.ERROR_OPTION) { + //The selected process did not complete successfully + JOptionPane.showMessageDialog(null, "An error occured. No file was chosen."); + } else { + JOptionPane.showMessageDialog(null, "Unknown operation occured."); + } + } else if (command.equals("Open")) { + retVal = fileChooser.showOpenDialog(null); + //Approve(Save was clicked) + if (retVal == JFileChooser.APPROVE_OPTION) { + + String filePath = fileChooser.getSelectedFile().getPath(); + try { + FileInputStream fr = new FileInputStream(filePath); + InputStreamReader isr = new InputStreamReader(fr, "UTF-8"); + BufferedReader reader = new BufferedReader(isr); + StringBuffer buffer = new StringBuffer(); + + String line = null; + while ((line = reader.readLine()) != null) { + buffer.append(line + "\n"); + } + + reader.close(); + + textPane.setText(buffer.toString()); + } catch (FileNotFoundException ex) { + JOptionPane.showMessageDialog(null, "The file was not found."); + }catch (IOException ex) { + ex.printStackTrace(); + } + + } + + }//end else if. + + + + }//end of ActionPerformed method + + }//end of action listener + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/LatexComponent.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/LatexComponent.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/LatexComponent.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/LatexComponent.java 2010-12-20 20:11:34.000000000 +0000 @@ -0,0 +1,331 @@ +package org.mathpiper.ui.gui.consoles; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.mathpiper.interpreters.EvaluationResponse; +import org.mathpiper.interpreters.Interpreter; +import org.mathpiper.interpreters.Interpreters; +import org.mathpiper.lisp.Utility; +import org.scilab.forge.jlatexmath.JMathTeXException; +import org.scilab.forge.jlatexmath.TeXConstants; +import org.scilab.forge.jlatexmath.TeXFormula; +import org.scilab.forge.jlatexmath.TeXIcon; + +public class LatexComponent extends JPanel implements RenderingComponent, MouseListener { + + private TeXFormula texFormula; + private JLabel renderedResult; + private JTextField inputTextField; + private String resultString; + private String latexString; + private int toggle = 0; + private SpinButton spinButton; + private GoAwayButton goAwayButton; + private int fontPointSize; + private boolean latexMode = false; + private final GraphicConsole console; + + + public LatexComponent(int fontPointSize, GraphicConsole console) { + + this.console = console; + + this.fontPointSize = fontPointSize; + + this.latexString = "\\square"; + + + + this.renderedResult = new JLabel(); + + try { + texFormula = new TeXFormula(latexString); + TeXIcon icon = texFormula.createTeXIcon(TeXConstants.STYLE_DISPLAY, fontPointSize); + renderedResult.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + renderedResult.setAlignmentY(icon.getBaseLine()); + renderedResult.setIcon(icon); + } catch (JMathTeXException e) { + renderedResult.setText(resultString); + renderedResult.setAlignmentY(.9f); + } + + + + + renderedResult.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + renderedResult.setToolTipText("Click to see text versions of this expression."); + renderedResult.addMouseListener(new MouseAdapter() { + + public void mouseClicked(MouseEvent e) { + //eventOutput("Mouse clicked (# of clicks: " + e.getClickCount() + ")", e); + toggle = 0; + toggleView(); + } + + }//end method. + ); + + + inputTextField = new JTextField(10); + inputTextField.setAlignmentY(.7f); + inputTextField.setEditable(true); + inputTextField.setBackground(Color.white); + Font newFontSize = new Font(inputTextField.getFont().getName(), inputTextField.getFont().getStyle(), fontPointSize); + inputTextField.setFont(newFontSize); + inputTextField.setMaximumSize(inputTextField.getPreferredSize()); + inputTextField.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + //The enter key was pressed in the inputTextField. + removeAll(); + add(renderedResult); + LatexComponent.this.console.giveFocus(); + }//end method. + + }); + + inputTextField.getDocument().addDocumentListener(new DocumentListener() { + + public void changedUpdate(DocumentEvent e) { + } + + + public void insertUpdate(DocumentEvent e) { + editCode(); + } + + + public void removeUpdate(DocumentEvent e) { + editCode(); + } + + }); + + + inputTextField.repaint(); + + + this.setBackground(Color.white); + + this.setOpaque(true); + + this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + //this.add(latexResult); + + + spinButton = new SpinButton(); + spinButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + LatexComponent.this.toggleView(); + }//end method. + + }); + spinButton.setEnabled(true); + spinButton.setAlignmentY(.9f); + + + goAwayButton = new GoAwayButton(); + goAwayButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + //LatexComponent.this.goAway(); + //System.out.println(inputTextField.getText()); + }//end method. + + }); + goAwayButton.setEnabled(true); + goAwayButton.setAlignmentY(.9f); + + this.addMouseListener(this); + + + this.add(renderedResult); + this.add(inputTextField); + + + this.setFocusable(true); + + + }//end constructor. + + + public void giveFocus() + { + inputTextField.requestFocusInWindow(); + } + + + public void setScale(int scaleValue) { + + this.fontPointSize = scaleValue; + + TeXIcon icon = texFormula.createTeXIcon(TeXConstants.STYLE_DISPLAY, fontPointSize); + renderedResult.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + renderedResult.setAlignmentY(icon.getBaseLine()); + renderedResult.setIcon(icon); + renderedResult.repaint(); + + + + Font newFontSize = new Font(inputTextField.getFont().getName(), inputTextField.getFont().getStyle(), fontPointSize); + inputTextField.setFont(newFontSize); + inputTextField.setMaximumSize(inputTextField.getPreferredSize()); + inputTextField.repaint(); + + }//end method. + + + void eventOutput(String eventDescription, MouseEvent e) { + //System.out.println(eventDescription + " detected on " + e.getComponent().getClass().getName() + "."); + + } + + + public void mousePressed(MouseEvent e) { + //eventOutput("Mouse pressed (# of clicks: " + e.getClickCount() + ")", e); + } + + + public void mouseReleased(MouseEvent e) { + //eventOutput("Mouse released (# of clicks: " + e.getClickCount() + ")", e); + } + + + public void mouseEntered(MouseEvent e) { + //eventOutput("Mouse entered", e); + } + + + public void mouseExited(MouseEvent e) { + //eventOutput("Mouse exited", e); + } + + + public void mouseClicked(MouseEvent e) { + //eventOutput("Mouse clicked (# of clicks: " + e.getClickCount() + ")", e); + toggle = 0; + toggleView(); + + }//end method. + + + public void toggleView() { + this.removeAll(); + + this.add(renderedResult); + this.add(inputTextField); + + this.revalidate(); + this.repaint(); + } + + + private void goAway() { + this.removeAll(); + this.add(renderedResult); + } + + + public String getCodeResult() { + return resultString; + } + + + public boolean isLatexMode() { + return latexMode; + } + + + public void setLatexMode(boolean latexMode) { + this.latexMode = latexMode; + } + + + + + + public void editCode() { + + if (this.latexMode) { + + latexString = inputTextField.getText(); + } else { + Interpreter mathPiperInterpreter = Interpreters.getSynchronousInterpreter(); + + String mathPiperCode = inputTextField.getText(); + EvaluationResponse response = mathPiperInterpreter.evaluate("TeXForm(" + mathPiperCode + ");"); + + if (response.isExceptionThrown()) { + return; + } + + latexString = response.getResult(); + + if(latexString.equals("TeXForm()")) + { + latexString = "\\square"; + } + + try{ + + latexString = Utility.stripEndQuotesIfPresent(null, -1, latexString); + + latexString = Utility.stripEndDollarSigns(latexString); + } + catch(Exception e) + { + + } + } + + //System.out.println(latexString); + + TeXFormula texFormula2 = null; + try { + texFormula2 = new TeXFormula(latexString); + TeXIcon icon = texFormula2.createTeXIcon(TeXConstants.STYLE_DISPLAY, this.fontPointSize); + renderedResult.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + renderedResult.setAlignmentY(icon.getBaseLine()); + renderedResult.setIcon(icon); + renderedResult.repaint(); + + + texFormula = texFormula2; + } catch (Exception ex) { + } + + } + + + + public String toString() + { + if(latexMode) + { + return this.latexString; + } + else + { + return this.inputTextField.getText(); + } + } + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/MathPiperDocument.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/MathPiperDocument.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/MathPiperDocument.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/MathPiperDocument.java 2010-08-08 08:02:10.000000000 +0000 @@ -0,0 +1,125 @@ +package org.mathpiper.ui.gui.consoles; + +import java.util.Stack; +import javax.swing.JTextPane; +import javax.swing.event.DocumentEvent; +import javax.swing.text.AbstractDocument.DefaultDocumentEvent; +import javax.swing.text.AbstractDocument.ElementEdit; +import javax.swing.text.ComponentView; +import javax.swing.text.DefaultStyledDocument; +import javax.swing.text.Element; +import javax.swing.text.View; + +//Code from http://java-sl.com/tip_refresh_view.html. Stanislav Lapitsky +public class MathPiperDocument extends DefaultStyledDocument { + + public void refresh() { + refresh(0, getLength()); + } + + + public void refresh(int offset, int len) { + DefaultDocumentEvent changes = new DefaultDocumentEvent(offset, len, + DocumentEvent.EventType.CHANGE); + Element root = getDefaultRootElement(); + Element[] removed = new Element[0]; + Element[] added = new Element[0]; + changes.addEdit(new ElementEdit(root, 0, removed, added)); + changes.end(); + fireChangedUpdate(changes); + } + + + public void scanTree(int fontSize) { + Element root = this.getDefaultRootElement(); + Stack nodes = new Stack(); + nodes.push(root); + Element currentNode; + while (!nodes.isEmpty()) { + currentNode = nodes.pop(); + + int numberOfChildren = currentNode.getElementCount(); + + for (int i = 0; i < numberOfChildren; i++) { + Element child = currentNode.getElement(i); + nodes.push(child); + } + + //System.out.print(currentNode.getName() + " " + currentNode.isLeaf() + " " + currentNode.toString() ); + + /*Enumeration attributeNames = currentNode.getAttributes().getAttributeNames(); + while(attributeNames.hasMoreElements()) + { + System.out.println(" " + attributeNames.nextElement().toString()); + }*/ + + + + + /*if (currentNode.isLeaf()) { + SimpleAttributeSet attrs = new SimpleAttributeSet(currentNode.getAttributes()); + StyleConstants.setFontSize(attrs, fontSize); + this.setCharacterAttributes(currentNode.getStartOffset(), 1, attrs, true); + }*/ + + if (currentNode instanceof ComponentView) { + ComponentView componentView = (ComponentView) currentNode; + //System.out.println(componentView.getParent()); + /* + ResultHolder resultHolder = (ResultHolder) componentView.getComponent(); + resultHolder.setScale(fontSize); + */ + + } + + }//end while. + + + + + }//end method. + + + public void scanViews(JTextPane textPane, int fontSize) { + + View root = textPane.getUI().getRootView(textPane); + Stack nodes = new Stack(); + nodes.push(root); + View currentNode; + while (!nodes.isEmpty()) { + currentNode = nodes.pop(); + + for (int i = 0; i < currentNode.getViewCount(); i++) { + View child = currentNode.getView(i); + + nodes.push(child); + + }//end for. + + if (currentNode instanceof ComponentView) { + ComponentView componentView = (ComponentView) currentNode; + + //System.out.println(componentView.getParent()); + + Object object = componentView.getComponent(); + + if(object instanceof RenderingComponent ) + { + RenderingComponent renderingComponent = (RenderingComponent) object; + renderingComponent.setScale(fontSize); + } + } + + /*if (currentNode instanceof ParagraphView) { + ParagraphView paragraphView = (ParagraphView) currentNode; + + }*/ + + }//end while. + + }//end method. + +}//end class. + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/RenderingComponent.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/RenderingComponent.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/RenderingComponent.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/RenderingComponent.java 2010-08-08 08:02:10.000000000 +0000 @@ -0,0 +1,7 @@ +package org.mathpiper.ui.gui.consoles; + + +public interface RenderingComponent +{ + void setScale(int scale); +} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ResizableBorder.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ResizableBorder.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ResizableBorder.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ResizableBorder.java 2010-07-26 03:29:39.000000000 +0000 @@ -0,0 +1,101 @@ +package org.mathpiper.ui.gui.consoles; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +import javax.swing.SwingConstants; +import javax.swing.border.Border; + +// ResizableBorder.java + +public class ResizableBorder implements Border { + private int dist = 8; + + int locations[] = + { + SwingConstants.NORTH, SwingConstants.SOUTH, SwingConstants.WEST, + SwingConstants.EAST, SwingConstants.NORTH_WEST, + SwingConstants.NORTH_EAST, SwingConstants.SOUTH_WEST, + SwingConstants.SOUTH_EAST + }; + + int cursors[] = + { + Cursor.N_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR, + Cursor.E_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR, + Cursor.SW_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR + }; + + public ResizableBorder(int dist) { + this.dist = dist; + } + + public Insets getBorderInsets(Component component) { + return new Insets(dist, dist, dist, dist); + } + + public boolean isBorderOpaque() { + return false; + } + + public void paintBorder(Component component, Graphics g, int x, int y, + int w, int h) { + g.setColor(Color.black); + g.drawRect(x + dist / 2, y + dist / 2, w - dist, h - dist); + + if (component.hasFocus()) { + + + for (int i = 0; i < locations.length; i++) { + Rectangle rect = getRectangle(x, y, w, h, locations[i]); + g.setColor(Color.WHITE); + g.fillRect(rect.x, rect.y, rect.width - 1, rect.height - 1); + g.setColor(Color.BLACK); + g.drawRect(rect.x, rect.y, rect.width - 1, rect.height - 1); + } + } + } + + private Rectangle getRectangle(int x, int y, int w, int h, int location) { + switch (location) { + case SwingConstants.NORTH: + return new Rectangle(x + w / 2 - dist / 2, y, dist, dist); + case SwingConstants.SOUTH: + return new Rectangle(x + w / 2 - dist / 2, y + h - dist, dist, + dist); + case SwingConstants.WEST: + return new Rectangle(x, y + h / 2 - dist / 2, dist, dist); + case SwingConstants.EAST: + return new Rectangle(x + w - dist, y + h / 2 - dist / 2, dist, + dist); + case SwingConstants.NORTH_WEST: + return new Rectangle(x, y, dist, dist); + case SwingConstants.NORTH_EAST: + return new Rectangle(x + w - dist, y, dist, dist); + case SwingConstants.SOUTH_WEST: + return new Rectangle(x, y + h - dist, dist, dist); + case SwingConstants.SOUTH_EAST: + return new Rectangle(x + w - dist, y + h - dist, dist, dist); + } + return null; + } + + public int getCursor(MouseEvent me) { + Component c = me.getComponent(); + int w = c.getWidth(); + int h = c.getHeight(); + + for (int i = 0; i < locations.length; i++) { + Rectangle rect = getRectangle(0, 0, w, h, locations[i]); + if (rect.contains(me.getPoint())) + return cursors[i]; + } + + return Cursor.MOVE_CURSOR; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ResizableComponent.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ResizableComponent.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ResizableComponent.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ResizableComponent.java 2010-07-26 03:29:39.000000000 +0000 @@ -0,0 +1,49 @@ +package org.mathpiper.ui.gui.consoles; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JFrame; +import javax.swing.JPanel; + + +/* ResizableComponent.java */ + +public class ResizableComponent extends JFrame { + + private JPanel panel = new JPanel(null); + private Resizable resizer; + + + public ResizableComponent() { + + add(panel); + + JPanel area = new JPanel(); + area.setBackground(Color.white); + resizer = new Resizable(area); + resizer.setBounds(50, 50, 200, 150); + panel.add(resizer); + + + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(new Dimension(350, 300)); + setTitle("Resizable Component"); + setLocationRelativeTo(null); + + addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent me) { + + requestFocus(); + resizer.repaint(); + } + }); + } + + public static void main(String[] args) { + ResizableComponent rc = new ResizableComponent(); + rc.setVisible(true); + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/Resizable.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/Resizable.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/Resizable.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/Resizable.java 2010-07-26 03:29:39.000000000 +0000 @@ -0,0 +1,160 @@ +package org.mathpiper.ui.gui.consoles; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.MouseInputListener; + +// Resizable.java + +public class Resizable extends JComponent { + + public Resizable(Component comp) { + this(comp, new ResizableBorder(8)); + } + + public Resizable(Component comp, ResizableBorder border) { + setLayout(new BorderLayout()); + //this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + add(comp); + addMouseListener(resizeListener); + addMouseMotionListener(resizeListener); + setBorder(border); + } + + private void resize() { + if (getParent() != null && getParent() instanceof JComponent) { + ((JComponent)getParent()).revalidate(); + } + } + + MouseInputListener resizeListener = new MouseInputAdapter() { + public void mouseMoved(MouseEvent me) { + if (hasFocus()) { + ResizableBorder border = (ResizableBorder)getBorder(); + setCursor(Cursor.getPredefinedCursor(border.getCursor(me))); + } + } + + public void mouseExited(MouseEvent mouseEvent) { + setCursor(Cursor.getDefaultCursor()); + } + + private int cursor; + private Point startPos = null; + + public void mousePressed(MouseEvent me) { + ResizableBorder border = (ResizableBorder)getBorder(); + cursor = border.getCursor(me); + startPos = me.getPoint(); + requestFocus(); + repaint(); + } + + public void mouseDragged(MouseEvent me) { + + if (startPos != null) { + + int x = getX(); + int y = getY(); + int w = getWidth(); + int h = getHeight(); + + int dx = me.getX() - startPos.x; + int dy = me.getY() - startPos.y; + + switch (cursor) { + case Cursor.N_RESIZE_CURSOR: + if (!(h - dy < 50)) { + setBounds(x, y + dy, w, h - dy); + resize(); + } + break; + + case Cursor.S_RESIZE_CURSOR: + if (!(h + dy < 50)) { + setBounds(x, y, w, h + dy); + startPos = me.getPoint(); + resize(); + } + break; + + case Cursor.W_RESIZE_CURSOR: + if (!(w - dx < 50)) { + setBounds(x + dx, y, w - dx, h); + resize(); + } + break; + + case Cursor.E_RESIZE_CURSOR: + if (!(w + dx < 50)) { + setBounds(x, y, w + dx, h); + startPos = me.getPoint(); + resize(); + } + break; + + case Cursor.NW_RESIZE_CURSOR: + if (!(w - dx < 50) && !(h - dy < 50)) { + setBounds(x + dx, y + dy, w - dx, h - dy); + resize(); + } + break; + + case Cursor.NE_RESIZE_CURSOR: + if (!(w + dx < 50) && !(h - dy < 50)) { + setBounds(x, y + dy, w + dx, h - dy); + startPos = new Point(me.getX(), startPos.y); + resize(); + } + break; + + case Cursor.SW_RESIZE_CURSOR: + if (!(w - dx < 50) && !(h + dy < 50)) { + setBounds(x + dx, y, w - dx, h + dy); + startPos = new Point(startPos.x, me.getY()); + resize(); + } + break; + + case Cursor.SE_RESIZE_CURSOR: + if (!(w + dx < 50) && !(h + dy < 50)) { + setBounds(x, y, w + dx, h + dy); + startPos = me.getPoint(); + resize(); + } + break; + + case Cursor.MOVE_CURSOR: + Rectangle bounds = getBounds(); + bounds.translate(dx, dy); + setBounds(bounds); + resize(); + } + + + setCursor(Cursor.getPredefinedCursor(cursor)); + } + } + + public void mouseReleased(MouseEvent mouseEvent) { + startPos = null; + } + }; + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + + public Dimension getMaximumSize() { + return getPreferredSize(); + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ResultHolder.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ResultHolder.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/ResultHolder.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/ResultHolder.java 2010-12-29 01:32:10.000000000 +0000 @@ -0,0 +1,240 @@ +package org.mathpiper.ui.gui.consoles; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JTextField; +import org.mathpiper.ui.gui.Utility; + +import org.scilab.forge.jlatexmath.JMathTeXException; +import org.scilab.forge.jlatexmath.TeXConstants; +import org.scilab.forge.jlatexmath.TeXFormula; +import org.scilab.forge.jlatexmath.TeXIcon; + +public class ResultHolder extends JPanel implements RenderingComponent, MouseListener { + + private TeXFormula texFormula; + private JLabel renderedResult; + private JTextField codeResult; + private JTextField latexResult; + private String resultString; + private String latexString; + private int toggle = 0; + private SpinButton spinButton; + private GoAwayButton goAwayButton; + + + public ResultHolder(String latexString, String resultString, int fontPointSize) { + + + this.latexString = latexString; + this.resultString = resultString; + + + this.renderedResult = new JLabel(); + + try { + texFormula = new TeXFormula(latexString); + TeXIcon icon = texFormula.createTeXIcon(TeXConstants.STYLE_DISPLAY, fontPointSize); + renderedResult.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + renderedResult.setAlignmentY(icon.getBaseLine()); + renderedResult.setIcon(icon); + } catch (JMathTeXException e) { + renderedResult.setText(resultString); + renderedResult.setAlignmentY(.9f); + } + + + + + renderedResult.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + renderedResult.setToolTipText("Click to see text versions of this expression."); + renderedResult.addMouseListener(new MouseAdapter() { + + public void mouseClicked(MouseEvent e) { + //eventOutput("Mouse clicked (# of clicks: " + e.getClickCount() + ")", e); + + int buttonNumber = e.getButton(); + + if (buttonNumber == MouseEvent.BUTTON3) { + JPopupMenu popup = new JPopupMenu(); + JMenuItem menuItem = new JMenuItem("Save image to file"); + menuItem.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Utility.saveImageOfComponent(ResultHolder.this); + } + + }); + + popup.add(menuItem); + popup.show(ResultHolder.this, 10, 10); + + + } else { + toggle = 0; + toggleView(); + } + + } + + }//end method. + ); + + codeResult = new JTextField(resultString); + codeResult.setAlignmentY(.7f); + codeResult.setEditable(false); + codeResult.setBackground(Color.white); + Font newFontSize = new Font(codeResult.getFont().getName(), codeResult.getFont().getStyle(), fontPointSize); + codeResult.setFont(newFontSize); + codeResult.setMaximumSize(codeResult.getPreferredSize()); + codeResult.repaint(); + + + latexResult = new JTextField("$" + latexString + "$"); + latexResult.setAlignmentY(.7f); + latexResult.setEditable(false); + latexResult.setBackground(Color.white); + newFontSize = new Font(latexResult.getFont().getName(), latexResult.getFont().getStyle(), fontPointSize); + latexResult.setFont(newFontSize); + latexResult.setMaximumSize(latexResult.getPreferredSize()); + latexResult.repaint(); + + + this.setBackground(Color.white); + + this.setOpaque(true); + + this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + this.add(renderedResult); + + + spinButton = new SpinButton(); + spinButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + ResultHolder.this.toggleView(); + }//end method. + + }); + spinButton.setEnabled(true); + spinButton.setAlignmentY(.9f); + + + goAwayButton = new GoAwayButton(); + goAwayButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + ResultHolder.this.goAway(); + }//end method. + + }); + goAwayButton.setEnabled(true); + goAwayButton.setAlignmentY(.9f); + + this.addMouseListener(this); + + }//end constructor. + + + public void setScale(int scaleValue) { + + TeXIcon icon = texFormula.createTeXIcon(TeXConstants.STYLE_DISPLAY, scaleValue); + renderedResult.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + renderedResult.setAlignmentY(icon.getBaseLine()); + renderedResult.setIcon(icon); + renderedResult.repaint(); + + + Font newFontSize = new Font(codeResult.getFont().getName(), codeResult.getFont().getStyle(), scaleValue); + codeResult.setFont(newFontSize); + codeResult.setMaximumSize(codeResult.getPreferredSize()); + codeResult.repaint(); + + + newFontSize = new Font(latexResult.getFont().getName(), latexResult.getFont().getStyle(), scaleValue); + latexResult.setFont(newFontSize); + latexResult.setMaximumSize(latexResult.getPreferredSize()); + latexResult.repaint(); + + }//end method. + + + void eventOutput(String eventDescription, MouseEvent e) { + System.out.println(eventDescription + " detected on " + e.getComponent().getClass().getName() + "."); + + } + + + public void mousePressed(MouseEvent e) { + //eventOutput("Mouse pressed (# of clicks: " + e.getClickCount() + ")", e); + } + + + public void mouseReleased(MouseEvent e) { + //eventOutput("Mouse released (# of clicks: " + e.getClickCount() + ")", e); + } + + + public void mouseEntered(MouseEvent e) { + //eventOutput("Mouse entered", e); + } + + + public void mouseExited(MouseEvent e) { + //eventOutput("Mouse exited", e); + } + + + public void mouseClicked(MouseEvent e) { + //eventOutput("Mouse clicked (# of clicks: " + e.getClickCount() + ")", e); + toggle = 0; + toggleView(); + + }//end method. + + + public void toggleView() { + this.removeAll(); + + if (toggle == 1) { + toggle = 0; + this.add(latexResult); + } else { + toggle = 1; + + this.add(codeResult); + } + + this.add(spinButton); + this.add(goAwayButton); + + this.revalidate(); + this.repaint(); + } + + + private void goAway() { + this.removeAll(); + this.add(renderedResult); + } + + + public String getCodeResult() { + return resultString; + } + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/SpinButton.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/SpinButton.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/SpinButton.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/SpinButton.java 2010-07-25 20:35:48.000000000 +0000 @@ -0,0 +1,131 @@ +package org.mathpiper.ui.gui.consoles; + +import java.awt.BasicStroke; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Color; + +import java.awt.Cursor; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import javax.swing.*; +import javax.swing.plaf.UIResource; + + +public class SpinButton extends JButton implements SwingConstants +{ + + private Color shadow; + private Color darkShadow; + private Color highlight; + + private BasicStroke thickStroke = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + + public SpinButton() { + super(); + + this.setBackground(UIManager.getColor("control")); + this.shadow = UIManager.getColor("controlShadow"); + this.darkShadow = UIManager.getColor("controlDkShadow"); + this.highlight = UIManager.getColor("controlLtHighlight"); + + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + + this.setToolTipText("Select a different text view of this expression."); + } + + + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + Color origColor; + boolean isPressed, isEnabled; + int w, h, size; + + w = getSize().width; + h = getSize().height; + origColor = g2d.getColor(); + isPressed = getModel().isPressed(); + isEnabled = isEnabled(); + + g2d.setColor(getBackground()); + g2d.fillRect(1, 1, w-2, h-2); + + /// Draw the border + if (getBorder() != null && !(getBorder() instanceof UIResource)) { + paintBorder(g2d); + } else if (isPressed) { + g2d.setColor(shadow); + g2d.drawRect(0, 0, w-1, h-1); + } else { + //Use the background color set above + g2d.drawLine(0, 0, 0, h-1); + g2d.drawLine(1, 0, w-2, 0); + + g2d.setColor(highlight); //Inner 3D border. + g2d.drawLine(1, 1, 1, h-3); + g2d.drawLine(2, 1, w-3, 1); + + g2d.setColor(shadow); //Inner 3D border. + g2d.drawLine(1, h-2, w-2, h-2); + g2d.drawLine(w-2, 1, w-2, h-3); + + g2d.setColor(darkShadow); //Backdrop shadow. + g2d.drawLine(0, h-1, w-1, h-1); + g2d.drawLine(w-1, h-1, w-1, 0); + } + + + if(h < 6 || w < 6) { + g2d.setColor(origColor); + return; + } + + if (isPressed) { + g2d.translate(1, 1); + } + + + g2d.setColor(Color.BLUE); + g2d.setStroke(thickStroke); + + g2d.drawLine(7, 12, 7, 3); + + g2d.drawLine(7,3, 3, 6); + g2d.drawLine(7,3, 11, 6); + + + + + + + if (isPressed) { + g2d.translate(-1, -1); + } + + + g2d.setColor(origColor); + + } + + + public Dimension getPreferredSize() { + return new Dimension(16, 16); + } + + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/StructureDialog.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/StructureDialog.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/consoles/StructureDialog.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/consoles/StructureDialog.java 2010-07-22 17:07:40.000000000 +0000 @@ -0,0 +1,20 @@ +package org.mathpiper.ui.gui.consoles; + +import javax.swing.*; + +public class StructureDialog extends JDialog { + + EditorPaneStructure pnlStructure; + public StructureDialog(JEditorPane source) { + //super(parent, "Structure"); + super(); + + pnlStructure=new EditorPaneStructure(source); + pnlStructure.refresh(); + getContentPane().add(pnlStructure); + setSize(700,500); + setLocationRelativeTo(null); + + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + } +} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/EnvironmentViewer.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/EnvironmentViewer.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/EnvironmentViewer.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/EnvironmentViewer.java 2011-01-29 01:58:56.000000000 +0000 @@ -13,7 +13,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.ui.gui; @@ -22,16 +21,30 @@ import javax.swing.JFrame; import org.mathpiper.lisp.Environment; import java.awt.Container; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Map; +import javax.swing.CellEditor; import javax.swing.JButton; +import javax.swing.JMenuItem; import javax.swing.JPanel; +import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTable; @@ -43,9 +56,9 @@ import javax.swing.table.AbstractTableModel; import org.mathpiper.lisp.GlobalVariable; import org.mathpiper.lisp.Utility; -import org.mathpiper.lisp.userfunctions.Branch; -import org.mathpiper.lisp.userfunctions.MultipleArityUserFunction; -import org.mathpiper.lisp.userfunctions.SingleArityBranchingUserFunction; +import org.mathpiper.lisp.rulebases.Rule; +import org.mathpiper.lisp.rulebases.MultipleArityRulebase; +import org.mathpiper.lisp.rulebases.SingleArityRulebase; import org.mathpiper.ui.gui.MultiSplitLayout.Divider; import org.mathpiper.ui.gui.MultiSplitLayout.Leaf; import org.mathpiper.ui.gui.MultiSplitLayout.Split; @@ -59,11 +72,14 @@ private List tables = new ArrayList(); private JFrame frame; private FunctionNameComparator functionNameComparator = new FunctionNameComparator(); + private JPopupMenu popupMenu = new JPopupMenu(); + public EnvironmentViewer() { super(); } + public JFrame getViewerFrame(Environment aEnvironment) { frame = new javax.swing.JFrame(); @@ -108,6 +124,9 @@ contentPane.add(splitPane); + + + //Add global state. JTable table = this.getGlobalStateTable(aEnvironment); tables.add(table); @@ -136,15 +155,23 @@ tables.add(scrollPane); multiSplitPane.add(scrollPane, "four"); + JPanel buttonsPanel = new JPanel(); + JButton refreshButton = new JButton("Refresh"); refreshButton.addActionListener(this); refreshButton.setActionCommand("refresh"); - JPanel buttonsPanel = new JPanel(); buttonsPanel.add(refreshButton); + + JButton clearButton = new JButton("Clear"); + clearButton.addActionListener(this); + clearButton.setActionCommand("clear"); + buttonsPanel.add(clearButton); + contentPane.add(buttonsPanel, BorderLayout.NORTH); + frame.pack(); //frame.setAlwaysOnTop(true); frame.setTitle("MathPiper Environment"); @@ -158,25 +185,32 @@ return frame; } + public void actionPerformed(ActionEvent ae) { String actionCommand = ae.getActionCommand(); if (actionCommand.equalsIgnoreCase("refresh")) { - Iterator tablesIterator = tables.iterator(); - while (tablesIterator.hasNext()) { - JTable table = (JTable) tablesIterator.next(); - JScrollPane scrollPane = (JScrollPane) tablesIterator.next(); - //AbstractTableModel model = (AbstractTableModel) table.getModel(); - //model.fireTableDataChanged(); + this.refresh(); + } else if (actionCommand.equalsIgnoreCase("clear")) { + textArea.setText(""); + } - SwingUtilities.updateComponentTreeUI(scrollPane); + }//end method. - } - } + private void refresh() { + Iterator tablesIterator = tables.iterator(); + while (tablesIterator.hasNext()) { + JTable table = (JTable) tablesIterator.next(); + JScrollPane scrollPane = (JScrollPane) tablesIterator.next(); + //AbstractTableModel model = (AbstractTableModel) table.getModel(); + //model.fireTableDataChanged(); + SwingUtilities.updateComponentTreeUI(scrollPane); + } } + /** * Returns a GUI table which contains a sorted list of the user functions. * @@ -195,14 +229,17 @@ private static final long serialVersionUID = 1L; + public int getColumnCount() { return 1; } + public int getRowCount() { return map.size(); } + public String getColumnName(int column) { if (column == 0) { return "User Functions"; @@ -211,6 +248,7 @@ } } + public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 0) { return getKey(rowIndex); @@ -220,6 +258,7 @@ } + private String getKey(int a_index) { String retval = ""; ArrayList keyList = new ArrayList(map.keySet()); @@ -232,11 +271,54 @@ return retval; } + + }); + + table.addMouseListener(new MouseAdapter() { + + private void maybeShowPopup(MouseEvent e) { + JTable jTable = (JTable) e.getSource(); + + if (e.isPopupTrigger() && jTable.isEnabled()) { + Point p = new Point(e.getX(), e.getY()); + int col = jTable.columnAtPoint(p); + int row = jTable.rowAtPoint(p); + + // translate table index to model index + int mcol = jTable.getColumn( + jTable.getColumnName(col)).getModelIndex(); + + if (row >= 0 && row < jTable.getRowCount()) { + cancelCellEditing(jTable); + + // create popup menu... + JPopupMenu contextMenu = createContextMenu(row, mcol, jTable, map); + + // ... and show it + if (contextMenu != null + && contextMenu.getComponentCount() > 0) { + contextMenu.show(jTable, p.x, p.y); + } + } + } + } + + + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + }); return table; }//end class + /** * Returns a GUI table which contains a sorted list of the builtin functions. * @@ -255,14 +337,17 @@ private static final long serialVersionUID = 1L; + public int getColumnCount() { return 1; } + public int getRowCount() { return map.size(); } + public String getColumnName(int column) { if (column == 0) { return "Built-In Functions"; @@ -271,6 +356,7 @@ } } + public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 0) { return getKey(rowIndex); @@ -280,6 +366,7 @@ } + private String getKey(int a_index) { String retval = ""; ArrayList keyList = new ArrayList(map.keySet()); @@ -292,11 +379,13 @@ return retval; } + }); return table; }//end class + /** * Returns a GUI table which contains a sorted list of the global variables. * @@ -315,14 +404,17 @@ private static final long serialVersionUID = 1L; + public int getColumnCount() { return 2; } + public int getRowCount() { return map.size(); } + public String getColumnName(int column) { if (column == 0) { return "Global Variables"; @@ -331,6 +423,7 @@ } } + public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 0) { return getKey(rowIndex); @@ -340,6 +433,7 @@ } + private String getKey(int a_index) { String retval = ""; ArrayList keyList = new ArrayList(map.keySet()); @@ -352,11 +446,56 @@ return retval; } + + }); + + + table.addMouseListener(new MouseAdapter() { + + private void maybeShowPopup(MouseEvent e) { + JTable jTable = (JTable) e.getSource(); + + if (e.isPopupTrigger() && jTable.isEnabled()) { + Point p = new Point(e.getX(), e.getY()); + int col = jTable.columnAtPoint(p); + int row = jTable.rowAtPoint(p); + + // translate table index to model index + int mcol = jTable.getColumn( + jTable.getColumnName(col)).getModelIndex(); + + if (row >= 0 && row < jTable.getRowCount()) { + cancelCellEditing(jTable); + + // create popup menu... + JPopupMenu contextMenu = createContextMenu(row, mcol, jTable, map); + + // ... and show it + if (contextMenu != null + && contextMenu.getComponentCount() > 0) { + contextMenu.show(jTable, p.x, p.y); + } + } + } + } + + + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + }); + return table; }//end method. + /** * Returns a GUI table which contains a sorted list of the tokens. * @@ -375,14 +514,17 @@ private static final long serialVersionUID = 1L; + public int getColumnCount() { return 1; } + public int getRowCount() { return m_hash.size(); } + public String getColumnName(int column) { if (column == 0) { return "Tokens"; @@ -391,6 +533,7 @@ } } + public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 0) { return getKey(rowIndex); @@ -400,6 +543,7 @@ } + private String getKey(int a_index) { String retval = ""; ArrayList keyList = new ArrayList(m_hash.keySet()); @@ -412,6 +556,7 @@ return retval; } + }); return table; @@ -422,11 +567,13 @@ private JTable table; private Environment iEnvironment; + public GlobalVariableListener(JTable table, Environment aEnvironment) { this.table = table; this.iEnvironment = aEnvironment; } + public void valueChanged(ListSelectionEvent event) { if (event.getValueIsAdjusting()) { return; @@ -442,7 +589,7 @@ String name = (String) table.getValueAt(row, 0); GlobalVariable o = (GlobalVariable) table.getValueAt(row, 1); try { - String data = Utility.printExpression(o.getValue(), iEnvironment, 0); + String data = Utility.printMathPiperExpression(-1, o.getValue(), iEnvironment, 0); //System.out.println(data); textArea.append(name + ": " + data + "\n"); textArea.setCaretPosition(textArea.getDocument().getLength()); @@ -453,6 +600,7 @@ table.clearSelection(); }//end method + }//end class. private class FunctionListener implements ListSelectionListener { @@ -460,11 +608,13 @@ private JTable table; private Environment iEnvironment; + public FunctionListener(JTable table, Environment aEnvironment) { this.table = table; this.iEnvironment = aEnvironment; } + public void valueChanged(ListSelectionEvent event) { if (event.getValueIsAdjusting()) { return; @@ -481,12 +631,11 @@ String name = (String) table.getValueAt(row, 0); - MultipleArityUserFunction multipleArityUserfunction = (MultipleArityUserFunction) table.getModel().getValueAt(row, 1); + MultipleArityRulebase multipleArityUserfunction = (MultipleArityRulebase) table.getModel().getValueAt(row, 1); String defFileLocation = multipleArityUserfunction.iFileLocation; String location = "Not specified in a .def file."; - if(defFileLocation != null) - { + if (defFileLocation != null) { location = defFileLocation; } @@ -499,14 +648,14 @@ Iterator multipleArityUserFunctionIterator = multipleArityUserfunction.getFunctions(); while (multipleArityUserFunctionIterator.hasNext()) { - SingleArityBranchingUserFunction userFunction = (SingleArityBranchingUserFunction) multipleArityUserFunctionIterator.next(); + SingleArityRulebase userFunction = (SingleArityRulebase) multipleArityUserFunctionIterator.next(); Iterator rulesIterator = userFunction.getRules(); while (rulesIterator.hasNext()) { - Branch branchRuleBase = (Branch) rulesIterator.next(); + Rule branchRuleBase = (Rule) rulesIterator.next(); - String ruleDump = org.mathpiper.lisp.Utility.dumpRule(branchRuleBase, iEnvironment, userFunction); + String ruleDump = org.mathpiper.lisp.Utility.dumpRule(-1, branchRuleBase, iEnvironment, userFunction); textArea.append(ruleDump); textArea.append("\n"); textArea.setCaretPosition(textArea.getDocument().getLength()); @@ -519,6 +668,7 @@ table.clearSelection(); }//end method. + }//end class. private class DummyListener implements ListSelectionListener { @@ -526,11 +676,13 @@ private JTable table; private Environment iEnvironment; + public DummyListener(JTable table, Environment aEnvironment) { this.table = table; this.iEnvironment = aEnvironment; } + public void valueChanged(ListSelectionEvent event) { if (event.getValueIsAdjusting()) { return; @@ -544,14 +696,218 @@ table.clearSelection(); }//end method. - } //end class. + } //end class. - private class FunctionNameComparator implements Comparator{ + private class FunctionNameComparator implements Comparator { public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }//end method. + }//end class. -}//end class. \ No newline at end of file +//============================ + private static final String PROP_CHANGE_QUANTITY = "CHANGE_QUANTITY"; + + + private static String getClipboardContents(Object requestor) { + Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(requestor); + if (t != null) { + DataFlavor df = DataFlavor.stringFlavor; + if (df != null) { + try { + Reader r = df.getReaderForText(t); + char[] charBuf = new char[512]; + StringBuffer buf = new StringBuffer(); + int n; + while ((n = r.read(charBuf, 0, charBuf.length)) > 0) { + buf.append(charBuf, 0, n); + } + r.close(); + return (buf.toString()); + } catch (IOException ex) { + ex.printStackTrace(); + } catch (UnsupportedFlavorException ex) { + ex.printStackTrace(); + } + } + } + return null; + } + + + private static boolean isClipboardContainingText(Object requestor) { + Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(requestor); + return t != null + && (t.isDataFlavorSupported(DataFlavor.stringFlavor) || t.isDataFlavorSupported(DataFlavor.plainTextFlavor)); + } + + + private static void setClipboardContents(String s) { + StringSelection selection = new StringSelection(s); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents( + selection, selection); + } + + private JPanel jContentPane; + private JScrollPane jScrollPane; + + + private void cancelCellEditing(JTable table) { + CellEditor ce = table.getCellEditor(); + if (ce != null) { + ce.cancelCellEditing(); + } + } + + + private JPopupMenu createContextMenu(final int rowIndex, final int columnIndex, JTable table, Map map) { + + final Map finalMap = map; + + JPopupMenu contextMenu = new JPopupMenu(); + + final JTable jTable = table; + + JMenuItem copyMenu = new JMenuItem(); + copyMenu.setText("Copy"); + copyMenu.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Object value = jTable.getModel().getValueAt(rowIndex, + columnIndex); + setClipboardContents(value == null ? "" : value.toString()); + } + + }); + contextMenu.add(copyMenu); + + JMenuItem pasteMenu = new JMenuItem(); + pasteMenu.setText("Paste"); + if (isClipboardContainingText(this) && table.getModel().isCellEditable(rowIndex, columnIndex)) { + pasteMenu.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + String value = getClipboardContents(EnvironmentViewer.this); + jTable.getModel().setValueAt(value, rowIndex, + columnIndex); + } + + }); + } else { + pasteMenu.setEnabled(false); + } + contextMenu.add(pasteMenu); + + + JMenuItem unbindMenu = new JMenuItem(); + unbindMenu.setText("Unbind"); + + unbindMenu.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + + Object object = jTable.getModel().getValueAt(rowIndex, columnIndex); + + if (object instanceof String) { + String string = (String) object; + + finalMap.remove(string); + + EnvironmentViewer.this.refresh(); + } + int x = 1; + } + + }); + + contextMenu.add(unbindMenu); + + + + switch (columnIndex) { + case 1: + break; + case 2: + break; + /* + case 3: + contextMenu.addSeparator(); + ActionListener changer = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + JMenuItem sourceItem = (JMenuItem) e.getSource(); + Object value = sourceItem.getClientProperty(PROP_CHANGE_QUANTITY); + if (value instanceof Integer) { + Integer changeValue = (Integer) value; + Integer currentValue = (Integer) jTable.getModel().getValueAt(rowIndex, columnIndex); + jTable.getModel().setValueAt( + new Integer(currentValue.intValue() + + changeValue.intValue()), rowIndex, + columnIndex); + } + } + + }; + JMenuItem changeItem = new JMenuItem(); + changeItem.setText("+1"); + changeItem.putClientProperty(PROP_CHANGE_QUANTITY, + new Integer(1)); + changeItem.addActionListener(changer); + contextMenu.add(changeItem); + + changeItem = new JMenuItem(); + changeItem.setText("-1"); + changeItem.putClientProperty(PROP_CHANGE_QUANTITY, + new Integer(-1)); + changeItem.addActionListener(changer); + contextMenu.add(changeItem); + + changeItem = new JMenuItem(); + changeItem.setText("+10"); + changeItem.putClientProperty(PROP_CHANGE_QUANTITY, + new Integer(10)); + changeItem.addActionListener(changer); + contextMenu.add(changeItem); + + changeItem = new JMenuItem(); + changeItem.setText("-10"); + changeItem.putClientProperty(PROP_CHANGE_QUANTITY, + new Integer(-10)); + changeItem.addActionListener(changer); + contextMenu.add(changeItem); + + changeItem = null; + break; + case 4: + break; + */ + default: + break; + } + return contextMenu; + } + + + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(new BorderLayout()); + jContentPane.add(getJScrollPane(), + java.awt.BorderLayout.CENTER); + } + return jContentPane; + } + + + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + //jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/FunctionInfo.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/FunctionInfo.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/FunctionInfo.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/FunctionInfo.java 2010-05-12 06:43:51.000000000 +0000 @@ -21,7 +21,7 @@ public class FunctionInfo { private String name; - private String scope; + private String access; private String description; public FunctionInfo() @@ -32,14 +32,14 @@ { this.name = name; this.description = description; - this.scope = "public"; + this.access = "public"; }//end constructor. - public FunctionInfo(String name, String scope, String description) + public FunctionInfo(String name, String access, String description) { this.name = name; - this.scope = scope; + this.access = access; this.description = description; }//end constructor. @@ -60,12 +60,12 @@ return description; }//end method. - public String getScope() + + public String getAccess() { - return scope; + return access; }//end method. - public String toString() { return(this.name); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/FunctionInfoTree.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/FunctionInfoTree.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/FunctionInfoTree.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/FunctionInfoTree.java 2010-05-12 06:43:51.000000000 +0000 @@ -43,12 +43,17 @@ FunctionInfo functionInfo = (FunctionInfo) userObject; - String scope = functionInfo.getScope(); + String access = functionInfo.getAccess(); - if (scope.equals("private")) { + if (access.equals("private")) { //this.setTextSelectionColor(Color.RED); //this.setTextNonSelectionColor(Color.RED); this.setForeground(Color.RED); + } + else if (access.equals("experimental")) { + //this.setTextSelectionColor(Color.RED); + //this.setTextNonSelectionColor(Color.RED); + this.setForeground(new Color(155,0,153)); } else { //this.setTextSelectionColor(Color.BLACK); //this.setTextNonSelectionColor(Color.BLACK); diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/FunctionTreePanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/FunctionTreePanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/FunctionTreePanel.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/FunctionTreePanel.java 2011-02-05 02:56:30.000000000 +0000 @@ -16,7 +16,6 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.ui.gui.help; - import java.awt.BorderLayout; import java.awt.Container; import java.awt.Dimension; @@ -27,7 +26,9 @@ import java.awt.event.ItemListener; import java.io.BufferedInputStream; import java.io.BufferedReader; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.net.URL; @@ -37,6 +38,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; @@ -44,14 +48,20 @@ import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JLabel; +import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; @@ -60,7 +70,6 @@ import org.mathpiper.interpreters.Interpreter; import org.mathpiper.interpreters.Interpreters; - public class FunctionTreePanel extends JPanel implements TreeSelectionListener, HyperlinkListener { private JScrollPane docsScrollPane; @@ -74,98 +83,146 @@ private FunctionInfoTree functionsTree; private Map documentationIndex; private RandomAccessFile documentFile; - private URL documentationURL; private JEditorPane editorPane; private static StringBuilder seeFunctionsBuilder = new StringBuilder(); - private ClassLoader classLoader; private List pageList; private ToolPanel toolPanel = null; private String selectedFunctionName = ""; private boolean showPrivateFunctions = false; + private boolean showExperimentalFunctions = true; private JScrollPane treeViewScrollPane; private JSplitPane splitPane; private JPanel treePanel; + private ArrayList helpListeners; - public FunctionTreePanel(ClassLoader classLoader) { - this.classLoader = classLoader; + public FunctionTreePanel() throws FileNotFoundException { + + helpListeners = new ArrayList(); this.setLayout(new BorderLayout()); pageList = new ArrayList(); pageList.add("HomePage"); - URL fileURL = classLoader.getSystemResource("org/mathpiper/ui/gui/help/data/function_categories.txt"); - if (fileURL != null) //File is on the classpath. - { - //System.out.println("Found categories file."); - loadCategories(fileURL); - loadDocumentationIndex(classLoader.getSystemResource("org/mathpiper/ui/gui/help/data/documentation_index.txt")); + InputStream functionCategoriesStream = FunctionTreePanel.class.getResourceAsStream("/org/mathpiper/ui/gui/help/data/function_categories.txt"); - documentationURL = classLoader.getSystemResource("org/mathpiper/ui/gui/help/data/documentation.txt"); -//System.out.println(documentationURL); + if (functionCategoriesStream == null) { + throw new FileNotFoundException("The file function_categories.txt was not found."); + } - createTree(); + loadCategories(functionCategoriesStream); - ToolTipManager.sharedInstance().registerComponent(functionsTree); + InputStream documentationIndexStream = FunctionTreePanel.class.getResourceAsStream("/org/mathpiper/ui/gui/help/data/documentation_index.txt"); -//tree.setRootVisible(false); + if (documentationIndexStream == null) { + throw new FileNotFoundException("The file documentation_index.txt was not found."); + } - treePanel = new JPanel(); - treePanel.setLayout(new BorderLayout()); - treePanel.add(functionsTree); - treeViewScrollPane = new JScrollPane(treePanel); - treeViewScrollPane.getVerticalScrollBar().setUnitIncrement(60); - treeViewScrollPane.getVerticalScrollBar().setBlockIncrement(180); + loadDocumentationIndex(documentationIndexStream); + createTree(); + ToolTipManager.sharedInstance().registerComponent(functionsTree); - editorPane = new JEditorPane(); - editorPane.setEditable(false); - editorPane.setEditorKit(new javax.swing.text.html.HTMLEditorKit()); - editorPane.addHyperlinkListener(this); - //editorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); + treePanel = new JPanel(); + treePanel.setLayout(new BorderLayout()); + treePanel.add(functionsTree); + treeViewScrollPane = new JScrollPane(treePanel); + treeViewScrollPane.getVerticalScrollBar().setUnitIncrement(60); + treeViewScrollPane.getVerticalScrollBar().setBlockIncrement(180); - //JdocsScrollPane editorScrollPane = new JScrollPane(editorPane); - docsScrollPane = new JScrollPane(editorPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeViewScrollPane, docsScrollPane); - splitPane.setOneTouchExpandable(true); - //tree.getPreferredScrollableViewportSize().width; - splitPane.setDividerLocation(290); - this.add(splitPane); - toolPanel = new ToolPanel(); - home(); + editorPane = new JEditorPane(); + editorPane.setEditable(false); + editorPane.setEditorKit(new javax.swing.text.html.HTMLEditorKit()); + editorPane.addHyperlinkListener(this); + //editorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); + + //JdocsScrollPane editorScrollPane = new JScrollPane(editorPane); + docsScrollPane = new JScrollPane(editorPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + + + JTabbedPane tabbedPane = new JTabbedPane(); + + JPanel treePanelContainer = new JPanel(); + + + //Collapse tree button. + JButton collapseButton = new javax.swing.JButton("Collapse"); + collapseButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + collapse(); + } + + }); + collapseButton.setEnabled(true); + collapseButton.setToolTipText("Collapse function tree."); + add(collapseButton); + + treePanelContainer.setLayout(new BorderLayout()); + + Box treeToolPanel = new Box(BoxLayout.X_AXIS); + + treeToolPanel.add(collapseButton); + + treeToolPanel.add(Box.createHorizontalGlue()); + + treePanelContainer.add(treeToolPanel, BorderLayout.NORTH); + + treePanelContainer.add(treeViewScrollPane); + + tabbedPane.addTab("Functions", null, treePanelContainer, "Functions tree."); + + tabbedPane.addTab("Search", null, new SearchPanel(), "Search the function descriptions."); + + + splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tabbedPane, docsScrollPane); + splitPane.setOneTouchExpandable(true); + //tree.getPreferredScrollableViewportSize().width; + splitPane.setDividerLocation(290); + this.add(splitPane); + + toolPanel = new ToolPanel(); + home(); - }//end if. }//end constructor. - private void loadCategories(URL url) { + private void loadCategories(InputStream inputStream) { BufferedReader categoriesFile = null; List userFunctions = new ArrayList(); List programmerFunctions = new ArrayList(); List operators = new ArrayList(); + + + try { - categoriesFile = new BufferedReader(new InputStreamReader(url.openStream())); + categoriesFile = new BufferedReader(new InputStreamReader(inputStream)); String line; + + while ((line = categoriesFile.readLine()) != null) { line = line + ",Alphabetical"; - String[] functionDataLine = line.split(","); - String functionCategory = functionDataLine[0].trim(); + List functionDatalineFields = parseCSV(line); - String[] functionData = Arrays.copyOfRange(functionDataLine, 1/*Removing overall category*/, functionDataLine.length); + String functionCategory = functionDatalineFields.get(0).trim(); + + functionDatalineFields.remove(0); + + String[] functionDatalineFieldsArray = functionDatalineFields.toArray(new String[functionDatalineFields.size()]); //line.split(","); if (functionCategory.equalsIgnoreCase("User Functions")) { - userFunctions.add(functionData); + userFunctions.add(functionDatalineFieldsArray); } else if (functionCategory.equalsIgnoreCase("Programmer Functions")) { - programmerFunctions.add(functionData); + programmerFunctions.add(functionDatalineFieldsArray); } else { - operators.add(functionData); + operators.add(functionDatalineFieldsArray); } }//end while. @@ -189,10 +246,36 @@ }//end method. + private List parseCSV(String line) { + List list = new ArrayList(); + String CSV_PATTERN = "\"([^\"]+?)\",?|([^,]+),?|,"; + Pattern csvRE = Pattern.compile(CSV_PATTERN); + Matcher m = csvRE.matcher(line); + // For each field + while (m.find()) { + String match = m.group(); + if (match == null) { + break; + } + if (match.endsWith(",")) { // trim trailing , + match = match.substring(0, match.length() - 1); + } + if (match.startsWith("\"")) { // assume also ends with + match = match.substring(1, match.length() - 1); + } + //if (match.length() == 0) + //match = null; + list.add(match); + } + return list; + } + + private void populateUserFunctionNodeWithCategories() { userFunctionsNode = new DefaultMutableTreeNode(new FunctionInfo("User Functions", "Functions for MathPiper users.")); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Alphabetical", "All functions in alphabetical order."))); + userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Analytic Geometry", "Functions that are related to analytic geometry."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Built In", "Functions that are implemented in Java."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Calculus Related (Symbolic)", "Functions for differentiation, integration, and solving of equations."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Combinatorics", "Combinatorics related functions."))); @@ -201,7 +284,7 @@ userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Control Flow", "Controls the order in which statements or function calls are executed."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Differential Equations", "In this section, some facilities for solving differential equations are described. Currently only simple equations without auxiliary conditions are supported."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Expression Manipulation", "This section describes functions which allow expressions to be manipulated."))); - userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Expression Simplification", "This section describes function that allow simplification of expressions."))); + userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Expression Simplification", "This section describes functions that allow simplification of expressions."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Functional Operators", "These operators can help the user to program in the style of functional programming languages such as Miranda or Haskell."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Input/Output", "Functions for input, output, and plotting."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Linear Algebra", "Functions used to manipulate vectors (represented as lists) and matrices (represented as lists of lists)."))); @@ -221,11 +304,14 @@ userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Series", "Functions which operate on series."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Solvers (Numeric)", "Functions for solving equations numerically."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Solvers (Symbolic)", "By solving one tries to find a mathematical object that meets certain criteria."))); - userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Special", "In this section, special and transcendental mathematical functions are described."))); + userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Special Functions", "In this section, special and transcendental mathematical functions are described."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Statistics & Probability", "Statistics & Probability."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("String Manipulation", "Functions for manipulating strings."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Transforms", "In this section, some facilities for various transforms are described."))); + userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Trigonometry (Numeric)", "Functions for working with trigonometry numerically."))); + userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Trigonometry (Symbolic)", "Functions for working with trigonometry symbolically."))); userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Variables", "Functions that work with variables."))); + userFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Visualization", "Functions that help visualize data."))); }//end method. @@ -235,6 +321,7 @@ programmerFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Alphabetical", "All functions in alphabetical order."))); programmerFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Built In", "MathPiper has a small set of built-in functions and a large library of user-defined functions. Some built-in functions are in this section."))); + programmerFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Debugging", "Functions used for debugging MathPiper code."))); programmerFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Error Reporting", "Functions which are useful for reporting errors to the user."))); programmerFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Native Objects", "Functions for allowing the MathPiper interpreter access native code."))); programmerFunctionsNode.add(new DefaultMutableTreeNode(new FunctionInfo("Numerical (Arbitrary Precision)", "Functions for programming numerical calculations with arbitrary precision."))); @@ -247,37 +334,46 @@ private void populateNode(DefaultMutableTreeNode treeNode, String[][] functionDataStringArray) { for (int row = 0; row < functionDataStringArray.length; row++) { - if ((this.showPrivateFunctions == true && functionDataStringArray[row][1].equals("private")) || functionDataStringArray[row][1].equals("public")) { - - //Populate. - for (int column = 3; column < functionDataStringArray[row].length; column++) { - String category = functionDataStringArray[row][column]; - //System.out.println("XXXXX " + descriptionsStringArray[row][column]); - - - boolean hasCategory = false; - Enumeration children = treeNode.children(); - for (; children.hasMoreElements();) { - DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement(); - if (child.getUserObject().toString().equalsIgnoreCase(category)) //Add leaf to existing category. - { - child.add(new DefaultMutableTreeNode(new FunctionInfo(functionDataStringArray[row][0], functionDataStringArray[row][1], functionDataStringArray[row][2]))); - hasCategory = true; - } + if (this.showPrivateFunctions == true && functionDataStringArray[row][1].equals("private")) { + //Pass through to populate. + } else if (this.showExperimentalFunctions == true && functionDataStringArray[row][1].equals("experimental")) { + //Pass through to populate. + } else if (functionDataStringArray[row][1].equals("public")) { + //Pass through to populate. + } else { + //Skip populate. + continue; + } + //Populate. + for (int column = 3; column < functionDataStringArray[row].length; column++) { + String category = functionDataStringArray[row][column]; + //System.out.println("XXXXX " + descriptionsStringArray[row][column]); - }//end for. - if (hasCategory == false) { - DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(new FunctionInfo(functionDataStringArray[row][0], functionDataStringArray[row][1], functionDataStringArray[row][2])); - DefaultMutableTreeNode categoryNode = new DefaultMutableTreeNode(functionDataStringArray[row][column]); - categoryNode.add(leaf); - treeNode.add(categoryNode); + boolean hasCategory = false; + Enumeration children = treeNode.children(); + for (; children.hasMoreElements();) { + DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement(); + if (child.getUserObject().toString().equalsIgnoreCase(category)) //Add leaf to existing category. + { + child.add(new DefaultMutableTreeNode(new FunctionInfo(functionDataStringArray[row][0], functionDataStringArray[row][1], functionDataStringArray[row][2]))); + hasCategory = true; } - }//end column for. - }//end public/private if. + }//end for. + + if (hasCategory == false) { + DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(new FunctionInfo(functionDataStringArray[row][0], functionDataStringArray[row][1], functionDataStringArray[row][2])); + DefaultMutableTreeNode categoryNode = new DefaultMutableTreeNode(functionDataStringArray[row][column]); + categoryNode.add(leaf); + treeNode.add(categoryNode); + } + + }//end column for. + + }//end row for. @@ -385,10 +481,10 @@ }//end method. - private void loadDocumentationIndex(URL url) { + private void loadDocumentationIndex(InputStream inputStream) { documentationIndex = new HashMap(); try { - BufferedReader documentationIndexReader = new BufferedReader(new InputStreamReader(url.openStream())); + BufferedReader documentationIndexReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = documentationIndexReader.readLine()) != null) { @@ -435,7 +531,7 @@ public boolean viewFunction(String functionName, boolean save) { if (this.documentationIndex.containsKey(functionName)) { - + String functionIndexesString = (String) this.documentationIndex.get(functionName); String[] functionIndexes = functionIndexesString.split(","); int startIndex = Integer.parseInt(functionIndexes[0]); @@ -446,22 +542,27 @@ //System.out.println("yyyy " + functionName + " " + startIndex + " " + endIndex + " " + length); try { - //documentFile.seek(startIndex); - //documentFile.read(documentationData, 0, length); + BufferedInputStream documentationStream = new BufferedInputStream(FunctionTreePanel.class.getResourceAsStream("/org/mathpiper/ui/gui/help/data/documentation.txt")); + + if (documentationStream == null) { + throw new FileNotFoundException("The file documentation.txt was not found."); + } + + documentationStream.skip(startIndex); + documentationStream.read(documentationData, 0, length); + //docsStream.close(); + - // System.out.print("docsurl: " + documentationURL); - BufferedInputStream docsStream = new BufferedInputStream(documentationURL.openStream()); - docsStream.skip(startIndex); - docsStream.read(documentationData, 0, length); - docsStream.close(); String documentationDataString = new String(documentationData); - documentationDataString = documentationDataString.replace("$", ""); + //documentationDataString = documentationDataString.replace("$", ""); String html = textToHtml(documentationDataString); + html = processLatex(html); + setPage(functionName, html, save); //functionInfo = nodeInfo; @@ -479,15 +580,93 @@ }//end method. + public static String processLatex(String html) { + StringBuilder stringBuilder = new StringBuilder(); + + int startIndex = -1; + + int endIndex = -1; + + for (int index = 0; index < html.length(); index++) { + if (html.charAt(index) == '$') { + if (html.charAt(index - 1) == '\\') { + //Strip \ character in escaped \$. + stringBuilder.deleteCharAt(stringBuilder.length() - 1); + stringBuilder.append(html.charAt(index)); + } else { + if (startIndex == -1) { + startIndex = index + 1; + + endIndex = 0; + } else { + endIndex = index; + + String latexCode = html.substring(startIndex, endIndex); + + latexCode = latexCode.replace(" ", ""); + + //String latexEmbedString = " "; + + String latexEmbedString = " "; + + //System.out.println("LATEX: " + latexEmbedString); + + stringBuilder.append(latexEmbedString); + + startIndex = -1; + + endIndex = -1; + }//end else. + + }//end else. + } else { + if (endIndex == -1) { + stringBuilder.append(html.charAt(index)); + } + } + }//end for. + + + return stringBuilder.toString(); + } + + private static String applyBold(String line) { - line = line.replaceAll("\\{", ""); - line = line.replaceAll("\\}", ""); - return line; + + + //line = line.replaceAll("\\{", ""); + //line = line.replaceAll("\\}", ""); + + StringBuilder stringBuilder = new StringBuilder(); + + int startIndex = -1; + + int endIndex = -1; + + for (int index = 0; index < line.length(); index++) { + if (line.charAt(index) == '{') { + stringBuilder.append(""); + } else if (line.charAt(index) == '}') { + stringBuilder.append(""); + } else { + stringBuilder.append(line.charAt(index)); + } + + }//end for. + + + return stringBuilder.toString(); }//end method. + /*private static String applyPre(String line) { + line = line.replaceAll("\\[", "

    ");
    +    line = line.replaceAll("\\]", "
    "); + return line; + }//end method. + */ public static String textToHtml(String scriptCode) { -//s = "*CMD D --- take derivative of expression with respect to variable\n*STD\n*CALL\n D(variable) expression\n D(list) expression\n D(variable,n) expression\n\n*PARMS\n\n{variable} -- variable\n\n{list} -- a list of variables\n\n{expression} -- expression to take derivatives of\n\n{n} -- order of derivative\n\n*DESC\n\nThis function calculates the derivative of the expression {expr} with\nrespect to the variable {var} and returns it. If the third calling\nformat is used, the {n}-th derivative is determined. Yacas knows\nhow to differentiate standard functions such as {Ln}\nand {Sin}.\n\nThe {D} operator is threaded in both {var} and\n{expr}. This means that if either of them is a list, the function is\napplied to each entry in the list. The results are collected in\nanother list which is returned. If both {var} and {expr} are a\nlist, their lengths should be equal. In this case, the first entry in\nthe list {expr} is differentiated with respect to the first entry in\nthe list {var}, the second entry in {expr} is differentiated with\nrespect to the second entry in {var}, and so on.\n\nThe {D} operator returns the original function if $n=0$, a common\nmathematical idiom that simplifies many formulae.\n\n*E.G.\n\n In> D(x)Sin(x*y)\n Out> y*Cos(x*y);\n In> D({x,y,z})Sin(x*y)\n Out> {y*Cos(x*y),x*Cos(x*y),0};\n In> D(x,2)Sin(x*y)\n Out> -Sin(x*y)*y^2;\n In> D(x){Sin(x),Cos(x)}\n Out> {Cos(x),-Sin(x)};\n\n*SEE Integrate, Taylor, Diverge, Curl\n"; +//s = "*CMD D --- take derivative of expression with respect to variable\n*STD\n*CALL\n D(variable) expression\n D(list) expression\n D(variable,n) expression\n\n*PARMS\n\n{variable} -- variable\n\n{list} -- a list of variables\n\n{expression} -- expression to take derivatives of\n\n{n} -- order of derivative\n\n*DESC\n\nThis function calculates the derivative of the expression {expr} with\nrespect to the variable {var} and returns it. If the third calling\nformat is used, the {n}-th derivative is determined. Yacas knows\nhow to differentiate standard functions such as {Ln}\nand {Sin}.\n\nThe {D} operator is threaded in both {var} and\n{expr}. This means that if either of them is a list, the function is\napplied to each entry in the list. The results are collected in\nanother list which is returned. If both {var} and {expr} are a\nlist, their lengths should be equal. In this case, the first entry in\nthe list {expr} is differentiated with respect to the first entry in\nthe list {var}, the second entry in {expr} is differentiated with\nrespect to the second entry in {var}, and so on.\n\nThe {D} operator returns the original function if $n=0$, a common\nmathematical idiom that simplifies many formulae.\n\n*E.G.\n\n In> D(x)Sin(x*y)\n Result: y*Cos(x*y);\n In> D({x,y,z})Sin(x*y)\n Result: {y*Cos(x*y),x*Cos(x*y),0};\n In> D(x,2)Sin(x*y)\n Result: -Sin(x*y)*y^2;\n In> D(x){Sin(x),Cos(x)}\n Result: {Cos(x),-Sin(x)};\n\n*SEE Integrate, Taylor, Diverge, Curl\n"; scriptCode = scriptCode.replace("&", "&"); scriptCode = scriptCode.replace("<", "<"); @@ -591,7 +770,8 @@ } line = applyBold(line); - //foldOutput = foldOutput + line; + //line = applyPre(line); Removed the []
     symbol replacement because it clashes with normal brackets.
    +
     
     
                         html.append(line);
    @@ -619,7 +799,7 @@
                             break;
                         }
                         if (line.equalsIgnoreCase("")) {
    -                        html.append("
    \n"); + html.append("\n"); continue; } @@ -643,11 +823,33 @@ seeFunctionsBuilder.append("" + seeFunction + ", "); } - html.append("

    \nSee also:\n

    " + seeFunctionsBuilder.toString() + "\n"); + html.append("

    See also:

    " + seeFunctionsBuilder.toString() + "\n"); seeFunctionsBuilder.delete(0, seeFunctionsBuilder.length()); - } + } else if (line.startsWith("*SOURCE")) { + + html.append("

    Source:

    "); + + line = line.substring(7, line.length()); + line = line.trim(); + + if(line.endsWith(".mpw")) + { + html.append(line); + html.append("
    View source code\n"); + } + else + { + html.append( + "This is a built-in function and its source file is written in Java.
    " + + "The path to the Java source code for this function is:
    " + line.substring(1, line.length()) + "

    " + + "The source code can be browsed on the MathPiper project site at:
    " + + "http://code.google.com/p/mathpiper/source/browse/"); + + }//end else. + + }//end else/if. @@ -666,8 +868,63 @@ //System.out.println("YYYPiperDocsYYY: " + url.getPath() + " reference: " + url.getRef() + " query: " + url.getQuery() ); if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - String urlString = url.toString(); - String functionName = urlString.substring(7, urlString.length()); + String functionName = ""; + + if (url != null) { + + //System.out.println("XXXXX: " + url); + + String protocol = url.getProtocol(); + + if (protocol.equalsIgnoreCase("file")) { + String mpwFilePath = url.getFile(); + + if(mpwFilePath.endsWith(".mpw")) + { + + java.io.InputStream inputStream = FunctionTreePanel.class.getResourceAsStream(mpwFilePath); + + if (inputStream != null) //File is on the classpath. + { + + try{ + String mpwFileText = convertStreamToString(inputStream); + + HelpEvent helpEvent = new HelpEvent(mpwFilePath, mpwFileText); + + this.notifyListeners(helpEvent); + + inputStream.close(); + } + catch(Exception e) + { + System.out.println(e.getMessage()); + } + + }//end if. + + }else + { + //.java file. + //HelpEvent helpEvent = new HelpEvent(mpwFilePath, null); + //this.notifyListeners(helpEvent); + } + + } else { + String urlString = url.toString(); + functionName = urlString.substring(7, urlString.length()); + } + + + + + } else { + //Hack to get around problem of null url object being returned for the := operator. + if (event.getDescription().contains("http://:=")) { + functionName = ":="; + } + } + //System.out.println(functionName); viewFunction(functionName, true); @@ -677,13 +934,14 @@ }//end method. - private int pageIndex = -1; private void setPage(String functionName, String html, boolean save) { editorPane.setText(html); + //HTMLEditorKit editorKit = (HTMLEditorKit) editorPane.getEditorKit(); + //Style style = editorKit.getStyleSheet().getRule("object"); //forward button logic. @@ -729,7 +987,6 @@ verticalScrollBar.setValue(verticalScrollBar.getMinimum()); } - }); @@ -779,27 +1036,71 @@ private void home() { - toolPanel.sourceButtonEnabled(false); + //toolPanel.sourceButtonEnabled(false); + + String homePageText = "

    MathPiper Function Documentation.

    \n" + + "
    \n" + + "Open the tree nodes to the left to access the function documentation. \n"; + + + setPage("HomePage", homePageText, true); + }//end method. + + + public String convertStreamToString(InputStream inputStream) throws IOException { + + if (inputStream != null) { + StringBuilder stringBuilder = new StringBuilder(); + String line; + + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + while ((line = reader.readLine()) != null) { + stringBuilder.append(line).append("\n"); + } + } finally { + inputStream.close(); + } + return stringBuilder.toString(); + } else { + return ""; + } + }//end method. + + + + public void addHelpListener(HelpListener listener) { + helpListeners.add(listener); + } + + public void removeHelpListener(HelpListener listener) { + helpListeners.remove(listener); + } + + protected void notifyListeners(HelpEvent helpEvent) { + + for (HelpListener listener : helpListeners) { + listener.helpEvent(helpEvent); + }//end for. - setPage("HomePage", "Home page", true); }//end method. + public JPanel getToolPanel() { return toolPanel; }//end method. - private class ToolPanel extends JPanel implements ItemListener { private JLabel label; - private JButton sourceButton; - private JButton collapseButton; + //private JButton sourceButton; private JButton backButton; private JButton forwardButton; private JButton homeButton; private JButton fontSizeIncreaseButton; private JButton fontSizeDecreaseButton; + private JCheckBox showExperimentalFunctionsCheckBox; private JCheckBox showPrivateFunctionsCheckBox; private boolean isShowPrivateFunctions = false; @@ -810,42 +1111,30 @@ //View source button. - sourceButton = new javax.swing.JButton("Source"); + /*sourceButton = new javax.swing.JButton("Source"); sourceButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { //source(); } - }); sourceButton.setEnabled(false); sourceButton.setToolTipText("View script source."); - add(sourceButton); - - - //Collapse tree button. - collapseButton = new javax.swing.JButton("Collapse"); - collapseButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - collapse(); - } - - - }); - collapseButton.setEnabled(true); - collapseButton.setToolTipText("Collapse function tree."); - add(collapseButton); + add(sourceButton);*/ + showExperimentalFunctionsCheckBox = new JCheckBox("Experimental"); + showExperimentalFunctionsCheckBox.setSelected(true); + showExperimentalFunctionsCheckBox.addItemListener(this); + add(showExperimentalFunctionsCheckBox); showPrivateFunctionsCheckBox = new JCheckBox("Private"); + showPrivateFunctionsCheckBox.setSelected(false); showPrivateFunctionsCheckBox.addItemListener(this); add(showPrivateFunctionsCheckBox); - add(Box.createGlue()); //fontSize increase button. @@ -868,7 +1157,6 @@ }//end method. - }); fontSizeIncreaseButton.setEnabled(true); //add(fontSizeIncreaseButton); @@ -883,7 +1171,6 @@ back(); } - }); backButton.setEnabled(false); add(backButton); @@ -897,7 +1184,6 @@ forward(); } - }); forwardButton.setEnabled(false); add(forwardButton); @@ -911,7 +1197,6 @@ home(); } - }); homeButton.setEnabled(true); add(homeButton); @@ -922,9 +1207,9 @@ }//end constructor. - public void sourceButtonEnabled(Boolean state) { - sourceButton.setEnabled(state); - }//end method. + //public void sourceButtonEnabled(Boolean state) { + // sourceButton.setEnabled(state); + //}//end method. public void backButtonEnabled(Boolean state) { @@ -940,22 +1225,138 @@ public void itemStateChanged(ItemEvent ie) { Object source = ie.getSource(); - if (source == showPrivateFunctionsCheckBox) { + if (source == showPrivateFunctionsCheckBox || source == showExperimentalFunctionsCheckBox) { + if (source == showPrivateFunctionsCheckBox) { + + if (ie.getStateChange() == ItemEvent.SELECTED) { + showPrivateFunctions = true; + } else { + showPrivateFunctions = false; + }//end if/else. + + } else if (source == showExperimentalFunctionsCheckBox) { + + if (ie.getStateChange() == ItemEvent.SELECTED) { + showExperimentalFunctions = true; + } else { + showExperimentalFunctions = false; + }//end if/else. - if (ie.getStateChange() == ItemEvent.SELECTED) { - showPrivateFunctions = true; - } else { - showPrivateFunctions = false; - }//end if/else. + + }//end if. treePanel.removeAll(); createTree(); treePanel.add(functionsTree); - treeViewScrollPane.revalidate(); + }//End if. + + + }//end method. + + }//end class. + + private class SearchPanel extends JPanel implements ActionListener, ListSelectionListener { + + private JTextField searchTextField; + private Vector hits = new Vector(); + private JScrollPane listScroller; + private JList list; + + + public SearchPanel() { + this.setLayout(new BorderLayout()); + + searchTextField = new JTextField(); + + searchTextField.setActionCommand("search"); + + searchTextField.addActionListener(this); + + this.add(searchTextField, BorderLayout.NORTH); + + + hits.add("Enter a search term or phrase into the"); + hits.add("above text field and press to search."); + hits.add(" "); + hits.add("Select a returned function to view its documentation."); + + list = new JList(hits); + list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + list.addListSelectionListener(this); + list.setVisibleRowCount(-1); + + listScroller = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + + this.add(listScroller); + + + }//end constructor. + + + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("search")) { + JTextField textField = (JTextField) e.getSource(); + + String searchString = textField.getText(); + + searchString = searchString.toLowerCase(); + + hits.removeAllElements(); + + int index = 0; + + //Search user functions. + hits.add("USER FUNCTIONS:"); + + for (index = 0; index < userFunctionsData.length; index++) { + if (userFunctionsData[index][0].toLowerCase().contains(searchString) || userFunctionsData[index][2].toLowerCase().contains(searchString)) { + hits.add(userFunctionsData[index][0] + " -- " + userFunctionsData[index][2] + "."); + } + }//end for. + + + //Search programmer functions. + hits.add(" "); + hits.add("PROGRAMMER FUNCTIONS:"); + + for (index = 0; index < programmerFunctionsData.length; index++) { + if (programmerFunctionsData[index][0].toLowerCase().contains(searchString) || programmerFunctionsData[index][2].toLowerCase().contains(searchString)) { + hits.add(programmerFunctionsData[index][0] + " -- " + programmerFunctionsData[index][2] + "."); + } + }//end for. + + + //Search operators. + hits.add(" "); + hits.add("OPERATORS:"); + + for (index = 0; index < operatorsData.length; index++) { + if (operatorsData[index][0].toLowerCase().contains(searchString) || operatorsData[index][2].toLowerCase().contains(searchString)) { + hits.add(operatorsData[index][0] + " -- " + operatorsData[index][2] + "."); + } + }//end for. + + + list.setListData(hits); + + listScroller.revalidate(); }//end if. + + }//end method. + + + public void valueChanged(ListSelectionEvent e) { + JList list = (JList) e.getSource(); + if (!list.getSelectionModel().getValueIsAdjusting()) { + String function = (String) list.getSelectedValue(); + if (function != null) { + String functionName = function.split("-")[0].trim(); + viewFunction(functionName, true); + } + } }//end method. @@ -967,21 +1368,31 @@ JFrame frame = new javax.swing.JFrame(); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - FunctionTreePanel helpPanel = new FunctionTreePanel(FunctionTreePanel.class.getClassLoader()); + FunctionTreePanel functionTreePanel = null; + + try { + + functionTreePanel = new FunctionTreePanel(); + + Container contentPane = frame.getContentPane(); + contentPane.add(functionTreePanel.getToolPanel(), BorderLayout.NORTH); + contentPane.add(functionTreePanel, BorderLayout.CENTER); + + frame.pack(); + + frame.setTitle("MathPiper Help"); + frame.setSize(new Dimension(700, 700)); + //frame.setResizable(false); + frame.setPreferredSize(new Dimension(700, 700)); + frame.setLocationRelativeTo(null); // added + + frame.setVisible(true); + + } catch (FileNotFoundException fnfe) { + System.out.println(fnfe.getMessage()); + } - Container contentPane = frame.getContentPane(); - contentPane.add(helpPanel.getToolPanel(), BorderLayout.NORTH); - contentPane.add(helpPanel, BorderLayout.CENTER); - - frame.pack(); -//frame.setAlwaysOnTop(true); - frame.setTitle("MathPiper Help"); - frame.setSize(new Dimension(700, 700)); - //frame.setResizable(false); - frame.setPreferredSize(new Dimension(700, 700)); - frame.setLocationRelativeTo(null); // added - frame.setVisible(true); }//end main. } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/HelpEvent.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/HelpEvent.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/HelpEvent.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/HelpEvent.java 2010-07-16 05:04:03.000000000 +0000 @@ -0,0 +1,47 @@ +package org.mathpiper.ui.gui.help; + + +public class HelpEvent +{ + private String filePath = null; + + private String sourceCode = null; + + + public HelpEvent() + { + super(); + } + + + public HelpEvent(String filePath, String sourceCode) + { + this.filePath = filePath; + + this.sourceCode = sourceCode; + } + + + + public String getFilePath() { + return filePath; + } + + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + + public String getSourceCode() { + return sourceCode; + } + + + public void setSourceCode(String sourceCode) { + this.sourceCode = sourceCode; + } + + + +}//end class. \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/HelpListener.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/HelpListener.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/HelpListener.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/HelpListener.java 2010-07-15 19:13:30.000000000 +0000 @@ -0,0 +1,8 @@ +package org.mathpiper.ui.gui.help; + + +public interface HelpListener +{ + public void helpEvent(HelpEvent helpEvent); + +}// end interface. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/HelpPanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/HelpPanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/HelpPanel.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/HelpPanel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *///}}} -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.help; - -import javax.swing.JEditorPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - - -public class HelpPanel extends JPanel{ - private JScrollPane docsScrollPane; - private JEditorPane editorPane; - - public HelpPanel() - { - editorPane = new JEditorPane(); - editorPane.setEditorKit(new javax.swing.text.html.HTMLEditorKit()); - //JdocsScrollPane editorScrollPane = new JScrollPane(editorPane); - docsScrollPane = new JScrollPane(editorPane,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED ); - - - - }//end constructor. -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/RenderedLatex.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/RenderedLatex.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/help/RenderedLatex.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/help/RenderedLatex.java 2010-06-29 02:08:00.000000000 +0000 @@ -0,0 +1,38 @@ +package org.mathpiper.ui.gui.help; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Insets; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import org.scilab.forge.jlatexmath.TeXConstants; +import org.scilab.forge.jlatexmath.TeXFormula; +import org.scilab.forge.jlatexmath.TeXIcon; +import org.scilab.forge.jlatexmath.DefaultTeXFont; +import org.scilab.forge.jlatexmath.cyrillic.CyrillicRegistration; +import org.scilab.forge.jlatexmath.greek.GreekRegistration; + +public class RenderedLatex extends JLabel { + + public RenderedLatex() { + super(); + //this.setText("Hello."); + + + } + + + public void setLatex(String latexString) { + + DefaultTeXFont.registerAlphabet(new CyrillicRegistration()); + DefaultTeXFont.registerAlphabet(new GreekRegistration()); + TeXFormula formula = new TeXFormula(latexString); + TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 17); + icon.setInsets(new Insets(1, 1, 1, 1)); + this.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + this.setAlignmentY(icon.getBaseLine()); + this.setIcon(icon); + + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/cHotEqn.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/cHotEqn.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/cHotEqn.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/cHotEqn.java 2009-10-28 17:24:49.000000000 +0000 @@ -0,0 +1,2893 @@ +/***************************************************************************** +* * +* HotEqn Equation Viewer Component * +* * +****************************************************************************** +* Java-Coponent to view mathematical Equations provided in the LaTeX language* +****************************************************************************** + +Copyright 2006 Stefan M�ller and Christian Schmid + +This file is part of the HotEqn package. + + HotEqn 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; + HotEqn is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +****************************************************************************** +* * +* Constructor: * +* cHotEqn() Construtor without any initial equation. * +* cHotEqn(String equation) Construtor with initial equation to display. * +* cHotEqn(String equation, Applet app, String name) * +* The same as above if used in an applet * +* with applet name. * +* * +* Public Methods: * +* void setEquation(String equation) Sets the current equation. * +* String getEquation() Returns the current equation. * +* void setDebug(boolean debug) Switches debug mode on and off. * +* boolean isDebug() Returns the debug mode. * +* void setFontname(String fontname) Sets one of the java fonts. * +* String getFontname() Returns the current fontname. * +* void setFontsizes(int g1, int g2, int g3, int g4) Sets the fontsizes * +* for rendering. Possible values are * +* 18, 14, 16, 12, 10 and 8. * +* void setBackground(Color BGColor) Sets the background color. * +* Overrides method in class component. * +* Color getBackground() Returns the used background color. * +* Overrides method in class component. * +* void setForeground(Color FGColor) Sets the foreground color. * +* Overrides method in class component. * +* Color getForeground() Returns the used foreground color. * +* Overrides method in class component. * +* void setBorderColor(Color border) Sets color of the optional border. * +* Color getBorderColor() Returns the color of the border. * +* void setBorder(boolean borderB) Switches the border on or off. * +* boolean isBorder() Returns wether or not a border is * +* displayed. * +* void setRoundRectBorder(boolean borderB) * +* Switches between a round and a * +* rectangular border. * +* TRUE: round border * +* FALSE: rectangular border * +* boolean isRoundRectBorder() Returns if the border is round or * +* rectangular. * +* void setEnvColor(Color env) Sets color of the environment. * +* Color getEnvColor() Returns the color of the environment. * +* void setHAlign(String halign) Sets the horizontal alignment. * +* Possible values are: left, center and * +* right. * +* String getHAlign() Returns the horizontal alignment. * +* void setVAlign(String valign) Sets the vertical alignment. * +* Possible values are: top, middle and * +* bottom. * +* public String getVAlign() Returns the vertical alignment. * +* void setEditable(boolean editableB) Makes the component almost editable.* +* Parts of the displayed equation are * +* selectable when editable is set true. * +* This is turned on by default. * +* boolean isEditable() Returns wether or not the equation * +* is editable (selectable). * +* String getSelectedArea() Return selected area of an equation. * +* Dimension getPreferredSize() Returns the prefered size required to * +* display the entire shown equation. * +* Overrides method in class component. * +* Dimension getMinimumSize() This method return the same value as * +* getPreferedSize * +* Overrides method in class component. * +* Dimension getSizeof(String equation) Returns the size required to * +* display the given equation. * +* void addActionListener(ActionListener listener) * +* Adds the specified action listener to * +* receive action events from this text * +* field. * +* void removeActionListener(ActionListener listener) * +* Removes the specified action listener * +* to receive action events from this * +* text field. * +* Image getImage() Returns the HotEqn image * +* * +****************************************************************************** +************ Version 0.x ************************************* +* 15.07.1996 Beginn * +* 18.07.1996 Parameter Erweiterung * +* 22.07.1996 Scanner: Token Tabelle * +* 24.07.1996 Br�che \frac{ }{ } * +* 25.07.1996 Wurzel \sqrt{}, Tief _, Hoch ^, rekur. Schrift * +* ********** Version 1.0 ************************************* +* 26.07.1996 Array \array * +* 29.07.1996 Klammern \left ( | \{ \[ \right ) | \} \] * +* public setEquation(String equation) f�r JS * +* 30.07.1996 Griechische Symbole in Scanner * +* 04.08.1996 Greek Symbole werden EINZELN vom Netz geladen * +* 05.08.1996 Greek Zeichensatz erneuern (schwarz-weiss Prob.) * +* ********** Version 1.01 ************************************* +* 29.08.1996 \sum Summen, \prod Produkte * +* ********** Version 1.02 ************************************* +* 23.09.1996 Diverse Akzente \bar \hat \acute \grave \dot * +* \tilde \ddot * +* ********** Version 1.03 ************************************* +* 24.09.1996 �bergabemechanismus zwischen den verschiedenen * +* Applets auf einer HTML-Seite * +* ********** Version 1.04 ************************************* +* evalMFile bei Mouse-Klick (->JS->Plugin) * +* engGetFull * +* 14.10.1996 Matrix2LaTeX holt aktuelle Matrix vom Plugin * +* und ruft setRightSide auf * +* 15.10.1996 Alle Plugin-Funktionen mit Argument, muessen * +* das Argument aus JS holen "var VCLabHandle" * +************ Version 1.05 ************************************* +* 18.10.1996 L�sung Applet -> Plugin (alles zur�ck !!) * +************ Version 1.1 ************************************* +* 04.01.1997 Integral \int_{}^{} * +* Limes \lim \infty \arrow * +* 22.01.1997 Korrektur der engGetFull() Methode * +****************************************************************************** +************** Release of Version 2.0 ************************************* +* * +* 1997 Chr. Schmid, S. Mueller * +* Redesign wegen Matlab 5 * +* 05.11.1997 Umbenennungen der Parameter * +* alt: neu: * +* engEvalString mEvalString * +* eval mEvalString * +* evalMFile mEvalMFile * +* engGetFull mGetArray * +* Matrix2LaTeX mMatrix2LaTeX * +* 09.11.1997 Background und Foreground Color, Border, Size * +* 10.11.1997 Separation into HotEqn(no MATLAB) and mHotEqn(MATLAB) version * +* 12.11.1997 Scanner compactified, parser small changes: * +* new methof: adjustBox for recalculation of box size after * +* function calls. * +* \sin \cos .... not italics * +* 16.11.1997 setEquation(String LeftSideS, String RightSideS) method added * +* 23.11.1997 Paint not reentrant * +* 13.11.1997 Binary operators (Kopka: LaTeX: Kap. 5.3.3) prepared * +* (2.00c) quantities and their negation ( " Kap. 5.3.4) " * +* Arrows ( " Kap. 5.3.5) " * +* various additional symbols ( " Kap. 5.3.6) " * +* additional horizontal spaces \, \; \: \! prepared * +* \not prepared * +* 29.11.1997 Scanner optimized (2.00d) * +* 30.11.1997 Paint buffered (2.00e) * +* 03.12.1997 horizontal spaces, \not, \not{} implemented (2.00f) * +* 06.12.1997 ! cdot cdots lim sup etc. ( ) oint arrows some symb. (2.00g) * +* 08.12.1997 left and right [] (2.00h) * +* 08.12.1997 default font plain (2.00i) * +* 11.12.1997 SINGLE (false) argument and STANDARD (true) * +* (e.g. \not A or \not{a+B} ) for all commands, where single * +* or multiple arguments are allowed (_ ^ \sum ... ) (2.00j) * +* 13.12.1997 A_i^2 (i plotted over 2, according to LaTex) (2.00k) * +* 14.12.1997 LaTeX Syntax for brackets, beautified array,frac,fonts (2.00l) * +* 18.12.1997 scanner reduced to one scan, tokens now stored in array(2.00m) * +* 19.12.1997 all bracket types implemented by font/draw (2.00n) * +* 20.12.1997 bracket section new, Null,ScanInit deadlock removed (2.00o) * +* 22.12.1997 separation of HotEqn.java EqScanner.java EqToken.java (2.00p) * +* \choose \atop * +* 26.12.1997 overline underline overbrace underbrace stackrel (2.00q) * +* \fgcolor{rrggbb}{...} \bgcolor{rrggbb}{...} (2.00r) * +* 30.12.1997 ScanInit,setEqation combined \choose modified to \atop (2.00s) * +* and some other minor optimizations * +* 31.12.1997 overline underline sqrt retuned (2.00t) * +* overbrace and underbrace uses arc, new <> Angle * +* right brackets with SUB and SUP * +* 31.12.1997 getWidth() getHeight() Ermittl. d. Groesse v. aussen (2.00u) * +* \begin{array}{...} ... \end{array} * +* 01.01.1998 Tokens stored dynamically (limit 500 tokens removed) (2.00v) * +* Some minor optimization in serveral functions * +* 02.01.1998 \fbox \mbox \widehat \widetilde (2.00w) * +* 02.01.1998 drawArc used for brackets, \widetilde good (2.00x) * +* 03.01.1998 expect()-methods to check on expected tokens (2.00y) * +* 04.01.1998 redesign of thread synchronization, getWidth|Height OK (2.00y1)* +* some minor optimization in parser and documentation * +* 04.01.1998 minor error with SpaceChar corrected * +* \begin{eqnarray} implemented (2.00z) * +* 08.01.1998 minor corrections for TeX-generated fonts (2.00z1)* +* 09.01.1998 *{} for \begin{array} implemented (2.00z2)* +* 13.01.1998 new media tracking, cached images, FGBGcolor corrected (2.00z4)* +* 15.01.1998 Synchronisation with update changed because of overrun (2.00z5)* +* Default space for erroneous images * +* * +* 17.01.1998 Separation into HotEqn and dHotEqn version. (2.01) * +* HotEqn is only for Eqn. viewing and dHotEqn includes * +* all public methods. The mHotEqn is now based on dHotEqn. * +* Hourglass activity indicator added. * +* 18.01.1998 Image cache realized by hash table (2.01a) * +* 06.02.1998 New align parameter halign, valign. Correct alignment (2.01b) * +* 27.02.1998 \sqrt[ ]{} (2.01c) * +* 04.03.1998 Better spacing within brackets (2.01d) * +****************************************************************************** +* 1998 S. Mueller, Chr. Schmid * +* 19.01.1998 AWT component for use in other applications (like buttons, * +* scrollbars, labels, textareas,...) (2.01b) * +* 10.03.1998 adjustments (2.01b1)* +* 11.03.1998 migration to JDK1.1.5 (2.01d1)* +* 14.03.1998 migration to the new event model and public methods (2.01d2)* +* 20.03.1998 setPreferredSize() setMinimumSize() (2.01d3)* +* 04.04.1998 this.getSize()... in paint wieder eingebaut (2.01d4)* +* PropertyChange... ---> automatic resize of bean * +* 11.04.1998 java-files renamed cHotEqn.java --> bHotEqn.java (Bean)(2.01d5)* +* setBorder() setRoundRectBorder() * +* 12.04.1998 partial rearranging of variables and methods * +* bHotEqn -> separated into cHotEqn & bHotEqn (2.02) * +* 26.04.1998 possible workarround for getImage()-problem (2.02a) * +* 27.04.1998 Toolkit.getDefaultToolkit().getImage() is buggy for * +* Netscape 4.04 and 4.05 (JDK1.1x) (see getSymbol(...) * +* 02.05.1998 image-loading problem solved (2.02b) * +* output to System.out only if debug==true * +* 09.05.1998 selectable equations (minor error correction 2.01f)(2.03) * +* 30.03.1998 GreekFontDescents corrected (better for Communicator) (2.01e) * +* 12.05.1998 see mHotEqn and EqScanner (2.01f) * +* 22.05.1998 modified border radius calculation (2.01g) * +* 10.04.1999 corrected alpha value in Color Mask Filter (2.01h) * +* 21.05.1998 selection almost completed (2.03a) * +* 24.05.1998 setEditable(), isEditable(), getselectedArea() (2.03b) * +* fontsize-problem solved, starts with editable=true * +************** Release of Version 3.00 ************************************* +* 2001 Chr. Schmid * +* 18.01.2001 modified according to old HotEqn, SymbolLoader added, three * +* parameter constructor for applet context with applet name, * +* events corrected, edit mode highlight with transparency * +* 14.05.2001 getImage method added (3.01) * +* 15.06.2001 getImage method returns null when Image not ready (3.02) * +* 01.12.2001 edit mode on mouse down,drag,up and new string search (3.03) * +* 18.02.2002 faster version with one scan in generateImage (3.04) * +* 19.02.2002 Environment color parameter + methods (3.04) * +* 20.02.2002 New SymbolLoader with packed gif files (fast and small) (3.10) * +* 23.03.2002 New method getSizeof to determine size of equation (3.11) * +* 27.10.2002 Package atp introduced (3.12) * +************** Release of Version 4.00 ************************************* +* 14.07.2003 Adapted to XPCom. Same as 3.12,only mHotEqn affected (4.00) * +* 27.09.2004 Symbol loader Image file read instead of -1 now 0 (4.01) * +* 14.09.2006 \sech and \csch added (4.02) * +*****************************************************************************/ + +// **** localWidth u. localHeight nur bei getPreferredSize() zur�ckgeben + +package org.mathpiper.ui.gui.hoteqn; + +// package bHotEqn; // for Bean-compilation to avoid double filenames + +//import atp.*; +import java.util.*; +import java.awt.*; +import java.awt.image.*; +import java.awt.event.*; +import java.applet.Applet; // wenn Component von Applet aufgerufen wird. +import java.net.URL; // for image loading in beans +import java.io.InputStream; // +import java.io.IOException; +import java.io.*; +import java.util.StringTokenizer; + +public class cHotEqn extends Component + implements MouseListener, MouseMotionListener { + +private static final String VERSION = "cHotEqn V 4.02 "; + +private int width = 0; +private int height = 0; +private String nameS = null; +private String equation = null; +private String Fontname = "Helvetica"; + +ActionListener actionListener; // Post action events to listeners + +private EqScanner eqScan; +private EqToken eqTok; + +private Font f1 = new Font(Fontname,Font.PLAIN, 16); +private Font f2 = new Font(Fontname,Font.PLAIN, 14); +private Font f3 = new Font(Fontname,Font.PLAIN, 11); +private Font f4 = new Font(Fontname,Font.PLAIN, 10); + +private static final float mk = 2.0f; // Umschaltfaktor f�r Klammerndarstellung (font,zeichnen) + +private static final int GreekFontSizes[] = { 8,10,12,14,18 }; // vorhandene GreekFonts +private static final int GreekFontDescents[] = { 2, 3, 4, 5, 6 }; // vorhandene GreekFonts Descents +private int GreekSize[] = {14,12,10, 8}; +private int GreekDescent[] = { 3, 3, 3, 3}; +private static final int EmbedFontSizes[] = { 9,11,14,16,22 }; // zugeordnete normale Fonts + +/* greek font embedding characteristic based on Helvetica + + nominal font size 18 14 12 10 8 + greek leading 1 0 0 0 0 + greek height 23 16 15 13 11 + greek ascent 18 14 12 10 8 + greek descent 6 5 4 3 2 + embed size 22 16 14 11 9 + embed leading 1 1 0 0 0 + embed height 26 19 16 14 12 + embed ascent 20 15 13 11 9 + embed descent 6 3 3 3 3 +*/ + +private Image bufferImage; // double buffer image +private boolean imageOK = false; +private int localWidth = 0; +private int localHeight = 0; + +private Color BGColor = Color.white; +private Color EnvColor = Color.white; +private Color FGColor = Color.black; +private Color BorderColor = Color.red; +private boolean borderB = false; +private boolean roundRectBorderB = false; +private int border = 0; +private String halign = "left"; +private String valign = "top"; +private int xpos = 0; +private int ypos = 0; +private boolean drawn = false; // drawn Semaphore fuer paint + +private SymbolLoader symbolLoader; // flexible fontloader +private MediaTracker tracker; // global image tracker +private Hashtable imageH = new Hashtable (13); // Hashtable fuer Image Cache (Primzahl) + +private Applet app; // Applet-Handle: wegen Netscape 4.x Bug mit Toolkit...getImage() +public boolean appletB = false; // true wenn fuer HotEqn - cHotEqn benutzt +public boolean beanB = false; // true wenn als Bean benutzt +public boolean debug = true; // debug-Meldungen + +private boolean editMode = false; // Editor mode: select parts of equation +private boolean editableB = true; +private int mouse1X = 0; +private int mouse1Y = 0; +private int mouse2X = 0; +private int mouse2Y = 0; +private int xOFF = 0; +private int yOFF = 0; +private int y0 = 0; +private int x0 = 0; +private int y1 = 0; +private int x1 = 0; +private int editModeRec = 5; +private boolean editModeFind = false; +private int editModeCount1 = 0; +private int editModeCount2 = 0; +private Image selectImage; + +//************************* Constructor () **************************************** +public cHotEqn() { + this("cHotEqn", null, "cHotEqn"); +} + +public cHotEqn(String equation) { + this(equation, null, "cHotEqn"); +} + +public cHotEqn(String equation, Applet app, String nameS) { + this.app = app; // Handle fuer Applet fuer Applet.getImage() + this.equation = equation; + this.nameS = nameS; + addMouseListener(this); + addMouseMotionListener(this); + if (app != null) appletB=true; + symbolLoader = new SymbolLoader(); // Fontlader + tracker = new MediaTracker(this); // Mediatracker fuer Images + eqScan = new EqScanner(equation); // Scanner zur Erkennung der Token + System.out.println(VERSION+nameS); +} + +//************************* Public Methods *********************************** + +public void setEquation(String equation) { + this.equation = equation; + eqScan.setEquation(equation); + drawn = false; + imageOK = false; + repaint(); +} +public String getEquation() { return equation; } + +public void printStatus( String s) { + if (debug) System.out.println(nameS + " " + s); +} + +private void displayStatus( String s) { + if (debug) {if (appletB) app.showStatus(nameS + " " + s); else printStatus(s);} +} + +public Image getImage() { + if (imageOK) return bufferImage; else return null; +} + +public void setDebug(boolean debug) { + this.debug = debug; +} +public boolean isDebug() { return debug; } + +public void setFontname(String fontname) { Fontname = fontname;} +public String getFontname() { return Fontname;} + +public void setFontsizes(int gsize1, int gsize2, int gsize3, int gsize4) { + int size1 = 16; + int size2 = 14; + int size3 = 11; + int size4 = 9; + + GreekSize[0]=0; + GreekSize[1]=0; + GreekSize[2]=0; + GreekSize[3]=0; + + // Fontgr��en f�r alle Zeichen und die Griechischen Symbole und Sonderzeichen + for (int i=0; i width) {toosmall=true; xpos=0;} + if (localHeight > height) {toosmall=true; ypos=1;} + // Calculate position + int xoff=border; + int yoff=border; + switch (xpos) { + case 0: break; + case 1: xoff=(width-area0.dx)/2; break; + case 2: xoff=width-border-area0.dx-1; break; + } + switch (ypos) { + case 0: break; + case 1: yoff=border-(localHeight-height)/2; break; + case 2: yoff=height-border-area0.dy_neg-area0.dy_pos; break; + } + //System.out.println("nach 1. eqn"); + g.drawImage(genImage,xoff,yoff,xoff+area0.dx,yoff+area0.dy_pos+area0.dy_neg+1,0,height-area0.dy_pos,area0.dx,height+area0.dy_neg+1 ,this); + //System.out.println("nach 2. eqn"); + geng.dispose(); + if (toosmall) printStatus("(width,height) given=("+width+","+height + +") used=("+localWidth+","+localHeight+")"); + imageOK = true; + drawn = true; + xOFF=xoff; + yOFF=yoff+area0.dy_pos; + notify(); // notifiy that painting has been completed +} // end generateImage + +/* slower version with two scans +private synchronized void generateImage (Graphics g) { + BoxC area = new BoxC(); + BoxC area0 = new BoxC(); + g.setFont(f1); + g.setColor(BGColor); + g.fillRect(0,0,width,height); + border=0; + if (borderB && roundRectBorderB) { + g.setColor(EnvColor); + g.fillRect(0,0,width,height); + g.setColor(BGColor); + g.fillRoundRect(0,0,width-1,height-1,20,20); + g.setColor(BorderColor); + g.drawRoundRect(0,0,width-1,height-1,20,20); + border=5; + } else { + if (borderB && !roundRectBorderB) { + g.setColor(BorderColor); + g.drawRect(0,0,width-1,height-1); + border=5; + } + } + g.setColor(FGColor); + + //FontMetrics fM = g.getFontMetrics(); + //System.out.println("getAscent = "+fM.getAscent() ); + //System.out.println("getDescent = "+fM.getDescent() ); + //System.out.println("getHeight = "+fM.getHeight() ); + //System.out.println("getLeading = "+fM.getLeading() ); + //System.out.println("getMaxAdvance = "+fM.getMaxAdvance() ); + //System.out.println("getMaxAscent = "+fM.getMaxAscent() ); + //System.out.println("getMaxDecent = "+fM.getMaxDecent() ); + //System.out.println("getMaxDescent = "+fM.getMaxDescent() ); + + // Scanner zur�cksetzen & Gleichung in d. Mitte d. Fensters + + //imageH.clear(); // Image Cache leeren (nicht erforderlich) + //System.out.println("vor 1. eqn"); + eqScan.start(); + area0 = eqn(0,150, false, g, 1); + displayStatus(" "); + + // set alignment + xpos=0; // left + if (halign.equals("center")) xpos=1; + else if (halign.equals("right")) xpos=2; + + ypos=0; // top + if (valign.equals("middle")) ypos=1; + else if (valign.equals("bottom")) ypos=2; + + // Calculate actual size + localWidth = 1+area0.dx+2*border; + localHeight = 1+area0.dy_pos+area0.dy_neg+2*border; + + // Test size and modify alignment if too small + boolean toosmall = false; + if (localWidth > width) {toosmall=true; xpos=0;} + if (localHeight > height) {toosmall=true; ypos=1;} + // Calculate position + int xoff=border; + int yoff=area0.dy_pos+border; + switch (xpos) { + case 0: break; + case 1: xoff=(width-area0.dx)/2; break; + case 2: xoff=width-border-area0.dx-1; break; + } + switch (ypos) { + case 0: break; + case 1: yoff=border+area0.dy_pos-(localHeight-height)/2; break; + case 2: yoff=height-border-area0.dy_neg-1; break; + } + //System.out.println("nach 1. eqn"); + eqScan.start(); + area = eqn(xoff,yoff,true,g,1); + //System.out.println("nach 2. eqn"); + if (toosmall) printStatus("(width,height) given=("+width+","+height + +") used=("+localWidth+","+localHeight+")"); + imageOK = true; + drawn = true; + xOFF=xoff; + yOFF=yoff; + notify(); // notifiy that painting has been completed +} // end generateImage +*/ + + +//*************************************************************************** +//*************************************************************************** +//*************** Parser-Routinen ****************** +private BoxC eqn(int x, int y, boolean disp, Graphics g, int rec){ + // different number of parameters + return eqn(x, y, disp, g, rec, true); // Standard Argument (e.g. A_{.....}) +} // end eqn + + +private BoxC eqn(int x, int y, boolean disp, Graphics g, int rec, boolean Standard_Single){ +// Parameter: Baselinekoordinaten: x und y +// Zeichnen oder Gr��e berechnen: disp (true/false) +// Rekursionstiefe (Br�che, Hoch,Tief,...) +// Single (e.g. A_3)(false) o. Standard argument (e.g. A_{3+x})(true) + +// die Methode: boxReturn = adjustBox(box,boxReturn) ersetzt die separate +// Berechnung der neuen Boxgr��en nach einem Funktionsaufruf + BoxC box = new BoxC(); // f�r R�ckgaben von Funktionsaufrufen + BoxC boxReturn = new BoxC(); // akkumuliert die max. Boxgr��e + + boolean Standard_Single_flag = true; + boolean Space_flag = false; + boolean editModeFindLEFT = false; + int editModeCount = 0; + int editModeCountLEFT = 0; + int eqToktyp; + //String eqTokstringS; + + while (!eqScan.EoT() && Standard_Single_flag) { + eqTok = eqScan.nextToken(); + if (editMode && disp) editModeCount = eqScan.get_count(); + + Space_flag = false; + //System.out.print (eqTok.typ); + //if ( disp) System.out.println("Token ="+eqTok.typ); + editModeCountLEFT = editModeCount; + eqToktyp = eqTok.typ; + //eqTokstringS = eqTok.stringS; + + switch(eqTok.typ) { + case EqToken.AndSym: + case EqToken.DBackSlash: + case EqToken.END: + case EqToken.EndSym: + case EqToken.RIGHT: + if (editModeFind && disp) { + //System.out.println("RighteditModeCount ="+editModeCount); + if (editModeCount > editModeCount2) editModeCount2 = editModeCount; + if (editModeCount < editModeCount1) editModeCount1 = editModeCount; + } + return boxReturn; + case EqToken.ACCENT: + box = ACCENT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.ANGLE: + box = ANGLE(x+boxReturn.dx,y,disp,g); + break; + case EqToken.ARRAY: + if (editModeFind && disp) editModeFindLEFT = true; + box = ARRAY(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.BEGIN: + if (editModeFind && disp) editModeFindLEFT = true; + box = BEGIN(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.BeginSym: + box = eqn(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.FGColor: + box = FG_BGColor(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.BGColor: + box = FG_BGColor(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.FBOX: + if (editModeFind && disp) editModeFindLEFT = true; + box = FBOX(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.Id: + box = Id(x+boxReturn.dx,y,disp,g); + break; + case EqToken.NOT: + box = NOT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.Op: + box = Op(x+boxReturn.dx,y,disp,g); + break; + case EqToken.FRAC: + box = FRAC(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.ATOP: + box = FRAC(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.FUNC: + case EqToken.Num: + box = Plain(x+boxReturn.dx,y,disp,g); + break; + case EqToken.SYMBOP: + box = SYMBOP(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.SYMBOPD: + box = SYMBOP(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.LEFT: + if (editModeFind && disp) editModeFindLEFT = true; + box = LEFT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.LIM: + box = LIM(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.MBOX: + box = MBOX(x+boxReturn.dx,y,disp,g); + break; + case EqToken.OverBRACE: + box = OverBRACE(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.UnderBRACE: + box = UnderBRACE(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.OverLINE: + box = OverUnderLINE(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.UnderLINE: + box = OverUnderLINE(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.Paren: + box = Paren(x+boxReturn.dx,y,disp,g); + break; + case EqToken.SPACE: + box = SPACE(x+boxReturn.dx,y,disp,g); + break; + case EqToken.SQRT: + if (editModeFind && disp) editModeFindLEFT = true; + box = SQRT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.STACKREL: + box = STACKREL(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.SUP: + box = SUP(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.SUB: + box = SUB(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.SYMBOLBIG: + box = SYMBOLBIG(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.VEC: + box = VEC(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.SpaceChar: + box = new BoxC(0,0,0); + // bei SpaceChar gilt immer noch eqn(...,false) (single eqn) + Space_flag = true; + break; + case EqToken.Invalid: + case EqToken.Null: + box = new BoxC(0,0,0); + break; + default: + printStatus("Parser: unknown token: "+eqTok.typ+" "+eqTok.stringS); + // einfach ignorieren + } // end switch + + if (disp) { + if (editMode) { + //System.out.println("x+boxReturn.dx = "+(x+boxReturn.dx)+" mouse1X = "+mouse1X+" x+boxReturn.dx+box.dx ="+(x+boxReturn.dx+box.dx)); + if (!editModeFind) { + if ( x+boxReturn.dx <= mouse1X && + mouse1X <= (x+boxReturn.dx+box.dx) && + (y-box.dy_pos) <= mouse1Y && + mouse1Y <= (y+box.dy_neg) ) { + //System.out.println("Anfang token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec); + x0 = x1 = mouse1X; + y0 = y1 = mouse1Y; + editModeFind = true; + editModeCount1 = editModeCount; + editModeCount2 = editModeCount; + } + } + if (!editModeFind) { + if ( x+boxReturn.dx <= mouse2X && + mouse2X <= (x+boxReturn.dx+box.dx) && + (y-box.dy_pos) <= mouse2Y && + mouse2Y <= (y+box.dy_neg) ) { + //System.out.println("Anfang2token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec); + x0 = x1 = mouse2X; + y0 = y1 = mouse2Y; + editModeFind = true; + editModeCount1 = editModeCount; + editModeCount2 = editModeCount; + int dummyX = mouse2X; + int dummyY = mouse2Y; + mouse2X = mouse1X; + mouse2Y = mouse1Y; + mouse1X = dummyX; + mouse1Y = dummyY; + } + } + //System.out.println("Token ="+eqToktyp+" editModeFind ="+editModeFind+" editModeFindLEFT ="+editModeFindLEFT); + if (editModeFind) { + //System.out.println("Mitte token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec+" "+editModeCount1+" "+editModeCount2); + x0 = Math.min(x0, x + boxReturn.dx); + x1 = Math.max(x1, x + boxReturn.dx + box.dx); + y0 = Math.min(y0, y - box.dy_pos); + y1 = Math.max(y1, y + box.dy_neg); + //g.setColor(Color.green); + //g.drawRect(x0, y0, x1-x0, y1-y0); + //g.setColor(FGColor); + if (editModeRec>rec) editModeRec = rec; + switch(eqToktyp) { + case EqToken.LEFT : + case EqToken.FBOX : + case EqToken.MBOX : + case EqToken.BEGIN : + case EqToken.ARRAY : + case EqToken.SQRT : + editModeFindLEFT = true; + if (editModeCountLEFT > editModeCount2) editModeCount2 = editModeCountLEFT; + if (editModeCountLEFT < editModeCount1) editModeCount1 = editModeCountLEFT; + editModeCount = eqScan.get_count(); + //System.out.println("MBOX/FBOX/LEFT handling"); + } // end switch + if (editModeCount > editModeCount2) editModeCount2 = editModeCount; + if (editModeCount < editModeCount1) editModeCount1 = editModeCount; + //System.out.println("editModeCount1 "+editModeCount1); + //System.out.println("editModeCount2 "+editModeCount2); + if ( x+boxReturn.dx <= mouse2X && + mouse2X <= (x+boxReturn.dx+box.dx) && + (y-box.dy_pos) <= mouse2Y && + mouse2Y <= (y+box.dy_neg) ) { + //System.out.println("Ende token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec); + //g.setColor(Color.red); + //g.drawRect(x0, y0, x1-x0, y1-y0); + //g.setColor(FGColor); + if (editModeRec == rec) { + editMode = false; + editModeFind = false; + //System.out.println("editModeCount "+editModeCount); + } + } + } // end editModeFind + } // end editMode + if (editModeFindLEFT) { + //System.out.println("find LEFT token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec+" "+editModeCount1+" "+editModeCount2); + x0 = Math.min(x0, x + boxReturn.dx); + x1 = Math.max(x1, x + boxReturn.dx + box.dx); + y0 = Math.min(y0, y - box.dy_pos); + y1 = Math.max(y1, y + box.dy_neg); + //g.setColor(Color.green); + //g.drawRect(x0, y0, x1-x0, y1-y0); + //g.setColor(FGColor); + switch(eqToktyp) { + case EqToken.LEFT : + case EqToken.FBOX : + case EqToken.MBOX : + case EqToken.BEGIN : + case EqToken.ARRAY : + case EqToken.SQRT : + if (editModeCountLEFT > editModeCount2) editModeCount2 = editModeCountLEFT; + if (editModeCountLEFT < editModeCount1) editModeCount1 = editModeCountLEFT; + editModeCount = eqScan.get_count(); + //System.out.println("MBOX/FBOX/LEFT handling"); + } // end switch + if (editModeCount > editModeCount2) editModeCount2 = editModeCount; + if (editModeCount < editModeCount1) editModeCount1 = editModeCount; + //System.out.println("editModeCount1 "+editModeCount1); + //System.out.println("editModeCount2 "+editModeCount2); + editModeFindLEFT = false; + } // end editModeFindLEFT + } // end disp + + boxReturn.dx += box.dx; + boxReturn.dy_pos = Math.max(boxReturn.dy_pos,box.dy_pos); + boxReturn.dy_neg = Math.max(boxReturn.dy_neg,box.dy_neg); + if (!Standard_Single && !Space_flag) Standard_Single_flag = false; // Single argument (e.g. A_3) + } // end while + return boxReturn; +} // end eqn + + +//************************************************************************ +private BoxC ACCENT(int x, int y, boolean disp, Graphics g, int rec) { +// Akzente: \dot \ddot \hat \grave \acute \tilde +// eqTok.stringS enth�lt das/die darzustellende(n) Zeichen + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + String accentS = eqTok.stringS; + + + // nur bei disp=true mu� Scanner sp�ter zur�ckgesetzt werden + if (disp) count = eqScan.get_count(); + + + // Gr��e der Argument-Box berechnen + box = eqn(x,y,false,g,rec,false); + int dx = Math.max(box.dx,fM.stringWidth(accentS)); + int dy_pos = box.dy_pos + (int)(fM.getAscent()/2); + int dy_neg = box.dy_neg; + + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x,y-dy_pos,dx,dy_pos+dy_neg); + + // Argument zeichnen + box = eqn(x,y,true,g,rec,false); + + // Mittenverschiebung ausrechenen + int d_dx = 3*(int)( (dx-fM.stringWidth(accentS))/4 ); + + if (accentS.equals(".") | accentS.equals("..")) { + g.drawString(accentS,x+d_dx,y-fM.getAscent()); + } + else if (accentS.equals("�") | accentS.equals("`")) { + g.drawString(accentS,x+d_dx,y-(int)(fM.getAscent()/3)); + } + else g.drawString(accentS,x+d_dx,y-(int)(fM.getAscent()*2/3)); + } // end disp + return new BoxC(dx,dy_pos,dy_neg); +} // end ACCENT + +//************************************************************************ +private BoxC ANGLE(int x, int y, boolean disp, Graphics g) { + // Spitze Klammern < und > + + BoxC box = new BoxC(); + FontMetrics fM = g.getFontMetrics(); + int dx = g.getFont().getSize()/2; + int dy_pos = fM.getHeight()-fM.getDescent(); + int dy_neg = fM.getDescent(); + + // nur bei disp zeichnen + if (disp) { + int yp = y-dy_pos+1; + int yn = y+dy_neg-1; + int m = (yp+yn)/2; + if (eqTok.stringS.equals("<")) { + g.drawLine(x+dx,yp,x,m); + g.drawLine(x,m,x+dx,yn); + } else { + g.drawLine(x,yp,x+dx,m); + g.drawLine(x+dx,m,x,yn); + } + } // end disp + return new BoxC(dx,dy_pos,dy_neg); +} // end ACCENT + +//************************************************************************ +private BoxC ARRAY(int x, int y, boolean disp, Graphics g, int rec) { + int dx = 0; + int dy_pos = 0; + int dy_neg = 0; + int dy_pos_max= 0; + int dx_eqn[] = new int[100]; // Breite Spaltenelemente + int dy_pos_eqn[] = new int[100]; // H�he Zeilenelemente + int dy_neg_eqn[] = new int[100]; // H�he Zeilenelemente + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + // Abstand 1 quad hinter Element + int quad = g.getFont().getSize(); + + // nur bei disp=true mu� Scanner sp�ter zur�ckgesetzt werden + if (disp) count = eqScan.get_count(); + + // "{" vom Scanner holen + if (!expect(EqToken.BeginSym, "ARRAY: BeginSym")) return new BoxC(0,0,0); + + // Schleife: Zeilen + for (int y_i = 0; y_i<99; y_i++) { + dy_pos = 0; + dy_neg = 0; + + // Schleife: Spalten + for (int x_i=0; x_i<99; x_i++) { + // Gr��e der Argument-Box berechnen + box = eqn(x,y,false,g,rec); + + dy_pos = Math.max(dy_pos,box.dy_pos); + dy_neg = Math.max(dy_neg,box.dy_neg); + + // Breitesten Elemente pro Spalte + dx_eqn[x_i] = Math.max(dx_eqn[x_i],box.dx+quad); + + // Trennzeichen am SPALTENende + if ((eqTok.typ==EqToken.DBackSlash) || + (eqTok.typ==EqToken.EndSym)) break; + } // end Spalten + + // H�chste und tiefste Zeilenh�he + dy_pos_eqn[y_i] = Math.max(dy_pos_eqn[y_i],dy_pos); + dy_neg_eqn[y_i] = Math.max(dy_neg_eqn[y_i],dy_neg); + dy_pos_max += (dy_pos + dy_neg); + + // Trennzeichen am ARRAY-Ende + if (eqTok.typ == EqToken.EndSym) break; + } // end Zeilen + + + // maximale Zeilenbreite bestimmen + int dx_max = 0; + for (int i=0; i<99; i++) dx_max += dx_eqn[i]; + + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x,y-dy_pos_max/2-fM.getDescent(),dx_max,dy_pos_max); + + // "{" vom Scanner holen + expect(EqToken.BeginSym, "ARRAY: Begin"); + + // Schleife: Zeilen + dy_pos = 0; + for (int y_i=0; y_i<99; y_i++) { + dx = 0; + if (y_i==0) { dy_pos = dy_pos_eqn[y_i]; } + else { dy_pos += (dy_neg_eqn[y_i-1] + dy_pos_eqn[y_i]); } + // Schleife: Spalten + for (int x_i=0; x_i<99; x_i++) { + // Gr��e der Argument-Box berechnen + box = eqn(x+dx,y-dy_pos_max/2-fM.getDescent()+dy_pos,true,g,rec); + dx += dx_eqn[x_i]; + + // Trennzeichen am SPALTENende + if ((eqTok.typ == EqToken.DBackSlash) || + (eqTok.typ == EqToken.EndSym)) break; + } // end Spalten + // Trennzeichen am ARRAY-Ende + if (eqTok.typ == EqToken.EndSym) break; + } // end Zeilen + } // end disp + + return new BoxC(dx_max-quad,dy_pos_max/2+fM.getDescent(),dy_pos_max/2-fM.getDescent()); +} // end ARRAY + +//************************************************************************ +private BoxC BEGIN(int x, int y, boolean disp, Graphics g, int rec) { + int dx, dx_max = 0; + int dy_pos, dy_neg, dy_top, dy_max = 0; + int dx_eqn[] = new int[100]; // Breite Spaltenelemente + int dy_pos_eqn[] = new int[100]; // H�he Zeilenelemente + int dy_neg_eqn[] = new int[100]; // H�he Zeilenelemente + int format[] = new int[100]; // Format 1-l 2-c 3-r 4-@ + int format_count[]= new int[100]; // f�r getcount() bei @-Einsch�ben + int format_dx = 0; // dx bei @-Einsch�ben + int format_dy_pos = 0; // dy_pos bei @-Einsch�ben + int format_dy_neg = 0; // dy_neg bei @-Einsch�ben + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + int quad = g.getFont().getSize(); + int i = 0; + boolean flag = false; + boolean flag_end = false; + boolean format_flag = true; + boolean array_eqnarray= true; // default: \begin{array} + int times = 0; // Zahl bei *{xxx} + int count2 =0; + + if (!expect(EqToken.BeginSym)) return new BoxC(0,0,0); + + if (eqScan.nextToken().stringS.equals("eqnarray")) array_eqnarray = false; + + if (!expect(EqToken.EndSym, "BEGIN: EndSym")) return new BoxC(0,0,0); + + if (array_eqnarray) { + count = eqScan.get_count(); + if (!expect(EqToken.BeginSym)) { + // NO format-string + format_flag = false; + eqScan.set_count(count); + } + } + + + if (array_eqnarray && format_flag) { + // *********** Format Angaben erkennen ********* + // l left(1) c center(2) r right(3) + // @{...} Einschub statt Zwischenraum(4) + + EqToken token = new EqToken(); + token = eqScan.nextToken(); + + while (token.typ != EqToken.EndSym) { + StringBuffer SBuffer = new StringBuffer(token.stringS); + for (int z=0; z")) { + g.drawLine(ddh,m,dh,yp); + g.drawLine(ddh,m,dh,yn); + } + else if (Bracket.equals("{")) { + for (int i=s;i<2+s;i++) { + int dpi=d+i; + arc(g,dd+i,ypr,r,180,-60); + g.drawLine(dpi,ypr,dpi,m-r); + arc(g,x+i,m-r,r,0,-90); + arc(g,x+i,m+r,r,0,90); + g.drawLine(dpi,m+r,dpi,ynr); + arc(g,dd+i,ynr,r,180,60); + } + } + else if (Bracket.equals("}")) { + for (int i=s;i<2+s;i++) { + int dpi=d+i; + arc(g,x+i,ypr,r,0,60); + g.drawLine(dpi,ypr,dpi,m-r); + arc(g,dd+i,m-r,r,-180,90); + arc(g,dd+i,m+r,r,180,-90); + g.drawLine(dpi,m+r,dpi,ynr); + arc(g,x+i,ynr,r,0,-60); + } + } +} // drawBracket + +//************************************************************************ +private BoxC LEFT(int x, int y, boolean disp, Graphics g, int rec) { + int dx_left = 0; + int dx_right = 0; + BoxC box = new BoxC(); + int count = 0; + Font localFont = g.getFont(); + int quad = localFont.getSize(); + int mkq = (int)(mk * quad); + int space = quad/9; + Font BracketFont; + FontMetrics BracketMetrics; + + // nur bei disp=true mu� Scanner sp�ter zur�ckgesetzt werden + if (disp) count = eqScan.get_count(); + + // Klammertyp f�r linke Seite vom Scanner holen + String LeftBracket = eqScan.nextToken().stringS; + + // Gr��e der Argument-Box berechnen + box = eqn(x,y,false,g,rec); + int dx = box.dx; + int dy_pos = box.dy_pos; + int dy_neg = box.dy_neg; + int yp = y-dy_pos+1; + int yn = y+dy_neg-1; + + // Klammertyp f�r rechte Seite vom Scanner holen + String RightBracket = eqScan.nextToken().stringS; + + // Klammergr��e berechnen + int BracketSize = dy_pos+dy_neg-2; + + BracketFont = new Font("Helvetica",Font.PLAIN,BracketSize); + g.setFont(BracketFont); + BracketMetrics = g.getFontMetrics(); + if (LeftBracket.equals("<") || LeftBracket.equals(">")) { + dx_left = quad; + } + else if (BracketSize < mkq) { + dx_left = BracketMetrics.stringWidth(LeftBracket); + if ("([{)]}".indexOf(LeftBracket) >= 0) dx_left += space; + } + else dx_left = quad; + + if (RightBracket.equals("<") || RightBracket.equals(">")) { + dx_right = quad; + } + else if (BracketSize < mkq) { + dx_right = BracketMetrics.stringWidth(RightBracket); + if ("([{)]}".indexOf(RightBracket) >= 0) dx_right += space; + } + else dx_right = quad; + g.setFont(localFont); + + // hinter Klammer Hoch-/Tiefstellung + int count2 = eqScan.get_count(); + // "SUB" + int SUB_dx = 0; + int SUB_baseline = 0; + if (eqScan.nextToken().typ == EqToken.SUB) { + box = SUB(x,y,false,g,rec,false); + SUB_dx=box.dx; + SUB_baseline = yn+box.dy_pos-(box.dy_pos+box.dy_neg)/2; + dy_neg += (box.dy_pos+box.dy_neg)/2; + } else eqScan.set_count(count2); + int count1 = eqScan.get_count(); + + // "SUP" + int SUP_dx = 0; + int SUP_baseline = 0; + if (eqScan.nextToken().typ == EqToken.SUP) { + box = SUP(x,y,false,g,rec,false); + SUP_dx = box.dx; + SUP_baseline = yp+box.dy_pos-(box.dy_pos+box.dy_neg)/2; + dy_pos += (box.dy_pos+box.dy_neg)/2; + } else eqScan.set_count(count1); + SUB_dx = Math.max(SUB_dx,SUP_dx); + + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x+dx_left,y-dy_pos,dx,dy_pos+dy_neg); + + // linker Klammertyp vom Scanner holen + LeftBracket = eqScan.nextToken().stringS; + if (!LeftBracket.equals(".")) { + if (BracketSize < mkq && !(LeftBracket.equals("<") || LeftBracket.equals(">"))) { + // linke Klammern mit font zeichnen + g.setFont(BracketFont); + g.drawString(LeftBracket,x,yn-BracketMetrics.getDescent() + -BracketMetrics.getLeading()/2); + g.setFont(localFont); + } else + //linke Klammern direkt zeichnen + drawBracket (g,LeftBracket,x,dx_left,yp,yn,quad,0); + } + + // Argument zeichnen + box = eqn(x+dx_left,y,true,g,rec); + + // rechter Klammertyp vom Scanner holen + RightBracket = eqScan.nextToken().stringS; + if (!RightBracket.equals(".")) { + if (BracketSize < mkq && !(RightBracket.equals("<") || RightBracket.equals(">"))) { + // rechte Klammern mit font zeichnen + g.setFont(BracketFont); + if ("([{)]}".indexOf(RightBracket) < 0) space = 0; + g.drawString(RightBracket,x+dx+dx_left+space,yn-BracketMetrics.getDescent() + -BracketMetrics.getLeading()/2); + g.setFont(localFont); + } else + //rechte Klammern direkt zeichnen + drawBracket (g,RightBracket,x+dx+dx_left,dx_right,yp,yn,-quad,-1); + } + // hinter Klammer Hoch-/Tiefstellung + count2 = eqScan.get_count(); + // "SUB" + if (expect(EqToken.SUB)) + box = SUB(x+dx+dx_left+dx_right,SUB_baseline,true,g,rec,false); + else eqScan.set_count(count2); + count1 = eqScan.get_count(); + // "SUP" + if (expect(EqToken.SUP)) + box = SUP(x+dx+dx_left+dx_right,SUP_baseline,true,g,rec,false); + else eqScan.set_count(count1); + } // end disp + return new BoxC(dx+dx_left+dx_right+SUB_dx,dy_pos+2,dy_neg+2); +} // end LEFT + +//************************************************************************ +private BoxC LIM(int x, int y, boolean disp, Graphics g, int rec){ + int dx = 0; + BoxC box = new BoxC(); + int SUB_dx = 0; + int SUB_baseline = 0; + + FontMetrics fM = g.getFontMetrics(); + String stringS = eqTok.stringS; + + // es mu� Scanner sp�ter zur�ckgesetzt werden + int count = eqScan.get_count(); + + int im_dx = dx = fM.stringWidth(stringS); + int dy_pos = fM.getHeight()-fM.getDescent(); + int dy_neg = fM.getDescent(); + + if (expect(EqToken.SUB)) { + box = SUB(x,y,false,g,rec,false); + SUB_dx=box.dx; + dx = Math.max(dx,box.dx); + SUB_baseline = box.dy_pos; + dy_neg = box.dy_pos+box.dy_neg; + } else eqScan.set_count(count); + + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + //g.drawRect(x,y-dy_pos,dx,dy_pos+dy_neg); + g.drawString(stringS,x+(dx-im_dx)/2,y); + if (expect(EqToken.SUB)) + box = SUB(x+(dx-SUB_dx)/2,y+SUB_baseline,true,g,rec,false); + else eqScan.set_count(count); + } // end disp + + return new BoxC(dx,dy_pos,dy_neg); +} // end LIM + +//************************************************************************ +private BoxC MBOX(int x, int y, boolean disp, Graphics g) { + // \mbox{...} plain text within equations + int dx = 0; + int dy_pos = 0; + int dy_neg = 0; + BoxC box = new BoxC(); + + // "{" vom Scanner holen + if (!expect(EqToken.BeginSym)) return new BoxC(0,0,0); + + while (!eqScan.EoT()) { + eqTok = eqScan.nextToken(); + if (eqTok.typ != EqToken.EndSym) { + box = Plain(x+dx, y, disp, g); + dx += box.dx; + dy_pos = Math.max(dy_pos,box.dy_pos); + dy_neg = Math.max(dy_neg,box.dy_neg); + } + else break; + } + + return new BoxC(dx, dy_pos, dy_neg); +} // end MBOX + +//********************************************************************** +private BoxC NOT(int x, int y, boolean disp, Graphics g, int rec){ +// Negation: \not or \not{ } + BoxC box = new BoxC(); + + box = eqn(x,y,disp,g,rec,false); + + if (disp) g.drawLine(x + box.dx/4 , y + box.dy_neg, + x + (box.dx*3)/4, y - box.dy_pos ); + return box; +} // end NOT + +//************************************************************************ +private BoxC Op(int x, int y, boolean disp, Graphics g) { +// Operatoren + FontMetrics fM = g.getFontMetrics(); + + if (disp) g.drawString(eqTok.stringS,x+1,y); + return new BoxC(fM.stringWidth(eqTok.stringS) + 2, + fM.getHeight()-fM.getDescent(), + fM.getDescent()); +} // end Op + +//************************************************************************* +private BoxC OverBRACE(int x, int y, boolean disp, Graphics g, int rec) { + int count = 0; + BoxC box = new BoxC(); + int r = g.getFont().getSize()/4; + int rh = r/2; + int SUP_dx = 0; + int SUP_base = 0; + int SUP_dy = 0; + + // nur bei disp=true mu� Scanner sp�ter zur�ckgesetzt werden + if (disp) count = eqScan.get_count(); + + // Gr��e der Argument-Box berechnen + box = eqn(x,y,false,g,rec,false); + int dx = box.dx; + int dxh = dx/2; + int x_middle = dxh; + int dy_pos = box.dy_pos; + int dy_neg = box.dy_neg; + + // "SUP" behandeln, FALLS vorhanden + int count1 = eqScan.get_count(); + if (expect(EqToken.SUP)) { + box = SUP(x,y,false,g,rec,false); + SUP_dx = box.dx; + x_middle = Math.max(x_middle,SUP_dx/2); + SUP_base = dy_pos + box.dy_neg; + SUP_dy = box.dy_pos + box.dy_neg; + } else eqScan.set_count(count1); + + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + int xx = x + x_middle-dxh; + box = eqn(xx, y, true, g, rec, false); + int rred = (int)(r*0.86602540378444); + for (int i=0;i<2;i++) { + int ypi = y-dy_pos-rh+i; + arc(g,xx+rred,ypi+r,r,90,60); + g.drawLine(xx+rred,ypi,xx+dxh-r,ypi); + arc(g,xx+dxh-r,ypi-r,r,0,-90); + arc(g,xx+dxh+r,ypi-r,r,-90,-90); + g.drawLine(xx+dxh+r,ypi,xx+dx-rred,ypi); + arc(g,xx+dx-rred,ypi+r,r,90,-60); + } + count1 = eqScan.get_count(); + if (expect(EqToken.SUP)) + box = SUP(x+x_middle-SUP_dx/2, y-SUP_base-r-rh,true,g,rec,false); + else eqScan.set_count(count1); + } // end disp + + dy_pos += SUP_dy + r + rh ; + dx = Math.max(dx,SUP_dx); + + return new BoxC(dx,dy_pos,dy_neg); +} // end OverBRACE + + +//************************************************************************* +private BoxC UnderBRACE(int x, int y, boolean disp, Graphics g, int rec) { + int count = 0; + BoxC box = new BoxC(); + int r = g.getFont().getSize()/4; + int rh = r/2; + int SUB_dx = 0; + int SUB_base = 0; + int SUB_dy = 0; + + // nur bei disp=true mu� Scanner sp�ter zur�ckgesetzt werden + if (disp) count = eqScan.get_count(); + + // Gr��e der Argument-Box berechnen + box = eqn(x,y,false,g,rec,false); + int dx = box.dx; + int dxh = dx/2; + int x_middle = dxh; + int dy_pos = box.dy_pos; + int dy_neg = box.dy_neg; + + // "SUB" behandeln, FALLS vorhanden + int count1 = eqScan.get_count(); + if (expect(EqToken.SUB)) { + box = SUB(x,y,false,g,rec,false); + SUB_dx = box.dx; + x_middle = Math.max(x_middle,SUB_dx/2); + SUB_base = dy_neg + box.dy_pos; + SUB_dy = box.dy_pos + box.dy_neg; + } else eqScan.set_count(count1); + + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + int xx = x + x_middle-dxh; + box = eqn(xx, y, true, g, rec, false); + int rred = (int)(r*0.86602540378444); + for (int i=0;i<2;i++) { + int ypi = y+dy_neg+rh-i; + arc(g,xx+rred,ypi-r,r,-90,-60); + g.drawLine(xx+rred,ypi,xx+dxh-r,ypi); + arc(g,xx+dxh-r,ypi+r,r,90,-90); + arc(g,xx+dxh+r,ypi+r,r,90,90); + g.drawLine(xx+dxh+r,ypi,xx+dx-rred,ypi); + arc(g,xx+dx-rred,ypi-r,r,-90,60); + } + count1 = eqScan.get_count(); + if (eqScan.nextToken().typ == EqToken.SUB) + box = SUB(x+x_middle-SUB_dx/2, y+SUB_base+r+rh,true,g,rec,false); + else eqScan.set_count(count1); + } // end disp + + dy_neg += SUB_dy + r + rh ; + dx = Math.max(dx,SUB_dx); + + return new BoxC(dx,dy_pos,dy_neg); +} // end UnderBRACE + +//************************************************************************ +private BoxC OverUnderLINE(int x, int y, boolean disp, Graphics g, int rec, + boolean OverUnder) { + int count = 0; + BoxC box = new BoxC(); + + // nur bei disp=true mu� Scanner sp�ter zur�ckgesetzt werden + if (disp) count = eqScan.get_count(); + + // Gr��e der Argument-Box berechnen + box = eqn(x,y,false,g,rec,false); + if (OverUnder) box.dy_pos += 2; // Platz �ber Strich + else box.dy_neg += 2; // Platz unter Strich + int dy_pos=box.dy_pos; + int dy_neg=box.dy_neg; + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + if (OverUnder) g.drawLine(x+1, y-dy_pos+2, x+box.dx-1, y-dy_pos+2); + else g.drawLine(x, y+dy_neg-2, x+box.dx, y+dy_neg-2); + box = eqn(x,y,true,g,rec,false); + } + return new BoxC(box.dx,dy_pos,dy_neg); +} // end OverUnderLINE + +//************************************************************************ +private BoxC Paren(int x, int y, boolean disp, Graphics g){ + FontMetrics fM = g.getFontMetrics(); + int space = g.getFont().getSize()/9; + int dx = fM.stringWidth(eqTok.stringS); + int i = "([{)]}".indexOf(eqTok.stringS); + if (i >= 0) { + dx += space; + if (i > 2 ) x += space; + } + if (disp) g.drawString(eqTok.stringS,x,y); + return new BoxC( dx, + fM.getHeight()-fM.getDescent(), + fM.getDescent()); +} // end Paren + +//************************************************************************ +private BoxC Plain(int x, int y, boolean disp, Graphics g){ + FontMetrics fM = g.getFontMetrics(); + + if (disp) g.drawString(eqTok.stringS,x,y); + return new BoxC( fM.stringWidth(eqTok.stringS), + fM.getHeight()-fM.getDescent(), + fM.getDescent()); +} // end Plain + +//************************************************************************ +private BoxC SPACE(int x, int y, boolean disp, Graphics g){ + // additional positive or negative space between elements + int dx = 0; + Font font = g.getFont(); + try { dx = Integer.parseInt(eqTok.stringS);} + catch (NumberFormatException e){ dx = 0; } + dx = ( dx * font.getSize()) / 18; + return new BoxC(dx,0,0); +} // end SPACE + +//************************************************************************ +private BoxC SQRT(int x, int y, boolean disp, Graphics g, int rec) { + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + int dx_n = 0; + int dy_pos_n = 0; + int dy_neg_n = 0; + int dy_n = 0; + boolean n_sqrt = false; + + // nur bei disp=true mu� Scanner sp�ter zur�ckgesetzt werden + if (disp) count = eqScan.get_count(); + + // etwas Platz f�r den Haken der Wurzel + int dx_Haken = fM.stringWidth("A"); + int dx_Hakenh = dx_Haken/2; + + + // \sqrt[...]{...} + int count1 = eqScan.get_count(); + EqToken token = new EqToken(); + token = eqScan.nextToken(); + if (token.stringS.equals("[")) { + // Gr��e der [n.ten] Wurzel + rec_Font(g,rec+1); + box = eqn(x,y,false,g,rec+1,true); + rec_Font(g,rec); + dx_n = box.dx; + dy_pos_n = box.dy_pos; + dy_neg_n = box.dy_neg; + dy_n = dy_neg_n + dy_pos_n; + n_sqrt = true; + } + else eqScan.set_count(count1); + + // Gr��e der Argument-Box berechnen + box = eqn(x,y,false,g,rec,false); + int dx = box.dx + dx_Haken; + int dy_pos = box.dy_pos + 2; // zus�tzlicher Platz �ber Querstrich + int dy_neg = box.dy_neg; + + if (n_sqrt & dx_n>dx_Hakenh) dx += dx_n - dx_Hakenh; + + // nur bei disp=true wird Scanner zur�ckgesetzt + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x,y-dy_pos,dx,dy_pos+dy_neg); + + // Wurzelzeichen + int dx_n_h = 0; + if (n_sqrt & dx_n > dx_Hakenh) dx_n_h = dx_n - dx_Hakenh; + g.drawLine(x+dx_n_h+1,y-dy_pos/2, x+dx_n_h+dx_Hakenh,y+dy_neg-1); + g.drawLine(x+dx_n_h+dx_Hakenh,y+dy_neg-1, x+dx_n_h+dx_Haken-2,y-dy_pos+2); + g.drawLine(x+dx_n_h+dx_Haken-2,y-dy_pos+2, x+dx,y-dy_pos+2 ); + + if (n_sqrt) { + token = eqScan.nextToken(); + rec_Font(g,rec+1); + if (dx_n>=dx_Hakenh){ + g.drawLine(x+1,y-dy_pos/2, x+dx_n_h+1,y-dy_pos/2); + box = eqn(x+1,y- dy_pos/2 - dy_neg_n-1,true,g,rec+1,true); + } + else box = eqn(x+1+(dx_Hakenh-dx_n),y- dy_pos/2 - dy_neg_n-1,true,g,rec+1,true); + rec_Font(g,rec); + } + + // Argument zeichnen + box = eqn(x+dx_n_h+dx_Haken,y,true,g,rec,false); + + } // end disp + + if (n_sqrt & dy_pos/2 deren Gr��e zur�ckgibt. ** +//*********************************************************************** +class BoxC { + public int dx; + public int dy_pos; + public int dy_neg; + + public BoxC(int dx, int dy_pos, int dy_neg) { + // Constructor MIT Initialisierung + this.dx = dx; + this.dy_pos = dy_pos; + this.dy_neg = dy_neg; } + + public BoxC() { + // Constructor OHNE Initialisierung + this.dx = 0; + this.dy_pos = 0; + this.dy_neg = 0; } +} // end class BoxC + + +//************************************************************* +//** Filter-Class, die als R�ckgabewert das Pixel veraendert ** +//** mit mask wird der RGB-Farbwert rrggbb vorgegeben, der ** +//** den Farbwert schwarz ersetzt. ** +class ColorMaskFilter extends RGBImageFilter { + Color color; + boolean maskORinvert = false; + +//Filter for normal Image + ColorMaskFilter (Color mask) { + color = mask; + maskORinvert = false; + canFilterIndexColorModel = true; + } + +//Filter for highlight + ColorMaskFilter (Color mask, boolean maskB) { + color = mask; + maskORinvert = maskB; + canFilterIndexColorModel = true; + } + + public int filterRGB(int x, int y, int pixel) { + if (maskORinvert) return 0x1fff0000; // rot transparent + int p = pixel & 0xffffff; + if (p == 0xffffff) {return p;} else {return 255 << 24 | color.getRGB();} + } + +} // end ColorMaskFilter + +// SymbolLoader for packed font files (fast speed) +class SymbolLoader { +private ImageProducer [] imageSources = {null,null,null,null,null}; +private String [] fontsizes = {"8","10","12","14","18"}; +private Hashtable fontdesH = new Hashtable (189); +//Fonts are included in HotEqn zip/jar file +private static boolean kLocalFonts=true; + +public SymbolLoader() { } +// dummy constructor + +public Image getImage( boolean appletB, boolean beanB, String filenameS, + Graphics g, Applet app) { + StringTokenizer st = new StringTokenizer(filenameS, "/"); + String fontsize = st.nextToken(); + fontsize = (st.nextToken()).substring(5); + String fn = st.nextToken(); + int k = -1; + for (boolean loop = true; loop;) { + if (fontsizes[++k].equals(fontsize)) loop=false; + if (k==4) loop=false; + } + //System.out.println(fontsizes[k]); + if (imageSources[k] == null) { + imageSources[k]=getBigImage(appletB, beanB, "Fonts"+fontsize+".gif", app); + String desname = "Des"+fontsize+".gif"; + BufferedInputStream istream = null; + // load font descriptors + try { + if (kLocalFonts) { + InputStream ip = getClass().getResourceAsStream(desname); + //System.out.println("ip"); + istream = new BufferedInputStream(getClass().getResourceAsStream(desname)); + //System.out.println("nlocal"); + } else { + //Try loading external Font files in component/applet/bean specific manner + if (!appletB & !beanB) { + // component code + istream = new BufferedInputStream((new URL(desname)).openStream()); + } else if (appletB) { + // applet code + istream = new BufferedInputStream((new URL(app.getCodeBase(), desname)).openStream()); + //System.out.println("file"); + } else { + // bean code + // beanB==true + try { + istream = new BufferedInputStream(getClass().getResource(desname).openStream()); + } catch (Exception ex) { } + } + } + ObjectInputStream p = new ObjectInputStream(istream); + int len = (int)p.readInt(); + for (int i=0;i imageBytes.length) { //haven't yet allocated enough space + byte[] tempImageBytes= (byte[]) imageBytes.clone(); + imageBytes = new byte[totalBytes]; + System.arraycopy(tempImageBytes, 0, imageBytes, 0, alreadyRead); + } + } + if (numBytes == 0) break; + } + //Create an ImageProducer from the image bytes + source = Toolkit.getDefaultToolkit().createImage(imageBytes).getSource(); + } + catch (Exception io) {} + return source; +} // end getLocalImageSource + +} // end class SymbolLoader + +/* +// SymbolLoader for unpacked font files (slow speed) +class SymbolLoader { + +public SymbolLoader() { } +// dummy constructor + +//Fonts are included in HotEqn zip/jar file +private static boolean kLocalFonts=true; + +public Image getImage( boolean appletB, boolean beanB, String filenameS, + Graphics g, Applet app) { + ImageProducer imageSource=null; + Image image=null; + + if(kLocalFonts) { + imageSource = getLocalImageSource(filenameS); + } + if(imageSource==null) { //Fonts are not local + kLocalFonts=false; //don't attempt to load local fonts anymore + + //Try loading external Font files in component/applet/bean specific manner + if (!appletB & !beanB) { + // component code + imageSource=Toolkit.getDefaultToolkit().getImage( filenameS ).getSource(); + } else if (appletB) { + // applet code + imageSource= app.getImage(app.getCodeBase(), filenameS ).getSource(); + } else { + // bean code + // beanB==true + try { + URL url = getClass().getResource( filenameS ); + imageSource = (ImageProducer) url.getContent(); + } catch (Exception ex) { + } + } + } + if(imageSource!=null) { + image = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource( + imageSource, new ColorMaskFilter(g.getColor()))); + } + return image; +} // end getImage + +ImageProducer getLocalImageSource(String resourceName) { + //Try loading images from jar + ImageProducer source = null; + try { + // Next line assumes that Fonts are in the same jar file as SymbolLoader + // Since resourceName doesn't start with a "/", resourceName is treated + // as the relative path to the image file from the directory where + // SymbolLoader.class is. + InputStream imageStream = getClass().getResourceAsStream(resourceName); + int numBytes = imageStream.available();//System.out.println(numBytes); + byte[] imageBytes = new byte[numBytes]; +//System.out.println(numBytes); + // Note: If all bytes are immediately available, the while loop just + // executes once and could be replaced by the line: + // imageStream.read(imageBytes,0,numBytes); + // This may always be the case for the small Font images + + int alreadyRead = 0; + int justRead = 0; + while (justRead != -1) { + justRead = imageStream.read(imageBytes,alreadyRead,numBytes); + if(justRead != -1) { //didn't get all the bytes + alreadyRead += justRead; //Total Read so far + numBytes = imageStream.available(); //Amount left to read + int totalBytes = alreadyRead + numBytes; //total bytes needed to + //store everything we know about +//System.out.println("+"+numBytes); + if((totalBytes) > imageBytes.length) { //haven't yet allocated enough space + byte[] tempImageBytes= (byte[]) imageBytes.clone(); + imageBytes = new byte[totalBytes]; + System.arraycopy(tempImageBytes, 0, imageBytes, 0, alreadyRead); + } + } + } + //Create an ImageProducer from the image bytes + source = Toolkit.getDefaultToolkit().createImage(imageBytes).getSource(); + } + catch (Exception io) {} + return source; +} // end getLocalImageSource + +} // end class SymbolLoader +*/ + Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Des10.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Des10.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Des12.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Des12.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Des14.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Des14.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Des18.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Des18.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Des8.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Des8.gif differ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/EqScanner.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/EqScanner.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/EqScanner.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/EqScanner.java 2010-02-13 08:24:11.000000000 +0000 @@ -0,0 +1,572 @@ +/***************************************************************************** +* * +* S C A N N E R * +* for * +* HotEqn Equation Applet * +* * +****************************************************************************** +* Die Klasse "EqScanner" stellt Methoden zur Erkennung * +* der Elemente (Token) in einer equation zur Verf�gung. * +****************************************************************************** + +Copyright 2006 Stefan M�ller and Christian Schmid + +This file is part of the HotEqn package. + + HotEqn 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; + HotEqn is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +****************************************************************************** +* Methoden: * +* EqToken nextToken() next Token * +* boolean EoT() true, if Tokenende achieved * +* void start() countT=-1: Scanner reset, but * +* not rescan. * +* int get_count() value "countT" (for recursive Token) * +* void set_count(int) calls init() and jumps up countT=int * +* void setEquation(eq) eq scan and in TokenV store * +* * +* Methoden (intern): * +* EqToken ScanNextToken() next Token out equations string * +* char getChar() current char * +* void advance() eine Stelle weiterschalten * +* * +************** Version 2.0 ********************************************* +* 1997,1998 Chr. Schmid, S. Mueller * +* * +* 22.12.1997 Separation from HotEqn.java (2.00p) * +* 22.12.1997 \choose \atop * +* 23.12.1997 overline underline overbrace underbrace stackrel begin end * +* 30.12.1997 \choose mapped to \atop + () (2.00s) * +* setEquation, ScanInit combined * +* 31.12.1997 <> Angle new (2.00t) * +* 01.01.1998 Tokens stored dynamically (limit 500 tokens removed) (2.00v) * +* 08.01.1998 Rearranged and new symbols (2.00z1)* +* 13.01.1998 new media tracking, cached images, get/set_img neu (2.00z4)* +* Symbols and greek symbols scanning reorganized * +* 18.01.1998 Image cache realized by hash table (2.01a) * +* get_img and set_img removed * +* 27.02.1998 \sqrt[ ]{} (2.01c) * +* 03.05.1998 bug: if \ is last char --> StringIndexOutOfBoundsExc.. (2.02a) * +* line 335: additional EOF-checking * +* 21.05.1998 getSelectedArea(count1,count2) return the selected part(2.03) * +* 27.10.2002 Package atp introduced (3.12) * +************** Release of Version 4.00 ************************************* +* 14.07.2003 Adapted to XPCom. Same as 3.12,only mHotEqn affected (4.00) * +* 14.09.2006 \sech and \csch added (4.02) * +* * +*****************************************************************************/ + +package org.mathpiper.ui.gui.hoteqn; + +//package bHotEqn; + +//import atp.*; +import java.util.*; + +class EqScanner { + private String equation; // equation than String + private int count; // Character Position + private int countT; // Token Position + private EqToken token; // Momentary Token + private boolean EOF = false; // File end Variable + //public boolean inScanPaint = false; // Scan semaphore + private Vector TokenV = new Vector (50,50); // dynamic Vector with alln Tokens + private boolean selectB = false; // find selected area + private boolean collectB = false; + private int selectCount1 = 0; + private int selectCount2 = 0; + private StringBuffer selectSB = new StringBuffer(""); + +public EqScanner(String equation) { + // Constructor + token = new EqToken(EqToken.Null); + setEquation(equation); +} + +public String getSelectedArea(int count1, int count2) { + // return the mouse-selected part of the equation as a LaTeX-string + + selectCount1 = Math.min(count1, count2); + selectCount2 = Math.max(count1, count2); + selectB = true; + selectSB = new StringBuffer(""); + + setEquation(this.equation); // New scan, strike ends. + + selectB = false; + return selectSB.toString(); +} + +public void setEquation(String equation) { + //if (inScanPaint) return; // Semaphore + //inScanPaint=true; + // To share the equation + this.equation = equation; + + // Scanner back space und EINmal equation scannen. + // Tokens in TokenV store + + int i = 0; + int ii = 0; + int countBeginEnd = 0; + + EOF = false; + countT = -1; + count = -1; + TokenV.removeAllElements(); // all remove the old token. + advance(); // empty eauation intercept. + while (!EOF) { + countT ++; + if (selectB && (countT == selectCount1 )) collectB=true; + TokenV.addElement(ScanNextToken()); + if (selectB && (countT == selectCount2 )) collectB=false; + //System.out.println("scanNextToken "+((EqToken)TokenV.lastElement()).stringS); + } + countT = -1; + + // Eliminate language conflicts: + // { ... \choose ... } --> \choose{ ... }{ ... } + // { ... \atop ... } --> \atop{ ... }{ ... } + while ( i < TokenV.size() ) { + if (((EqToken)TokenV.elementAt(i)).typ == EqToken.CHOOSE){ + + // single { search + ii = i-1; + countBeginEnd = 0; + while ( ii>0 ) { + if ( ((EqToken)TokenV.elementAt(ii)).typ == EqToken.EndSym ) countBeginEnd--; + else if ( ((EqToken)TokenV.elementAt(ii)).typ == EqToken.BeginSym ) countBeginEnd++; + if ( countBeginEnd == 1 ) break; + ii--; + } // end while ii + + // single } search + int jj = i+1; + countBeginEnd = 0; + while ( jj < TokenV.size() ) { + if ( ((EqToken)TokenV.elementAt(jj)).typ == EqToken.EndSym ) countBeginEnd++; + else if ( ((EqToken)TokenV.elementAt(jj)).typ == EqToken.BeginSym ) countBeginEnd--; + if ( countBeginEnd == 1 ) break; + jj++; + } // end while jj + if ((countBeginEnd == 1) && (ii >=0)) { + + // right bracket ) insert + TokenV.insertElementAt(new EqToken(EqToken.Paren,")"),jj+1); + TokenV.insertElementAt(new EqToken(EqToken.RIGHT),jj+1); + + // at \choose }{ insert + TokenV.setElementAt(new EqToken(EqToken.EndSym),i); + TokenV.insertElementAt(new EqToken(EqToken.BeginSym),i+1); + + // \atop einsetzen mit bracket ( + TokenV.insertElementAt(new EqToken(EqToken.ATOP),ii); + TokenV.insertElementAt(new EqToken(EqToken.Paren,"("),ii); + TokenV.insertElementAt(new EqToken(EqToken.LEFT),ii); + + i +=4; // 4 Token nach rechts ger�ckt + + } // end if + + } // end if \choose + else if ( ((EqToken)TokenV.elementAt(i)).typ == EqToken.ATOP ){ + + // single { search + ii = i-1; + countBeginEnd = 0; + while ( ii>0 ) { + if ( ((EqToken)TokenV.elementAt(ii)).typ == EqToken.EndSym ) countBeginEnd--; + else if ( ((EqToken)TokenV.elementAt(ii)).typ == EqToken.BeginSym ) countBeginEnd++; + if ( countBeginEnd == 1 ) break; + ii--; + } // end while ii + if ( ii >= 0 ) { + + // at \atop }{ insert + TokenV.setElementAt(new EqToken(EqToken.EndSym),i); + TokenV.insertElementAt(new EqToken(EqToken.BeginSym),i+1); + + // \atop copy to new location + TokenV.insertElementAt(new EqToken(EqToken.ATOP),ii); + i +=2; // 2 Token nach rechts ger�ckt + + } // end if + + } // end if \atop + + i++; + } // end while i + + // Eliminate language conflicts: + // \sqrt[ ... ]{ ... } --> \sqrt[ ... }{ ... } + i = 0; + while ( i < TokenV.size()-2 ) { + if (((EqToken)TokenV.elementAt(i)).typ == EqToken.SQRT){ + if (((EqToken)TokenV.elementAt(i+1)).typ == EqToken.Paren) { + ii = i+2; + countBeginEnd = 0; + int countParen = 1; + while ( ii= TokenV.size() ) { + countT = TokenV.size()-1; + return new EqToken(EqToken.Null); + } + else { + return (EqToken)TokenV.elementAt(countT); + } +} // end nextToken + +public boolean EoT() { + // True if End Of Tokens + return countT == TokenV.size()-1; +} // end EoT + +private char getChar() { + return equation.charAt(count); +} // end nextChar + +private void advance() { + if (collectB) selectSB.append(equation.charAt(count)); + if (count < equation.length()-1) { + count++; + EOF = false;} + else { count = equation.length(); + EOF = true;} +} // end advance + +private EqToken ScanNextToken() { + // Determination of next Tokens + // Token are separated by delimiters. + StringBuffer SBuffer = new StringBuffer(""); + String SBufferString = new String(""); + EqToken SlashToken = new EqToken(); + char eqchar; + boolean tag = false; // alround Boolean + + while (!EOF) { + eqchar = getChar(); // current Char out Equation + switch (eqchar) { + case '\n': + case '\r': + case '\t': advance(); + break; + case ' ': advance(); + return new EqToken(EqToken.SpaceChar,new String(" ")); + case '+': case '-': case '*': case '/': + case '=': case '<': case '>': case '#': + case '~': case ';': case ':': case ',': + case '!': advance(); + return new EqToken(EqToken.Op,String.valueOf(eqchar)); + case '{': advance(); + return new EqToken(EqToken.BeginSym); + case '}': advance(); + return new EqToken(EqToken.EndSym); + case '[': + case ']': + case '(': + case ')': + case '|': advance(); + return new EqToken(EqToken.Paren,String.valueOf(eqchar)); + case '&': advance(); + return new EqToken(EqToken.AndSym); + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': + case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': + case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': + case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': + case 'V': case 'W': case 'X': case 'Y': case 'Z': case '\'': case'@': + SBuffer.append(eqchar); + advance(); + tag = false; + while (!EOF && !tag) { + eqchar = getChar(); + switch (eqchar) { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': case '\'': case'@': + SBuffer.append(eqchar); + advance(); + break; + default: + tag = true; + break; + } + } + return new EqToken(EqToken.Id,SBuffer.toString()); + + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': case '.': + SBuffer.append(eqchar); + advance(); + tag = false; + while (!EOF && !tag) { + eqchar = getChar(); + switch (eqchar) { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': case '.': + SBuffer.append(eqchar); + advance(); + break; + default: + tag = true; + break; + } + } + return new EqToken(EqToken.Num,SBuffer.toString()); + + case '\\': + // ///////////////////////////////////// + // all Token with BACKSLASH begin + // It is always \command (in command are only letters) + advance(); + tag = false; + if (EOF) break; + eqchar = getChar(); + switch (eqchar) { + case '\\': advance(); + return new EqToken(EqToken.DBackSlash); + case '{': advance(); + return new EqToken(EqToken.Paren,String.valueOf(eqchar)); + case '|': advance(); + return new EqToken(EqToken.Paren,"||"); + case '}': advance(); + return new EqToken(EqToken.Paren,String.valueOf(eqchar)); + case ',': advance(); + return new EqToken(EqToken.SPACE,"3"); + case ':': advance(); + return new EqToken(EqToken.SPACE,"4"); + case ';': advance(); + return new EqToken(EqToken.SPACE,"5"); + case '!': advance(); + return new EqToken(EqToken.SPACE,"-3"); + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': + case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': + case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': + case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': + case 'V': case 'W': case 'X': case 'Y': case 'Z': + SBuffer.append(eqchar); + advance(); + tag = false; + while (!EOF && !tag) { + eqchar = getChar(); + switch (eqchar) { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + SBuffer.append(eqchar); + advance(); + break; + default: + tag = true; + break; + } + } + SBufferString=SBuffer.toString(); + if (SBufferString.equals("acute")) + return new EqToken(EqToken.ACCENT,"�"); + if (SBufferString.equals("array")) + return new EqToken(EqToken.ARRAY); + if (SBufferString.equals("bar")) + return new EqToken(EqToken.VEC,"bar"); + if (SBufferString.equals("ddot")) + return new EqToken(EqToken.ACCENT,".."); + if (SBufferString.equals("dot")) + return new EqToken(EqToken.ACCENT,"."); + if (SBufferString.equals("frac")) + return new EqToken(EqToken.FRAC); + if (SBufferString.equals("grave")) + return new EqToken(EqToken.ACCENT,"`"); + if (SBufferString.equals("hat")) + return new EqToken(EqToken.ACCENT,"^"); + if (SBufferString.equals("int")) + return new EqToken(EqToken.SYMBOLBIG,"int"); + if (SBufferString.equals("oint")) + return new EqToken(EqToken.SYMBOLBIG,"oint"); + if (SBufferString.equals("left")) + return new EqToken(EqToken.LEFT); + if (SBufferString.equals("limsup")) + return new EqToken(EqToken.LIM,"lim sup"); + if (SBufferString.equals("liminf")) + return new EqToken(EqToken.LIM,"lim inf"); + if (SBufferString.equals("prod")) + return new EqToken(EqToken.SYMBOLBIG,"prod"); + if (SBufferString.equals("right")) + return new EqToken(EqToken.RIGHT); + if (SBufferString.equals("sqrt")) + return new EqToken(EqToken.SQRT); + if (SBufferString.equals("sum")) + return new EqToken(EqToken.SYMBOLBIG,"sum"); + if (SBufferString.equals("tilde")) + return new EqToken(EqToken.ACCENT,"~"); + if (SBufferString.equals("vec")) + return new EqToken(EqToken.VEC); + if (SBufferString.equals("widehat")) + return new EqToken(EqToken.VEC,"widehat"); + if (SBufferString.equals("widetilde")) + return new EqToken(EqToken.VEC,"widetilde"); + if (SBufferString.equals("quad")) + return new EqToken(EqToken.SPACE,"18"); + if (SBufferString.equals("qquad")) + return new EqToken(EqToken.SPACE,"36"); + if (SBufferString.equals("backslash")) + return new EqToken(EqToken.Num,"\\"); + if (SBufferString.equals("langle")) + return new EqToken(EqToken.ANGLE,"<"); + if (SBufferString.equals("rangle")) + return new EqToken(EqToken.ANGLE,">"); + + if (SBufferString.equals("not")) + return new EqToken(EqToken.NOT); + + if (SBufferString.equals("atop")) + return new EqToken(EqToken.ATOP); + if (SBufferString.equals("choose")) + return new EqToken(EqToken.CHOOSE); + + if (SBufferString.equals("overline")) + return new EqToken(EqToken.OverLINE); + if (SBufferString.equals("underline")) + return new EqToken(EqToken.UnderLINE); + + if (SBufferString.equals("overbrace")) + return new EqToken(EqToken.OverBRACE); + if (SBufferString.equals("underbrace")) + return new EqToken(EqToken.UnderBRACE); + + if (SBufferString.equals("stackrel")) + return new EqToken(EqToken.STACKREL); + + if (SBufferString.equals("begin")) + return new EqToken(EqToken.BEGIN); + if (SBufferString.equals("end")) + return new EqToken(EqToken.END); + + if (SBufferString.equals("fgcolor")) + return new EqToken(EqToken.FGColor); + if (SBufferString.equals("bgcolor")) + return new EqToken(EqToken.BGColor); + + if (SBufferString.equals("fbox")) + return new EqToken(EqToken.FBOX); + if (SBufferString.equals("mbox")) + return new EqToken(EqToken.MBOX); + + if (" arccos arcsin arctan arg cos cosh cot coth csc csch def deg dim exp hom ker lg ln log sec sech sin sinh tan tanh " + .indexOf(" "+SBufferString+" ")>=0) return new EqToken(EqToken.FUNC,SBufferString); + if (" det gcd inf lim max min Pr sup " + .indexOf(" "+SBufferString+" ")>=0) return new EqToken(EqToken.LIM,SBufferString); + + if ((" alpha delta epsilon iota kappa lambda nu omega pi sigma theta tau upsilon varepsilon varpi vartheta" + +" pm mp times div cdot cdots ldots ast star amalg cap cup uplus sqcap sqcup vee wedge wr circ bullet diamond lhd rhd oslash odot Box bigtriangleup triangleleft triangleright oplus ominus otimes" + +" ll subset sqsubset in vdash models gg supset sqsupset ni dashv perp neq doteq approx cong equiv propto prec sim simeq asymp smile frown bowtie succ" + +" aleph forall hbar exists imath neg flat ell Re angle Im backslash mho Box prime emptyset triangle nabla partial top bot Join infty vdash dashv" + +" Fourier Laplace leftarrow gets hookrightarrow leftharpoondown rightarrow to rightharpoondown leadsto leftrightarrow mapsto hookleftarrow leftharpoonup rightharpoonup rightleftharpoons longleftarrow longrightarrow longleftrightarrow longmapsto ") + .indexOf(" "+SBufferString+" ")>=0) return new EqToken(EqToken.SYMBOP,SBufferString); + + if ((" beta chi eta gamma mu psi phi rho varrho varsigma varphi xi zeta" + +" le leq ge geq vdots ddots natural jmath bigtriangledown sharp uparrow downarrow updownarrow nearrow searrow swarrow nwarrow succeq mid preceq paralll subseteq sqsubseteq supseteq sqsupseteq clubsuit diamondsuit heartsuit spaofuit wp dagger ddagger setminus unlhd unrhd bigcirc ") + .indexOf(" "+SBufferString+" ")>=0) return new EqToken(EqToken.SYMBOPD,SBufferString); + + if ((" Delta Gamma Lambda Omega Pi Phi Psi Sigma Theta Upsilon Xi" + +" Leftarrow Rightarrow Leftrightarrow Longleftarrow Longrightarrow Longleftrightarrow Diamond ") + .indexOf(" "+SBufferString+" ")>=0) return new EqToken(EqToken.SYMBOP,SBufferString+"Big"); + + if ((" Uparrow Downarrow Updownarrow ") + .indexOf(" "+SBufferString+" ")>=0) return new EqToken(EqToken.SYMBOPD,SBufferString+"Big"); + + default : + tag = true; + advance(); + System.out.println("Scanner invalid tag: \\"+SBuffer.toString()); + return new EqToken(EqToken.Invalid); + } // end switch \command (all backslash commands) + + + case '^': advance(); + return new EqToken(EqToken.SUP); + case '_': advance(); + return new EqToken(EqToken.SUB); + default: advance(); + System.out.println("Scanner invalid character: "+eqchar); + return new EqToken(EqToken.Invalid); + } // end switch + } // end while + return new EqToken(EqToken.Null); +} // end ScanNextToken + + +} // end class EqScanner + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/EqToken.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/EqToken.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/EqToken.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/EqToken.java 2009-10-28 17:24:49.000000000 +0000 @@ -0,0 +1,114 @@ +/***************************************************************************** +* * +* T O K E N * +* for * +* HotEqn Equation Applet * +* * +****************************************************************************** +* Liste aller unterst�tzten Token * +* Token werden vom Scanner erkannt und vom Parser ausgewertet. * +****************************************************************************** + +Copyright 2006 Stefan M�ller and Christian Schmid + +This file is part of the HotEqn package. + + HotEqn 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; + HotEqn is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +************** Version 2.0 ********************************************* +* 1997 Chr. Schmid, S. Mueller * +* * +* 22.12.1997 Separation from HotEqn.java (2.00p) * +* 30.12.1997 new EqToken constructor (2.00s) * +* 31.12.1997 <> Angle new (2.00t) * +* 13.01.1998 new media tracking, cached images (2.00z4)* +* 18.01.1998 Image cache realized by hash table (2.01a) * +* 27.10.2002 Package atp introduced (3.12) * +************** Release of Version 4.00 ************************************* +* 14.07.2003 Adapted to XPCom. Same as 3.12,only mHotEqn affected (4.00) * +* * +*****************************************************************************/ + +package org.mathpiper.ui.gui.hoteqn; + +class EqToken { + public int typ; // type of token + public String stringS; // symbol id + + // Tokenliste | Token | int | Bedeutung + // ------------------------------------------------------------- + public final static int EOF = 0; // End of Equation + public final static int Id = 1; // Variable + public final static int Num = 2; // Numeral + public final static int BeginSym = 3; // logische Klammer { + public final static int EndSym = 4; // logische Klammer } + public final static int ANGLE = 5; // Klammer < oder > + public final static int AndSym = 7; // & Trennzeichen (array) + public final static int DBackSlash = 8; // \\ Trennzeichen (array) + public final static int FUNC = 9; // \sin \cos ... nicht kursiv!! + + public final static int SUP = 10; // ^ Hochstellen + public final static int SUB = 11; // _ Tiefstellen + public final static int FRAC = 12; // Bruch + public final static int SQRT = 13; // Wurzel + public final static int VEC = 14; // Vektor + public final static int ARRAY = 15; // Vektoren u. Matrizen + public final static int LEFT = 16; // Left + public final static int RIGHT = 17; // Right + public final static int SYMBOP = 18; // Greek and operational symbols without descents + public final static int SYMBOPD = 19; // Greek and operational symbols with descents + public final static int SYMBOLBIG = 20; // Summe Produkt Integral + public final static int ACCENT = 22; // Akzente ^~.�`.. + public final static int LIM = 24; // Limes + public final static int SpaceChar = 25; // space ' ' + + public final static int BEGIN = 50; // begin{array} + public final static int END = 51; // end{array} + + public final static int Null = 99; // Nix (sollte nie erreicht werden) + public final static int Invalid = 100; // Falsches Zeichen + + public final static int Op = 108; // <>#~;:,+-*/=! + public final static int Paren = 109; // ( [ \{ \| | ) ] \} + public final static int NOT = 110; // negation \not + public final static int SPACE = 113; // additional horizantal space + public final static int CHOOSE = 114; // { ... \choose ... } + public final static int ATOP = 115; // { ... \atop ... } + public final static int OverLINE = 116; // overline{...} + public final static int UnderLINE = 117; // underline{...} + public final static int OverBRACE = 118; // overbrace{...}^{...} + public final static int UnderBRACE = 119; // underbrace{...}_{...} + public final static int STACKREL = 120; // stackrel{...}{...} + public final static int FGColor = 121; // \fgcolor + public final static int BGColor = 122; // \bgcolor + public final static int FBOX = 123; // \fbox + public final static int MBOX = 124; // \mbox + + + // Constructor mit Initialisierung + public EqToken(int typ, String stringS) { + this.typ = typ; + this.stringS = stringS; + } + + public EqToken(int typ) { + this.typ = typ; + this.stringS = ""; + } + + // Constructor ohne Initialisierung + public EqToken() { + this.typ = 0; + this.stringS = ""; + } +} // end class EqToken + + Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Fonts10.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Fonts10.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Fonts12.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Fonts12.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Fonts14.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Fonts14.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Fonts18.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Fonts18.gif differ Binary files /tmp/M_qTNYZCre/mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/Fonts8.gif and /tmp/ri3y5GGJ3_/mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/Fonts8.gif differ diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/sHotEqn.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/sHotEqn.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/hoteqn/sHotEqn.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/hoteqn/sHotEqn.java 2010-05-19 05:58:45.000000000 +0000 @@ -0,0 +1,2863 @@ +/***************************************************************************** +* * +* HotEqn Equation Viewer Swing Component * +* * +****************************************************************************** +* Java-Coponent to view mathematical Equations provided in the LaTeX language* +****************************************************************************** + +Copyright 2006 Stefan Muller and Christian Schmid + +This file is part of the HotEqn package. + + HotEqn 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; + HotEqn is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +****************************************************************************** +* * +* Constructor: * +* sHotEqn() Construtor without any initial equation. * +* sHotEqn(String equation) Construtor with initial equation to display. * +* sHotEqn(String equation, JApplet app, String name) * +* The same as above if used in an applet * +* with applet name. * +* * +* Public Methods: * +* void setEquation(String equation) Sets the current equation. * +* String getEquation() Returns the current equation. * +* void setDebug(boolean debug) Switches debug mode on and off. * +* boolean isDebug() Returns the debug mode. * +* void setFontname(String fontname) Sets one of the java fonts. * +* String getFontname() Returns the current fontname. * +* void setFontsizes(int g1, int g2, int g3, int g4) Sets the fontsizes * +* for rendering. Possible values are * +* 18, 14, 16, 12, 10 and 8. * +* void setBackground(Color BGColor) Sets the background color. * +* Overrides method in class component. * +* Color getBackground() Returns the used background color. * +* Overrides method in class component. * +* void setForeground(Color FGColor) Sets the foreground color. * +* Overrides method in class component. * +* Color getForeground() Returns the used foreground color. * +* Overrides method in class component. * +* void setBorderColor(Color border) Sets color of the optional border. * +* Color getBorderColor() Returns the color of the border. * +* void setBorder(boolean borderB) Switches the border on or off. * +* boolean isBorder() Returns wether or not a border is * +* displayed. * +* void setRoundRectBorder(boolean borderB) * +* Switches between a round and a * +* rectangular border. * +* TRUE: round border * +* FALSE: rectangular border * +* boolean isRoundRectBorder() Returns if the border is round or * +* rectangular. * +* void setEnvColor(Color env) Sets color of the environment. * +* Color getEnvColor() Returns the color of the environment. * +* void setHAlign(String halign) Sets the horizontal alignment. * +* Possible values are: left, center and * +* right. * +* String getHAlign() Returns the horizontal alignment. * +* void setVAlign(String valign) Sets the vertical alignment. * +* Possible values are: top, middle and * +* bottom. * +* public String getVAlign() Returns the vertical alignment. * +* void setEditable(boolean editableB) Makes the component almost editable.* +* Parts of the displayed equation are * +* selectable when editable is set true. * +* This is turned on by default. * +* boolean isEditable() Returns wether or not the equation * +* is editable (selectable). * +* String getSelectedArea() Return selected area of an equation. * +* Dimension getPreferredSize() Returns the prefered size required to * +* display the entire shown equation. * +* Overrides method in class component. * +* Dimension getMinimumSize() This method return the same value as * +* getPreferedSize * +* Overrides method in class component. * +* Dimension getSizeof(String equation) Returns the size required to * +* display the given equation. * +* void addActionListener(ActionListener listener) * +* Adds the specified action listener to * +* receive action events from this text * +* field. * +* void removeActionListener(ActionListener listener) * +* Removes the specified action listener * +* to receive action events from this * +* text field. * +* Image getImage() Returns the HotEqn image * +* * +****************************************************************************** +************ Version 0.x ************************************* +* 15.07.1996 Start. * +* 18.07.1996 Parameter Expansion * +* 22.07.1996 Scanner: Token Table * +* 24.07.1996 Fraction \frac{ }{ } * +* 25.07.1996 Root \sqrt{}, Tief _, High ^, recursive. Font. * +* ********** Version 1.0 ************************************* +* 26.07.1996 Array \array * +* 29.07.1996 Parentheses \left ( | \{ \[ \right ) | \} \] * +* public setEquation(String equation) for JS * +* 30.07.1996 Greek symbols in Scanner * +* 04.08.1996 Greek Symbols isolation to be downloaded from the net. * +* 05.08.1996 Greek character set refresh (black and white Prob.) * +* ********** Version 1.01 ************************************* +* 29.08.1996 \sum Sum, \prod Product * +* ********** Version 1.02 ************************************* +* 23.09.1996 Various large \bar \hat \acute \grave \dot * +* \tilde \ddot * +* ********** Version 1.03 ************************************* +* 24.09.1996 Handing over mechanism between the various * +* applets on an HTML page. * +* ********** Version 1.04 ************************************* +* evalMFile at mouse-click (->JS->Plugin) * +* engGetFull * +* 14.10.1996 Matrix2LaTeX retrieves current matrix by the plugin * +* and calls on setRightSide. * +* 15.10.1996 All plugin functions with arguments that have to * +* the argument from JS fetch "var VCLabHandle" * +************ Version 1.05 ************************************* +* 18.10.1996 Solution Applet -> Plugin (everything back to results !!) * +************ Version 1.1 ************************************* +* 04.01.1997 Integral \int_{}^{} * +* Limits \lim \infty \arrow * +* 22.01.1997 Corrected the engGetFull() method * +****************************************************************************** +************** Release of Version 2.0 ************************************* +* * +* 1997 Chr. Schmid, S. Mueller * +* Redesigned for Matlab 5 * +* 05.11.1997 Renaming of the parameters * +* old: new: * +* engEvalString mEvalString * +* eval mEvalString * +* evalMFile mEvalMFile * +* engGetFull mGetArray * +* Matrix2LaTeX mMatrix2LaTeX * +* 09.11.1997 Background and Foreground Color, Border, Size * +* 10.11.1997 Separation into HotEqn(no MATLAB) and mHotEqn(MATLAB) version * +* 12.11.1997 Scanner compactified, parser small changes: * +* new methof: adjustBox for recalculation of box size after * +* function calls. * +* \sin \cos .... not italics * +* 16.11.1997 setEquation(String LeftSideS, String RightSideS) method added * +* 23.11.1997 Paint not reentrant * +* 13.11.1997 Binary operators (Kopka: LaTeX: Kap. 5.3.3) prepared * +* (2.00c) quantities and their negation ( " Kap. 5.3.4) " * +* Arrows ( " Kap. 5.3.5) " * +* various additional symbols ( " Kap. 5.3.6) " * +* additional horizontal spaces \, \; \: \! prepared * +* \not prepared * +* 29.11.1997 Scanner optimized (2.00d) * +* 30.11.1997 Paint buffered (2.00e) * +* 03.12.1997 horizontal spaces, \not, \not{} implemented (2.00f) * +* 06.12.1997 ! cdot cdots lim sup etc. ( ) oint arrows some symb. (2.00g) * +* 08.12.1997 left and right [] (2.00h) * +* 08.12.1997 default font plain (2.00i) * +* 11.12.1997 SINGLE (false) argument and STANDARD (true) * +* (e.g. \not A or \not{a+B} ) for all commands, where single * +* or multiple arguments are allowed (_ ^ \sum ... ) (2.00j) * +* 13.12.1997 A_i^2 (i plotted over 2, according to LaTex) (2.00k) * +* 14.12.1997 LaTeX Syntax for brackets, beautified array,frac,fonts (2.00l) * +* 18.12.1997 scanner reduced to one scan, tokens now stored in array(2.00m) * +* 19.12.1997 all bracket types implemented by font/draw (2.00n) * +* 20.12.1997 bracket section new, Null,ScanInit deadlock removed (2.00o) * +* 22.12.1997 separation of HotEqn.java EqScanner.java EqToken.java (2.00p) * +* \choose \atop * +* 26.12.1997 overline underline overbrace underbrace stackrel (2.00q) * +* \fgcolor{rrggbb}{...} \bgcolor{rrggbb}{...} (2.00r) * +* 30.12.1997 ScanInit,setEqation combined \choose modified to \atop (2.00s) * +* and some other minor optimizations * +* 31.12.1997 overline underline sqrt retuned (2.00t) * +* overbrace and underbrace uses arc, new <> Angle * +* right brackets with SUB and SUP * +* 31.12.1997 getWidth() getHeight() Ermittl. d. Groesse v. aussen (2.00u) * +* \begin{array}{...} ... \end{array} * +* 01.01.1998 Tokens stored dynamically (limit 500 tokens removed) (2.00v) * +* Some minor optimization in serveral functions * +* 02.01.1998 \fbox \mbox \widehat \widetilde (2.00w) * +* 02.01.1998 drawArc used for brackets, \widetilde good (2.00x) * +* 03.01.1998 expect()-methods to check on expected tokens (2.00y) * +* 04.01.1998 redesign of thread synchronization, getWidth|Height OK (2.00y1)* +* some minor optimization in parser and documentation * +* 04.01.1998 minor error with SpaceChar corrected * +* \begin{eqnarray} implemented (2.00z) * +* 08.01.1998 minor corrections for TeX-generated fonts (2.00z1)* +* 09.01.1998 *{} for \begin{array} implemented (2.00z2)* +* 13.01.1998 new media tracking, cached images, FGBGcolor corrected (2.00z4)* +* 15.01.1998 Synchronisation with update changed because of overrun (2.00z5)* +* Default space for erroneous images * +* * +* 17.01.1998 Separation into HotEqn and dHotEqn version. (2.01) * +* HotEqn is only for Eqn. viewing and dHotEqn includes * +* all public methods. The mHotEqn is now based on dHotEqn. * +* Hourglass activity indicator added. * +* 18.01.1998 Image cache realized by hash table (2.01a) * +* 06.02.1998 New align parameter halign, valign. Correct alignment (2.01b) * +* 27.02.1998 \sqrt[ ]{} (2.01c) * +* 04.03.1998 Better spacing within brackets (2.01d) * +****************************************************************************** +* 1998 S. Mueller, Chr. Schmid * +* 19.01.1998 AWT component for use in other applications (like buttons, * +* scrollbars, labels, textareas,...) (2.01b) * +* 10.03.1998 adjustments (2.01b1)* +* 11.03.1998 migration to JDK1.1.5 (2.01d1)* +* 14.03.1998 migration to the new event model and public methods (2.01d2)* +* 20.03.1998 setPreferredSize() setMinimumSize() (2.01d3)* +* 04.04.1998 this.getSize()... in paint reinstalled. (2.01d4)* +* PropertyChange... ---> automatic resize of bean * +* 11.04.1998 java-files renamed cHotEqn.java --> bHotEqn.java (Bean)(2.01d5)* +* setBorder() setRoundRectBorder() * +* 12.04.1998 partial rearranging of variables and methods * +* bHotEqn -> separated into cHotEqn & bHotEqn (2.02) * +* 26.04.1998 possible workarround for getImage()-problem (2.02a) * +* 27.04.1998 Toolkit.getDefaultToolkit().getImage() is buggy for * +* Netscape 4.04 and 4.05 (JDK1.1x) (see getSymbol(...) * +* 02.05.1998 image-loading problem solved (2.02b) * +* output to System.out only if debug==true * +* 09.05.1998 selectable equations (minor error correction 2.01f)(2.03) * +* 30.03.1998 GreekFontDescents corrected (better for Communicator) (2.01e) * +* 12.05.1998 see mHotEqn and EqScanner (2.01f) * +* 22.05.1998 modified border radius calculation (2.01g) * +* 10.04.1999 corrected alpha value in Color Mask Filter (2.01h) * +* 21.05.1998 selection almost completed (2.03a) * +* 24.05.1998 setEditable(), isEditable(), getselectedArea() (2.03b) * +* fontsize-problem solved, starts with editable=true * +************** Release of Version 3.00 ************************************* +* 2001 Chr. Schmid * +* 18.01.2001 modified according to old HotEqn, SymbolLoader added, three * +* parameter constructor for applet context with applet name, * +* events corrected, edit mode highlight with transparency * +* 14.05.2001 getImage method added (3.01) * +* 15.06.2001 getImage method returns null when Image not ready (3.02) * +* 01.12.2001 edit mode on mouse down,drag,up and new string search (3.03) * +* 18.02.2002 faster version with one scan in generateImage (3.04) * +* 19.02.2002 Environment color parameter + methods (3.04) * +* 20.02.2002 New SymbolLoader with packed gif files (fast and small) (3.10) * +* 23.03.2002 New method getSizeof to determine size of equation (3.11) * +* 27.10.2002 Package atp introduced (3.12) * +************** Release of Version 4.00 ************************************* +* 28.10.2002 Swing version forked from cHotEqn 3.12 (4.00) * +* Thanks to Markus Schlicht * +*****************************************************************************/ + +package org.mathpiper.ui.gui.hoteqn; + +// **** localWidth u. localHeight only at getPreferredSize() to give back + +// package bHotEqn; // for Bean-compilation to avoid double filenames + +import java.util.*; +//changed 13.10.2002 //import java.awt.*; +import java.awt.image.*; +import java.awt.event.*; +//changed 13.10.2002 //import java.applet.Applet; // If component is called by applet. +import java.net.URL; // for image loading in beans +import java.io.*; +import java.util.StringTokenizer; + +import javax.swing.*; //changed 13.10.2002 +import java.awt.Font; //changed 13.10.2002 +import java.awt.Color; //changed 13.10.2002 +import java.awt.Image; //changed 13.10.2002 +import java.awt.Graphics; //changed 13.10.2002 +import java.awt.MediaTracker; //changed 13.10.2002 +import java.awt.Dimension; //changed 13.10.2002 +import java.awt.Toolkit; //changed 13.10.2002 +import java.awt.AWTEventMulticaster; //changed 13.10.2002 +import java.awt.AWTEvent; //changed 13.10.2002 +import java.awt.Polygon; //changed 13.10.2002 +import java.awt.FontMetrics; //changed 13.10.2002 +import java.awt.Rectangle; //changed 13.10.2002 + +public class sHotEqn extends JComponent //changed 13.10.2002 + implements MouseListener, MouseMotionListener { + +private static final String VERSION = "sHotEqn V 4.00 "; + +private int width = 0; +private int height = 0; +private String nameS = null; +private String equation = null; +private String Fontname = "Helvetica"; + +ActionListener actionListener; // Post action events to listeners + +private EqScanner eqScan; +private EqToken eqTok; + +private Font f1 = new Font(Fontname,Font.PLAIN, 16); +private Font f2 = new Font(Fontname,Font.PLAIN, 14); +private Font f3 = new Font(Fontname,Font.PLAIN, 11); +private Font f4 = new Font(Fontname,Font.PLAIN, 10); + +private static final float mk = 2.0f; // Switchable factor for parentheses (font,draw) + +private static final int GreekFontSizes[] = { 8,10,12,14,18 }; // Default GreekFonts +private static final int GreekFontDescents[] = { 2, 3, 4, 5, 6 }; // Default GreekFonts Descents +private int GreekSize[] = {14,12,10, 8}; +private int GreekDescent[] = { 3, 3, 3, 3}; +private static final int EmbedFontSizes[] = { 9,11,14,16,22 }; // Assigned normal Fonts + +/* greek font embedding characteristic based on Helvetica + + nominal font size 18 14 12 10 8 + greek leading 1 0 0 0 0 + greek height 23 16 15 13 11 + greek ascent 18 14 12 10 8 + greek descent 6 5 4 3 2 + embed size 22 16 14 11 9 + embed leading 1 1 0 0 0 + embed height 26 19 16 14 12 + embed ascent 20 15 13 11 9 + embed descent 6 3 3 3 3 +*/ + +private Image bufferImage; // double buffer image +private boolean imageOK = false; +private int localWidth = 0; +private int localHeight = 0; + +private Color BGColor = Color.white; +private Color EnvColor = Color.white; +private Color FGColor = Color.black; +private Color BorderColor = Color.red; +private boolean borderB = false; //If true, draws a border around the component. +private boolean roundRectBorderB = false; //Makes the border rounded. +private int border = 0; +private String halign = "left"; +private String valign = "top"; +private int xpos = 0; +private int ypos = 0; +private boolean drawn = false; // drawn Semaphore for paint + +private sSymbolLoader symbolLoader; // flexible fontloader +private MediaTracker tracker; // global image tracker +private Hashtable imageH = new Hashtable (13); // Hashtable for Image Cache (prime) + +private JApplet app; //changed 13.10.2002 // Applet-Handle: because Netscape 4.x Bug mit Toolkit...getImage() +public boolean appletB = false; // true if for HotEqn - sHotEqn used +public boolean beanB = false; // true when used as bean. +public boolean debug = false; // debug-reporting. + +private boolean editMode = false; // Editor mode: select parts of equation +private boolean editableB = true; +private int mouse1X = 0; +private int mouse1Y = 0; +private int mouse2X = 0; +private int mouse2Y = 0; +private int xOFF = 0; +private int yOFF = 0; +private int y0 = 0; +private int x0 = 0; +private int y1 = 0; +private int x1 = 0; +private int editModeRec = 5; +private boolean editModeFind = false; +private int editModeCount1 = 0; +private int editModeCount2 = 0; +private Image selectImage; + +//************************* Constructor () **************************************** +public sHotEqn() { + this("sHotEqn", null, "sHotEqn"); +} + +public sHotEqn(String equation) { + this(equation, null, "sHotEqn"); +} + +public sHotEqn(String equation, JApplet app, String nameS) {//changed 13.10.2002 + this.app = app; // Handle for Applet for Applet.getImage() + this.equation = equation; + this.nameS = nameS; + addMouseListener(this); + addMouseMotionListener(this); + if (app != null) appletB=true; + symbolLoader = new sSymbolLoader(); // Font loader. + tracker = new MediaTracker(this); // Media tracker for Images + eqScan = new EqScanner(equation); // Scanner to detect the Token. + //System.out.println(VERSION+nameS); +} + +//************************* Public Methods *********************************** + +public void setEquation(String equation) { + this.equation = equation; + eqScan.setEquation(equation); + drawn = false; + imageOK = false; + repaint(); +} +public String getEquation() { return equation; } + +public void printStatus( String s) { + if (debug) System.out.println(nameS + " " + s); +} + +private void displayStatus( String s) { + if (debug) {if (appletB) app.showStatus(nameS + " " + s); else printStatus(s);} +} + +public Image getImage() { + if (imageOK) return bufferImage; else return null; +} + +public void setDebug(boolean debug) { + this.debug = debug; +} +public boolean isDebug() { return debug; } + +public void setFontname(String fontname) { Fontname = fontname;} +public String getFontname() { return Fontname;} + +public void setFontsizes(int gsize1, int gsize2, int gsize3, int gsize4) { + int size1 = 16; + int size2 = 14; + int size3 = 11; + int size4 = 9; + + GreekSize[0]=0; + GreekSize[1]=0; + GreekSize[2]=0; + GreekSize[3]=0; + + // Fontlargen for all the characters and the Greek symbols and special characters. + for (int i=0; i width) {toosmall=true; xpos=0;} + if (localHeight > height) {toosmall=true; ypos=1;} + // Calculate position + int xoff=border; + int yoff=border; + switch (xpos) { + case 0: break; + case 1: xoff=(width-area0.dx)/2; break; + case 2: xoff=width-border-area0.dx-1; break; + } + switch (ypos) { + case 0: break; + case 1: yoff=border-(localHeight-height)/2; break; + case 2: yoff=height-border-area0.dy_neg-area0.dy_pos; break; + } + //System.out.println("after 1. eqn"); + g.drawImage(genImage,xoff,yoff,xoff+area0.dx,yoff+area0.dy_pos+area0.dy_neg+1,0,height-area0.dy_pos,area0.dx,height+area0.dy_neg+1 ,this); + //System.out.println("after 2. eqn"); + geng.dispose(); + if (toosmall) printStatus("(width,height) given=("+width+","+height +") used=("+localWidth+","+localHeight+")"); + imageOK = true; + drawn = true; + xOFF=xoff; + yOFF=yoff+area0.dy_pos; + notify(); // notifiy that painting has been completed +} // end generateImage + +/* slower version with two scans +private synchronized void generateImage (Graphics g) { + BoxC area = new BoxC(); + BoxC area0 = new BoxC(); + g.setFont(f1); + g.setColor(BGColor); + g.fillRect(0,0,width,height); + border=0; + if (borderB && roundRectBorderB) { + g.setColor(EnvColor); + g.fillRect(0,0,width,height); + g.setColor(BGColor); + g.fillRoundRect(0,0,width-1,height-1,20,20); + g.setColor(BorderColor); + g.drawRoundRect(0,0,width-1,height-1,20,20); + border=5; + } else { + if (borderB && !roundRectBorderB) { + g.setColor(BorderColor); + g.drawRect(0,0,width-1,height-1); + border=5; + } + } + g.setColor(FGColor); + + //FontMetrics fM = g.getFontMetrics(); + //System.out.println("getAscent = "+fM.getAscent() ); + //System.out.println("getDescent = "+fM.getDescent() ); + //System.out.println("getHeight = "+fM.getHeight() ); + //System.out.println("getLeading = "+fM.getLeading() ); + //System.out.println("getMaxAdvance = "+fM.getMaxAdvance() ); + //System.out.println("getMaxAscent = "+fM.getMaxAscent() ); + //System.out.println("getMaxDecent = "+fM.getMaxDecent() ); + //System.out.println("getMaxDescent = "+fM.getMaxDescent() ); + + // Scanner reset & equation in d. Mitte d. Fensters + + //imageH.clear(); // Image Cache leeren (nicht erforderlich) + //System.out.println("before 1. eqn"); + eqScan.start(); + area0 = eqn(0,150, false, g, 1); + displayStatus(" "); + + // set alignment + xpos=0; // left + if (halign.equals("center")) xpos=1; + else if (halign.equals("right")) xpos=2; + + ypos=0; // top + if (valign.equals("middle")) ypos=1; + else if (valign.equals("bottom")) ypos=2; + + // Calculate actual size + localWidth = 1+area0.dx+2*border; + localHeight = 1+area0.dy_pos+area0.dy_neg+2*border; + + // Test size and modify alignment if too small + boolean toosmall = false; + if (localWidth > width) {toosmall=true; xpos=0;} + if (localHeight > height) {toosmall=true; ypos=1;} + // Calculate position + int xoff=border; + int yoff=area0.dy_pos+border; + switch (xpos) { + case 0: break; + case 1: xoff=(width-area0.dx)/2; break; + case 2: xoff=width-border-area0.dx-1; break; + } + switch (ypos) { + case 0: break; + case 1: yoff=border+area0.dy_pos-(localHeight-height)/2; break; + case 2: yoff=height-border-area0.dy_neg-1; break; + } + //System.out.println("after 1. eqn"); + eqScan.start(); + area = eqn(xoff,yoff,true,g,1); + //System.out.println("after 2. eqn"); + if (toosmall) printStatus("(width,height) given=("+width+","+height + +") used=("+localWidth+","+localHeight+")"); + imageOK = true; + drawn = true; + xOFF=xoff; + yOFF=yoff; + notify(); // notifiy that painting has been completed +} // end generateImage +*/ + + +//*************************************************************************** +//*************************************************************************** +//*************** Parser-routine ****************** +private BoxC eqn(int x, int y, boolean disp, Graphics g, int rec){ + // different number of parameters + return eqn(x, y, disp, g, rec, true); // Standard Argument (e.g. A_{.....}) +} // end eqn + + +private BoxC eqn(int x, int y, boolean disp, Graphics g, int rec, boolean Standard_Single){ +// Parameter: Baseline coordinates: x and y +// or drawing large calculate: disp (true/false) +// Recursion (break, high,low,...) +// Single (e.g. A_3)(false) o. Standard argument (e.g. A_{3+x})(true) + +// the method: boxReturn = adjustBox(box,boxReturn) replaces the separate +// calculation of the new box size after a function call + BoxC box = new BoxC(); // for R�ckgaben function calls + BoxC boxReturn = new BoxC(); // accumulates the max. box size + + boolean Standard_Single_flag = true; + boolean Space_flag = false; + boolean editModeFindLEFT = false; + int editModeCount = 0; + int editModeCountLEFT = 0; + int eqToktyp; + //String eqTokstringS; + + while (!eqScan.EoT() && Standard_Single_flag) { + eqTok = eqScan.nextToken(); + if (editMode && disp) editModeCount = eqScan.get_count(); + + Space_flag = false; + //System.out.print (eqTok.typ); + //if ( disp) System.out.println("Token ="+eqTok.typ); + editModeCountLEFT = editModeCount; + eqToktyp = eqTok.typ; + //eqTokstringS = eqTok.stringS; + + switch(eqTok.typ) { + case EqToken.AndSym: + case EqToken.DBackSlash: + case EqToken.END: + case EqToken.EndSym: + case EqToken.RIGHT: + if (editModeFind && disp) { + //System.out.println("RighteditModeCount ="+editModeCount); + if (editModeCount > editModeCount2) editModeCount2 = editModeCount; + if (editModeCount < editModeCount1) editModeCount1 = editModeCount; + } + return boxReturn; + case EqToken.ACCENT: + box = ACCENT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.ANGLE: + box = ANGLE(x+boxReturn.dx,y,disp,g); + break; + case EqToken.ARRAY: + if (editModeFind && disp) editModeFindLEFT = true; + box = ARRAY(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.BEGIN: + if (editModeFind && disp) editModeFindLEFT = true; + box = BEGIN(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.BeginSym: + box = eqn(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.FGColor: + box = FG_BGColor(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.BGColor: + box = FG_BGColor(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.FBOX: + if (editModeFind && disp) editModeFindLEFT = true; + box = FBOX(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.Id: + box = Id(x+boxReturn.dx,y,disp,g); + break; + case EqToken.NOT: + box = NOT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.Op: + box = Op(x+boxReturn.dx,y,disp,g); + break; + case EqToken.FRAC: + box = FRAC(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.ATOP: + box = FRAC(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.FUNC: + case EqToken.Num: + box = Plain(x+boxReturn.dx,y,disp,g); + break; + case EqToken.SYMBOP: + box = SYMBOP(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.SYMBOPD: + box = SYMBOP(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.LEFT: + if (editModeFind && disp) editModeFindLEFT = true; + box = LEFT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.LIM: + box = LIM(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.MBOX: + box = MBOX(x+boxReturn.dx,y,disp,g); + break; + case EqToken.OverBRACE: + box = OverBRACE(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.UnderBRACE: + box = UnderBRACE(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.OverLINE: + box = OverUnderLINE(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.UnderLINE: + box = OverUnderLINE(x+boxReturn.dx,y,disp,g,rec,false); + break; + case EqToken.Paren: + box = Paren(x+boxReturn.dx,y,disp,g); + break; + case EqToken.SPACE: + box = SPACE(x+boxReturn.dx,y,disp,g); + break; + case EqToken.SQRT: + if (editModeFind && disp) editModeFindLEFT = true; + box = SQRT(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.STACKREL: + box = STACKREL(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.SUP: + box = SUP(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.SUB: + box = SUB(x+boxReturn.dx,y,disp,g,rec,true); + break; + case EqToken.SYMBOLBIG: + box = SYMBOLBIG(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.VEC: + box = VEC(x+boxReturn.dx,y,disp,g,rec); + break; + case EqToken.SpaceChar: + box = new BoxC(0,0,0); + // bei SpaceChar gilt immer noch eqn(...,false) (single eqn) + Space_flag = true; + break; + case EqToken.Invalid: + case EqToken.Null: + box = new BoxC(0,0,0); + break; + default: + printStatus("Parser: unknown token: "+eqTok.typ+" "+eqTok.stringS); + //ignore + } // end switch + + if (disp) { + if (editMode) { + //System.out.println("x+boxReturn.dx = "+(x+boxReturn.dx)+" mouse1X = "+mouse1X+" x+boxReturn.dx+box.dx ="+(x+boxReturn.dx+box.dx)); + if (!editModeFind) { + if ( x+boxReturn.dx <= mouse1X && + mouse1X <= (x+boxReturn.dx+box.dx) && + (y-box.dy_pos) <= mouse1Y && + mouse1Y <= (y+box.dy_neg) ) { + //System.out.println("Top token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec); + x0 = x1 = mouse1X; + y0 = y1 = mouse1Y; + editModeFind = true; + editModeCount1 = editModeCount; + editModeCount2 = editModeCount; + } + } + if (!editModeFind) { + if ( x+boxReturn.dx <= mouse2X && + mouse2X <= (x+boxReturn.dx+box.dx) && + (y-box.dy_pos) <= mouse2Y && + mouse2Y <= (y+box.dy_neg) ) { + //System.out.println("Top2token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec); + x0 = x1 = mouse2X; + y0 = y1 = mouse2Y; + editModeFind = true; + editModeCount1 = editModeCount; + editModeCount2 = editModeCount; + int dummyX = mouse2X; + int dummyY = mouse2Y; + mouse2X = mouse1X; + mouse2Y = mouse1Y; + mouse1X = dummyX; + mouse1Y = dummyY; + } + } + //System.out.println("Token ="+eqToktyp+" editModeFind ="+editModeFind+" editModeFindLEFT ="+editModeFindLEFT); + if (editModeFind) { + //System.out.println("Mitte token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec+" "+editModeCount1+" "+editModeCount2); + x0 = Math.min(x0, x + boxReturn.dx); + x1 = Math.max(x1, x + boxReturn.dx + box.dx); + y0 = Math.min(y0, y - box.dy_pos); + y1 = Math.max(y1, y + box.dy_neg); + //g.setColor(Color.green); + //g.drawRect(x0, y0, x1-x0, y1-y0); + //g.setColor(FGColor); + if (editModeRec>rec) editModeRec = rec; + switch(eqToktyp) { + case EqToken.LEFT : + case EqToken.FBOX : + case EqToken.MBOX : + case EqToken.BEGIN : + case EqToken.ARRAY : + case EqToken.SQRT : + editModeFindLEFT = true; + if (editModeCountLEFT > editModeCount2) editModeCount2 = editModeCountLEFT; + if (editModeCountLEFT < editModeCount1) editModeCount1 = editModeCountLEFT; + editModeCount = eqScan.get_count(); + //System.out.println("MBOX/FBOX/LEFT handling"); + } // end switch + if (editModeCount > editModeCount2) editModeCount2 = editModeCount; + if (editModeCount < editModeCount1) editModeCount1 = editModeCount; + //System.out.println("editModeCount1 "+editModeCount1); + //System.out.println("editModeCount2 "+editModeCount2); + if ( x+boxReturn.dx <= mouse2X && + mouse2X <= (x+boxReturn.dx+box.dx) && + (y-box.dy_pos) <= mouse2Y && + mouse2Y <= (y+box.dy_neg) ) { + //System.out.println("Ende token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec); + //g.setColor(Color.red); + //g.drawRect(x0, y0, x1-x0, y1-y0); + //g.setColor(FGColor); + if (editModeRec == rec) { + editMode = false; + editModeFind = false; + //System.out.println("editModeCount "+editModeCount); + } + } + } // end editModeFind + } // end editMode + if (editModeFindLEFT) { + //System.out.println("find LEFT token "+eqToktyp+" "+eqTokstringS+" "+rec+" "+editModeRec+" "+editModeCount1+" "+editModeCount2); + x0 = Math.min(x0, x + boxReturn.dx); + x1 = Math.max(x1, x + boxReturn.dx + box.dx); + y0 = Math.min(y0, y - box.dy_pos); + y1 = Math.max(y1, y + box.dy_neg); + //g.setColor(Color.green); + //g.drawRect(x0, y0, x1-x0, y1-y0); + //g.setColor(FGColor); + switch(eqToktyp) { + case EqToken.LEFT : + case EqToken.FBOX : + case EqToken.MBOX : + case EqToken.BEGIN : + case EqToken.ARRAY : + case EqToken.SQRT : + if (editModeCountLEFT > editModeCount2) editModeCount2 = editModeCountLEFT; + if (editModeCountLEFT < editModeCount1) editModeCount1 = editModeCountLEFT; + editModeCount = eqScan.get_count(); + //System.out.println("MBOX/FBOX/LEFT handling"); + } // end switch + if (editModeCount > editModeCount2) editModeCount2 = editModeCount; + if (editModeCount < editModeCount1) editModeCount1 = editModeCount; + //System.out.println("editModeCount1 "+editModeCount1); + //System.out.println("editModeCount2 "+editModeCount2); + editModeFindLEFT = false; + } // end editModeFindLEFT + } // end disp + + boxReturn.dx += box.dx; + boxReturn.dy_pos = Math.max(boxReturn.dy_pos,box.dy_pos); + boxReturn.dy_neg = Math.max(boxReturn.dy_neg,box.dy_neg); + if (!Standard_Single && !Space_flag) Standard_Single_flag = false; // Single argument (e.g. A_3) + } // end while + return boxReturn; +} // end eqn + + +//************************************************************************ +private BoxC ACCENT(int x, int y, boolean disp, Graphics g, int rec) { +// accents: \dot \ddot \hat \grave \acute \tilde +// eqTok.stringS contain the be displayed(n) character + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + String large = eqTok.stringS; + + + //Only disp=true must Scanner later reset will + if (disp) count = eqScan.get_count(); + + + // large Argument-Box calculate + box = eqn(x,y,false,g,rec,false); + int dx = Math.max(box.dx,fM.stringWidth(large)); + int dy_pos = box.dy_pos + (int)(fM.getAscent()/2); + int dy_neg = box.dy_neg; + + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x,y-dy_pos,dx,dy_pos+dy_neg); + + // Argument draw + box = eqn(x,y,true,g,rec,false); + + // Mittenverschiebung ausrechenen + int d_dx = 3*(int)( (dx-fM.stringWidth(large))/4 ); + + if (large.equals(".") | large.equals("..")) { + g.drawString(large,x+d_dx,y-fM.getAscent()); + } + else if (large.equals("�") | large.equals("`")) { + g.drawString(large,x+d_dx,y-(int)(fM.getAscent()/3)); + } + else g.drawString(large,x+d_dx,y-(int)(fM.getAscent()*2/3)); + } // end disp + return new BoxC(dx,dy_pos,dy_neg); +} // end ACCENT + +//************************************************************************ +private BoxC ANGLE(int x, int y, boolean disp, Graphics g) { + // Spitze Klammern < und > + + BoxC box = new BoxC(); + FontMetrics fM = g.getFontMetrics(); + int dx = g.getFont().getSize()/2; + int dy_pos = fM.getHeight()-fM.getDescent(); + int dy_neg = fM.getDescent(); + + // only disp draw + if (disp) { + int yp = y-dy_pos+1; + int yn = y+dy_neg-1; + int m = (yp+yn)/2; + if (eqTok.stringS.equals("<")) { + g.drawLine(x+dx,yp,x,m); + g.drawLine(x,m,x+dx,yn); + } else { + g.drawLine(x,yp,x+dx,m); + g.drawLine(x+dx,m,x,yn); + } + } // end disp + return new BoxC(dx,dy_pos,dy_neg); +} // end ACCENT + +//************************************************************************ +private BoxC ARRAY(int x, int y, boolean disp, Graphics g, int rec) { + int dx = 0; + int dy_pos = 0; + int dy_neg = 0; + int dy_pos_max= 0; + int dx_eqn[] = new int[100]; // Breite columnselemente + int dy_pos_eqn[] = new int[100]; // H�he rowselemente + int dy_neg_eqn[] = new int[100]; // H�he rowselemente + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + // Abstand 1 quad hinter Element + int quad = g.getFont().getSize(); + + // only disp=true only Scanner later reset will + if (disp) count = eqScan.get_count(); + + // "{" vom Scanner holen + if (!expect(EqToken.BeginSym, "ARRAY: BeginSym")) return new BoxC(0,0,0); + + // loop: rows + for (int y_i = 0; y_i<99; y_i++) { + dy_pos = 0; + dy_neg = 0; + + // loop: columns + for (int x_i=0; x_i<99; x_i++) { + // large der Argument-Box calculate + box = eqn(x,y,false,g,rec); + + dy_pos = Math.max(dy_pos,box.dy_pos); + dy_neg = Math.max(dy_neg,box.dy_neg); + + // Breitesten Elemente pro column + dx_eqn[x_i] = Math.max(dx_eqn[x_i],box.dx+quad); + + // delimiter am columnsende + if ((eqTok.typ==EqToken.DBackSlash) || + (eqTok.typ==EqToken.EndSym)) break; + } // end columns + + // H�chste und tiefste rowsh�he + dy_pos_eqn[y_i] = Math.max(dy_pos_eqn[y_i],dy_pos); + dy_neg_eqn[y_i] = Math.max(dy_neg_eqn[y_i],dy_neg); + dy_pos_max += (dy_pos + dy_neg); + + // delimiter am ARRAY-Ende + if (eqTok.typ == EqToken.EndSym) break; + } // end rows + + + // maximum rows wide determine + int dx_max = 0; + for (int i=0; i<99; i++) dx_max += dx_eqn[i]; + + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x,y-dy_pos_max/2-fM.getDescent(),dx_max,dy_pos_max); + + // "{" vom Scanner holen + expect(EqToken.BeginSym, "ARRAY: Begin"); + + // loop: rows + dy_pos = 0; + for (int y_i=0; y_i<99; y_i++) { + dx = 0; + if (y_i==0) { dy_pos = dy_pos_eqn[y_i]; } + else { dy_pos += (dy_neg_eqn[y_i-1] + dy_pos_eqn[y_i]); } + // loop: columns + for (int x_i=0; x_i<99; x_i++) { + // large der Argument-Box calculate + box = eqn(x+dx,y-dy_pos_max/2-fM.getDescent()+dy_pos,true,g,rec); + dx += dx_eqn[x_i]; + + // delimiter am columnsende + if ((eqTok.typ == EqToken.DBackSlash) || + (eqTok.typ == EqToken.EndSym)) break; + } // end columns + // delimiter am ARRAY-Ende + if (eqTok.typ == EqToken.EndSym) break; + } // end rows + } // end disp + + return new BoxC(dx_max-quad,dy_pos_max/2+fM.getDescent(),dy_pos_max/2-fM.getDescent()); +} // end ARRAY + +//************************************************************************ +private BoxC BEGIN(int x, int y, boolean disp, Graphics g, int rec) { + int dx, dx_max = 0; + int dy_pos, dy_neg, dy_top, dy_max = 0; + int dx_eqn[] = new int[100]; // Breite columns elemente + int dy_pos_eqn[] = new int[100]; // H�he rows element + int dy_neg_eqn[] = new int[100]; // H�he rows elemente + int format[] = new int[100]; // Format 1-l 2-c 3-r 4-@ + int format_count[]= new int[100]; // f�r getcount() bei @-Einsch�ben + int format_dx = 0; // dx bei @-Einsch�ben + int format_dy_pos = 0; // dy_pos bei @-Einsch�ben + int format_dy_neg = 0; // dy_neg bei @-Einsch�ben + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + int quad = g.getFont().getSize(); + int i = 0; + boolean flag = false; + boolean flag_end = false; + boolean format_flag = true; + boolean array_eqnarray= true; // default: \begin{array} + int times = 0; // Zahl bei *{xxx} + int count2 =0; + + if (!expect(EqToken.BeginSym)) return new BoxC(0,0,0); + + if (eqScan.nextToken().stringS.equals("eqnarray")) array_eqnarray = false; + + if (!expect(EqToken.EndSym, "BEGIN: EndSym")) return new BoxC(0,0,0); + + if (array_eqnarray) { + count = eqScan.get_count(); + if (!expect(EqToken.BeginSym)) { + // NO format-string + format_flag = false; + eqScan.set_count(count); + } + } + + + if (array_eqnarray && format_flag) { + // *********** Format Angaben erkennen ********* + // l left(1) c center(2) r right(3) + // @{...} Einschub statt Zwischenraum(4) + + EqToken token = new EqToken(); + token = eqScan.nextToken(); + + while (token.typ != EqToken.EndSym) { + StringBuffer SBuffer = new StringBuffer(token.stringS); + for (int z=0; z")) { + g.drawLine(ddh,m,dh,yp); + g.drawLine(ddh,m,dh,yn); + } + else if (Bracket.equals("{")) { + for (int i=s;i<2+s;i++) { + int dpi=d+i; + arc(g,dd+i,ypr,r,180,-60); + g.drawLine(dpi,ypr,dpi,m-r); + arc(g,x+i,m-r,r,0,-90); + arc(g,x+i,m+r,r,0,90); + g.drawLine(dpi,m+r,dpi,ynr); + arc(g,dd+i,ynr,r,180,60); + } + } + else if (Bracket.equals("}")) { + for (int i=s;i<2+s;i++) { + int dpi=d+i; + arc(g,x+i,ypr,r,0,60); + g.drawLine(dpi,ypr,dpi,m-r); + arc(g,dd+i,m-r,r,-180,90); + arc(g,dd+i,m+r,r,180,-90); + g.drawLine(dpi,m+r,dpi,ynr); + arc(g,x+i,ynr,r,0,-60); + } + } +} // drawBracket + +//************************************************************************ +private BoxC LEFT(int x, int y, boolean disp, Graphics g, int rec) { + int dx_left = 0; + int dx_right = 0; + BoxC box = new BoxC(); + int count = 0; + Font localFont = g.getFont(); + int quad = localFont.getSize(); + int mkq = (int)(mk * quad); + int space = quad/9; + Font BracketFont; + FontMetrics BracketMetrics; + + // only disp=true only Scanner later reset will + if (disp) count = eqScan.get_count(); + + // Klammertyp f�r linke Seite vom Scanner holen + String LeftBracket = eqScan.nextToken().stringS; + + // large der Argument-Box calculate + box = eqn(x,y,false,g,rec); + int dx = box.dx; + int dy_pos = box.dy_pos; + int dy_neg = box.dy_neg; + int yp = y-dy_pos+1; + int yn = y+dy_neg-1; + + // Klammertyp f�r rechte Seite vom Scanner holen + String RightBracket = eqScan.nextToken().stringS; + + // Klammerlarge calculate + int BracketSize = dy_pos+dy_neg-2; + + BracketFont = new Font("Helvetica",Font.PLAIN,BracketSize); + g.setFont(BracketFont); + BracketMetrics = g.getFontMetrics(); + if (LeftBracket.equals("<") || LeftBracket.equals(">")) { + dx_left = quad; + } + else if (BracketSize < mkq) { + dx_left = BracketMetrics.stringWidth(LeftBracket); + if ("([{)]}".indexOf(LeftBracket) >= 0) dx_left += space; + } + else dx_left = quad; + + if (RightBracket.equals("<") || RightBracket.equals(">")) { + dx_right = quad; + } + else if (BracketSize < mkq) { + dx_right = BracketMetrics.stringWidth(RightBracket); + if ("([{)]}".indexOf(RightBracket) >= 0) dx_right += space; + } + else dx_right = quad; + g.setFont(localFont); + + // hinter Klammer Hoch-/Tiefstellung + int count2 = eqScan.get_count(); + // "SUB" + int SUB_dx = 0; + int SUB_baseline = 0; + if (eqScan.nextToken().typ == EqToken.SUB) { + box = SUB(x,y,false,g,rec,false); + SUB_dx=box.dx; + SUB_baseline = yn+box.dy_pos-(box.dy_pos+box.dy_neg)/2; + dy_neg += (box.dy_pos+box.dy_neg)/2; + } else eqScan.set_count(count2); + int count1 = eqScan.get_count(); + + // "SUP" + int SUP_dx = 0; + int SUP_baseline = 0; + if (eqScan.nextToken().typ == EqToken.SUP) { + box = SUP(x,y,false,g,rec,false); + SUP_dx = box.dx; + SUP_baseline = yp+box.dy_pos-(box.dy_pos+box.dy_neg)/2; + dy_pos += (box.dy_pos+box.dy_neg)/2; + } else eqScan.set_count(count1); + SUB_dx = Math.max(SUB_dx,SUP_dx); + + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x+dx_left,y-dy_pos,dx,dy_pos+dy_neg); + + // linker Klammertyp vom Scanner holen + LeftBracket = eqScan.nextToken().stringS; + if (!LeftBracket.equals(".")) { + if (BracketSize < mkq && !(LeftBracket.equals("<") || LeftBracket.equals(">"))) { + // linke Klammern mit font draw + g.setFont(BracketFont); + g.drawString(LeftBracket,x,yn-BracketMetrics.getDescent() + -BracketMetrics.getLeading()/2); + g.setFont(localFont); + } else + //linke Klammern direkt draw + drawBracket (g,LeftBracket,x,dx_left,yp,yn,quad,0); + } + + // Argument draw + box = eqn(x+dx_left,y,true,g,rec); + + // rechter Klammertyp vom Scanner holen + RightBracket = eqScan.nextToken().stringS; + if (!RightBracket.equals(".")) { + if (BracketSize < mkq && !(RightBracket.equals("<") || RightBracket.equals(">"))) { + // rechte Klammern mit font draw + g.setFont(BracketFont); + if ("([{)]}".indexOf(RightBracket) < 0) space = 0; + g.drawString(RightBracket,x+dx+dx_left+space,yn-BracketMetrics.getDescent() + -BracketMetrics.getLeading()/2); + g.setFont(localFont); + } else + //rechte Klammern direkt draw + drawBracket (g,RightBracket,x+dx+dx_left,dx_right,yp,yn,-quad,-1); + } + // hinter Klammer Hoch-/Tiefstellung + count2 = eqScan.get_count(); + // "SUB" + if (expect(EqToken.SUB)) + box = SUB(x+dx+dx_left+dx_right,SUB_baseline,true,g,rec,false); + else eqScan.set_count(count2); + count1 = eqScan.get_count(); + // "SUP" + if (expect(EqToken.SUP)) + box = SUP(x+dx+dx_left+dx_right,SUP_baseline,true,g,rec,false); + else eqScan.set_count(count1); + } // end disp + return new BoxC(dx+dx_left+dx_right+SUB_dx,dy_pos+2,dy_neg+2); +} // end LEFT + +//************************************************************************ +private BoxC LIM(int x, int y, boolean disp, Graphics g, int rec){ + int dx = 0; + BoxC box = new BoxC(); + int SUB_dx = 0; + int SUB_baseline = 0; + + FontMetrics fM = g.getFontMetrics(); + String stringS = eqTok.stringS; + + // es only Scanner later reset will + int count = eqScan.get_count(); + + int im_dx = dx = fM.stringWidth(stringS); + int dy_pos = fM.getHeight()-fM.getDescent(); + int dy_neg = fM.getDescent(); + + if (expect(EqToken.SUB)) { + box = SUB(x,y,false,g,rec,false); + SUB_dx=box.dx; + dx = Math.max(dx,box.dx); + SUB_baseline = box.dy_pos; + dy_neg = box.dy_pos+box.dy_neg; + } else eqScan.set_count(count); + + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + //g.drawRect(x,y-dy_pos,dx,dy_pos+dy_neg); + g.drawString(stringS,x+(dx-im_dx)/2,y); + if (expect(EqToken.SUB)) + box = SUB(x+(dx-SUB_dx)/2,y+SUB_baseline,true,g,rec,false); + else eqScan.set_count(count); + } // end disp + + return new BoxC(dx,dy_pos,dy_neg); +} // end LIM + +//************************************************************************ +private BoxC MBOX(int x, int y, boolean disp, Graphics g) { + // \mbox{...} plain text within equations + int dx = 0; + int dy_pos = 0; + int dy_neg = 0; + BoxC box = new BoxC(); + + // "{" vom Scanner holen + if (!expect(EqToken.BeginSym)) return new BoxC(0,0,0); + + while (!eqScan.EoT()) { + eqTok = eqScan.nextToken(); + if (eqTok.typ != EqToken.EndSym) { + box = Plain(x+dx, y, disp, g); + dx += box.dx; + dy_pos = Math.max(dy_pos,box.dy_pos); + dy_neg = Math.max(dy_neg,box.dy_neg); + } + else break; + } + + return new BoxC(dx, dy_pos, dy_neg); +} // end MBOX + +//********************************************************************** +private BoxC NOT(int x, int y, boolean disp, Graphics g, int rec){ +// Negation: \not or \not{ } + BoxC box = new BoxC(); + + box = eqn(x,y,disp,g,rec,false); + + if (disp) g.drawLine(x + box.dx/4 , y + box.dy_neg, + x + (box.dx*3)/4, y - box.dy_pos ); + return box; +} // end NOT + +//************************************************************************ +private BoxC Op(int x, int y, boolean disp, Graphics g) { +// Operatoren + FontMetrics fM = g.getFontMetrics(); + + if (disp) g.drawString(eqTok.stringS,x+1,y); + return new BoxC(fM.stringWidth(eqTok.stringS) + 2, + fM.getHeight()-fM.getDescent(), + fM.getDescent()); +} // end Op + +//************************************************************************* +private BoxC OverBRACE(int x, int y, boolean disp, Graphics g, int rec) { + int count = 0; + BoxC box = new BoxC(); + int r = g.getFont().getSize()/4; + int rh = r/2; + int SUP_dx = 0; + int SUP_base = 0; + int SUP_dy = 0; + + // only disp=true only Scanner later reset will + if (disp) count = eqScan.get_count(); + + // large der Argument-Box calculate + box = eqn(x,y,false,g,rec,false); + int dx = box.dx; + int dxh = dx/2; + int x_middle = dxh; + int dy_pos = box.dy_pos; + int dy_neg = box.dy_neg; + + // "SUP" behandeln, FALLS beforehanden + int count1 = eqScan.get_count(); + if (expect(EqToken.SUP)) { + box = SUP(x,y,false,g,rec,false); + SUP_dx = box.dx; + x_middle = Math.max(x_middle,SUP_dx/2); + SUP_base = dy_pos + box.dy_neg; + SUP_dy = box.dy_pos + box.dy_neg; + } else eqScan.set_count(count1); + + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + int xx = x + x_middle-dxh; + box = eqn(xx, y, true, g, rec, false); + int rred = (int)(r*0.86602540378444); + for (int i=0;i<2;i++) { + int ypi = y-dy_pos-rh+i; + arc(g,xx+rred,ypi+r,r,90,60); + g.drawLine(xx+rred,ypi,xx+dxh-r,ypi); + arc(g,xx+dxh-r,ypi-r,r,0,-90); + arc(g,xx+dxh+r,ypi-r,r,-90,-90); + g.drawLine(xx+dxh+r,ypi,xx+dx-rred,ypi); + arc(g,xx+dx-rred,ypi+r,r,90,-60); + } + count1 = eqScan.get_count(); + if (expect(EqToken.SUP)) + box = SUP(x+x_middle-SUP_dx/2, y-SUP_base-r-rh,true,g,rec,false); + else eqScan.set_count(count1); + } // end disp + + dy_pos += SUP_dy + r + rh ; + dx = Math.max(dx,SUP_dx); + + return new BoxC(dx,dy_pos,dy_neg); +} // end OverBRACE + + +//************************************************************************* +private BoxC UnderBRACE(int x, int y, boolean disp, Graphics g, int rec) { + int count = 0; + BoxC box = new BoxC(); + int r = g.getFont().getSize()/4; + int rh = r/2; + int SUB_dx = 0; + int SUB_base = 0; + int SUB_dy = 0; + + // only disp=true only Scanner later reset will + if (disp) count = eqScan.get_count(); + + // large der Argument-Box calculate + box = eqn(x,y,false,g,rec,false); + int dx = box.dx; + int dxh = dx/2; + int x_middle = dxh; + int dy_pos = box.dy_pos; + int dy_neg = box.dy_neg; + + // "SUB" behandeln, FALLS beforehanden + int count1 = eqScan.get_count(); + if (expect(EqToken.SUB)) { + box = SUB(x,y,false,g,rec,false); + SUB_dx = box.dx; + x_middle = Math.max(x_middle,SUB_dx/2); + SUB_base = dy_neg + box.dy_pos; + SUB_dy = box.dy_pos + box.dy_neg; + } else eqScan.set_count(count1); + + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + int xx = x + x_middle-dxh; + box = eqn(xx, y, true, g, rec, false); + int rred = (int)(r*0.86602540378444); + for (int i=0;i<2;i++) { + int ypi = y+dy_neg+rh-i; + arc(g,xx+rred,ypi-r,r,-90,-60); + g.drawLine(xx+rred,ypi,xx+dxh-r,ypi); + arc(g,xx+dxh-r,ypi+r,r,90,-90); + arc(g,xx+dxh+r,ypi+r,r,90,90); + g.drawLine(xx+dxh+r,ypi,xx+dx-rred,ypi); + arc(g,xx+dx-rred,ypi-r,r,-90,60); + } + count1 = eqScan.get_count(); + if (eqScan.nextToken().typ == EqToken.SUB) + box = SUB(x+x_middle-SUB_dx/2, y+SUB_base+r+rh,true,g,rec,false); + else eqScan.set_count(count1); + } // end disp + + dy_neg += SUB_dy + r + rh ; + dx = Math.max(dx,SUB_dx); + + return new BoxC(dx,dy_pos,dy_neg); +} // end UnderBRACE + +//************************************************************************ +private BoxC OverUnderLINE(int x, int y, boolean disp, Graphics g, int rec, + boolean OverUnder) { + int count = 0; + BoxC box = new BoxC(); + + // only disp=true only Scanner later reset will + if (disp) count = eqScan.get_count(); + + // large der Argument-Box calculate + box = eqn(x,y,false,g,rec,false); + if (OverUnder) box.dy_pos += 2; // place over Strich + else box.dy_neg += 2; // place unter Strich + int dy_pos=box.dy_pos; + int dy_neg=box.dy_neg; + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + if (OverUnder) g.drawLine(x+1, y-dy_pos+2, x+box.dx-1, y-dy_pos+2); + else g.drawLine(x, y+dy_neg-2, x+box.dx, y+dy_neg-2); + box = eqn(x,y,true,g,rec,false); + } + return new BoxC(box.dx,dy_pos,dy_neg); +} // end OverUnderLINE + +//************************************************************************ +private BoxC Paren(int x, int y, boolean disp, Graphics g){ + FontMetrics fM = g.getFontMetrics(); + int space = g.getFont().getSize()/9; + int dx = fM.stringWidth(eqTok.stringS); + int i = "([{)]}".indexOf(eqTok.stringS); + if (i >= 0) { + dx += space; + if (i > 2 ) x += space; + } + if (disp) g.drawString(eqTok.stringS,x,y); + return new BoxC( dx, + fM.getHeight()-fM.getDescent(), + fM.getDescent()); +} // end Paren + +//************************************************************************ +private BoxC Plain(int x, int y, boolean disp, Graphics g){ + FontMetrics fM = g.getFontMetrics(); + + if (disp) g.drawString(eqTok.stringS,x,y); + return new BoxC( fM.stringWidth(eqTok.stringS), + fM.getHeight()-fM.getDescent(), + fM.getDescent()); +} // end Plain + +//************************************************************************ +private BoxC SPACE(int x, int y, boolean disp, Graphics g){ + // additional positive or negative space between elements + int dx = 0; + Font font = g.getFont(); + try { dx = Integer.parseInt(eqTok.stringS);} + catch (NumberFormatException e){ dx = 0; } + dx = ( dx * font.getSize()) / 18; + return new BoxC(dx,0,0); +} // end SPACE + +//************************************************************************ +private BoxC SQRT(int x, int y, boolean disp, Graphics g, int rec) { + BoxC box = new BoxC(); + int count = 0; + FontMetrics fM = g.getFontMetrics(); + int dx_n = 0; + int dy_pos_n = 0; + int dy_neg_n = 0; + int dy_n = 0; + boolean n_sqrt = false; + + // only disp=true only Scanner later reset will + if (disp) count = eqScan.get_count(); + + // something place for the hook of the root. + int dx_Haken = fM.stringWidth("A"); + int dx_Hakenh = dx_Haken/2; + + + // \sqrt[...]{...} + int count1 = eqScan.get_count(); + EqToken token = new EqToken(); + token = eqScan.nextToken(); + if (token.stringS.equals("[")) { + // large der [n.ten] root + rec_Font(g,rec+1); + box = eqn(x,y,false,g,rec+1,true); + rec_Font(g,rec); + dx_n = box.dx; + dy_pos_n = box.dy_pos; + dy_neg_n = box.dy_neg; + dy_n = dy_neg_n + dy_pos_n; + n_sqrt = true; + } + else eqScan.set_count(count1); + + // large der Argument-Box calculate + box = eqn(x,y,false,g,rec,false); + int dx = box.dx + dx_Haken; + int dy_pos = box.dy_pos + 2; // additional place over overbar + int dy_neg = box.dy_neg; + + if (n_sqrt & dx_n>dx_Hakenh) dx += dx_n - dx_Hakenh; + + // only disp=true is Scanner reset + if (disp) { + eqScan.set_count(count); + + //g.drawRect(x,y-dy_pos,dx,dy_pos+dy_neg); + + // root character + int dx_n_h = 0; + if (n_sqrt & dx_n > dx_Hakenh) dx_n_h = dx_n - dx_Hakenh; + g.drawLine(x+dx_n_h+1,y-dy_pos/2, x+dx_n_h+dx_Hakenh,y+dy_neg-1); + g.drawLine(x+dx_n_h+dx_Hakenh,y+dy_neg-1, x+dx_n_h+dx_Haken-2,y-dy_pos+2); + g.drawLine(x+dx_n_h+dx_Haken-2,y-dy_pos+2, x+dx,y-dy_pos+2 ); + + if (n_sqrt) { + token = eqScan.nextToken(); + rec_Font(g,rec+1); + if (dx_n>=dx_Hakenh){ + g.drawLine(x+1,y-dy_pos/2, x+dx_n_h+1,y-dy_pos/2); + box = eqn(x+1,y- dy_pos/2 - dy_neg_n-1,true,g,rec+1,true); + } + else box = eqn(x+1+(dx_Hakenh-dx_n),y- dy_pos/2 - dy_neg_n-1,true,g,rec+1,true); + rec_Font(g,rec); + } + + // Argument draw + box = eqn(x+dx_n_h+dx_Haken,y,true,g,rec,false); + + } // end disp + + if (n_sqrt & dy_pos/2 imageBytes.length) { //haven't yet allocated enough space + byte[] tempImageBytes= (byte[]) imageBytes.clone(); + imageBytes = new byte[totalBytes]; + System.arraycopy(tempImageBytes, 0, imageBytes, 0, alreadyRead); + } + } + if (numBytes == 0) break; + } + //Create an ImageProducer from the image bytes + source = Toolkit.getDefaultToolkit().createImage(imageBytes).getSource(); + } + catch (Exception io) {} + return source; +} // end getLocalImageSource + +} // end class sSymbolLoader + +/* +// sSymbolLoader for unpacked font files (slow speed) +class sSymbolLoader { + +public sSymbolLoader() { } +// dummy constructor + +//Fonts are included in HotEqn zip/jar file +private static boolean kLocalFonts=true; + +public Image getImage( boolean appletB, boolean beanB, String filenameS, + Graphics g, JApplet app) { + ImageProducer imageSource=null; + Image image=null; + + if(kLocalFonts) { + imageSource = getLocalImageSource(filenameS); + } + if(imageSource==null) { //Fonts are not local + kLocalFonts=false; //don't attempt to load local fonts anymore + + //Try loading external Font files in component/applet/bean specific manner + if (!appletB & !beanB) { + // component code + imageSource=Toolkit.getDefaultToolkit().getImage( filenameS ).getSource(); + } else if (appletB) { + // applet code + imageSource= app.getImage(app.getCodeBase(), filenameS ).getSource(); + } else { + // bean code + // beanB==true + try { + URL url = getClass().getResource( filenameS ); + imageSource = (ImageProducer) url.getContent(); + } catch (Exception ex) { + } + } + } + if(imageSource!=null) { + image = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource( + imageSource, new ColorMaskFilter(g.getColor()))); + } + return image; +} // end getImage + +ImageProducer getLocalImageSource(String resourceName) { + //Try loading images from jar + ImageProducer source = null; + try { + // Next line assumes that Fonts are in the same jar file as sSymbolLoader + // Since resourceName doesn't start with a "/", resourceName is treated + // as the relative path to the image file from the directory where + // sSymbolLoader.class is. + InputStream imageStream = getClass().getResourceAsStream(resourceName); + int numBytes = imageStream.available();//System.out.println(numBytes); + byte[] imageBytes = new byte[numBytes]; +//System.out.println(numBytes); + // Note: If all bytes are immediately available, the while loop just + // executes once and could be replaced by the line: + // imageStream.read(imageBytes,0,numBytes); + // This may always be the case for the small Font images + + int alreadyRead = 0; + int justRead = 0; + while (justRead != -1) { + justRead = imageStream.read(imageBytes,alreadyRead,numBytes); + if(justRead != -1) { //didn't get all the bytes + alreadyRead += justRead; //Total Read so far + numBytes = imageStream.available(); //Amount left to read + int totalBytes = alreadyRead + numBytes; //total bytes needed to + //store everything we know about +//System.out.println("+"+numBytes); + if((totalBytes) > imageBytes.length) { //haven't yet allocated enough space + byte[] tempImageBytes= (byte[]) imageBytes.clone(); + imageBytes = new byte[totalBytes]; + System.arraycopy(tempImageBytes, 0, imageBytes, 0, alreadyRead); + } + } + } + //Create an ImageProducer from the image bytes + source = Toolkit.getDefaultToolkit().createImage(imageBytes).getSource(); + } + catch (Exception io) {} + return source; +} // end getLocalImageSource + +} // end class sSymbolLoader +*/ + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/ScreenCapture.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/ScreenCapture.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/ScreenCapture.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/ScreenCapture.java 2010-12-29 01:32:10.000000000 +0000 @@ -0,0 +1,218 @@ +package org.mathpiper.ui.gui; + + +/*This code was obtained from http://www.discoverteenergy.com/files/ScreenImage.java + There was no license associated with the code. */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import java.io.*; +import javax.imageio.*; +import javax.swing.*; + +public class ScreenCapture +{ + /* + * Create a BufferedImage for Swing components. + * The entire component will be captured to an image. + * + * @param component Swing component to create image from + * @param fileName name of file to be created or null + * @return image the image for the given region + * @exception IOException if an error occurs during writing + */ + public static BufferedImage createImage(JComponent component, String fileName) + throws IOException + { + Dimension d = component.getSize(); + + if (d.width == 0) + { + d = component.getPreferredSize(); + component.setSize( d ); + } + + Rectangle region = new Rectangle(0, 0, d.width, d.height); + return ScreenCapture.createImage(component, region, fileName); + } + + /* + * Create a BufferedImage for Swing components. + * All or part of the component can be captured to an image. + * + * @param component Swing component to create image from + * @param region The region of the component to be captured to an image + * @param fileName name of file to be created or null + * @return image the image for the given region + * @exception IOException if an error occurs during writing + */ + public static BufferedImage createImage(JComponent component, Rectangle region, String fileName) + throws IOException + { + boolean opaqueValue = component.isOpaque(); + component.setOpaque( true ); + BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = image.createGraphics(); + g2d.setClip( region ); + component.paint( g2d ); + g2d.dispose(); + component.setOpaque( opaqueValue ); + ScreenCapture.writeImage(image, fileName); + return image; + } + + /* + * Create a BufferedImage for AWT components. + * + * @param component AWT component to create image from + * @param fileName name of file to be created or null + * @return image the image for the given region + * @exception AWTException see Robot class constructors + * @exception IOException if an error occurs during writing + */ + public static BufferedImage createImage(Component component, String fileName) + throws AWTException, IOException + { + Point p = new Point(0, 0); + SwingUtilities.convertPointToScreen(p, component); + Rectangle region = component.getBounds(); + region.x = p.x; + region.y = p.y; + return ScreenCapture.createImage(region, fileName); + } + + /** + * Convenience method to create a BufferedImage of the desktop + * + * @param fileName name of file to be created or null + * @return image the image for the given region + * @exception AWTException see Robot class constructors + * @exception IOException if an error occurs during writing + */ + public static BufferedImage createDesktopImage(String fileName) + throws AWTException, IOException + { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + Rectangle region = new Rectangle(0, 0, d.width, d.height); + return ScreenCapture.createImage(region, fileName); + } + + /** + * Create a BufferedImage from a rectangular region on the screen. + * + * @param region region on the screen to create image from + * @param fileName name of file to be created or null + * @return image the image for the given region + * @exception AWTException see Robot class constructors + * @exception IOException if an error occurs during writing + */ + public static BufferedImage createImage(Rectangle region, String fileName) + throws AWTException, IOException + { + BufferedImage image = new Robot().createScreenCapture( region ); + ScreenCapture.writeImage(image, fileName); + return image; + } + + /** + * Write a BufferedImage to a File. + * + * @param image image to be written + * @param fileName name of file to be created + * @exception IOException if an error occurs during writing + */ + public static void writeImage(BufferedImage image, String fileName) + throws IOException + { + if (fileName == null) return; + + int offset = fileName.lastIndexOf( "." ); + String type = offset == -1 ? "png" : fileName.substring(offset + 1); + + ImageIO.write(image, type, new File( fileName )); + } + + public static void main(String args[]) + throws Exception + { + final JFrame frame = new JFrame(); + final JTextArea textArea = new JTextArea(30, 60); + final JScrollPane scrollPane = new JScrollPane( textArea ); + frame.getContentPane().add( scrollPane ); + + JMenuBar menuBar = new JMenuBar(); + frame.setJMenuBar( menuBar ); + JMenu menu = new JMenu( "File" ); + ScreenCapture.createImage(menu, "menu.jpg"); + menuBar.add( menu ); + JMenuItem menuItem = new JMenuItem( "Frame Image" ); + menu.add( menuItem ); + menuItem.addActionListener( new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + // Let the menu close and repaint itself before taking the image + + new Thread() + { + public void run() + { + try + { + Thread.sleep(50); + System.out.println("Creating frame.jpg"); + frame.repaint(); + ScreenCapture.createImage(frame, "frame.jpg"); + } + catch(Exception exc) { System.out.println(exc); } + } + }.start(); + }; + }); + + final JButton button = new JButton("Create Images"); + button.addActionListener( new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + try + { + System.out.println("Creating desktop.jpg"); + ScreenCapture.createDesktopImage( "desktop.jpg" ); + System.out.println("Creating frame.jpg"); + ScreenCapture.createImage(frame, "frame.jpg"); + System.out.println("Creating scrollpane.jpg"); + ScreenCapture.createImage(scrollPane, "scrollpane.jpg"); + System.out.println("Creating textarea.jpg"); + ScreenCapture.createImage(textArea, "textarea.jpg"); + System.out.println("Creating button.jpg"); + ScreenCapture.createImage(button, "button.jpg"); + button.setText("button refreshed"); + button.paintImmediately(button.getBounds()); + System.out.println("Creating refresh.jpg"); + ScreenCapture.createImage(button, "refresh.jpg"); + System.out.println("Creating region.jpg"); + Rectangle r = new Rectangle(0, 0, 100, 16); + ScreenCapture.createImage(textArea, r, "region.png"); + } + catch(Exception exc) { System.out.println(exc); } + } + }); + frame.getContentPane().add(button, BorderLayout.SOUTH); + + try + { + FileReader fr = new FileReader( "ScreenCapture.java" ); + BufferedReader br = new BufferedReader(fr); + textArea.read( br, null ); + br.close(); + } + catch(Exception e) {} + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setLocationRelativeTo( null ); + frame.setVisible(true); + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/Utility.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/Utility.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/Utility.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/Utility.java 2010-12-29 01:32:10.000000000 +0000 @@ -0,0 +1,26 @@ +package org.mathpiper.ui.gui; + +import java.io.File; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import org.mathpiper.ui.gui.consoles.ResultHolder; + +public class Utility { + + public static void saveImageOfComponent(JComponent component) { + JFileChooser saveImageFileChooser = new JFileChooser(); + + int returnValue = saveImageFileChooser.showSaveDialog(component); + + if (returnValue == JFileChooser.APPROVE_OPTION) { + File exportImageFile = saveImageFileChooser.getSelectedFile(); + try { + ScreenCapture.createImage(component, exportImageFile.getAbsolutePath()); + } catch (java.io.IOException ioe) { + ioe.printStackTrace(); + }//end try/catch. + + } + } + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.html mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.html --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.html 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.html 2009-12-30 02:31:26.000000000 +0000 @@ -20,12 +20,12 @@


    Applet HTML Page

    - + ' ' ' -' +' Java support does not seem to be installed in your browser, so the console is not available. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ConsoleApplet.java 2010-07-23 05:26:16.000000000 +0000 @@ -17,6 +17,14 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.ui.gui.worksheets; +import org.mathpiper.ui.gui.worksheets.hints.Hints; +import org.mathpiper.ui.gui.worksheets.hints.HintWindow; +import org.mathpiper.ui.gui.worksheets.hints.HintItem; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.PromptedStringLine; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.ImageLine; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.MathOutputLine; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.PromptedGraph2DLine; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.PromptedFormulaLine; import org.mathpiper.interpreters.Interpreter; import org.mathpiper.interpreters.Interpreters; import org.mathpiper.io.CachedStandardFileInputStream; @@ -58,7 +66,7 @@ int cursorPos = 0; final int inset = 5; final static String inputPrompt = "In> "; - final static String outputPrompt = "Out> "; + final static String outputPrompt = "Result: "; static final int fontHeight = 14; private Font font = new Font("Verdana", Font.PLAIN, fontHeight); private static final int nrHistoryLines = 100; @@ -558,7 +566,7 @@ gatheredMultiLine = gatheredMultiLine + inputLine.substring(0, inputLine.length() - 1); } else { - performRequest("Out> ", gatheredMultiLine + inputLine, true); + performRequest("Result: ", gatheredMultiLine + inputLine, true); } resetInput(); } @@ -788,7 +796,7 @@ gatheredMultiLine = gatheredMultiLine + inputLine.substring(0, inputLine.length() - 1); } else { - performRequest("Out> ", gatheredMultiLine + inputLine, true); + performRequest("Result: ", gatheredMultiLine + inputLine, true); } resetInput(); refreshHintWindow(); @@ -879,6 +887,8 @@ calculating = false; addOutputLine(outputStringBuffer.toString()); + + if (response.isExceptionThrown() == true) { addLinesStatic(48, "Error> ", response.getExceptionMessage()); @@ -1430,7 +1440,7 @@ refreshHintWindow(); inputDirty = true; outputDirty = true; - performRequest("Out> ", expression, false); + performRequest("Result: ", expression, false); inputDirty = true; outputDirty = true; repaint(); @@ -1488,10 +1498,10 @@ { dollared = dollared.substring(plotPos + 7); //System.out.println("Plotting: ["+dollared+"]"); - addLine(new PromptedGraph2DLine(48, "Out>", iPromptFont, iPromptColor, dollared)); + addLine(new PromptedGraph2DLine(48, "Result:", iPromptFont, iPromptColor, dollared)); } else { - addLine(new PromptedFormulaLine(48, "Out>", iPromptFont, iPromptColor, dollared)); + addLine(new PromptedFormulaLine(48, "Result:", iPromptFont, iPromptColor, dollared)); } dollarPos = outp.indexOf("$"); } @@ -1555,7 +1565,8 @@ public void stopCurrentCalculation() { - interpreter.getEnvironment().iEvalDepth = interpreter.getEnvironment().iMaxEvalDepth + 100; + //interpreter.getEnvironment().iEvalDepth = interpreter.getEnvironment().iMaxEvalDepth + 100; + interpreter.haltEvaluation(); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ConsolePanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ConsolePanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ConsolePanel.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ConsolePanel.java 2010-07-23 05:26:16.000000000 +0000 @@ -17,6 +17,13 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.ui.gui.worksheets; +import org.mathpiper.ui.gui.worksheets.hints.Hints; +import org.mathpiper.ui.gui.worksheets.hints.HintWindow; +import org.mathpiper.ui.gui.worksheets.hints.HintItem; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.PromptedStringLine; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.MathOutputLine; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.PromptedGraph2DLine; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.PromptedFormulaLine; import org.mathpiper.interpreters.Interpreter; import org.mathpiper.interpreters.Interpreters; import org.mathpiper.io.CachedStandardFileInputStream; @@ -58,7 +65,7 @@ int cursorPos = 0; final int inset = 5; final static String inputPrompt = "In> "; - final static String outputPrompt = "Out> "; + final static String outputPrompt = "Result: "; static final int fontHeight = 14; private Font font = new Font("Verdana", Font.PLAIN, fontHeight); private static final int nrHistoryLines = 100; @@ -93,11 +100,11 @@ public void init() { System.out.println("Initializing."); - this.setSize(400, 400); //todo:tk: + this.setSize(500, 500); //todo:tk: setBackground(bkColor); setLayout(null); - this.setPreferredSize(new Dimension(400,400)); + this.setPreferredSize(new Dimension(500,500)); this.setFocusable(true); requestFocus(); addKeyListener(this); @@ -597,7 +604,7 @@ gatheredMultiLine = gatheredMultiLine + inputLine.substring(0, inputLine.length() - 1); } else { - performRequest("Out> ", gatheredMultiLine + inputLine, true); + performRequest("Result: ", gatheredMultiLine + inputLine, true); } resetInput(); } @@ -827,7 +834,7 @@ gatheredMultiLine = gatheredMultiLine + inputLine.substring(0, inputLine.length() - 1); } else { - performRequest("Out> ", gatheredMultiLine + inputLine, true); + performRequest("Result: ", gatheredMultiLine + inputLine, true); } resetInput(); refreshHintWindow(); @@ -1471,7 +1478,7 @@ refreshHintWindow(); inputDirty = true; outputDirty = true; - performRequest("Out> ", expression, false); + performRequest("Result: ", expression, false); inputDirty = true; outputDirty = true; repaint(); @@ -1529,10 +1536,10 @@ { dollared = dollared.substring(plotPos + 7); //System.out.println("Plotting: ["+dollared+"]"); - addLine(new PromptedGraph2DLine(48, "Out>", iPromptFont, iPromptColor, dollared)); + addLine(new PromptedGraph2DLine(48, "Result:", iPromptFont, iPromptColor, dollared)); } else { - addLine(new PromptedFormulaLine(48, "Out>", iPromptFont, iPromptColor, dollared)); + addLine(new PromptedFormulaLine(48, "Result:", iPromptFont, iPromptColor, dollared)); } dollarPos = outp.indexOf("$"); } @@ -1596,7 +1603,9 @@ public void stopCurrentCalculation() { - interpreter.getEnvironment().iEvalDepth = interpreter.getEnvironment().iMaxEvalDepth + 100; + //interpreter.getEnvironment().iEvalDepth = interpreter.getEnvironment().iMaxEvalDepth + 100; + interpreter.haltEvaluation(); + } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/FormulaViewApplet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/FormulaViewApplet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/FormulaViewApplet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/FormulaViewApplet.java 2010-04-02 06:35:47.000000000 +0000 @@ -18,13 +18,13 @@ package org.mathpiper.ui.gui.worksheets; -import org.mathpiper.ui.gui.worksheets.TexParser; +import org.mathpiper.ui.gui.worksheets.latexparser.TexParser; +import org.mathpiper.ui.gui.worksheets.symbolboxes.ScaledGraphics; +import org.mathpiper.ui.gui.worksheets.symbolboxes.SymbolBox; import java.awt.*; import java.applet.*; -import java.awt.event.*; -import java.io.*; -import java.net.*; +import org.mathpiper.ui.gui.worksheets.symbolboxes.Position; public class FormulaViewApplet extends Applet { @@ -32,7 +32,7 @@ Graphics offGraphics = null; Dimension offDimension = null; - SBox expression = null; + SymbolBox expression = null; public void init() { @@ -111,14 +111,14 @@ // Clear Background Dimension d = getSize(); // g.setColor(Color.white); - // g.fillRect(0, 0, d.width, d.height); + // g.fillRect(0, 0, d.getTextWidth, d.getTextHeight); // All graphics should be black from now on g.setColor(Color.black); - GraphicsPrimitives gp = new GraphicsPrimitives(g); + ScaledGraphics sg = new ScaledGraphics(g); - gp.setLineThickness(0); + sg.setLineThickness(0); if (expression == null) { @@ -132,8 +132,8 @@ } if (expression != null) { - expression.calculatePositions(gp, 3, new java.awt.Point(1, d.height/2)); - expression.render(gp); + expression.calculatePositions(sg, 3, new Position(1, d.height/2)); + expression.render(sg); } } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/GrapherApplet.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/GrapherApplet.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/GrapherApplet.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/GrapherApplet.java 2010-01-22 08:53:44.000000000 +0000 @@ -18,9 +18,8 @@ package org.mathpiper.ui.gui.worksheets; -import java.net.*; +import org.mathpiper.ui.gui.worksheets.mathoutputlines.Grapher; import java.awt.*; -import java.io.*; import java.awt.event.*; public class GrapherApplet extends java.applet.Applet implements KeyListener diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/Grapher.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/Grapher.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/Grapher.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/Grapher.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,344 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - -import java.awt.*; - -public class Grapher -{ - public double xmin, ymin, xmax, ymax; - String iCallList; - String execList; - String token; - int graphx = 0; - int graphy = 0; - int graphWidth = 10; - int graphHeight = 10; - int axesFontHeight = 12; - FontMetrics fontMetrics = null; - int exampleWidth = 48; - - Grapher(String aCallList) - { - xmin = 1e200; - ymin = 1e200; - xmax = -xmin; - ymax = -ymin; - iCallList = aCallList; - runCallList(null); - } - - - void nextToken() - { - int startPos = 0; - while (startPos < execList.length() && execList.charAt(startPos) == ' ') - startPos++; - int endPos = startPos; - while (endPos < execList.length() && execList.charAt(endPos) != ' ') - endPos++; - token = execList.substring(startPos, endPos); - execList = execList.substring(endPos); - } - - - void runCallList(Graphics g) - { - try - { - Graphics2D g2d = null; - if (g != null) - { - if (g instanceof Graphics2D) - { - g2d = (Graphics2D)g; - } - } - - execList = iCallList; - nextToken(); - while (token.length() > 0) - { - if (token.equals("lines2d")) - { - int i; - nextToken(); - int nr = Integer.parseInt(token); - nextToken(); - double x2,y2=0; - x2 = Float.parseFloat(token); - nextToken(); - y2 = Float.parseFloat(token); - if (g == null) - { - if (xmin > x2) xmin = x2; - if (xmax < x2) xmax = x2; - if (ymin > y2) ymin = y2; - if (ymax < y2) ymax = y2; - } - double x1,y1; - for (i=1;i x2) xmin = x2; - if (xmax < x2) xmax = x2; - if (ymin > y2) ymin = y2; - if (ymax < y2) ymax = y2; - } - if (g != null) - { - int xPix1 = (int)(graphx + graphWidth * (x1 - xmin) / (xmax - xmin)); - int yPix1 = (int)(graphy + graphHeight * (1.0 - (y1 - ymin) / (ymax - ymin))); - int xPix2 = (int)(graphx + graphWidth * (x2 - xmin) / (xmax - xmin)); - int yPix2 = (int)(graphy + graphHeight * (1.0 - (y2 - ymin) / (ymax - ymin))); - g.drawLine(xPix1, yPix1, xPix2, yPix2); - } - } - } - else if (token.equals("pencolor")) - { - nextToken(); - int red = Integer.parseInt(token); - nextToken(); - int green = Integer.parseInt(token); - nextToken(); - int blue = Integer.parseInt(token); - if (g != null) - { - g.setColor(new Color(red, green, blue)); - } - } - else if (token.equals("pensize")) - { - nextToken(); - float width = Float.parseFloat(token); - if (g != null) - { - if (g2d != null) - { - g2d.setStroke(new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - } - } - } - else - { - //TODO raise an exception here - return; - } - nextToken(); - } - } - catch (Exception e) - { - //TODO handle exception here - } - } - - - void determineGraphBounds(int xleft, int ytop, Dimension d) - { - if (fontMetrics != null) - { - exampleWidth = fontMetrics.stringWidth("100000"); - } - graphx = xleft + exampleWidth; - graphy = ytop + axesFontHeight; - graphWidth = d.width - (3 * exampleWidth) / 2; - graphHeight = d.height - 3 * axesFontHeight; - } - public void paint(Graphics g, int xleft, int ytop, Dimension d) - { - Shape clip = g.getClip(); - Rectangle r = clip.getBounds(); - Graphics2D g2d = null; - if (g instanceof Graphics2D) - { - g2d = (Graphics2D)g; - } - if (g2d != null) - { - g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); - } - int clipHeight = d.height; - if (ytop+clipHeight > r.y+r.height) - { - clipHeight = r.y+r.height-ytop; - } - g.setClip(xleft, ytop, d.width, clipHeight); - - // Erase the previous image - g.setColor(Color.white); - g.fillRect(xleft, ytop, d.width, d.height); - - Font font; - font = new Font("Verdana", Font.PLAIN, axesFontHeight); - g.setFont(font); - fontMetrics = g.getFontMetrics(font); - determineGraphBounds(xleft, ytop, d); - - Color grey = new Color(164, 164, 164); - - double x, y; - - PlotRange xRange = new PlotRange(xmin, xmax, d.width / ((3 * exampleWidth) / 2)); - int xtick = ((int)(xmin / xRange.TickSize() - 1)); - if (xRange.TickSize() * xtick < xmin) - xtick = xtick + 1; - double xstart = xRange.TickSize() * xtick; - { - g.setColor(Color.black); - for (x = xstart; x <= xmax; x += xRange.TickSize()) - { - int xPix = (int)(graphx + graphWidth * (x - xmin) / (xmax - xmin)); - g.setColor(grey); - g.drawLine(xPix, graphy, xPix, graphy + graphHeight); - g.setColor(Color.black); - String num = xRange.Format(xtick); - int numWidth = fontMetrics.stringWidth(num); - g.drawString(num, xPix - numWidth / 2, graphy + graphHeight + fontMetrics.getAscent()); - xtick++; - } - - PlotRange yRange = new PlotRange(ymin, ymax, d.height / (axesFontHeight * 2)); - int ytick = ((int)(ymin / yRange.TickSize() - 1)); - if (yRange.TickSize() * ytick < ymin) - ytick = ytick + 1; - double ystart = yRange.TickSize() * ytick; - for (y = ystart; y <= ymax; y += yRange.TickSize()) - { - int yPix = (int)(graphy + graphHeight * (ymax - y) / (ymax - ymin)); - g.setColor(grey); - g.drawLine(graphx, yPix, graphx + graphWidth, yPix); - g.setColor(Color.black); - String num = yRange.Format(ytick); - int numWidth = fontMetrics.stringWidth(num); - g.drawString(num, graphx - numWidth - 8, yPix + fontMetrics.getAscent() - (axesFontHeight) / 2); - ytick++; - } - } - - int graphClipHeight = graphHeight; - if (graphy+graphClipHeight > r.y+r.height) - { - graphClipHeight = r.y+r.height-graphy; - } - - g.setClip(graphx,graphy,graphWidth,graphClipHeight); - runCallList(g); - g.setClip(xleft, ytop, d.width, clipHeight); - g.setColor(Color.black); - if (g2d != null) - { - g2d.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - } - g.drawRect(graphx, graphy, graphWidth, graphHeight); - g.setClip(clip); - } - - - - /* - * Determine the ticks of the graph. The calling routine should first determine the minimum and maximum values, and - * the number of steps (based on size of the axis to draw relative to font size). - * - * Steps will always be m*10^n, for some suitable n, with m either 1, 2 or 5. - */ - class PlotRange - { - public PlotRange(double aMinValue, double aMaxValue, int aMaxSteps) - { - iMinValue = aMinValue; - iMaxValue = aMaxValue; - iMaxSteps = aMaxSteps; - - //TODO handle zero length range - double range = aMaxValue - aMinValue; - iN = (int)(Math.log(range) / Math.log(10) - 1); - iN = iN - 1; - iStep = 1; - for (; ; ) - { - double tickSize = TickSize(); - int nrSteps = (int)(range / tickSize); - if (nrSteps <= aMaxSteps) - break; - switch (iStep) - { - case 1: - iStep = 2; - break; - case 2: - iStep = 5; - break; - case 5: - iN++; - iStep = 1; - break; - } - } - } - public double TickSize() - { - return iStep * Math.pow(10, iN); - } - - public String Format(int tick) - { - String result = ""; - int fct = tick * iStep; - if (iN >= 0 && iN < 3) - { - if (iN > 0) - fct = fct * 10; - if (iN > 1) - fct = fct * 10; - result = "" + fct; - } - else - { - int n = iN; - if (fct == 10 * (fct / 10)) - { - fct /= 10; - n += 1; - } - String ex = ""; - if (n != 0 && tick != 0) - ex = "e" + n; - result = "" + fct + ex; - } - return result; - } - - double iMinValue; - double iMaxValue; - int iMaxSteps; - - public int iN; - public int iStep; - } - -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/GraphicsPrimitives.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/GraphicsPrimitives.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/GraphicsPrimitives.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/GraphicsPrimitives.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - -import java.awt.*; - -public class GraphicsPrimitives -{ - static double viewScale = 1.0; - private Graphics iG = null; - private Graphics2D iG2D = null; - - int prevGray = -1; - - int prevSetFontSize = -1; - FontMetrics metrics = null; - - public GraphicsPrimitives(Graphics g) - { - iG = g; - if ( g instanceof Graphics2D ) - { - iG2D = (Graphics2D)g; - } - } - public void setLineThickness(float aThickness) - { - if (iG2D != null) - { - iG2D.setStroke(new BasicStroke((float)(aThickness*viewScale),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND)); - } - } - - public void drawLine(int x0, int y0, int x1, int y1) - { - iG.drawLine((int)(x0*viewScale),(int)(y0*viewScale),(int)(x1*viewScale),(int)(y1*viewScale)); - } - - - void setGray(int aGray) - { - if (prevGray != aGray) - { - prevGray = aGray; - iG.setColor(new Color(aGray, aGray, aGray)); - } - } - - public void drawText(String text, int x, int y) - { - iG.drawString(text, (int)(x*viewScale), (int)(y*viewScale)); - } - - - void setFontSize(int aSize) - { - int newFontSize = (int)(viewScale*aSize); - if (prevSetFontSize != newFontSize) - { - prevSetFontSize = newFontSize; - Font f = new Font ("Verdana", Font.PLAIN, newFontSize); - if (f != null) - { - iG.setFont(f); - metrics = iG.getFontMetrics(); - } - } - } - int getFontSize() - { - return (int)(prevSetFontSize/viewScale); - } - int textWidth(String s) - { - java.awt.geom.Rectangle2D m = metrics.getStringBounds(s,iG); - return (int)(m.getWidth()/viewScale); - } - int getAscent() - { - return (int)(metrics.getAscent()/viewScale); - } - double getDescent() - { - return (int)(metrics.getDescent()/viewScale); - } - -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/HintItem.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/HintItem.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/HintItem.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/HintItem.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - -public class HintItem -{ - public String base; - public String hint; - public String description; -}; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/HintItem.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/HintItem.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/HintItem.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/HintItem.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,26 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.ui.gui.worksheets.hints; + +public class HintItem +{ + public String base; + public String hint; + public String description; +}; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/Hints.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/Hints.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/Hints.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/Hints.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,33 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.ui.gui.worksheets.hints; + + +public class Hints +{ + public HintItem[] hintTexts = new HintItem[1024]; + int[] hoffsets = new int[256]; + + public Hints() + { + nrHintTexts = 0; + } + public int nrHintTexts; + +}; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/hints.txt mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/hints.txt --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/hints.txt 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/hints.txt 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,576 @@ +:Abs:Abs(x):absolute value or modulus of complex number: +:Add:Add(val1, val2, ...):find sum of a list of values: +:Add:Add({list}):: +:Append:Append(list, expr):append an entry at the end of a list: +:Apply:Apply(fn, arglist):apply a function to arguments: +:ArcCos:ArcCos(x):inverse trigonometric function arc-cosine: +:ArcSin:ArcSin(x):inverse trigonometric function arc-sine: +:ArcTan:ArcTan(x):inverse trigonometric function arc-tangent: +:Arg:Arg(x):argument of a complex number: +:Array'Create:Array'Create(size,init):create array: +:Array'CreateFromList:Array'CreateFromList(list):convert list to array: +:Array'Get:Array'Get(array,index):fetch array element: +:Array'Set:Array'Set(array,index,element):set array element: +:Array'Size:Array'Size(array):get array size: +:Array'ToList:Array'ToList(array):convert array to list: +:Assert:Assert("str") pred:: +:Assert:Assert("str", expr) pred:signal "soft" custom error: +:Assert:Assert() pred:: +:Assoc:Assoc(key, alist):return element stored in association list: +:AssocDelete:AssocDelete(alist, "key"):delete an entry in an association list: +:AssocDelete:AssocDelete(alist, {key, value}):: +:AssocIndices:AssocIndices(alist):return the keys in an association list: +:Atom:Atom("string"):convert string to atom: +:BaseVector:BaseVector(k, n):base vector: +:Bernoulli:Bernoulli(index):Bernoulli numbers and polynomials: +:Bernoulli:Bernoulli(index, x):: +:BernoulliDistribution:BernoulliDistribution(p):Bernoulli distribution: +:BigOh:BigOh(poly, var, degree):drop all terms of a certain order in a polynomial: +:Bin:Bin(n, m):binomial coefficients: +:BinSplitData:BinSplitData(n1,n2, a, b, c, d):computations of series by the binary splitting method: +:BinSplitFinal:BinSplitFinal({P,Q,B,T}):computations of series by the binary splitting method: +:BinSplitNum:BinSplitNum(n1, n2, a, b, c, d):computations of series by the binary splitting method: +:BinomialDistribution:BinomialDistribution(p,n):binomial distribution: +:BitAnd:BitAnd(n,m):bitwise and operation: +:BitOr:BitOr(n,m):bitwise or operation: +:BitXor:BitXor(n,m):bitwise xor operation: +:Bodied:Bodied("op", precedence):define function syntax (bodied function): +:BracketRational:BracketRational(x, eps):find optimal rational approximations: +:BubbleSort:BubbleSort(list, compare):sort a list: +:Builtin'Precision'Get:Builtin'Precision'Get():get the current precision: +:Builtin'Precision'Set:Builtin'Precision'Set(n):set the precision: +:CForm:CForm(expr):export expression to C++ code: +:CachedConstant:CachedConstant(cache, Cname, Cfunc):precompute multiple-precision constants: +:CanProve:CanProve(proposition):try to prove statement: +:Catalan:Catalan:Catalan's Constant: +:CatalanNumber:CatalanNumber(n):return the {n}th Catalan Number: +:Ceil:Ceil(x):round a number upwards: +:CharacteristicEquation:CharacteristicEquation(matrix,var):get characteristic polynomial of a matrix: +:Check:Check(predicate,"error text"):report "hard" errors: +:ChiSquareTest:ChiSquareTest(observed,expected):Pearson's ChiSquare test: +:ChiSquareTest:ChiSquareTest(observed,expected,params):: +:Cholesky:Cholesky(A):find the Cholesky Decomposition: +:Clear:Clear(var, ...):undo an assignment: +:ClearError:ClearError("str"):custom errors handlers: +:ClearErrors:ClearErrors():simple error handlers: +:CoFactor:CoFactor(M,i,j):cofactor of a matrix: +:Coef:Coef(expr, var, order):coefficient of a polynomial: +:Complex:Complex(r, c):construct a complex number: +:Concat:Concat(list1, list2, ...):concatenate lists: +:ConcatStrings:ConcatStrings(strings):concatenate strings: +:Conjugate:Conjugate(x):complex conjugate: +:ContFrac:ContFrac(x):continued fraction expansion: +:ContFrac:ContFrac(x, depth):: +:ContFracEval:ContFracEval(list):manipulate continued fractions: +:ContFracEval:ContFracEval(list, rest):: +:ContFracList:ContFracList(frac):manipulate continued fractions: +:ContFracList:ContFracList(frac, depth):: +:Contains:Contains(list, expr):test whether a list contains a certain element: +:Content:Content(expr):content of a univariate polynomial: +:Cos:Cos(x):trigonometric cosine function: +:Count:Count(list, expr):count the number of occurrences of an expression: +:CrossProduct:CrossProduct(a,b):outer product of vectors: +:Curl:Curl(vector, basis):curl of a vector field: +:CurrentFile:CurrentFile():return current input file: +:CurrentLine:CurrentLine():return current line number on input: +:Cyclotomic:Cyclotomic(n,x):construct the cyclotomic polynomial: +:D:D(list) expression:: +:D:D(variable) expression:take derivative of expression with respect to variable: +:D:D(variable,n) expression:: +:Decimal:Decimal(frac):decimal representation of a rational: +:DefLoad:DefLoad(name):load a {.def} file: +:DefMacroRuleBase:DefMacroRuleBase(name,params):define a function as a macro: +:DefMacroRuleBaseListed:DefMacroRuleBaseListed("name", params):define macro with variable number of arguments: +:DefaultTokenizer:DefaultTokenizer():select the default syntax tokenizer for parsing the input: +:Degree:Degree(expr):degree of a polynomial: +:Degree:Degree(expr, var):: +:Delete:Delete(list, n):delete an element from a list: +:Denom:Denom(expr):denominator of an expression: +:DestructiveAppend:DestructiveAppend(list, expr):destructively append an entry to a list: +:DestructiveDelete:DestructiveDelete(list, n):delete an element destructively from a list: +:DestructiveInsert:DestructiveInsert(list, n, expr):insert an element destructively into a list: +:DestructiveReplace:DestructiveReplace(list, n, expr):replace an entry destructively in a list: +:DestructiveReverse:DestructiveReverse(list):reverse a list destructively: +:Determinant:Determinant(M):determinant of a matrix: +:Diagonal:Diagonal(A):extract the diagonal from a matrix: +:DiagonalMatrix:DiagonalMatrix(d):construct a diagonal matrix: +:Difference:Difference(l1, l2):return the difference of two lists: +:Div:Div(x,y):Determine divisor of two mathematical objects: +:Diverge:Diverge(vector, basis):divergence of a vector field: +:Divisors:Divisors(n):number of divisors: +:DivisorsList:DivisorsList(n):the list of divisors: +:DivisorsSum:DivisorsSum(n):the sum of divisors: +:Dot:Dot(t1,t2):get dot product of tensors: +:Drop:Drop(list, -n):: +:Drop:Drop(list, n):drop a range of elements from a list: +:Drop:Drop(list, {m,n}):: +:DumpErrors:DumpErrors():simple error handlers: +:Echo:Echo(item):high-level printing routine: +:Echo:Echo(item,item,item,...):: +:Echo:Echo(list):: +:EigenValues:EigenValues(matrix):get eigenvalues of a matrix: +:EigenVectors:EigenVectors(A,eigenvalues):get eigenvectors of a matrix: +:Eliminate:Eliminate(var, value, expr):substitute and simplify: +:EndOfFile:EndOfFile:end-of-file marker: +:Equals:Equals(a,b):check equality: +:Euler:Euler(index):Euler numbers and polynomials: +:Euler:Euler(index,x):: +:Eulerian:Eulerian(n,m):Eulerian numbers: +:Eval:Eval(expr):force evaluation of expression: +:EvalFormula:EvalFormula(expr):print an evaluation nicely with ASCII art: +:EvaluateHornerScheme:EvaluateHornerScheme(coeffs,x):fast evaluation of polynomials: +:Exp:Exp(x):exponential function: +:Expand:Expand(expr):transform a polynomial to an expanded form: +:Expand:Expand(expr, var):: +:Expand:Expand(expr, varlist):: +:ExpandBrackets:ExpandBrackets(expr):expand all brackets: +:ExtraInfo'Get:ExtraInfo'Get(expr):annotate objects with additional information: +:ExtraInfo'Set:ExtraInfo'Set(expr,tag):annotate objects with additional information: +:Factor:Factor(x):factorization, in pretty form: +:FactorialSimplify:FactorialSimplify(expression):Simplify hypergeometric expressions containing factorials: +:Factorize:Factorize(list):product of a list of values: +:Factorize:Factorize(var, from, to, body):: +:Factors:Factors(x):factorization: +:False:False:boolean constant representing false: +:FermatNumber:FermatNumber(n):return the {n}th Fermat Number: +:FillList:FillList(expr, n):fill a list with a certain expression: +:Find:Find(list, expr):get the index at which a certain element occurs: +:FindFile:FindFile(name):find a file in the current path: +:FindFunction:FindFunction(function):find the library file where a function is defined: +:FindRealRoots:FindRealRoots(p):find the real roots of a polynomial: +:FlatCopy:FlatCopy(list):copy the top level of a list: +:Flatten:Flatten(expression,operator):flatten expression w.r.t. some operator: +:Floor:Floor(x):round a number downwards: +:For:For(init, pred, incr) body:C-style {for} loop: +:ForEach:ForEach(var, list) body:loop over all entries in list: +:FromBase:FromBase(base,"string"):conversion of a number from non-decimal base to decimal base: +:FromFile:FromFile(name) body:connect current input to a file: +:FromString:FromString(str) body;:connect current input to a string: +:FullForm:FullForm(expr):print an expression in LISP-format: +:FuncList:FuncList(expr):list of functions used in an expression: +:FuncListArith:FuncListArith(expr):list of functions used in an expression: +:FuncListSome:FuncListSome(expr, list):list of functions used in an expression: +:Function:Function("op", {arglist, ...}) body:: +:Function:Function("op", {arglist}) body:: +:Function:Function() func(arglist):declare or define a function: +:Function:Function() func(arglist, ...):: +:Gamma:Gamma(x):Euler's Gamma function: +:GarbageCollect:GarbageCollect():do garbage collection on unused memory: +:GaussianFactors:GaussianFactors(z):factorization in Gaussian integers: +:GaussianGcd:GaussianGcd(z,w):greatest common divisor in Gaussian integers: +:GaussianNorm:GaussianNorm(z):norm of a Gaussian integer: +:Gcd:Gcd(list):: +:Gcd:Gcd(n,m):greatest common divisor: +:GenericTypeName:GenericTypeName(object):get type name: +:GetCoreError:GetCoreError():get "hard" error string: +:GetError:GetError("str"):custom errors handlers: +:GetErrorTableau:GetErrorTableau():custom errors handlers: +:GetTime:GetTime(expr):measure the time taken by an evaluation: +:GlobalPop:GlobalPop():: +:GlobalPop:GlobalPop(var):restore variables using a global stack: +:GlobalPush:GlobalPush(expr):save variables using a global stack: +:GoldenRatio:GoldenRatio:the Golden Ratio: +:GreaterThan:GreaterThan(a,b):comparison predicate: +:GuessRational:GuessRational(x):find optimal rational approximations: +:GuessRational:GuessRational(x, digits):: +:HarmonicNumber:HarmonicNumber(n):return the {n}th Harmonic Number: +:HarmonicNumber:HarmonicNumber(n,r):: +:HasExpr:HasExpr(expr, x):check for expression containing a subexpression: +:HasExprArith:HasExprArith(expr, x):check for expression containing a subexpression: +:HasExprSome:HasExprSome(expr, x, list):check for expression containing a subexpression: +:HasFunc:HasFunc(expr, func):check for expression containing a function: +:HasFuncArith:HasFuncArith(expr, func):check for expression containing a function: +:HasFuncSome:HasFuncSome(expr, func, list):check for expression containing a function: +:Head:Head(list):the first element of a list: +:HeapSort:HeapSort(list, compare):sort a list: +:HessianMatrix:HessianMatrix(function,var):create the Hessian matrix: +:HilbertInverseMatrix:HilbertInverseMatrix(n):create a Hilbert inverse matrix: +:HilbertMatrix:HilbertMatrix(n):create a Hilbert matrix: +:HilbertMatrix:HilbertMatrix(n,m):: +:Hold:Hold(expr):keep expression unevaluated: +:HoldArg:HoldArg("operator",parameter):mark argument as not evaluated: +:HoldArgNr:HoldArgNr("function", arity, argNum):specify argument as not evaluated: +:Horner:Horner(expr, var):convert a polynomial into the Horner form: +:I:I:imaginary unit: +:Identity:Identity(n):make identity matrix: +:If:If(pred, then):branch point: +:If:If(pred, then, else):: +:Im:Im(x):imaginary part of a complex number: +:InNumericMode:InNumericMode():determine if currently in numeric mode: +:InProduct:InProduct(a,b):inner product of vectors (deprecated): +:InVerboseMode:InVerboseMode():set verbose output mode: +:Infinity:Infinity:constant representing mathematical infinity: +:Infix:Infix("op"):define function syntax (infix operator): +:Infix:Infix("op", precedence):: +:Insert:Insert(list, n, expr):insert an element into a list: +:IntLog:IntLog(n, base):integer part of logarithm: +:IntNthRoot:IntNthRoot(x, n):integer part of $n$-th root: +:IntPowerNum:IntPowerNum(x, n, mult, unity):optimized computation of integer powers: +:Integrate:Integrate(var) expr:: +:Integrate:Integrate(var, x1, x2) expr:integration: +:Intersection:Intersection(l1, l2):return the intersection of two lists: +:Inverse:Inverse(M):get inverse of a matrix: +:InverseTaylor:InverseTaylor(var, at, order) expr:Taylor expansion of inverse: +:IsAmicablePair:IsAmicablePair(m,n):test for a pair of amicable numbers: +:IsAtom:IsAtom(expr):test for an atom: +:IsBodied:IsBodied("op"):check for function syntax: +:IsBoolean:IsBoolean(expression):test for a Boolean value: +:IsBound:IsBound(var):test for a bound variable: +:IsCFormable:IsCFormable(expr):check possibility to export expression to C++ code: +:IsCFormable:IsCFormable(expr, funclist):: +:IsCarmichaelNumber:IsCarmichaelNumber(n):test for a Carmichael number: +:IsComposite:IsComposite(n):test for a composite number: +:IsConstant:IsConstant(expr):test for a constant: +:IsCoprime:IsCoprime(list):: +:IsCoprime:IsCoprime(m,n):test if integers are coprime : +:IsDiagonal:IsDiagonal(A):test for a diagonal matrix: +:IsError:IsError("str"):: +:IsError:IsError():check for custom error: +:IsEven:IsEven(n):test for an even integer: +:IsEvenFunction:IsEvenFunction(expression,variable):Return true if function is an even function, False otherwise: +:IsFreeOf:IsFreeOf(var, expr):test whether expression depends on variable: +:IsFreeOf:IsFreeOf({var, ...}, expr):: +:IsFunction:IsFunction(expr):test for a composite object: +:IsGaussianInteger:IsGaussianInteger(z):test for a Gaussian integer: +:IsGaussianPrime:IsGaussianPrime(z):test for a Gaussian prime: +:IsGaussianUnit:IsGaussianUnit(z):test for a Gaussian unit: +:IsGeneric:IsGeneric(object):check for generic object: +:IsHermitian:IsHermitian(A):test for a Hermitian matrix: +:IsIdempotent:IsIdempotent(A):test for an idempotent matrix: +:IsInfinity:IsInfinity(expr):test for an infinity: +:IsInfix:IsInfix("op"):check for function syntax: +:IsIrregularPrime:IsIrregularPrime(n):test for an irregular prime: +:IsList:IsList(expr):test for a list: +:IsLowerTriangular:IsLowerTriangular(A):test for a lower triangular matrix: +:IsMatrix:IsMatrix(expr):test for a matrix: +:IsMatrix:IsMatrix(pred,expr):: +:IsNegativeInteger:IsNegativeInteger(n):test for a negative integer: +:IsNegativeNumber:IsNegativeNumber(n):test for a negative number: +:IsNegativeReal:IsNegativeReal(expr):test for a numerically negative value: +:IsNonObject:IsNonObject(expr):test whether argument is not an {Object()}: +:IsNonZeroInteger:IsNonZeroInteger(n):test for a nonzero integer: +:IsNotZero:IsNotZero(n):test for a nonzero number: +:IsNumber:IsNumber(expr):test for a number: +:IsNumericList:IsNumericList({list}):test for a list of numbers: +:IsOdd:IsOdd(n):test for an odd integer: +:IsOddFunction:IsOddFunction(expression,variable):Return true if function is an odd function, False otherwise: +:IsOrthogonal:IsOrthogonal(A):test for an orthogonal matrix: +:IsPositiveInteger:IsPositiveInteger(n):test for a positive integer: +:IsPositiveNumber:IsPositiveNumber(n):test for a positive number: +:IsPositiveReal:IsPositiveReal(expr):test for a numerically positive value: +:IsPostfix:IsPostfix("op"):check for function syntax: +:IsPrefix:IsPrefix("op"):check for function syntax: +:IsPrime:IsPrime(n):test for a prime number: +:IsPrimePower:IsPrimePower(n):test for a power of a prime number: +:IsPromptShown:IsPromptShown():test for the Yacas prompt option: +:IsQuadraticResidue:IsQuadraticResidue(m,n):functions related to finite groups: +:IsRational:IsRational(expr):test whether argument is a rational: +:IsScalar:IsScalar(expr):test for a scalar: +:IsSkewSymmetric:IsSkewSymmetric(A):test for a skew-symmetric matrix: +:IsSmallPrime:IsSmallPrime(n):test for a (small) prime number: +:IsSquareFree:IsSquareFree(n):test for a square-free number: +:IsSquareMatrix:IsSquareMatrix(expr):test for a square matrix: +:IsSquareMatrix:IsSquareMatrix(pred,expr):: +:IsString:IsString(expr):test for an string: +:IsSymmetric:IsSymmetric(A):test for a symmetric matrix: +:IsTwinPrime:IsTwinPrime(n):test for a twin prime: +:IsUnitary:IsUnitary(A):test for a unitary matrix: +:IsUpperTriangular:IsUpperTriangular(A):test for an upper triangular matrix: +:IsVector:IsVector(expr):test for a vector: +:IsVector:IsVector(pred,expr):: +:IsZero:IsZero(n):test whether argument is zero: +:IsZeroVector:IsZeroVector(list):test whether list contains only zeroes: +:JacobiSymbol:JacobiSymbol(m,n):functions related to finite groups: +:JacobianMatrix:JacobianMatrix(functions,variables):calculate the Jacobian matrix of $n$ functions in $n$ variables: +:KnownFailure:KnownFailure(test):Mark a test as a known failure: +:LagrangeInterpolant:LagrangeInterpolant(xlist, ylist, var):polynomial interpolation: +:LambertW:LambertW(x):Lambert's $W$ function: +:LaplaceTransform:LaplaceTransform(t,s,func) :Laplace Transform: +:Lcm:Lcm(list):: +:Lcm:Lcm(n,m):least common multiple: +:LeadingCoef:LeadingCoef(poly):leading coefficient of a polynomial: +:LeadingCoef:LeadingCoef(poly, var):: +:LeftPrecedence:LeftPrecedence("op",precedence):set operator precedence: +:LegendreSymbol:LegendreSymbol(m,n):functions related to finite groups: +:Length:Length(object):the length of a list or string: +:LessThan:LessThan(a,b):comparison predicate: +:LeviCivita:LeviCivita(list):totally anti-symmetric Levi-Civita symbol: +:Limit:Limit(var, val) expr:limit of an expression: +:Limit:Limit(var, val, dir) expr:: +:LispRead:LispRead():read expressions in LISP syntax: +:LispReadListed:LispReadListed():read expressions in LISP syntax: +:List:List(expr1, expr2, ...):construct a list: +:Listify:Listify(expr):convert a function application to a list: +:Ln:Ln(x):natural logarithm: +:LnCombine:LnCombine(expr):combine logarithmic expressions using standard logarithm rules: +:LnExpand:LnExpand(expr):expand a logarithmic expression using standard logarithm rules: +:Load:Load(name):evaluate all expressions in a file: +:Local:Local(var, ...):declare new local variables: +:LocalSymbols:LocalSymbols(var1, var2, ...) body:create unique local symbols with given prefix: +:LogicTest:LogicTest(variables,expr1,expr2):verifying equivalence of two expressions: +:LogicVerify:LogicVerify(question,answer):verifying equivalence of two expressions: +:Macro:Macro("op", {arglist, ...}) body:: +:Macro:Macro("op", {arglist}) body:: +:Macro:Macro() func(arglist):declare or define a macro: +:Macro:Macro() func(arglist, ...):: +:MakeVector:MakeVector(var,n):vector of uniquely numbered variable names: +:Map:Map(fn, list):apply an $n$-ary function to all entries in a list: +:MapArgs:MapArgs(expr, fn):apply a function to all top-level arguments: +:MapSingle:MapSingle(fn, list):apply a unary function to all entries in a list: +:MatchLinear:MatchLinear(x,expr):match an expression to a polynomial of degree one in a variable: +:MathAbs:MathAbs(x) (absolute value of x, or |x| ):: +:MathAdd:MathAdd(x,y) (add two numbers):: +:MathAnd:MathAnd(...):built-in logical "and": +:MathArcCos:MathArcCos(x) (inverse cosine):: +:MathArcCosh:MathArcCosh(x) (inverse hyperbolic cosine):: +:MathArcSin:MathArcSin(x) (inverse sine):: +:MathArcSinh:MathArcSinh(x) (inverse hyperbolic sine):: +:MathArcTan:MathArcTan(x) (inverse tangent):: +:MathArcTanh:MathArcTanh(x) (inverse hyperbolic tangent):: +:MathCeil:MathCeil(x) (smallest integer not smaller than x):: +:MathCos:MathCos(x) (cosine):: +:MathCosh:MathCosh(x) (hyperbolic cosine):: +:MathDiv:MathDiv(x,y) (integer division, result is an integer):: +:MathDivide:MathDivide(x,y) (divide two numbers):: +:MathExp:MathExp(x) (exponential, base 2.718...):: +:MathFloor:MathFloor(x) (largest integer not larger than x):: +:MathGcd:MathGcd(n,m) (Greatest Common Divisor):: +:MathGetExactBits:MathGetExactBits(x):manipulate precision of floating-point numbers: +:MathLog:MathLog(x) (natural logarithm, for x>0):: +:MathMod:MathMod(x,y) (remainder of division, or x mod y):: +:MathMultiply:MathMultiply(x,y) (multiply two numbers):: +:MathNot:MathNot(expression):built-in logical "not": +:MathOr:MathOr(...):built-in logical "or": +:MathPower:MathPower(x,y) (power, x ^ y):: +:MathSetExactBits:MathSetExactBits(x,bits):manipulate precision of floating-point numbers: +:MathSin:MathSin(x) (sine):: +:MathSinh:MathSinh(x) (hyperbolic sine):: +:MathSqrt:MathSqrt(x) (square root, must be x>=0):: +:MathSubtract:MathSubtract(x,y) (subtract two numbers):: +:MathTan:MathTan(x) (tangent):: +:MathTanh:MathTanh(x) (hyperbolic tangent):: +:MatrixPower:MatrixPower(mat,n):get nth power of a square matrix: +:MatrixSolve:MatrixSolve(A,b):solve a system of equations: +:Max:Max(list):: +:Max:Max(x,y):maximum of a number of values: +:MaxEvalDepth:MaxEvalDepth(n):set the maximum evaluation depth: +:MaximumBound:MaximumBound(p):return upper bounds on the absolute values of real roots of a polynomial: +:Min:Min(list):: +:Min:Min(x,y):minimum of a number of values: +:MinimumBound:MinimumBound(p):return lower bounds on the absolute values of real roots of a polynomial: +:Minor:Minor(M,i,j):get principal minor of a matrix: +:Mod:Mod(x,y):Determine remainder of two mathematical objects after dividing one by the other: +:Moebius:Moebius(n):the Moebius function: +:MoebiusDivisorsList:MoebiusDivisorsList(n):the list of divisors and Moebius values: +:Monic:Monic(poly):monic part of a polynomial: +:Monic:Monic(poly, var):: +:MultiplyNum:MultiplyNum(x,y):optimized numerical multiplication: +:MultiplyNum:MultiplyNum(x,y,z,...):: +:MultiplyNum:MultiplyNum({x,y,z,...}):: +:N:N(expression):try determine numerical approximation of expression: +:N:N(expression, precision):: +:NFunction:NFunction("newname","funcname", {arglist}):make wrapper for numeric functions: +:NearRational:NearRational(x):find optimal rational approximations: +:NearRational:NearRational(x, digits):: +:NewLine:NewLine():print one or more newline characters: +:NewLine:NewLine(nr):: +:Newton:Newton(expr, var, initial, accuracy):solve an equation numerically with Newton's method: +:Newton:Newton(expr, var, initial, accuracy,min,max):: +:NewtonNum:NewtonNum(func, x0):: +:NewtonNum:NewtonNum(func, x0, prec0):: +:NewtonNum:NewtonNum(func, x0, prec0, order):low-level optimized Newton's iterations: +:NextPrime:NextPrime(i):generate a prime following a number: +:Nl:Nl():the newline character: +:NonN:NonN(expr):calculate part in non-numeric mode: +:Normalize:Normalize(v):normalize a vector: +:Not:Not expr:logical negation: +:NrArgs:NrArgs(expr):return number of top-level arguments: +:Nth:Nth(list, n):return the $n$-th element of a list: +:NthRoot:NthRoot(m,n):calculate/simplify nth root of an integer: +:NumRealRoots:NumRealRoots(p):return the number of real roots of a polynomial: +:Numer:Numer(expr):numerator of an expression: +:OMDef:OMDef(yacasForm, cd, name):define translations from Yacas to OpenMath and vice-versa.: +:OMDef:OMDef(yacasForm, cd, name, yacasToOM):: +:OMDef:OMDef(yacasForm, cd, name, yacasToOM, omToYacas):: +:OMForm:OMForm(expression):convert Yacas expression to OpenMath: +:OMRead:OMRead():convert expression from OpenMath to Yacas expression: +:Object:Object("pred", exp):create an incomplete type: +:OdeOrder:OdeOrder(eqn):return order of an ODE: +:OdeSolve:OdeSolve(expr1==expr2):general ODE solver: +:OdeTest:OdeTest(eqn,testsol):test the solution of an ODE: +:OldSolve:OldSolve(eq, var):old version of {Solve}: +:OldSolve:OldSolve(eqlist, varlist):: +:OpLeftPrecedence:OpLeftPrecedence("op"):get operator precedence: +:OpPrecedence:OpPrecedence("op"):get operator precedence: +:OpRightPrecedence:OpRightPrecedence("op"):get operator precedence: +:OrthoG:OrthoG(n, a, x);:Gegenbauer orthogonal polynomials: +:OrthoGSum:OrthoGSum(c, a, x);:sums of series of orthogonal polynomials: +:OrthoH:OrthoH(n, x);:Hermite orthogonal polynomials: +:OrthoHSum:OrthoHSum(c, x);:sums of series of orthogonal polynomials: +:OrthoL:OrthoL(n, a, x);:Laguerre orthogonal polynomials: +:OrthoLSum:OrthoLSum(c, a, x);:sums of series of orthogonal polynomials: +:OrthoP:OrthoP(n, a, b, x);:: +:OrthoP:OrthoP(n, x);:Legendre and Jacobi orthogonal polynomials: +:OrthoPSum:OrthoPSum(c, a, b, x);:: +:OrthoPSum:OrthoPSum(c, x);:sums of series of orthogonal polynomials: +:OrthoPoly:OrthoPoly(name, n, par, x):internal function for constructing orthogonal polynomials: +:OrthoPolySum:OrthoPolySum(name, c, par, x):internal function for computing series of orthogonal polynomials: +:OrthoT:OrthoT(n, x);:Chebyshev polynomials: +:OrthoTSum:OrthoTSum(c, x);:sums of series of orthogonal polynomials: +:OrthoU:OrthoU(n, x);:Chebyshev polynomials: +:OrthoUSum:OrthoUSum(c, x);:sums of series of orthogonal polynomials: +:OrthogonalBasis:OrthogonalBasis(W):create an orthogonal basis : +:OrthonormalBasis:OrthonormalBasis(W):create an orthonormal basis : +:Outer:Outer(t1,t2):get outer tensor product: +:PAdicExpand:PAdicExpand(n, p):p-adic expansion: +:PDF:PDF(dist,x):probability density function: +:PSolve:PSolve(poly, var):solve a polynomial equation: +:Partition:Partition(list, n):partition a list in sublists of equal length: +:PatchLoad:PatchLoad(name):execute commands between {} in file: +:PatchString:PatchString(string):execute commands between {} in strings: +:Permutations:Permutations(list):get all permutations of a list: +:Pi:Pi:mathematical constant, $pi$: +:Plot2D:Plot2D(f(x)):adaptive two-dimensional plotting: +:Plot2D:Plot2D(f(x), a b):: +:Plot2D:Plot2D(f(x), a b, option=value):: +:Plot2D:Plot2D(f(x), a b, option=value, ...):: +:Plot2D:Plot2D(list, ...):: +:Plot3DS:Plot3DS(f(x,y)):three-dimensional (surface) plotting: +:Plot3DS:Plot3DS(f(x,y), a b, c d):: +:Plot3DS:Plot3DS(f(x,y), a b, c d, option=value):: +:Plot3DS:Plot3DS(f(x,y), a b, c d, option=value, ...):: +:Plot3DS:Plot3DS(list, ...):: +:Pop:Pop(stack, n):remove an element from a stack: +:PopBack:PopBack(stack):remove an element from the bottom of a stack: +:PopFront:PopFront(stack):remove an element from the top of a stack: +:Postfix:Postfix("op"):define function syntax (postfix operator): +:Postfix:Postfix("op", precedence):: +:Prefix:Prefix("op"):define function syntax (prefix operator): +:Prefix:Prefix("op", precedence):: +:PrettyForm:PrettyForm(expr):print an expression nicely with ASCII art: +:PrimitivePart:PrimitivePart(expr):primitive part of a univariate polynomial: +:PrintList:PrintList(list):print list with padding: +:PrintList:PrintList(list, padding);:: +:Prog:Prog(statement1, statement2, ...):block of statements: +:ProperDivisors:ProperDivisors(n):the number of proper divisors: +:ProperDivisorsSum:ProperDivisorsSum(n):the sum of proper divisors: +:Pslq:Pslq(xlist,precision):search for integer relations between reals: +:Push:Push(stack, expr):add an element on top of a stack: +:RadSimp:RadSimp(expr):simplify expression with nested radicals: +:RamanujanSum:RamanujanSum(k,n):compute the "Ramanujan sum": +:RandVerifyArithmetic:RandVerifyArithmetic(n):Special purpose arithmetic verifiers: +:Random:Random():(pseudo-) random number generator: +:RandomIntegerMatrix:RandomIntegerMatrix(rows,cols,from,to):generate a matrix of random integers: +:RandomIntegerVector:RandomIntegerVector(nr, from, to):generate a vector of random integers: +:RandomPoly:RandomPoly(var,deg,coefmin,coefmax):construct a random polynomial: +:RandomSeed:RandomSeed(init):(pseudo-) random number generator: +:Rationalize:Rationalize(expr):convert floating point numbers to fractions: +:Re:Re(x):real part of a complex number: +:Read:Read():read an expression from current input: +:ReadCmdLineString:ReadCmdLineString(prompt):read an expression from command line and return in string: +:ReadToken:ReadToken():read a token from current input: +:RemoveDuplicates:RemoveDuplicates(list):remove any duplicates from a list: +:Replace:Replace(list, n, expr):replace an entry in a list: +:Retract:Retract("function",arity):erase rules for a function: +:Reverse:Reverse(list):return the reversed list (without touching the original): +:ReversePoly:ReversePoly(f, g, var, newvar, degree):solve $h(f(x)) = g(x) + O(x^n)$ for $h$: +:RightAssociative:RightAssociative("op"):declare associativity: +:RightPrecedence:RightPrecedence("op",precedence):set operator precedence: +:Rng:Rng(r):manipulate random number generators as objects: +:RngCreate:RngCreate():manipulate random number generators as objects: +:RngCreate:RngCreate(init):: +:RngCreate:RngCreate(option==value,...):: +:RngSeed:RngSeed(r, init):manipulate random number generators as objects: +:Round:Round(x):round a number to the nearest integer: +:RoundTo:RoundTo(number,precision):Round a real-valued result to a set number of digits: +:Rule:Rule("operator", arity,:define a rewrite rule: +:RuleBase:RuleBase(name,params):define function with a fixed number of arguments: +:RuleBaseArgList:RuleBaseArgList("operator", arity):obtain list of arguments: +:RuleBaseListed:RuleBaseListed("name", params):define function with variable number of arguments: +:Secure:Secure(body):guard the host OS: +:Select:Select(pred, list):select entries satisfying some predicate: +:Set:Set(var, exp):assignment: +:SetGlobalLazyVariable:SetGlobalLazyVariable(var,value):global variable is to be evaluated lazily: +:ShiftLeft:ShiftLeft(expr,bits):: +:ShiftRight:ShiftRight(expr,bits):: +:Sign:Sign(x):sign of a number: +:Simplify:Simplify(expr):try to simplify an expression: +:Sin:Sin(x):trigonometric sine function: +:Solve:Solve(eq, var):solve an equation: +:SolveMatrix:SolveMatrix(M,v):solve a linear system: +:Space:Space():print one or more spaces: +:Space:Space(nr):: +:Sparsity:Sparsity(matrix):get the sparsity of a matrix: +:Sqrt:Sqrt(x):square root: +:SquareFree:SquareFree(p):return the square-free part of polynomial: +:SquareFreeDivisorsList:SquareFreeDivisorsList(n):the list of square-free divisors: +:StirlingNumber1:StirlingNumber1(n,m):return the {n,m}th Stirling Number of the first kind: +:String:String(atom):convert atom to string: +:StringMid'Get:StringMid'Get(index,length,string):retrieve a substring: +:StringMid'Set:StringMid'Set(index,substring,string):change a substring: +:Subfactorial:Subfactorial(m):factorial and related functions: +:Subst:Subst(from, to) expr:perform a substitution: +:SuchThat:SuchThat(expr, var):special purpose solver: +:Sum:Sum(var, from, to, body):find sum of a sequence: +:SumForDivisors:SumForDivisors(var,n,expr):loop over divisors: +:SumTaylorNum:SumTaylorNum(x, NthTerm, TermFactor, order):: +:SumTaylorNum:SumTaylorNum(x, NthTerm, order):optimized numerical evaluation of Taylor series: +:SumTaylorNum:SumTaylorNum(x, ZerothTerm, TermFactor, order):: +:Swap:Swap(list, i1, i2):swap two elements in a list: +:SylvesterMatrix:SylvesterMatrix(poly1,poly2,variable):calculate the Sylvester matrix of two polynomials: +:SystemCall:SystemCall(str):pass a command to the shell: +:Table:Table(body, var, from, to, step):evaluate while some variable ranges over interval: +:TableForm:TableForm(list):print each entry in a list on a line: +:Tail:Tail(list):returns a list without its first element: +:Take:Take(list, -n):: +:Take:Take(list, n):take a sublist from a list, dropping the rest: +:Take:Take(list, {m,n}):: +:Tan:Tan(x):trigonometric tangent function: +:Taylor:Taylor(var, at, order) expr:univariate Taylor series expansion: +:TeXForm:TeXForm(expr):export expressions to $LaTeX$: +:TestYacas:TestYacas(question,answer):verifying equivalence of two expressions: +:Time:Time(expr):measure the time taken by a function: +:ToBase:ToBase(base, number):conversion of a number in decimal base to non-decimal base: +:ToFile:ToFile(name) body:connect current output to a file: +:ToStdout:ToStdout() body:select initial output stream for output: +:ToString:ToString() body:connect current output to a string: +:ToeplitzMatrix:ToeplitzMatrix(N):create a Toeplitz matrix: +:Trace:Trace(M):trace of a matrix: +:TraceExp:TraceExp(expr):evaluate with tracing enabled: +:TraceRule:TraceRule(template) expr:turn on tracing for a particular function: +:TraceStack:TraceStack(expression):show calling stack after an error occurs: +:Transpose:Transpose(M):get transpose of a matrix: +:TrapError:TrapError(expression,errorHandler):trap "hard" errors: +:TrigSimpCombine:TrigSimpCombine(expr):combine products of trigonometric functions: +:True:True:boolean constant representing true: +:TruncRadian:TruncRadian(r):remainder modulo $2*Pi$: +:Type:Type(expr):return the type of an expression: +:UnFence:UnFence("operator",arity):change local variable scope for a function: +:UnFlatten:UnFlatten(list,operator,identity):inverse operation of Flatten: +:UnList:UnList(list):convert a list to a function application: +:Undefined:Undefined:constant signifying an undefined result: +:Union:Union(l1, l2):return the union of two lists: +:UniqueConstant:UniqueConstant():create a unique identifier: +:Until:Until(pred) body:loop until a condition is met: +:Use:Use(name):load a file, but not twice: +:V:V(expression):set verbose output mode: +:VandermondeMatrix:VandermondeMatrix(vector):create the Vandermonde matrix: +:VarList:VarList(expr):list of variables appearing in an expression: +:VarListArith:VarListArith(expr):list of variables appearing in an expression: +:VarListSome:VarListSome(expr, list):list of variables appearing in an expression: +:Verify:Verify(question,answer):verifying equivalence of two expressions: +:VerifyArithmetic:VerifyArithmetic(x,n,m):Special purpose arithmetic verifiers: +:VerifyDiv:VerifyDiv(u,v):Special purpose arithmetic verifiers: +:While:While(pred) body:loop while a condition is met: +:WithValue:WithValue(var, val, expr):temporary assignment during an evaluation: +:WithValue:WithValue({var,...}, {val,...}, expr):: +:Write:Write(expr, ...):low-level printing routine: +:WriteString:WriteString(string):low-level printing routine for strings: +:WronskianMatrix:WronskianMatrix(func,var):create the Wronskian matrix: +:XmlExplodeTag:XmlExplodeTag(xmltext):convert XML strings to tag objects: +:XmlTokenizer:XmlTokenizer():select an XML syntax tokenizer for parsing the input: +:ZeroMatrix:ZeroMatrix(n):make a zero matrix: +:ZeroMatrix:ZeroMatrix(n, m):: +:ZeroVector:ZeroVector(n):create a vector with all zeroes: +:Zeta:Zeta(x):Riemann's Zeta function: +::::::: diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/HintWindow.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/HintWindow.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints/HintWindow.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints/HintWindow.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,158 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: + +package org.mathpiper.ui.gui.worksheets.hints; + +import org.mathpiper.ui.gui.worksheets.*; + + +public class HintWindow +{ + public String[] iText = new String[64]; + public String[] iDescription = new String[64]; + + public boolean iAllowSelection = true; + public int iNrDescriptions; + public int iMaxWidth; + public int iTextSize; + public int iCurrentPos; + public int iNrLines; + + public HintWindow(int aTextSize) + { + iNrLines = 0; + iNrDescriptions = 0; + iMaxWidth = 0; + iTextSize = aTextSize; + iCurrentPos = 0; + } + public void addLine(String aText) + { + if (iNrLines >= 20) return; + iText[iNrLines] = aText; + iNrLines++; + iMaxWidth = 0; + } + public void addDescription(String aText) + { + if (iNrDescriptions >= 20) return; + iDescription[iNrDescriptions] = aText; + iNrDescriptions++; + iMaxWidth = 0; + } + public void draw(int x, int y, MathPiperGraphicsContext aGraphicsContext) + { + aGraphicsContext.setFontSize(0,iTextSize); + if (iMaxWidth == 0) + { + int i; + for (i=0;iiMaxWidth) + iMaxWidth = width; + } + for (i=0;iiMaxWidth) + iMaxWidth = width; + } + iMaxWidth = iMaxWidth + 8; + } + + //System.out.println("iNrLines = "+iNrLines); + //System.out.println("iMaxWidth = "+iMaxWidth); + + int ix = x; + int iy = y; + int w = 5+iMaxWidth; + int h = height(aGraphicsContext); + iy -= (h+4); + + if (!iAllowSelection) + aGraphicsContext.setColor(221,221,238); + else + aGraphicsContext.setColor(221,221,238); + aGraphicsContext.fillRect(ix,iy,w,h); + aGraphicsContext.setColor(0,0,0); + aGraphicsContext.drawRect(ix,iy,w,h); + + int i; + + //System.out.println("iTextSize = "+iTextSize); + //System.out.println("aGraphicsContext.FontHeight() = "+aGraphicsContext.FontHeight()); + + for (i=0;i0) + { + int offset = (iNrLines+1)*aGraphicsContext.fontHeight()+7; + + aGraphicsContext.drawLine(ix+6,iy+offset-4-aGraphicsContext.fontHeight(),ix+w-6,iy+offset-4-aGraphicsContext.fontHeight()); + + aGraphicsContext.setFontSize(1,iTextSize); + for (i=0;i0) + { + aGraphicsContext.setFontSize(1,iTextSize); + h += iNrDescriptions*aGraphicsContext.fontHeight()+2; + // space for line + h+=7; + } + return h; + } + +} + + + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/Hints.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/Hints.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/Hints.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/Hints.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - - -public class Hints -{ - public HintItem[] hintTexts = new HintItem[1024]; - int[] hoffsets = new int[256]; - - public Hints() - { - nrHintTexts = 0; - } - public int nrHintTexts; - -}; diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints.txt mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints.txt --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/hints.txt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/hints.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,576 +0,0 @@ -:Abs:Abs(x):absolute value or modulus of complex number: -:Add:Add(val1, val2, ...):find sum of a list of values: -:Add:Add({list}):: -:Append:Append(list, expr):append an entry at the end of a list: -:Apply:Apply(fn, arglist):apply a function to arguments: -:ArcCos:ArcCos(x):inverse trigonometric function arc-cosine: -:ArcSin:ArcSin(x):inverse trigonometric function arc-sine: -:ArcTan:ArcTan(x):inverse trigonometric function arc-tangent: -:Arg:Arg(x):argument of a complex number: -:Array'Create:Array'Create(size,init):create array: -:Array'CreateFromList:Array'CreateFromList(list):convert list to array: -:Array'Get:Array'Get(array,index):fetch array element: -:Array'Set:Array'Set(array,index,element):set array element: -:Array'Size:Array'Size(array):get array size: -:Array'ToList:Array'ToList(array):convert array to list: -:Assert:Assert("str") pred:: -:Assert:Assert("str", expr) pred:signal "soft" custom error: -:Assert:Assert() pred:: -:Assoc:Assoc(key, alist):return element stored in association list: -:AssocDelete:AssocDelete(alist, "key"):delete an entry in an association list: -:AssocDelete:AssocDelete(alist, {key, value}):: -:AssocIndices:AssocIndices(alist):return the keys in an association list: -:Atom:Atom("string"):convert string to atom: -:BaseVector:BaseVector(k, n):base vector: -:Bernoulli:Bernoulli(index):Bernoulli numbers and polynomials: -:Bernoulli:Bernoulli(index, x):: -:BernoulliDistribution:BernoulliDistribution(p):Bernoulli distribution: -:BigOh:BigOh(poly, var, degree):drop all terms of a certain order in a polynomial: -:Bin:Bin(n, m):binomial coefficients: -:BinSplitData:BinSplitData(n1,n2, a, b, c, d):computations of series by the binary splitting method: -:BinSplitFinal:BinSplitFinal({P,Q,B,T}):computations of series by the binary splitting method: -:BinSplitNum:BinSplitNum(n1, n2, a, b, c, d):computations of series by the binary splitting method: -:BinomialDistribution:BinomialDistribution(p,n):binomial distribution: -:BitAnd:BitAnd(n,m):bitwise and operation: -:BitOr:BitOr(n,m):bitwise or operation: -:BitXor:BitXor(n,m):bitwise xor operation: -:Bodied:Bodied("op", precedence):define function syntax (bodied function): -:BracketRational:BracketRational(x, eps):find optimal rational approximations: -:BubbleSort:BubbleSort(list, compare):sort a list: -:Builtin'Precision'Get:Builtin'Precision'Get():get the current precision: -:Builtin'Precision'Set:Builtin'Precision'Set(n):set the precision: -:CForm:CForm(expr):export expression to C++ code: -:CachedConstant:CachedConstant(cache, Cname, Cfunc):precompute multiple-precision constants: -:CanProve:CanProve(proposition):try to prove statement: -:Catalan:Catalan:Catalan's Constant: -:CatalanNumber:CatalanNumber(n):return the {n}th Catalan Number: -:Ceil:Ceil(x):round a number upwards: -:CharacteristicEquation:CharacteristicEquation(matrix,var):get characteristic polynomial of a matrix: -:Check:Check(predicate,"error text"):report "hard" errors: -:ChiSquareTest:ChiSquareTest(observed,expected):Pearson's ChiSquare test: -:ChiSquareTest:ChiSquareTest(observed,expected,params):: -:Cholesky:Cholesky(A):find the Cholesky Decomposition: -:Clear:Clear(var, ...):undo an assignment: -:ClearError:ClearError("str"):custom errors handlers: -:ClearErrors:ClearErrors():simple error handlers: -:CoFactor:CoFactor(M,i,j):cofactor of a matrix: -:Coef:Coef(expr, var, order):coefficient of a polynomial: -:Complex:Complex(r, c):construct a complex number: -:Concat:Concat(list1, list2, ...):concatenate lists: -:ConcatStrings:ConcatStrings(strings):concatenate strings: -:Conjugate:Conjugate(x):complex conjugate: -:ContFrac:ContFrac(x):continued fraction expansion: -:ContFrac:ContFrac(x, depth):: -:ContFracEval:ContFracEval(list):manipulate continued fractions: -:ContFracEval:ContFracEval(list, rest):: -:ContFracList:ContFracList(frac):manipulate continued fractions: -:ContFracList:ContFracList(frac, depth):: -:Contains:Contains(list, expr):test whether a list contains a certain element: -:Content:Content(expr):content of a univariate polynomial: -:Cos:Cos(x):trigonometric cosine function: -:Count:Count(list, expr):count the number of occurrences of an expression: -:CrossProduct:CrossProduct(a,b):outer product of vectors: -:Curl:Curl(vector, basis):curl of a vector field: -:CurrentFile:CurrentFile():return current input file: -:CurrentLine:CurrentLine():return current line number on input: -:Cyclotomic:Cyclotomic(n,x):construct the cyclotomic polynomial: -:D:D(list) expression:: -:D:D(variable) expression:take derivative of expression with respect to variable: -:D:D(variable,n) expression:: -:Decimal:Decimal(frac):decimal representation of a rational: -:DefLoad:DefLoad(name):load a {.def} file: -:DefMacroRuleBase:DefMacroRuleBase(name,params):define a function as a macro: -:DefMacroRuleBaseListed:DefMacroRuleBaseListed("name", params):define macro with variable number of arguments: -:DefaultTokenizer:DefaultTokenizer():select the default syntax tokenizer for parsing the input: -:Degree:Degree(expr):degree of a polynomial: -:Degree:Degree(expr, var):: -:Delete:Delete(list, n):delete an element from a list: -:Denom:Denom(expr):denominator of an expression: -:DestructiveAppend:DestructiveAppend(list, expr):destructively append an entry to a list: -:DestructiveDelete:DestructiveDelete(list, n):delete an element destructively from a list: -:DestructiveInsert:DestructiveInsert(list, n, expr):insert an element destructively into a list: -:DestructiveReplace:DestructiveReplace(list, n, expr):replace an entry destructively in a list: -:DestructiveReverse:DestructiveReverse(list):reverse a list destructively: -:Determinant:Determinant(M):determinant of a matrix: -:Diagonal:Diagonal(A):extract the diagonal from a matrix: -:DiagonalMatrix:DiagonalMatrix(d):construct a diagonal matrix: -:Difference:Difference(l1, l2):return the difference of two lists: -:Div:Div(x,y):Determine divisor of two mathematical objects: -:Diverge:Diverge(vector, basis):divergence of a vector field: -:Divisors:Divisors(n):number of divisors: -:DivisorsList:DivisorsList(n):the list of divisors: -:DivisorsSum:DivisorsSum(n):the sum of divisors: -:Dot:Dot(t1,t2):get dot product of tensors: -:Drop:Drop(list, -n):: -:Drop:Drop(list, n):drop a range of elements from a list: -:Drop:Drop(list, {m,n}):: -:DumpErrors:DumpErrors():simple error handlers: -:Echo:Echo(item):high-level printing routine: -:Echo:Echo(item,item,item,...):: -:Echo:Echo(list):: -:EigenValues:EigenValues(matrix):get eigenvalues of a matrix: -:EigenVectors:EigenVectors(A,eigenvalues):get eigenvectors of a matrix: -:Eliminate:Eliminate(var, value, expr):substitute and simplify: -:EndOfFile:EndOfFile:end-of-file marker: -:Equals:Equals(a,b):check equality: -:Euler:Euler(index):Euler numbers and polynomials: -:Euler:Euler(index,x):: -:Eulerian:Eulerian(n,m):Eulerian numbers: -:Eval:Eval(expr):force evaluation of expression: -:EvalFormula:EvalFormula(expr):print an evaluation nicely with ASCII art: -:EvaluateHornerScheme:EvaluateHornerScheme(coeffs,x):fast evaluation of polynomials: -:Exp:Exp(x):exponential function: -:Expand:Expand(expr):transform a polynomial to an expanded form: -:Expand:Expand(expr, var):: -:Expand:Expand(expr, varlist):: -:ExpandBrackets:ExpandBrackets(expr):expand all brackets: -:ExtraInfo'Get:ExtraInfo'Get(expr):annotate objects with additional information: -:ExtraInfo'Set:ExtraInfo'Set(expr,tag):annotate objects with additional information: -:Factor:Factor(x):factorization, in pretty form: -:FactorialSimplify:FactorialSimplify(expression):Simplify hypergeometric expressions containing factorials: -:Factorize:Factorize(list):product of a list of values: -:Factorize:Factorize(var, from, to, body):: -:Factors:Factors(x):factorization: -:False:False:boolean constant representing false: -:FermatNumber:FermatNumber(n):return the {n}th Fermat Number: -:FillList:FillList(expr, n):fill a list with a certain expression: -:Find:Find(list, expr):get the index at which a certain element occurs: -:FindFile:FindFile(name):find a file in the current path: -:FindFunction:FindFunction(function):find the library file where a function is defined: -:FindRealRoots:FindRealRoots(p):find the real roots of a polynomial: -:FlatCopy:FlatCopy(list):copy the top level of a list: -:Flatten:Flatten(expression,operator):flatten expression w.r.t. some operator: -:Floor:Floor(x):round a number downwards: -:For:For(init, pred, incr) body:C-style {for} loop: -:ForEach:ForEach(var, list) body:loop over all entries in list: -:FromBase:FromBase(base,"string"):conversion of a number from non-decimal base to decimal base: -:FromFile:FromFile(name) body:connect current input to a file: -:FromString:FromString(str) body;:connect current input to a string: -:FullForm:FullForm(expr):print an expression in LISP-format: -:FuncList:FuncList(expr):list of functions used in an expression: -:FuncListArith:FuncListArith(expr):list of functions used in an expression: -:FuncListSome:FuncListSome(expr, list):list of functions used in an expression: -:Function:Function("op", {arglist, ...}) body:: -:Function:Function("op", {arglist}) body:: -:Function:Function() func(arglist):declare or define a function: -:Function:Function() func(arglist, ...):: -:Gamma:Gamma(x):Euler's Gamma function: -:GarbageCollect:GarbageCollect():do garbage collection on unused memory: -:GaussianFactors:GaussianFactors(z):factorization in Gaussian integers: -:GaussianGcd:GaussianGcd(z,w):greatest common divisor in Gaussian integers: -:GaussianNorm:GaussianNorm(z):norm of a Gaussian integer: -:Gcd:Gcd(list):: -:Gcd:Gcd(n,m):greatest common divisor: -:GenericTypeName:GenericTypeName(object):get type name: -:GetCoreError:GetCoreError():get "hard" error string: -:GetError:GetError("str"):custom errors handlers: -:GetErrorTableau:GetErrorTableau():custom errors handlers: -:GetTime:GetTime(expr):measure the time taken by an evaluation: -:GlobalPop:GlobalPop():: -:GlobalPop:GlobalPop(var):restore variables using a global stack: -:GlobalPush:GlobalPush(expr):save variables using a global stack: -:GoldenRatio:GoldenRatio:the Golden Ratio: -:GreaterThan:GreaterThan(a,b):comparison predicate: -:GuessRational:GuessRational(x):find optimal rational approximations: -:GuessRational:GuessRational(x, digits):: -:HarmonicNumber:HarmonicNumber(n):return the {n}th Harmonic Number: -:HarmonicNumber:HarmonicNumber(n,r):: -:HasExpr:HasExpr(expr, x):check for expression containing a subexpression: -:HasExprArith:HasExprArith(expr, x):check for expression containing a subexpression: -:HasExprSome:HasExprSome(expr, x, list):check for expression containing a subexpression: -:HasFunc:HasFunc(expr, func):check for expression containing a function: -:HasFuncArith:HasFuncArith(expr, func):check for expression containing a function: -:HasFuncSome:HasFuncSome(expr, func, list):check for expression containing a function: -:Head:Head(list):the first element of a list: -:HeapSort:HeapSort(list, compare):sort a list: -:HessianMatrix:HessianMatrix(function,var):create the Hessian matrix: -:HilbertInverseMatrix:HilbertInverseMatrix(n):create a Hilbert inverse matrix: -:HilbertMatrix:HilbertMatrix(n):create a Hilbert matrix: -:HilbertMatrix:HilbertMatrix(n,m):: -:Hold:Hold(expr):keep expression unevaluated: -:HoldArg:HoldArg("operator",parameter):mark argument as not evaluated: -:HoldArgNr:HoldArgNr("function", arity, argNum):specify argument as not evaluated: -:Horner:Horner(expr, var):convert a polynomial into the Horner form: -:I:I:imaginary unit: -:Identity:Identity(n):make identity matrix: -:If:If(pred, then):branch point: -:If:If(pred, then, else):: -:Im:Im(x):imaginary part of a complex number: -:InNumericMode:InNumericMode():determine if currently in numeric mode: -:InProduct:InProduct(a,b):inner product of vectors (deprecated): -:InVerboseMode:InVerboseMode():set verbose output mode: -:Infinity:Infinity:constant representing mathematical infinity: -:Infix:Infix("op"):define function syntax (infix operator): -:Infix:Infix("op", precedence):: -:Insert:Insert(list, n, expr):insert an element into a list: -:IntLog:IntLog(n, base):integer part of logarithm: -:IntNthRoot:IntNthRoot(x, n):integer part of $n$-th root: -:IntPowerNum:IntPowerNum(x, n, mult, unity):optimized computation of integer powers: -:Integrate:Integrate(var) expr:: -:Integrate:Integrate(var, x1, x2) expr:integration: -:Intersection:Intersection(l1, l2):return the intersection of two lists: -:Inverse:Inverse(M):get inverse of a matrix: -:InverseTaylor:InverseTaylor(var, at, order) expr:Taylor expansion of inverse: -:IsAmicablePair:IsAmicablePair(m,n):test for a pair of amicable numbers: -:IsAtom:IsAtom(expr):test for an atom: -:IsBodied:IsBodied("op"):check for function syntax: -:IsBoolean:IsBoolean(expression):test for a Boolean value: -:IsBound:IsBound(var):test for a bound variable: -:IsCFormable:IsCFormable(expr):check possibility to export expression to C++ code: -:IsCFormable:IsCFormable(expr, funclist):: -:IsCarmichaelNumber:IsCarmichaelNumber(n):test for a Carmichael number: -:IsComposite:IsComposite(n):test for a composite number: -:IsConstant:IsConstant(expr):test for a constant: -:IsCoprime:IsCoprime(list):: -:IsCoprime:IsCoprime(m,n):test if integers are coprime : -:IsDiagonal:IsDiagonal(A):test for a diagonal matrix: -:IsError:IsError("str"):: -:IsError:IsError():check for custom error: -:IsEven:IsEven(n):test for an even integer: -:IsEvenFunction:IsEvenFunction(expression,variable):Return true if function is an even function, False otherwise: -:IsFreeOf:IsFreeOf(var, expr):test whether expression depends on variable: -:IsFreeOf:IsFreeOf({var, ...}, expr):: -:IsFunction:IsFunction(expr):test for a composite object: -:IsGaussianInteger:IsGaussianInteger(z):test for a Gaussian integer: -:IsGaussianPrime:IsGaussianPrime(z):test for a Gaussian prime: -:IsGaussianUnit:IsGaussianUnit(z):test for a Gaussian unit: -:IsGeneric:IsGeneric(object):check for generic object: -:IsHermitian:IsHermitian(A):test for a Hermitian matrix: -:IsIdempotent:IsIdempotent(A):test for an idempotent matrix: -:IsInfinity:IsInfinity(expr):test for an infinity: -:IsInfix:IsInfix("op"):check for function syntax: -:IsIrregularPrime:IsIrregularPrime(n):test for an irregular prime: -:IsList:IsList(expr):test for a list: -:IsLowerTriangular:IsLowerTriangular(A):test for a lower triangular matrix: -:IsMatrix:IsMatrix(expr):test for a matrix: -:IsMatrix:IsMatrix(pred,expr):: -:IsNegativeInteger:IsNegativeInteger(n):test for a negative integer: -:IsNegativeNumber:IsNegativeNumber(n):test for a negative number: -:IsNegativeReal:IsNegativeReal(expr):test for a numerically negative value: -:IsNonObject:IsNonObject(expr):test whether argument is not an {Object()}: -:IsNonZeroInteger:IsNonZeroInteger(n):test for a nonzero integer: -:IsNotZero:IsNotZero(n):test for a nonzero number: -:IsNumber:IsNumber(expr):test for a number: -:IsNumericList:IsNumericList({list}):test for a list of numbers: -:IsOdd:IsOdd(n):test for an odd integer: -:IsOddFunction:IsOddFunction(expression,variable):Return true if function is an odd function, False otherwise: -:IsOrthogonal:IsOrthogonal(A):test for an orthogonal matrix: -:IsPositiveInteger:IsPositiveInteger(n):test for a positive integer: -:IsPositiveNumber:IsPositiveNumber(n):test for a positive number: -:IsPositiveReal:IsPositiveReal(expr):test for a numerically positive value: -:IsPostfix:IsPostfix("op"):check for function syntax: -:IsPrefix:IsPrefix("op"):check for function syntax: -:IsPrime:IsPrime(n):test for a prime number: -:IsPrimePower:IsPrimePower(n):test for a power of a prime number: -:IsPromptShown:IsPromptShown():test for the Yacas prompt option: -:IsQuadraticResidue:IsQuadraticResidue(m,n):functions related to finite groups: -:IsRational:IsRational(expr):test whether argument is a rational: -:IsScalar:IsScalar(expr):test for a scalar: -:IsSkewSymmetric:IsSkewSymmetric(A):test for a skew-symmetric matrix: -:IsSmallPrime:IsSmallPrime(n):test for a (small) prime number: -:IsSquareFree:IsSquareFree(n):test for a square-free number: -:IsSquareMatrix:IsSquareMatrix(expr):test for a square matrix: -:IsSquareMatrix:IsSquareMatrix(pred,expr):: -:IsString:IsString(expr):test for an string: -:IsSymmetric:IsSymmetric(A):test for a symmetric matrix: -:IsTwinPrime:IsTwinPrime(n):test for a twin prime: -:IsUnitary:IsUnitary(A):test for a unitary matrix: -:IsUpperTriangular:IsUpperTriangular(A):test for an upper triangular matrix: -:IsVector:IsVector(expr):test for a vector: -:IsVector:IsVector(pred,expr):: -:IsZero:IsZero(n):test whether argument is zero: -:IsZeroVector:IsZeroVector(list):test whether list contains only zeroes: -:JacobiSymbol:JacobiSymbol(m,n):functions related to finite groups: -:JacobianMatrix:JacobianMatrix(functions,variables):calculate the Jacobian matrix of $n$ functions in $n$ variables: -:KnownFailure:KnownFailure(test):Mark a test as a known failure: -:LagrangeInterpolant:LagrangeInterpolant(xlist, ylist, var):polynomial interpolation: -:LambertW:LambertW(x):Lambert's $W$ function: -:LaplaceTransform:LaplaceTransform(t,s,func) :Laplace Transform: -:Lcm:Lcm(list):: -:Lcm:Lcm(n,m):least common multiple: -:LeadingCoef:LeadingCoef(poly):leading coefficient of a polynomial: -:LeadingCoef:LeadingCoef(poly, var):: -:LeftPrecedence:LeftPrecedence("op",precedence):set operator precedence: -:LegendreSymbol:LegendreSymbol(m,n):functions related to finite groups: -:Length:Length(object):the length of a list or string: -:LessThan:LessThan(a,b):comparison predicate: -:LeviCivita:LeviCivita(list):totally anti-symmetric Levi-Civita symbol: -:Limit:Limit(var, val) expr:limit of an expression: -:Limit:Limit(var, val, dir) expr:: -:LispRead:LispRead():read expressions in LISP syntax: -:LispReadListed:LispReadListed():read expressions in LISP syntax: -:List:List(expr1, expr2, ...):construct a list: -:Listify:Listify(expr):convert a function application to a list: -:Ln:Ln(x):natural logarithm: -:LnCombine:LnCombine(expr):combine logarithmic expressions using standard logarithm rules: -:LnExpand:LnExpand(expr):expand a logarithmic expression using standard logarithm rules: -:Load:Load(name):evaluate all expressions in a file: -:Local:Local(var, ...):declare new local variables: -:LocalSymbols:LocalSymbols(var1, var2, ...) body:create unique local symbols with given prefix: -:LogicTest:LogicTest(variables,expr1,expr2):verifying equivalence of two expressions: -:LogicVerify:LogicVerify(question,answer):verifying equivalence of two expressions: -:Macro:Macro("op", {arglist, ...}) body:: -:Macro:Macro("op", {arglist}) body:: -:Macro:Macro() func(arglist):declare or define a macro: -:Macro:Macro() func(arglist, ...):: -:MakeVector:MakeVector(var,n):vector of uniquely numbered variable names: -:Map:Map(fn, list):apply an $n$-ary function to all entries in a list: -:MapArgs:MapArgs(expr, fn):apply a function to all top-level arguments: -:MapSingle:MapSingle(fn, list):apply a unary function to all entries in a list: -:MatchLinear:MatchLinear(x,expr):match an expression to a polynomial of degree one in a variable: -:MathAbs:MathAbs(x) (absolute value of x, or |x| ):: -:MathAdd:MathAdd(x,y) (add two numbers):: -:MathAnd:MathAnd(...):built-in logical "and": -:MathArcCos:MathArcCos(x) (inverse cosine):: -:MathArcCosh:MathArcCosh(x) (inverse hyperbolic cosine):: -:MathArcSin:MathArcSin(x) (inverse sine):: -:MathArcSinh:MathArcSinh(x) (inverse hyperbolic sine):: -:MathArcTan:MathArcTan(x) (inverse tangent):: -:MathArcTanh:MathArcTanh(x) (inverse hyperbolic tangent):: -:MathCeil:MathCeil(x) (smallest integer not smaller than x):: -:MathCos:MathCos(x) (cosine):: -:MathCosh:MathCosh(x) (hyperbolic cosine):: -:MathDiv:MathDiv(x,y) (integer division, result is an integer):: -:MathDivide:MathDivide(x,y) (divide two numbers):: -:MathExp:MathExp(x) (exponential, base 2.718...):: -:MathFloor:MathFloor(x) (largest integer not larger than x):: -:MathGcd:MathGcd(n,m) (Greatest Common Divisor):: -:MathGetExactBits:MathGetExactBits(x):manipulate precision of floating-point numbers: -:MathLog:MathLog(x) (natural logarithm, for x>0):: -:MathMod:MathMod(x,y) (remainder of division, or x mod y):: -:MathMultiply:MathMultiply(x,y) (multiply two numbers):: -:MathNot:MathNot(expression):built-in logical "not": -:MathOr:MathOr(...):built-in logical "or": -:MathPower:MathPower(x,y) (power, x ^ y):: -:MathSetExactBits:MathSetExactBits(x,bits):manipulate precision of floating-point numbers: -:MathSin:MathSin(x) (sine):: -:MathSinh:MathSinh(x) (hyperbolic sine):: -:MathSqrt:MathSqrt(x) (square root, must be x>=0):: -:MathSubtract:MathSubtract(x,y) (subtract two numbers):: -:MathTan:MathTan(x) (tangent):: -:MathTanh:MathTanh(x) (hyperbolic tangent):: -:MatrixPower:MatrixPower(mat,n):get nth power of a square matrix: -:MatrixSolve:MatrixSolve(A,b):solve a system of equations: -:Max:Max(list):: -:Max:Max(x,y):maximum of a number of values: -:MaxEvalDepth:MaxEvalDepth(n):set the maximum evaluation depth: -:MaximumBound:MaximumBound(p):return upper bounds on the absolute values of real roots of a polynomial: -:Min:Min(list):: -:Min:Min(x,y):minimum of a number of values: -:MinimumBound:MinimumBound(p):return lower bounds on the absolute values of real roots of a polynomial: -:Minor:Minor(M,i,j):get principal minor of a matrix: -:Mod:Mod(x,y):Determine remainder of two mathematical objects after dividing one by the other: -:Moebius:Moebius(n):the Moebius function: -:MoebiusDivisorsList:MoebiusDivisorsList(n):the list of divisors and Moebius values: -:Monic:Monic(poly):monic part of a polynomial: -:Monic:Monic(poly, var):: -:MultiplyNum:MultiplyNum(x,y):optimized numerical multiplication: -:MultiplyNum:MultiplyNum(x,y,z,...):: -:MultiplyNum:MultiplyNum({x,y,z,...}):: -:N:N(expression):try determine numerical approximation of expression: -:N:N(expression, precision):: -:NFunction:NFunction("newname","funcname", {arglist}):make wrapper for numeric functions: -:NearRational:NearRational(x):find optimal rational approximations: -:NearRational:NearRational(x, digits):: -:NewLine:NewLine():print one or more newline characters: -:NewLine:NewLine(nr):: -:Newton:Newton(expr, var, initial, accuracy):solve an equation numerically with Newton's method: -:Newton:Newton(expr, var, initial, accuracy,min,max):: -:NewtonNum:NewtonNum(func, x0):: -:NewtonNum:NewtonNum(func, x0, prec0):: -:NewtonNum:NewtonNum(func, x0, prec0, order):low-level optimized Newton's iterations: -:NextPrime:NextPrime(i):generate a prime following a number: -:Nl:Nl():the newline character: -:NonN:NonN(expr):calculate part in non-numeric mode: -:Normalize:Normalize(v):normalize a vector: -:Not:Not expr:logical negation: -:NrArgs:NrArgs(expr):return number of top-level arguments: -:Nth:Nth(list, n):return the $n$-th element of a list: -:NthRoot:NthRoot(m,n):calculate/simplify nth root of an integer: -:NumRealRoots:NumRealRoots(p):return the number of real roots of a polynomial: -:Numer:Numer(expr):numerator of an expression: -:OMDef:OMDef(yacasForm, cd, name):define translations from Yacas to OpenMath and vice-versa.: -:OMDef:OMDef(yacasForm, cd, name, yacasToOM):: -:OMDef:OMDef(yacasForm, cd, name, yacasToOM, omToYacas):: -:OMForm:OMForm(expression):convert Yacas expression to OpenMath: -:OMRead:OMRead():convert expression from OpenMath to Yacas expression: -:Object:Object("pred", exp):create an incomplete type: -:OdeOrder:OdeOrder(eqn):return order of an ODE: -:OdeSolve:OdeSolve(expr1==expr2):general ODE solver: -:OdeTest:OdeTest(eqn,testsol):test the solution of an ODE: -:OldSolve:OldSolve(eq, var):old version of {Solve}: -:OldSolve:OldSolve(eqlist, varlist):: -:OpLeftPrecedence:OpLeftPrecedence("op"):get operator precedence: -:OpPrecedence:OpPrecedence("op"):get operator precedence: -:OpRightPrecedence:OpRightPrecedence("op"):get operator precedence: -:OrthoG:OrthoG(n, a, x);:Gegenbauer orthogonal polynomials: -:OrthoGSum:OrthoGSum(c, a, x);:sums of series of orthogonal polynomials: -:OrthoH:OrthoH(n, x);:Hermite orthogonal polynomials: -:OrthoHSum:OrthoHSum(c, x);:sums of series of orthogonal polynomials: -:OrthoL:OrthoL(n, a, x);:Laguerre orthogonal polynomials: -:OrthoLSum:OrthoLSum(c, a, x);:sums of series of orthogonal polynomials: -:OrthoP:OrthoP(n, a, b, x);:: -:OrthoP:OrthoP(n, x);:Legendre and Jacobi orthogonal polynomials: -:OrthoPSum:OrthoPSum(c, a, b, x);:: -:OrthoPSum:OrthoPSum(c, x);:sums of series of orthogonal polynomials: -:OrthoPoly:OrthoPoly(name, n, par, x):internal function for constructing orthogonal polynomials: -:OrthoPolySum:OrthoPolySum(name, c, par, x):internal function for computing series of orthogonal polynomials: -:OrthoT:OrthoT(n, x);:Chebyshev polynomials: -:OrthoTSum:OrthoTSum(c, x);:sums of series of orthogonal polynomials: -:OrthoU:OrthoU(n, x);:Chebyshev polynomials: -:OrthoUSum:OrthoUSum(c, x);:sums of series of orthogonal polynomials: -:OrthogonalBasis:OrthogonalBasis(W):create an orthogonal basis : -:OrthonormalBasis:OrthonormalBasis(W):create an orthonormal basis : -:Outer:Outer(t1,t2):get outer tensor product: -:PAdicExpand:PAdicExpand(n, p):p-adic expansion: -:PDF:PDF(dist,x):probability density function: -:PSolve:PSolve(poly, var):solve a polynomial equation: -:Partition:Partition(list, n):partition a list in sublists of equal length: -:PatchLoad:PatchLoad(name):execute commands between {} in file: -:PatchString:PatchString(string):execute commands between {} in strings: -:Permutations:Permutations(list):get all permutations of a list: -:Pi:Pi:mathematical constant, $pi$: -:Plot2D:Plot2D(f(x)):adaptive two-dimensional plotting: -:Plot2D:Plot2D(f(x), a b):: -:Plot2D:Plot2D(f(x), a b, option=value):: -:Plot2D:Plot2D(f(x), a b, option=value, ...):: -:Plot2D:Plot2D(list, ...):: -:Plot3DS:Plot3DS(f(x,y)):three-dimensional (surface) plotting: -:Plot3DS:Plot3DS(f(x,y), a b, c d):: -:Plot3DS:Plot3DS(f(x,y), a b, c d, option=value):: -:Plot3DS:Plot3DS(f(x,y), a b, c d, option=value, ...):: -:Plot3DS:Plot3DS(list, ...):: -:Pop:Pop(stack, n):remove an element from a stack: -:PopBack:PopBack(stack):remove an element from the bottom of a stack: -:PopFront:PopFront(stack):remove an element from the top of a stack: -:Postfix:Postfix("op"):define function syntax (postfix operator): -:Postfix:Postfix("op", precedence):: -:Prefix:Prefix("op"):define function syntax (prefix operator): -:Prefix:Prefix("op", precedence):: -:PrettyForm:PrettyForm(expr):print an expression nicely with ASCII art: -:PrimitivePart:PrimitivePart(expr):primitive part of a univariate polynomial: -:PrintList:PrintList(list):print list with padding: -:PrintList:PrintList(list, padding);:: -:Prog:Prog(statement1, statement2, ...):block of statements: -:ProperDivisors:ProperDivisors(n):the number of proper divisors: -:ProperDivisorsSum:ProperDivisorsSum(n):the sum of proper divisors: -:Pslq:Pslq(xlist,precision):search for integer relations between reals: -:Push:Push(stack, expr):add an element on top of a stack: -:RadSimp:RadSimp(expr):simplify expression with nested radicals: -:RamanujanSum:RamanujanSum(k,n):compute the "Ramanujan sum": -:RandVerifyArithmetic:RandVerifyArithmetic(n):Special purpose arithmetic verifiers: -:Random:Random():(pseudo-) random number generator: -:RandomIntegerMatrix:RandomIntegerMatrix(rows,cols,from,to):generate a matrix of random integers: -:RandomIntegerVector:RandomIntegerVector(nr, from, to):generate a vector of random integers: -:RandomPoly:RandomPoly(var,deg,coefmin,coefmax):construct a random polynomial: -:RandomSeed:RandomSeed(init):(pseudo-) random number generator: -:Rationalize:Rationalize(expr):convert floating point numbers to fractions: -:Re:Re(x):real part of a complex number: -:Read:Read():read an expression from current input: -:ReadCmdLineString:ReadCmdLineString(prompt):read an expression from command line and return in string: -:ReadToken:ReadToken():read a token from current input: -:RemoveDuplicates:RemoveDuplicates(list):remove any duplicates from a list: -:Replace:Replace(list, n, expr):replace an entry in a list: -:Retract:Retract("function",arity):erase rules for a function: -:Reverse:Reverse(list):return the reversed list (without touching the original): -:ReversePoly:ReversePoly(f, g, var, newvar, degree):solve $h(f(x)) = g(x) + O(x^n)$ for $h$: -:RightAssociative:RightAssociative("op"):declare associativity: -:RightPrecedence:RightPrecedence("op",precedence):set operator precedence: -:Rng:Rng(r):manipulate random number generators as objects: -:RngCreate:RngCreate():manipulate random number generators as objects: -:RngCreate:RngCreate(init):: -:RngCreate:RngCreate(option==value,...):: -:RngSeed:RngSeed(r, init):manipulate random number generators as objects: -:Round:Round(x):round a number to the nearest integer: -:RoundTo:RoundTo(number,precision):Round a real-valued result to a set number of digits: -:Rule:Rule("operator", arity,:define a rewrite rule: -:RuleBase:RuleBase(name,params):define function with a fixed number of arguments: -:RuleBaseArgList:RuleBaseArgList("operator", arity):obtain list of arguments: -:RuleBaseListed:RuleBaseListed("name", params):define function with variable number of arguments: -:Secure:Secure(body):guard the host OS: -:Select:Select(pred, list):select entries satisfying some predicate: -:Set:Set(var, exp):assignment: -:SetGlobalLazyVariable:SetGlobalLazyVariable(var,value):global variable is to be evaluated lazily: -:ShiftLeft:ShiftLeft(expr,bits):: -:ShiftRight:ShiftRight(expr,bits):: -:Sign:Sign(x):sign of a number: -:Simplify:Simplify(expr):try to simplify an expression: -:Sin:Sin(x):trigonometric sine function: -:Solve:Solve(eq, var):solve an equation: -:SolveMatrix:SolveMatrix(M,v):solve a linear system: -:Space:Space():print one or more spaces: -:Space:Space(nr):: -:Sparsity:Sparsity(matrix):get the sparsity of a matrix: -:Sqrt:Sqrt(x):square root: -:SquareFree:SquareFree(p):return the square-free part of polynomial: -:SquareFreeDivisorsList:SquareFreeDivisorsList(n):the list of square-free divisors: -:StirlingNumber1:StirlingNumber1(n,m):return the {n,m}th Stirling Number of the first kind: -:String:String(atom):convert atom to string: -:StringMid'Get:StringMid'Get(index,length,string):retrieve a substring: -:StringMid'Set:StringMid'Set(index,substring,string):change a substring: -:Subfactorial:Subfactorial(m):factorial and related functions: -:Subst:Subst(from, to) expr:perform a substitution: -:SuchThat:SuchThat(expr, var):special purpose solver: -:Sum:Sum(var, from, to, body):find sum of a sequence: -:SumForDivisors:SumForDivisors(var,n,expr):loop over divisors: -:SumTaylorNum:SumTaylorNum(x, NthTerm, TermFactor, order):: -:SumTaylorNum:SumTaylorNum(x, NthTerm, order):optimized numerical evaluation of Taylor series: -:SumTaylorNum:SumTaylorNum(x, ZerothTerm, TermFactor, order):: -:Swap:Swap(list, i1, i2):swap two elements in a list: -:SylvesterMatrix:SylvesterMatrix(poly1,poly2,variable):calculate the Sylvester matrix of two polynomials: -:SystemCall:SystemCall(str):pass a command to the shell: -:Table:Table(body, var, from, to, step):evaluate while some variable ranges over interval: -:TableForm:TableForm(list):print each entry in a list on a line: -:Tail:Tail(list):returns a list without its first element: -:Take:Take(list, -n):: -:Take:Take(list, n):take a sublist from a list, dropping the rest: -:Take:Take(list, {m,n}):: -:Tan:Tan(x):trigonometric tangent function: -:Taylor:Taylor(var, at, order) expr:univariate Taylor series expansion: -:TeXForm:TeXForm(expr):export expressions to $LaTeX$: -:TestYacas:TestYacas(question,answer):verifying equivalence of two expressions: -:Time:Time(expr):measure the time taken by a function: -:ToBase:ToBase(base, number):conversion of a number in decimal base to non-decimal base: -:ToFile:ToFile(name) body:connect current output to a file: -:ToStdout:ToStdout() body:select initial output stream for output: -:ToString:ToString() body:connect current output to a string: -:ToeplitzMatrix:ToeplitzMatrix(N):create a Toeplitz matrix: -:Trace:Trace(M):trace of a matrix: -:TraceExp:TraceExp(expr):evaluate with tracing enabled: -:TraceRule:TraceRule(template) expr:turn on tracing for a particular function: -:TraceStack:TraceStack(expression):show calling stack after an error occurs: -:Transpose:Transpose(M):get transpose of a matrix: -:TrapError:TrapError(expression,errorHandler):trap "hard" errors: -:TrigSimpCombine:TrigSimpCombine(expr):combine products of trigonometric functions: -:True:True:boolean constant representing true: -:TruncRadian:TruncRadian(r):remainder modulo $2*Pi$: -:Type:Type(expr):return the type of an expression: -:UnFence:UnFence("operator",arity):change local variable scope for a function: -:UnFlatten:UnFlatten(list,operator,identity):inverse operation of Flatten: -:UnList:UnList(list):convert a list to a function application: -:Undefined:Undefined:constant signifying an undefined result: -:Union:Union(l1, l2):return the union of two lists: -:UniqueConstant:UniqueConstant():create a unique identifier: -:Until:Until(pred) body:loop until a condition is met: -:Use:Use(name):load a file, but not twice: -:V:V(expression):set verbose output mode: -:VandermondeMatrix:VandermondeMatrix(vector):create the Vandermonde matrix: -:VarList:VarList(expr):list of variables appearing in an expression: -:VarListArith:VarListArith(expr):list of variables appearing in an expression: -:VarListSome:VarListSome(expr, list):list of variables appearing in an expression: -:Verify:Verify(question,answer):verifying equivalence of two expressions: -:VerifyArithmetic:VerifyArithmetic(x,n,m):Special purpose arithmetic verifiers: -:VerifyDiv:VerifyDiv(u,v):Special purpose arithmetic verifiers: -:While:While(pred) body:loop while a condition is met: -:WithValue:WithValue(var, val, expr):temporary assignment during an evaluation: -:WithValue:WithValue({var,...}, {val,...}, expr):: -:Write:Write(expr, ...):low-level printing routine: -:WriteString:WriteString(string):low-level printing routine for strings: -:WronskianMatrix:WronskianMatrix(func,var):create the Wronskian matrix: -:XmlExplodeTag:XmlExplodeTag(xmltext):convert XML strings to tag objects: -:XmlTokenizer:XmlTokenizer():select an XML syntax tokenizer for parsing the input: -:ZeroMatrix:ZeroMatrix(n):make a zero matrix: -:ZeroMatrix:ZeroMatrix(n, m):: -:ZeroVector:ZeroVector(n):create a vector with all zeroes: -:Zeta:Zeta(x):Riemann's Zeta function: -::::::: diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/HintWindow.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/HintWindow.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/HintWindow.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/HintWindow.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,156 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - - -public class HintWindow -{ - public String[] iText = new String[64]; - public String[] iDescription = new String[64]; - - public boolean iAllowSelection = true; - public int iNrDescriptions; - public int iMaxWidth; - public int iTextSize; - public int iCurrentPos; - public int iNrLines; - - public HintWindow(int aTextSize) - { - iNrLines = 0; - iNrDescriptions = 0; - iMaxWidth = 0; - iTextSize = aTextSize; - iCurrentPos = 0; - } - public void addLine(String aText) - { - if (iNrLines >= 20) return; - iText[iNrLines] = aText; - iNrLines++; - iMaxWidth = 0; - } - public void addDescription(String aText) - { - if (iNrDescriptions >= 20) return; - iDescription[iNrDescriptions] = aText; - iNrDescriptions++; - iMaxWidth = 0; - } - public void draw(int x, int y, MathPiperGraphicsContext aGraphicsContext) - { - aGraphicsContext.setFontSize(0,iTextSize); - if (iMaxWidth == 0) - { - int i; - for (i=0;iiMaxWidth) - iMaxWidth = width; - } - for (i=0;iiMaxWidth) - iMaxWidth = width; - } - iMaxWidth = iMaxWidth + 8; - } - - //System.out.println("iNrLines = "+iNrLines); - //System.out.println("iMaxWidth = "+iMaxWidth); - - int ix = x; - int iy = y; - int w = 5+iMaxWidth; - int h = height(aGraphicsContext); - iy -= (h+4); - - if (!iAllowSelection) - aGraphicsContext.setColor(221,221,238); - else - aGraphicsContext.setColor(221,221,238); - aGraphicsContext.fillRect(ix,iy,w,h); - aGraphicsContext.setColor(0,0,0); - aGraphicsContext.drawRect(ix,iy,w,h); - - int i; - - //System.out.println("iTextSize = "+iTextSize); - //System.out.println("aGraphicsContext.FontHeight() = "+aGraphicsContext.FontHeight()); - - for (i=0;i0) - { - int offset = (iNrLines+1)*aGraphicsContext.fontHeight()+7; - - aGraphicsContext.drawLine(ix+6,iy+offset-4-aGraphicsContext.fontHeight(),ix+w-6,iy+offset-4-aGraphicsContext.fontHeight()); - - aGraphicsContext.setFontSize(1,iTextSize); - for (i=0;i0) - { - aGraphicsContext.setFontSize(1,iTextSize); - h += iNrDescriptions*aGraphicsContext.fontHeight()+2; - // space for line - h+=7; - } - return h; - } - -} - - - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ImageLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ImageLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ImageLine.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ImageLine.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - -import java.applet.Applet; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Image; - - class ImageLine extends MathOutputLine - { - Color bkColor = new Color(255, 255, 255); //TODO:tk:This variable was originally in ConsoleApplet. - ImageLine(Image aImage, Applet aApplet) - { - iImage = aImage; - iApplet = aApplet; - } - - public void draw(Graphics g, int x, int y) - { - if (iImage != null) - { - Dimension d = iApplet.getSize(); - g.drawImage(iImage, (d.width - iImage.getWidth(iApplet)) / 2, y, bkColor, iApplet); - } - } - - public int height(Graphics g) - { - return iImage.getHeight(iApplet); - } - Image iImage; - Applet iApplet; - } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/latexparser/SymbolBoxStack.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/latexparser/SymbolBoxStack.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/latexparser/SymbolBoxStack.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/latexparser/SymbolBoxStack.java 2010-02-26 08:35:35.000000000 +0000 @@ -0,0 +1,174 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +//}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.latexparser; + +import org.mathpiper.ui.gui.worksheets.symbolboxes.*; + + +public class SymbolBoxStack { + + SymbolBox[] stack = new SymbolBox[1024]; + + int stackDepth = 0; + + + public SymbolBox pop() { + stackDepth--; + + SymbolBox result = stack[stackDepth]; + + return result; + } + + void push(SymbolBox aSbox) { + + stack[stackDepth] = aSbox; + + stackDepth++; + } + + public int stackDepth() { + + return stackDepth; + } + + public void process(String aType) { + + if (aType.equals("=") || aType.equals("\\neq") || aType.equals("+") || aType.equals(",") || aType.equals("\\wedge") || aType.equals("\\vee") || aType.equals("<") || aType.equals(">") || aType.equals("<=") || aType.equals(">=")) { + + SymbolBox right = pop(); + SymbolBox left = pop(); + push(new InfixOperator(left, new SymbolName(aType), right)); + } else if (aType.equals("/")) { + + SymbolBox denom = pop(); + SymbolBox numer = pop(); + push(new Fraction(numer, denom)); + } else if (aType.equals("-/2")) { + + SymbolBox right = pop(); + SymbolBox left = pop(); + push(new InfixOperator(left, new SymbolName("-"), right)); + } else if (aType.equals("-/1")) { + + SymbolBox right = pop(); + push(new PrefixOperator(new SymbolName("-"), right)); + } else if (aType.equals("~")) { + + SymbolBox right = pop(); + push(new PrefixOperator(new SymbolName("~"), right)); + } else if (aType.equals("!")) { + + SymbolBox left = pop(); + push(new PrefixOperator(left, new SymbolName("!"))); + } else if (aType.equals("*")) { + + SymbolBox right = pop(); + SymbolBox left = pop(); + push(new InfixOperator(left, new SymbolName(""), right)); + } else if (aType.equals("[func]")) { + + SymbolBox right = pop(); + SymbolBox left = pop(); + push(new PrefixOperator(left, right)); + } else if (aType.equals("^")) { + + SymbolBox right = pop(); + SymbolBox left = pop(); + boolean appendToExisting = false; + + if (left instanceof SuperSubFix) { + + SuperSubFix sbox = (SuperSubFix) left; + + if (!sbox.hasSuperfix()) { + appendToExisting = true; + } + } + + if (appendToExisting) { + + SuperSubFix sbox = (SuperSubFix) left; + sbox.setSuperfix(right); + push(sbox); + } else { + push(new SuperSubFix(left, right, null)); + } + } else if (aType.equals("_")) { + + SymbolBox right = pop(); + SymbolBox left = pop(); + + if (left instanceof SuperSubFix) { + + SuperSubFix sbox = (SuperSubFix) left; + sbox.setSubfix(right); + push(sbox); + } else { + push(new SuperSubFix(left, null, right)); + } + } else if (aType.equals("[sqrt]")) { + + SymbolBox left = pop(); + push(new SquareRoot(left)); + } else if (aType.equals("[sum]")) { + push(new Sum()); + } else if (aType.equals("[int]")) { + push(new Integral()); + } else if (aType.equals("[roundBracket]")) { + + SymbolBox left = pop(); + push(new Bracket(left, "(", ")")); + } else if (aType.equals("[squareBracket]")) { + + SymbolBox left = pop(); + push(new Bracket(left, "[", "]")); + } else if (aType.equals("[accoBracket]")) { + + SymbolBox left = pop(); + push(new Bracket(left, "{", "}")); + } else if (aType.equals("[grid]")) { + + SymbolBox widthBox = pop(); + SymbolBox heightBox = pop(); + int width = Integer.parseInt(((SymbolName) widthBox).iSymbol); + int height = Integer.parseInt(((SymbolName) heightBox).iSymbol); + Grid grid = new Grid(width, height); + int i; + int j; + + for (j = height - 1; j >= 0; j--) { + + for (i = width - 1; i >= 0; i--) { + + SymbolBox value = pop(); + grid.setSBox(i, j, value); + } + } + + push(grid); + } else { + push(new SymbolName(aType)); + } + } + + public void processLiteral(String aExpression) { + push(new SymbolName(aExpression)); + } +}//end class + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/latexparser/TexParser.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/latexparser/TexParser.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/latexparser/TexParser.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/latexparser/TexParser.java 2010-04-02 06:35:47.000000000 +0000 @@ -0,0 +1,483 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.latexparser; + +import org.mathpiper.ui.gui.worksheets.symbolboxes.SymbolBox; + + +public class TexParser +{ + + static String singleOps = "^_+=,"; + int currentPos; + String iCurrentExpression; + String nextToken; + + private boolean showToken = false; + + private void showToken(String sourceName) + { + System.out.println(sourceName + ": " + nextToken); + } + + void nextToken() + { + nextToken = ""; + + if (currentPos == iCurrentExpression.length()) + { + + if(showToken) showToken("End of expression"); + + return; + } + + + while (currentPos < iCurrentExpression.length() && isSpace(iCurrentExpression.charAt(currentPos))) + { + //Skip spaces. + currentPos++; + } + + if (currentPos == iCurrentExpression.length()) + { + //Return if at end of expression. + + if(showToken) showToken("End of expression"); + return; + } + else if (isAlNum(iCurrentExpression.charAt(currentPos))) + { + + int startPos = currentPos; + + while (currentPos < iCurrentExpression.length() && isAlNum(iCurrentExpression.charAt(currentPos))) + { + currentPos++; + } + + nextToken = iCurrentExpression.substring(startPos, currentPos); + + if(showToken) showToken("Is alpha numeric"); + return; + } + + int c = iCurrentExpression.charAt(currentPos); + + if (c == '{') + { + nextToken = "{"; + currentPos++; + + if(showToken) showToken("Left brace"); + return; + } + else if (c == '}') + { + nextToken = "}"; + currentPos++; + + if(showToken) showToken("Right brace"); + return; + } + else if (singleOps.indexOf(c) >= 0) + { + nextToken = "" + (char)c; + currentPos++; + + if(showToken) showToken("Single operator"); + return; + } + else if (c == '\\') + { + + int startPos = currentPos; + + while (currentPos < iCurrentExpression.length() && (isAlNum(iCurrentExpression.charAt(currentPos)) || iCurrentExpression.charAt(currentPos) == '\\')) + { + currentPos++; + } + + nextToken = iCurrentExpression.substring(startPos, currentPos); + + if(showToken) showToken("Backslash"); + return; + } + + if(showToken) showToken("No match"); + } + + boolean matchToken(String token) + { + + if (nextToken.equals(token)) + + return true; + + System.out.println("Found " + nextToken + ", expected " + token); + + return false; + } + + public SymbolBox parse(String aExpression) + { + iCurrentExpression = aExpression; + currentPos = 0; + nextToken(); + + return parseTopExpression(); + } + + SymbolBox parseTopExpression() + { + + SymbolBoxStack builder = new SymbolBoxStack(); + + parseOneExpression10(builder); + + SymbolBox expression = builder.pop(); + + return expression; + } + + void parseOneExpression10(SymbolBoxStack builder) + { + parseOneExpression20(builder); + + // = , + while (nextToken.equals("=") || nextToken.equals("\\neq") || nextToken.equals(",")) + { + + String token = nextToken; + nextToken(); + parseOneExpression20(builder); + builder.process(token); + } + } + + void parseOneExpression20(SymbolBoxStack builder) + { + parseOneExpression25(builder); + + // +, - + while (nextToken.equals("+") || nextToken.equals("-") || nextToken.equals("\\wedge") || nextToken.equals("\\vee") || nextToken.equals("<") || nextToken.equals(">") || nextToken.equals("\\leq") || nextToken.equals("\\geq")) + { + + String token = nextToken; + + if (token.equals("-")) + token = "-/2"; + else if (token.equals("\\leq")) + token = "<="; + else if (token.equals("\\geq")) + token = ">="; + + nextToken(); + parseOneExpression25(builder); + builder.process(token); + } + } + + void parseOneExpression25(SymbolBoxStack builder) + { + parseOneExpression30(builder); + + // implicit * + while (nextToken.length() > 0 && !nextToken.equals("+") && !nextToken.equals("-") && !nextToken.equals("=") && !nextToken.equals("\\neq") && !nextToken.equals("}") && !nextToken.equals("&") && !nextToken.equals("\\wedge") && !nextToken.equals("\\vee") && !nextToken.equals("<") && !nextToken.equals(">") && !nextToken.equals("\\leq") && !nextToken.equals("\\geq") && !nextToken.equals("\\end") && !nextToken.equals("\\\\") && !nextToken.equals("\\right)") && !nextToken.equals("\\right]") && !nextToken.equals(",")) + { + + //System.out.println("nextToken = "+nextToken); + String token = "*"; + parseOneExpression30(builder); + + //System.out.println("After: nextToken = "+nextToken); + builder.process(token); + } + } + + void parseOneExpression30(SymbolBoxStack builder) + { + parseOneExpression40(builder); + + // _, ^ + while (nextToken.equals("_") || nextToken.equals("^") || nextToken.equals("!")) + { + + if (nextToken.equals("!")) + { + builder.process(nextToken); + nextToken(); + } + else + { + + String token = nextToken; + nextToken(); + parseOneExpression40(builder); + builder.process(token); + } + } + } + + void parseOneExpression40(SymbolBoxStack builder) + { + + // atom + if (nextToken.equals("{")) + { + nextToken(); + parseOneExpression10(builder); + + if (!nextToken.equals("}")) + { + System.out.println("Got " + nextToken + ", expected }"); + + return; + } + } + else if (nextToken.equals("\\left(")) + { + nextToken(); + parseOneExpression10(builder); + + if (!nextToken.equals("\\right)")) + { + System.out.println("Got " + nextToken + ", expected \\right)"); + + return; + } + + builder.process("[roundBracket]"); + } + else if (nextToken.equals("\\left[")) + { + nextToken(); + parseOneExpression10(builder); + + if (!nextToken.equals("\\right]")) + { + System.out.println("Got " + nextToken + ", expected \\right]"); + + return; + } + + builder.process("[squareBracket]"); + } + else if (nextToken.equals("\\sqrt")) + { + nextToken(); + parseOneExpression25(builder); + builder.process("[sqrt]"); + + return; + } + else if (nextToken.equals("\\exp")) + { + nextToken(); + builder.process("e"); + parseOneExpression40(builder); + builder.process("^"); + + return; + } + else if (nextToken.equals("\\imath")) + { + builder.process("i"); + } + else if (nextToken.equals("\\mathrm")) + { + nextToken(); + + if (!matchToken("{")) + + return; + + int startPos = currentPos; + + while (currentPos < iCurrentExpression.length() && iCurrentExpression.charAt(currentPos) != '}') + currentPos++; + + String literal = iCurrentExpression.substring(startPos, currentPos); + currentPos++; + builder.processLiteral(literal); + nextToken(); + + return; + } + else if (nextToken.equals("-")) + { + nextToken(); + parseOneExpression30(builder); + builder.process("-/1"); + + return; + } + else if (nextToken.equals("\\neg")) + { + nextToken(); + parseOneExpression30(builder); + builder.process("~"); + + return; + } + else if (nextToken.equals("\\sum")) + { + builder.process("[sum]"); + } + else if (nextToken.equals("\\int")) + { + builder.process("[int]"); + } + else if (nextToken.equals("\\frac")) + { + nextToken(); + parseOneExpression40(builder); + parseOneExpression40(builder); + builder.process("/"); + + return; + } + else if (nextToken.equals("\\begin")) + { + nextToken(); + + if (!matchToken("{")) + + return; + + nextToken(); + + String name = nextToken; + nextToken(); + + if (!matchToken("}")) + + return; + + if (name.equals("array")) + { + + int nrColumns = 0; + int nrRows = 0; + nextToken(); + + if (!matchToken("{")) + + return; + + nextToken(); + + String coldef = nextToken; + nextToken(); + + if (!matchToken("}")) + + return; + + nrColumns = coldef.length(); + nrRows = 1; + nextToken(); + + while (!nextToken.equals("\\end")) + { + parseOneExpression10(builder); + + if (nextToken.equals("\\\\")) + { + nrRows++; + nextToken(); + } + else if (nextToken.equals("&")) + { + nextToken(); + } + else + { + + // System.out.println("END? "+nextToken); + } + } + + nextToken(); + + if (!matchToken("{")) + + return; + + nextToken(); + + String name2 = nextToken; + nextToken(); + + if (!matchToken("}")) + + return; + + if (name2.equals("array")) + { + builder.process("" + nrRows); + builder.process("" + nrColumns); + builder.process("[grid]"); + } + } + } + else + { + builder.process(nextToken); + } + + nextToken(); + } + + boolean isSpace(int c) + { + + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + + return true; + + return false; + } + + boolean isAlNum(int c) + { + + if (isSpace(c)) + + return false; + + if (c == '{') + + return false; + + if (c == '}') + + return false; + + if (c == '\\') + + return false; + + if (singleOps.indexOf(c) >= 0) + + return false; + + return true; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/LatexRenderingController.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/LatexRenderingController.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/LatexRenderingController.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/LatexRenderingController.java 2010-07-06 06:16:59.000000000 +0000 @@ -0,0 +1,60 @@ +package org.mathpiper.ui.gui.worksheets; + +import java.awt.Dimension; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.scilab.forge.jlatexmath.TeXConstants; +import org.scilab.forge.jlatexmath.TeXFormula; +import org.scilab.forge.jlatexmath.TeXIcon; + +public class LatexRenderingController extends JPanel implements ChangeListener { + + private JSlider scaleSlider; + private JLabel texLabel; + private TeXFormula texFormula; + + public LatexRenderingController(TeXFormula texFormula, JLabel texLabel, int initialValue) { + super(); + this.texFormula = texFormula; + this.texLabel = texLabel; + + TeXIcon icon = texFormula.createTeXIcon(TeXConstants.STYLE_DISPLAY, initialValue); + texLabel.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + texLabel.setAlignmentY(icon.getBaseLine()); + texLabel.setIcon(icon); + + scaleSlider = new JSlider(JSlider.HORIZONTAL, 1, 500, initialValue); + scaleSlider.addChangeListener(this); + + //Turn on labels at major tick marks. + //framesPerSecond.setMajorTickSpacing(10); + //framesPerSecond.setMinorTickSpacing(1); + //framesPerSecond.setPaintTicks(true); + scaleSlider.setPaintLabels(true); + + this.add(new JLabel("Adjust Scale")); + this.add(scaleSlider); + + } + + public void stateChanged(ChangeEvent e) { + + JSlider source = (JSlider) e.getSource(); + //if (!source.getValueIsAdjusting()) { + int intValue = (int) source.getValue(); + + TeXIcon icon = texFormula.createTeXIcon(TeXConstants.STYLE_DISPLAY, intValue); + texLabel.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + texLabel.setAlignmentY(icon.getBaseLine()); + texLabel.setIcon(icon); + texLabel.repaint(); + + //} + }//end method. + + + }//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ListPanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ListPanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ListPanel.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ListPanel.java 2010-07-03 18:20:46.000000000 +0000 @@ -0,0 +1,489 @@ +package org.mathpiper.ui.gui.worksheets; // ViewList({{a},{b}}) + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; +import javax.swing.JPanel; +import org.mathpiper.lisp.Environment; +import org.mathpiper.lisp.cons.Cons; +import org.mathpiper.lisp.cons.ConsPointer; +import org.mathpiper.lisp.cons.SublistCons; +import org.mathpiper.ui.gui.worksheets.symbolboxes.Bounds; +import org.mathpiper.ui.gui.worksheets.symbolboxes.ScaledGraphics; + +public class ListPanel extends JPanel implements ViewPanel { + + private ConsNode headNode; + + protected double viewScale = 1; + + private Queue levelQueue = new LinkedList(); + + private Stack sequenceStack = new Stack(); + + private boolean paintedOnce = false; + + private int largestX = 0; + + private int largestY = 0; + + + public ListPanel(Environment aEnvironment, int aStackTop, ConsPointer consPointer, double viewScale) { + super(); + this.setOpaque(true); + this.viewScale = viewScale; + this.setBackground(Color.white); + + String sublistName = "( )"; + + //int startX = 0; //10; + //int xStep = 1; //60; + + int startY = 0; //10; + int yStep = 1; //40; + + + try { + + + Cons headCons = consPointer.getCons(); + + headNode = new ConsNode(); + if(headCons instanceof SublistCons) + { + headNode.setName(sublistName); + } + else + { + headNode.setName(headCons.car().toString()); + } + //headNode.setX(startX); + headNode.setY(startY); + + if(headCons == null) + { + throw new Exception("Null cons."); + } + + + if(!(headCons instanceof SublistCons)) + { + //Display a single non-list cons. + /*headNode = new ConsNode(); + headNode.setName(headCons.car().toString()); + headNode.setX(startX); + headNode.setY(startY); + * */ + } + else + { + ConsXHolder consXHolder = new ConsXHolder(headCons, headNode); + sequenceStack.push(consXHolder); + + ConsNode currentNode = null; + + while(!sequenceStack.empty()) + { + consXHolder = sequenceStack.pop(); + + //Remove rest because it has already been processed. + consXHolder.getCons().cdr().setCons(null); + + ConsPointer currentConsPointer = new ConsPointer(consXHolder.getCons()); + + currentNode = consXHolder.getConsNode(); + + if(currentConsPointer.getCons() == headCons) + { + //If this is the head cons, create the head node. + /*headNode = new ConsNode(); + currentNode = headNode; + currentNode.setX(startX); + currentNode.setY(startY);*/ + }//end if. + + while(currentConsPointer.cdr().getCons() != null || (currentConsPointer.car() instanceof ConsPointer && ((ConsPointer)currentConsPointer.car()).getCons() != null)) + { + if(currentConsPointer.cdr().getCons() != null) + { + //Go next. + currentConsPointer.goNext(aStackTop, aEnvironment); + ConsNode newNode = new ConsNode(); + if(! (currentConsPointer.getCons() instanceof SublistCons)) + { + String name = currentConsPointer.getCons().toString(); + newNode.setName(name); + } + else + { + newNode.setName(sublistName); + } + //newNode.setX(currentNode.getX() + xStep); + + /*if(newNode.getX() > largestX) + { + largestX = newNode.getX(); + }*/ + + currentNode.setCdr(newNode); + currentNode = newNode; + + if(currentConsPointer.getCons() instanceof SublistCons) + { + sequenceStack.push(new ConsXHolder(currentConsPointer.getCons(), currentNode)); + + if(currentConsPointer.getCons().cdr().getCons() == null) + { + break; + }//end if. + + }//end if. + + } + else + { + if((currentConsPointer.car() instanceof ConsPointer && ((ConsPointer)currentConsPointer.car()).getCons() == null))//! (currentConsPointer.getCons() instanceof SublistCons)) //(ConsPointer)currentConsPointer.car()).getCons() == null + { + break; + } + + //GoSub. + currentConsPointer.goSub(aStackTop, aEnvironment); + + if(currentConsPointer.getCons() instanceof SublistCons) + { + sequenceStack.push(new ConsXHolder(currentConsPointer.getCons(), currentNode)); //currentNode.getX())); + }//end if. + + ConsNode newNode = new ConsNode(); + + if(! (currentConsPointer.getCons() instanceof SublistCons)) + { + String name = currentConsPointer.getCons().toString(); + newNode.setName(name); + } + else + { + newNode.setName(sublistName); + } + + //newNode.setX(currentNode.getX()); //currentNode.getX()); + + currentNode.setCar(newNode); + + currentNode = newNode; + + levelQueue.add(currentNode); + + }//end else. + + }//end goNext while. + + }//end while. + + + int y = startY; + + while(levelQueue.peek() != null) + { + ConsNode consNode = levelQueue.poll(); + consNode.setY(y += yStep); + + if(consNode.getY() > largestY) + { + largestY = consNode.getY(); + } + } + + }//end else. + + + } catch (Exception e) { + e.printStackTrace(); + + + } + + + } + + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + + g2d.setStroke(new BasicStroke((float) (2), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + g2d.setColor(Color.black); + g2d.setBackground(Color.white); + ScaledGraphics sg = new ScaledGraphics(g2d); + sg.setLineThickness(1); + sg.setViewScale(viewScale); + int height = ScaledGraphics.fontForSize(1); + sg.setFontSize(height); + + if(headNode != null) + { + drawBox(headNode, 0, sg); + + }//end if + + if(paintedOnce == false) + { + super.revalidate(); + + paintedOnce = true; + } + + }//end method. + + private void drawBox(ConsNode currentNode, double previousRightX, ScaledGraphics sg) + { + + int height = 25; + int xGap = 10; + int yGap = 10; + int textOffset = 0; + + + + if(currentNode == null) + { + return; + } + + + double x = previousRightX + xGap; + + int y = currentNode.getY() * (height + yGap) + yGap; + + String name = currentNode.getName() ; + double textWidth = sg.getScaledTextWidth(name); + + if(textWidth < 25) + { + textOffset = ((int) (25 - textWidth)/2) + 1; + textWidth = 25; + } + else + { + textOffset = 3; + textWidth += 5; + } + + double boxWidth = textWidth + 25; + + + sg.drawRectangle(x, y, boxWidth, height); + + sg.drawLine(x + textWidth, y, x + textWidth, y + height); + + + if(name != null) + { + sg.setColor(Color.BLUE); + sg.drawscaledText(name, x + textOffset, y + 15, 1.0); + sg.setColor(Color.BLACK); + } + + if(currentNode.getCdr() != null) + { + currentNode.getCdr().setY(currentNode.getY()); + + sg.drawLine(x + boxWidth - 12, y + 12, x + boxWidth + xGap , y + 12); + } + + + if(largestX < (int) (x + boxWidth + xGap)) + { + largestX = (int) (x + boxWidth + xGap); + } + + + + if(currentNode.getCar() != null) + { + sg.drawLine(x + 13, y + 12, x + 13 , currentNode.getCar().getY() * (height + yGap) + yGap); + } + + drawBox(currentNode.getCdr(), x + boxWidth, sg); + + drawBox(currentNode.getCar(), previousRightX, sg); + + + }//end method. + + public Dimension getPreferredSize() { + if(paintedOnce) + { + Bounds maxBounds = new Bounds(0, (largestY + 1) * (25 + 10) + 10, 0, largestX); + + Dimension scaledDimension = maxBounds.getScaledDimension(this.viewScale); + + return scaledDimension; + } + else + { + return new Dimension(700,600); + } + + }//end method. + + public void setViewScale(double viewScale) { + this.viewScale = viewScale; + this.revalidate(); + this.repaint(); + } + + + private class ConsNode { + + private ConsNode car; + private ConsNode cdr; + private String name = ""; + private int y; + + public ConsNode() { + } + + + public ConsNode getCar() { + return car; + } + + public void setCar(ConsNode down) { + this.car = down; + } + + public ConsNode getCdr() { + return cdr; + } + + public void setCdr(ConsNode right) { + this.cdr = right; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + }//end class. + + + private class ConsXHolder { + + private Cons cons; + private ConsNode consNode; + + public ConsXHolder(Cons cons, ConsNode consNode){ + this.cons = cons; + + this.consNode = consNode; + } + + public Cons getCons() { + return cons; + } + + public void setCons(Cons cons) { + this.cons = cons; + } + + public ConsNode getConsNode() { + return consNode; + } + + public void setConsNode(ConsNode consNode) { + this.consNode = consNode; + } + + + + }//end class. + + + /* + Drawing Lists as Box Diagrams (from http://www.gnu.org/s/emacs/manual/html_node/elisp/Box-Diagrams.html) + + A list can be illustrated by a diagram in which the cons cells are shown as pairs of boxes, like dominoes. (The Lisp reader cannot read such an illustration; unlike the textual notation, which can be understood by both humans and computers, the box illustrations can be understood only by humans.) This picture represents the three-element list (rose violet buttercup): + + --- --- --- --- --- --- + | | |--> | | |--> | | |--> nil + --- --- --- --- --- --- + | | | + | | | + --> rose --> violet --> buttercup + + In this diagram, each box represents a slot that can hold or refer to any Lisp object. Each pair of boxes represents a cons cell. Each arrow represents a reference to a Lisp object, either an atom or another cons cell. + + In this example, the first box, which holds the car of the first cons cell, refers to or holds rose (a symbol). The second box, holding the cdr of the first cons cell, refers to the next pair of boxes, the second cons cell. The car of the second cons cell is violet, and its cdr is the third cons cell. The cdr of the third (and last) cons cell is nil. + + Here is another diagram of the same list, (rose violet buttercup), sketched in a different manner: + + --------------- ---------------- ------------------- + | car | cdr | | car | cdr | | car | cdr | + | rose | o-------->| violet | o-------->| buttercup | nil | + | | | | | | | | | + --------------- ---------------- ------------------- + + A list with no elements in it is the empty list; it is identical to the symbol nil. In other words, nil is both a symbol and a list. + + Here is the list (A ()), or equivalently (A nil), depicted with boxes and arrows: + + --- --- --- --- + | | |--> | | |--> nil + --- --- --- --- + | | + | | + --> A --> nil + + Here is a more complex illustration, showing the three-element list, ((pine needles) oak maple), the first element of which is a two-element list: + + --- --- --- --- --- --- + | | |--> | | |--> | | |--> nil + --- --- --- --- --- --- + | | | + | | | + | --> oak --> maple + | + | --- --- --- --- + --> | | |--> | | |--> nil + --- --- --- --- + | | + | | + --> pine --> needles + + The same list represented in the second box notation looks like this: + + -------------- -------------- -------------- + | car | cdr | | car | cdr | | car | cdr | + | o | o------->| oak | o------->| maple | nil | + | | | | | | | | | | + -- | --------- -------------- -------------- + | + | + | -------------- ---------------- + | | car | cdr | | car | cdr | + ------>| pine | o------->| needles | nil | + | | | | | | + -------------- ---------------- + */ +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/MathOutputLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/MathOutputLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/MathOutputLine.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/MathOutputLine.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.ui.gui.worksheets; - -import java.awt.Graphics; - -public abstract class MathOutputLine { - - public abstract void draw(Graphics g, int x, int y); - - public abstract int height(Graphics g); -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/Grapher.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/Grapher.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/Grapher.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/Grapher.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,318 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.mathoutputlines; + +import java.awt.*; + +public class Grapher { + + public double xmin, ymin, xmax, ymax; + String iCallList; + String execList; + String token; + int graphx = 0; + int graphy = 0; + int graphWidth = 10; + int graphHeight = 10; + int axesFontHeight = 12; + FontMetrics fontMetrics = null; + int exampleWidth = 48; + + public Grapher(String aCallList) { + xmin = 1e200; + ymin = 1e200; + xmax = -xmin; + ymax = -ymin; + iCallList = aCallList; + runCallList(null); + } + + void nextToken() { + int startPos = 0; + while (startPos < execList.length() && execList.charAt(startPos) == ' ') { + startPos++; + } + int endPos = startPos; + while (endPos < execList.length() && execList.charAt(endPos) != ' ') { + endPos++; + } + token = execList.substring(startPos, endPos); + execList = execList.substring(endPos); + } + + void runCallList(Graphics g) { + try { + Graphics2D g2d = null; + if (g != null) { + if (g instanceof Graphics2D) { + g2d = (Graphics2D) g; + } + } + + execList = iCallList; + nextToken(); + while (token.length() > 0) { + if (token.equals("lines2d")) { + int i; + nextToken(); + int nr = Integer.parseInt(token); + nextToken(); + double x2, y2 = 0; + x2 = Float.parseFloat(token); + nextToken(); + y2 = Float.parseFloat(token); + if (g == null) { + if (xmin > x2) { + xmin = x2; + } + if (xmax < x2) { + xmax = x2; + } + if (ymin > y2) { + ymin = y2; + } + if (ymax < y2) { + ymax = y2; + } + } + double x1, y1; + for (i = 1; i < nr; i++) { + x1 = x2; + y1 = y2; + nextToken(); + x2 = Float.parseFloat(token); + nextToken(); + y2 = Float.parseFloat(token); + if (g == null) { + if (xmin > x2) { + xmin = x2; + } + if (xmax < x2) { + xmax = x2; + } + if (ymin > y2) { + ymin = y2; + } + if (ymax < y2) { + ymax = y2; + } + } + if (g != null) { + int xPix1 = (int) (graphx + graphWidth * (x1 - xmin) / (xmax - xmin)); + int yPix1 = (int) (graphy + graphHeight * (1.0 - (y1 - ymin) / (ymax - ymin))); + int xPix2 = (int) (graphx + graphWidth * (x2 - xmin) / (xmax - xmin)); + int yPix2 = (int) (graphy + graphHeight * (1.0 - (y2 - ymin) / (ymax - ymin))); + g.drawLine(xPix1, yPix1, xPix2, yPix2); + } + } + } else if (token.equals("pencolor")) { + nextToken(); + int red = Integer.parseInt(token); + nextToken(); + int green = Integer.parseInt(token); + nextToken(); + int blue = Integer.parseInt(token); + if (g != null) { + g.setColor(new Color(red, green, blue)); + } + } else if (token.equals("pensize")) { + nextToken(); + float width = Float.parseFloat(token); + if (g != null) { + if (g2d != null) { + g2d.setStroke(new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + } + } + } else { + //TODO raise an exception here + return; + } + nextToken(); + } + } catch (Exception e) { + //TODO handle exception here + } + } + + void determineGraphBounds(int xleft, int ytop, Dimension d) { + if (fontMetrics != null) { + exampleWidth = fontMetrics.stringWidth("100000"); + } + graphx = xleft + exampleWidth; + graphy = ytop + axesFontHeight; + graphWidth = d.width - (3 * exampleWidth) / 2; + graphHeight = d.height - 3 * axesFontHeight; + } + + public void paint(Graphics g, int xleft, int ytop, Dimension d) { + Shape clip = g.getClip(); + Rectangle r = clip.getBounds(); + Graphics2D g2d = null; + if (g instanceof Graphics2D) { + g2d = (Graphics2D) g; + } + if (g2d != null) { + g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + } + int clipHeight = d.height; + if (ytop + clipHeight > r.y + r.height) { + clipHeight = r.y + r.height - ytop; + } + g.setClip(xleft, ytop, d.width, clipHeight); + + // Erase the previous image + g.setColor(Color.white); + g.fillRect(xleft, ytop, d.width, d.height); + + Font font; + font = new Font("Verdana", Font.PLAIN, axesFontHeight); + g.setFont(font); + fontMetrics = g.getFontMetrics(font); + determineGraphBounds(xleft, ytop, d); + + Color grey = new Color(164, 164, 164); + + double x, y; + + PlotRange xRange = new PlotRange(xmin, xmax, d.width / ((3 * exampleWidth) / 2)); + int xtick = ((int) (xmin / xRange.TickSize() - 1)); + if (xRange.TickSize() * xtick < xmin) { + xtick = xtick + 1; + } + double xstart = xRange.TickSize() * xtick; + { + g.setColor(Color.black); + for (x = xstart; x <= xmax; x += xRange.TickSize()) { + int xPix = (int) (graphx + graphWidth * (x - xmin) / (xmax - xmin)); + g.setColor(grey); + g.drawLine(xPix, graphy, xPix, graphy + graphHeight); + g.setColor(Color.black); + String num = xRange.Format(xtick); + int numWidth = fontMetrics.stringWidth(num); + g.drawString(num, xPix - numWidth / 2, graphy + graphHeight + fontMetrics.getAscent()); + xtick++; + } + + PlotRange yRange = new PlotRange(ymin, ymax, d.height / (axesFontHeight * 2)); + int ytick = ((int) (ymin / yRange.TickSize() - 1)); + if (yRange.TickSize() * ytick < ymin) { + ytick = ytick + 1; + } + double ystart = yRange.TickSize() * ytick; + for (y = ystart; y <= ymax; y += yRange.TickSize()) { + int yPix = (int) (graphy + graphHeight * (ymax - y) / (ymax - ymin)); + g.setColor(grey); + g.drawLine(graphx, yPix, graphx + graphWidth, yPix); + g.setColor(Color.black); + String num = yRange.Format(ytick); + int numWidth = fontMetrics.stringWidth(num); + g.drawString(num, graphx - numWidth - 8, yPix + fontMetrics.getAscent() - (axesFontHeight) / 2); + ytick++; + } + } + + int graphClipHeight = graphHeight; + if (graphy + graphClipHeight > r.y + r.height) { + graphClipHeight = r.y + r.height - graphy; + } + + g.setClip(graphx, graphy, graphWidth, graphClipHeight); + runCallList(g); + g.setClip(xleft, ytop, d.width, clipHeight); + g.setColor(Color.black); + if (g2d != null) { + g2d.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + } + g.drawRect(graphx, graphy, graphWidth, graphHeight); + g.setClip(clip); + } + + /* + * Determine the ticks of the graph. The calling routine should first determine the minimum and maximum values, and + * the number of steps (based on size of the axis to draw relative to font size). + * + * Steps will always be m*10^n, for some suitable n, with m either 1, 2 or 5. + */ + class PlotRange { + + public PlotRange(double aMinValue, double aMaxValue, int aMaxSteps) { + iMinValue = aMinValue; + iMaxValue = aMaxValue; + iMaxSteps = aMaxSteps; + + //TODO handle zero length range + double range = aMaxValue - aMinValue; + iN = (int) (Math.log(range) / Math.log(10) - 1); + iN = iN - 1; + iStep = 1; + for (;;) { + double tickSize = TickSize(); + int nrSteps = (int) (range / tickSize); + if (nrSteps <= aMaxSteps) { + break; + } + switch (iStep) { + case 1: + iStep = 2; + break; + case 2: + iStep = 5; + break; + case 5: + iN++; + iStep = 1; + break; + } + } + } + + public double TickSize() { + return iStep * Math.pow(10, iN); + } + + public String Format(int tick) { + String result = ""; + int fct = tick * iStep; + if (iN >= 0 && iN < 3) { + if (iN > 0) { + fct = fct * 10; + } + if (iN > 1) { + fct = fct * 10; + } + result = "" + fct; + } else { + int n = iN; + if (fct == 10 * (fct / 10)) { + fct /= 10; + n += 1; + } + String ex = ""; + if (n != 0 && tick != 0) { + ex = "e" + n; + } + result = "" + fct + ex; + } + return result; + } + double iMinValue; + double iMaxValue; + int iMaxSteps; + public int iN; + public int iStep; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/ImageLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/ImageLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/ImageLine.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/ImageLine.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,46 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.mathoutputlines; + +import java.applet.Applet; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; + +public class ImageLine extends MathOutputLine { + + Color bkColor = new Color(255, 255, 255); //TODO:tk:This variable was originally in ConsoleApplet. + + public ImageLine(Image aImage, Applet aApplet) { + iImage = aImage; + iApplet = aApplet; + } + + public void draw(Graphics g, int x, int y) { + if (iImage != null) { + Dimension d = iApplet.getSize(); + g.drawImage(iImage, (d.width - iImage.getWidth(iApplet)) / 2, y, bkColor, iApplet); + } + } + + public int height(Graphics g) { + return iImage.getHeight(iApplet); + } + Image iImage; + Applet iApplet; +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/MathOutputLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/MathOutputLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/MathOutputLine.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/MathOutputLine.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,27 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.mathoutputlines; + +import java.awt.Graphics; + +public abstract class MathOutputLine { + + public abstract void draw(Graphics g, int x, int y); + + public abstract int height(Graphics g); +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedFormulaLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedFormulaLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedFormulaLine.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedFormulaLine.java 2010-02-26 02:36:14.000000000 +0000 @@ -0,0 +1,73 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.mathoutputlines; + +import org.mathpiper.ui.gui.worksheets.latexparser.TexParser; +import org.mathpiper.ui.gui.worksheets.*; +import org.mathpiper.ui.gui.worksheets.symbolboxes.ScaledGraphics; +import org.mathpiper.ui.gui.worksheets.symbolboxes.SymbolBox; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import org.mathpiper.ui.gui.worksheets.symbolboxes.Position; + +public class PromptedFormulaLine extends MathOutputLine { + + SymbolBox sBoxExpression; + + public PromptedFormulaLine(int aIndent, String aPrompt, Font aPromptFont, Color aPromptColor, String aLine) { + iIndent = aIndent; + iPrompt = aPrompt; + iPromptFont = aPromptFont; + iPromptColor = aPromptColor; + + TexParser parser = new TexParser(); + sBoxExpression = parser.parse(aLine); + } + + public void draw(Graphics g, int x, int y) { + int hgt = height(g); + { + g.setColor(iPromptColor); + g.setFont(iPromptFont); + FontMetrics fontMetrics = g.getFontMetrics(); + g.drawString(iPrompt, x, y + fontMetrics.getAscent() + (hgt - fontMetrics.getHeight()) / 2); + } + + g.setColor(Color.black); + ScaledGraphics sg = new ScaledGraphics(g); + sg.setLineThickness(0); + sBoxExpression.calculatePositions(sg, 3, new Position(x + iIndent, (y + sBoxExpression.getCalculatedAscent() + 10))); + sBoxExpression.render(sg); + } + + public int height(Graphics g) { + if (height == -1) { + ScaledGraphics sg = new ScaledGraphics(g); + sBoxExpression.calculatePositions(sg, 3, new Position(0, 0)); + height = (int) sBoxExpression.getDimension().height + 20; + } + return height; + } + int height = -1; + int iIndent; + private String iPrompt; + private Font iPromptFont; + private Color iPromptColor; +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedGraph2DLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedGraph2DLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedGraph2DLine.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedGraph2DLine.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,50 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.mathoutputlines; + +import org.mathpiper.ui.gui.worksheets.*; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; + +public class PromptedGraph2DLine extends MathOutputLine { + + public PromptedGraph2DLine(int aIndent, String aPrompt, Font aPromptFont, Color aPromptColor, String aLine) { + iIndent = aIndent; + iPrompt = aPrompt; + iPromptFont = aPromptFont; + iPromptColor = aPromptColor; + iGrapher = new Grapher(aLine); + } + Grapher iGrapher; + + public void draw(Graphics g, int x, int y) { + iGrapher.paint(g, x, y, size); + } + + public int height(Graphics g) { + return size.height; + } + Dimension size = new Dimension(320, 240); + int iIndent; + private String iPrompt; + private Font iPromptFont; + private Color iPromptColor; +} + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedStringLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedStringLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedStringLine.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/PromptedStringLine.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,68 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.mathoutputlines; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; + +public class PromptedStringLine extends MathOutputLine { + + public PromptedStringLine(int aIndent, String aPrompt, String aText, Font aPromptFont, Font aFont, Color aPromptColor, Color aColor) { + iIndent = aIndent; + iPrompt = aPrompt; + iText = aText; + iPromptFont = aPromptFont; + iFont = aFont; + iPromptColor = aPromptColor; + iColor = aColor; + } + + public void draw(Graphics g, int x, int y) { + { + g.setColor(iPromptColor); + g.setFont(iPromptFont); + FontMetrics fontMetrics = g.getFontMetrics(); + g.drawString(iPrompt, x, y + fontMetrics.getAscent()); + if (iIndent != 0) { + x += iIndent; + } else { + x += fontMetrics.stringWidth(iPrompt); + } + } + { + g.setColor(iColor); + g.setFont(iFont); + FontMetrics fontMetrics = g.getFontMetrics(); + g.drawString(iText, x, y + fontMetrics.getAscent()); + } + } + + public int height(Graphics g) { + g.setFont(iFont); + FontMetrics fontMetrics = g.getFontMetrics(); + return fontMetrics.getHeight(); + } + int iIndent; + private String iPrompt; + private String iText; + private Font iPromptFont; + private Font iFont; + private Color iPromptColor; + private Color iColor; +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/StringLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/StringLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/StringLine.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/mathoutputlines/StringLine.java 2010-01-22 08:53:44.000000000 +0000 @@ -0,0 +1,48 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} + +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.mathoutputlines; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; + +public class StringLine extends MathOutputLine { + + StringLine(String aText, Font aFont, Color aColor) { + iText = aText; + iFont = aFont; + iColor = aColor; + } + + public void draw(Graphics g, int x, int y) { + g.setColor(iColor); + g.setFont(iFont); + FontMetrics fontMetrics = g.getFontMetrics(); + g.drawString(iText, x, y + fontMetrics.getHeight()); + } + + public int height(Graphics g) { + g.setFont(iFont); + FontMetrics fontMetrics = g.getFontMetrics(); + return fontMetrics.getHeight(); + } + private String iText; + private Font iFont; + private Color iColor; +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/MathPanelController.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/MathPanelController.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/MathPanelController.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/MathPanelController.java 2010-03-13 07:56:22.000000000 +0000 @@ -0,0 +1,69 @@ +package org.mathpiper.ui.gui.worksheets; + +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.mathpiper.ui.gui.worksheets.symbolboxes.SymbolBox; + +public class MathPanelController extends JPanel implements ChangeListener, ItemListener { + + private JSlider scaleSlider; + private ViewPanel viewPanel; + + public MathPanelController(ViewPanel viewPanel, double initialValue) { + super(); + this.viewPanel = viewPanel; + + scaleSlider = new JSlider(JSlider.HORIZONTAL, 1, 100, (int) (initialValue*10)); + scaleSlider.addChangeListener(this); + + //Turn on labels at major tick marks. + //framesPerSecond.setMajorTickSpacing(10); + //framesPerSecond.setMinorTickSpacing(1); + //framesPerSecond.setPaintTicks(true); + scaleSlider.setPaintLabels(true); + + this.add(new JLabel("Adjust Scale")); + this.add(scaleSlider); + + JCheckBox drawBoundingBoxCheckBox = new JCheckBox("Draw Bounding Boxes"); + + drawBoundingBoxCheckBox.setSelected(SymbolBox.isDrawBoundingBox()); + + drawBoundingBoxCheckBox.addItemListener(this); + + this.add(drawBoundingBoxCheckBox); + + + } + + public void stateChanged(ChangeEvent e) { + + JSlider source = (JSlider) e.getSource(); + //if (!source.getValueIsAdjusting()) { + int intValue = (int) source.getValue(); + double doubleValue = intValue / 10.0; + //System.out.println("XXX: " + doubleValue); + viewPanel.setViewScale(doubleValue); + viewPanel.repaint(); + + //} + }//end method. + + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + SymbolBox.setDrawBoundingBox(true); + viewPanel.repaint(); + + } else { + SymbolBox.setDrawBoundingBox(false); + viewPanel.repaint(); + } + + }//end method. + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/MathPanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/MathPanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/MathPanel.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/MathPanel.java 2010-04-02 07:38:34.000000000 +0000 @@ -0,0 +1,190 @@ + + +package org.mathpiper.ui.gui.worksheets; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import javax.swing.JPanel; +import org.mathpiper.ui.gui.worksheets.symbolboxes.Bounds; +import org.mathpiper.ui.gui.worksheets.symbolboxes.Position; +import org.mathpiper.ui.gui.worksheets.symbolboxes.ScaledGraphics; +import org.mathpiper.ui.gui.worksheets.symbolboxes.SymbolBox; + + public class MathPanel extends JPanel implements ViewPanel, MouseListener + { + protected SymbolBox symbolBox; + protected double viewScale = 1; + private boolean paintedOnce = false; + private int xOffset = 0; + private int yOffset = 0; + + public MathPanel(SymbolBox symbolBox, double viewScale) + { + this.symbolBox = symbolBox; + this.setOpaque(true); + this.viewScale = viewScale; + this.setBackground(Color.white); + + this.addMouseListener(this); + + + //Bounds bounds = search(symbolBox); + + //xOffset = Math.abs((int) bounds.left); + //yOffset = Math.abs((int) bounds.top); + + + + } + + + public void paint(Graphics g) + { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + + g2d.setStroke(new BasicStroke((float) (2), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + g2d.setColor(Color.black); + g2d.setBackground(Color.white); + ScaledGraphics sg = new ScaledGraphics(g2d); + sg.setLineThickness(0); + sg.setViewScale(viewScale); + + //int iIndent = 0; + double calculatedAscent = symbolBox.getCalculatedAscent(); + + if(paintedOnce == false) + { + symbolBox.calculatePositions(sg, 3, new Position(0, 0)); + Bounds bounds = search(symbolBox); + + xOffset = Math.abs((int) bounds.left); + yOffset = Math.abs((int) bounds.top); + + super.revalidate(); + + paintedOnce = true; + + }//end if. + + symbolBox.calculatePositions(sg, 3, new Position(xOffset, yOffset)); + SymbolBox.setSequence(1); + symbolBox.render(sg); + + } + + + public Dimension getPreferredSize() { + if(paintedOnce) + { + Bounds maxBounds = search(symbolBox); + + //System.out.println(maxBounds.toString()); + + Dimension scaledDimension = maxBounds.getScaledDimension(this.viewScale); + + return scaledDimension; + } + else + { + return new Dimension(700,600); + } + + }//end method. + + + public void setViewScale(double viewScale) + { + this.viewScale = viewScale; + this.revalidate(); + this.repaint(); + } + + + public Bounds search(SymbolBox currentNode) + { + Bounds myBounds = currentNode.getScaledBounds(viewScale); + + double topMost = myBounds.getTop(); + double bottomMost = myBounds.getBottom(); + double leftMost = myBounds.getLeft(); + double rightMost = myBounds.getRight(); + /* + double topMost = currentNode.getCalculatedPosition().getY() - currentNode.getDimension().getHeight() ; + double bottomMost = currentNode.getCalculatedPosition().getY(); + double leftMost = currentNode.getCalculatedPosition().getX(); + double rightMost = currentNode.getCalculatedPosition().getX() + currentNode.getDimension().getWidth(); + */ + + SymbolBox[] children = currentNode.getChildren(); + + if(children.length != 0) + { + for(SymbolBox child:children) + { + if(child != null) + { + Bounds bounds = search(child); + + if(bounds.getTop() < topMost) + { + topMost = bounds.getTop(); + } + + if(bounds.getBottom() > bottomMost) + { + bottomMost = bounds.getBottom(); + } + + if(bounds.getLeft() < leftMost) + { + leftMost = bounds.getLeft(); + } + + if(bounds.getRight() > rightMost) + { + rightMost = bounds.getRight(); + } + + //return new Bounds(topMost, bottomMost, leftMost, rightMost); + } + } + + }//end if. + + return new Bounds(topMost, bottomMost, leftMost, rightMost); + }//end method. + + + public void mouseClicked(MouseEvent me) + { + System.out.println("X: " + me.getX() + " Y: " + me.getY()); + } + + public void mouseEntered(MouseEvent me) + { + } + + public void mouseExited(MouseEvent me) + { + } + + public void mousePressed(MouseEvent me) + { + } + + public void mouseReleased(MouseEvent me) + { + } + + + + + }//end class. \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/PromptedFormulaLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/PromptedFormulaLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/PromptedFormulaLine.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/PromptedFormulaLine.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; - - class PromptedFormulaLine extends MathOutputLine - { - - PromptedFormulaLine(int aIndent, String aPrompt, Font aPromptFont, Color aPromptColor, String aLine) - { - iIndent = aIndent; - iPrompt = aPrompt; - iPromptFont = aPromptFont; - iPromptColor = aPromptColor; - - TexParser parser = new TexParser(); - expression = parser.parse(aLine); - } - SBox expression; - - public void draw(Graphics g, int x, int y) - { - int hgt = height(g); - { - g.setColor(iPromptColor); - g.setFont(iPromptFont); - FontMetrics fontMetrics = g.getFontMetrics(); - g.drawString(iPrompt, x, y + fontMetrics.getAscent() + (hgt - fontMetrics.getHeight()) / 2); - } - - g.setColor(Color.black); - GraphicsPrimitives gp = new GraphicsPrimitives(g); - gp.setLineThickness(0); - expression.calculatePositions(gp, 3, new java.awt.Point(x + iIndent, y + expression.getCalculatedAscent() + 10)); - expression.render(gp); - } - - public int height(Graphics g) - { - if (height == -1) - { - GraphicsPrimitives gp = new GraphicsPrimitives(g); - expression.calculatePositions(gp, 3, new java.awt.Point(0, 0)); - height = expression.getDimension().height + 20; - } - return height; - } - int height = -1; - int iIndent; - private String iPrompt; - private Font iPromptFont; - private Color iPromptColor; - } - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/PromptedGraph2DLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/PromptedGraph2DLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/PromptedGraph2DLine.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/PromptedGraph2DLine.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.ui.gui.worksheets; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; - -class PromptedGraph2DLine extends MathOutputLine { - - PromptedGraph2DLine(int aIndent, String aPrompt, Font aPromptFont, Color aPromptColor, String aLine) { - iIndent = aIndent; - iPrompt = aPrompt; - iPromptFont = aPromptFont; - iPromptColor = aPromptColor; - iGrapher = new Grapher(aLine); - } - Grapher iGrapher; - - public void draw(Graphics g, int x, int y) { - iGrapher.paint(g, x, y, size); - } - - public int height(Graphics g) { - return size.height; - } - Dimension size = new Dimension(320, 240); - int iIndent; - private String iPrompt; - private Font iPromptFont; - private Color iPromptColor; -} - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/PromptedStringLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/PromptedStringLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/PromptedStringLine.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/PromptedStringLine.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.ui.gui.worksheets; - -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; - -class PromptedStringLine extends MathOutputLine { - - PromptedStringLine(int aIndent, String aPrompt, String aText, Font aPromptFont, Font aFont, Color aPromptColor, Color aColor) { - iIndent = aIndent; - iPrompt = aPrompt; - iText = aText; - iPromptFont = aPromptFont; - iFont = aFont; - iPromptColor = aPromptColor; - iColor = aColor; - } - - public void draw(Graphics g, int x, int y) { - { - g.setColor(iPromptColor); - g.setFont(iPromptFont); - FontMetrics fontMetrics = g.getFontMetrics(); - g.drawString(iPrompt, x, y + fontMetrics.getAscent()); - if (iIndent != 0) { - x += iIndent; - } else { - x += fontMetrics.stringWidth(iPrompt); - } - } - { - g.setColor(iColor); - g.setFont(iFont); - FontMetrics fontMetrics = g.getFontMetrics(); - g.drawString(iText, x, y + fontMetrics.getAscent()); - } - } - - public int height(Graphics g) { - g.setFont(iFont); - FontMetrics fontMetrics = g.getFontMetrics(); - return fontMetrics.getHeight(); - } - int iIndent; - private String iPrompt; - private String iText; - private Font iPromptFont; - private Font iFont; - private Color iPromptColor; - private Color iColor; -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/SBoxBuilder.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/SBoxBuilder.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/SBoxBuilder.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/SBoxBuilder.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,1093 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -//}}} -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.ui.gui.worksheets; - -import java.awt.*; - - -public class SBoxBuilder -{ - - SBox[] stack = new SBox[1024]; - int stackDepth = 0; - - static int fontForSize(int aSize) - { - - if (aSize > 3) - aSize = 3; - - if (aSize < 0) - aSize = 0; - - switch (aSize) - { - - case 0: - return 6; - - case 1: - return 8; - - case 2: - return 12; - - case 3: - return 16; - - default: - return 16; - } - } - - public SBox pop() - { - stackDepth--; - - SBox result = stack[stackDepth]; - - return result; - } - - void push(SBox aSbox) - { - stack[stackDepth] = aSbox; - stackDepth++; - } - - public int stackDepth() - { - - return stackDepth; - } - - public void process(String aType) - { - - if (aType.equals("=") || aType.equals("\\neq") || aType.equals("+") || aType.equals(",") || aType.equals("\\wedge") || aType.equals("\\vee") || aType.equals("<") || aType.equals(">") || aType.equals("<=") || aType.equals(">=")) - { - - SBox right = pop(); - SBox left = pop(); - push(new SBoxInfixOperator(left, new SBoxSymbolName(aType), right)); - } - else if (aType.equals("/")) - { - - SBox denom = pop(); - SBox numer = pop(); - push(new SBoxDivisor(numer, denom)); - } - else if (aType.equals("-/2")) - { - - SBox right = pop(); - SBox left = pop(); - push(new SBoxInfixOperator(left, new SBoxSymbolName("-"), right)); - } - else if (aType.equals("-/1")) - { - - SBox right = pop(); - push(new SBoxPrefixOperator(new SBoxSymbolName("-"), right)); - } - else if (aType.equals("~")) - { - - SBox right = pop(); - push(new SBoxPrefixOperator(new SBoxSymbolName("~"), right)); - } - else if (aType.equals("!")) - { - - SBox left = pop(); - push(new SBoxPrefixOperator(left, new SBoxSymbolName("!"))); - } - else if (aType.equals("*")) - { - - SBox right = pop(); - SBox left = pop(); - push(new SBoxInfixOperator(left, new SBoxSymbolName(""), right)); - } - else if (aType.equals("[func]")) - { - - SBox right = pop(); - SBox left = pop(); - push(new SBoxPrefixOperator(left, right)); - } - else if (aType.equals("^")) - { - - SBox right = pop(); - SBox left = pop(); - boolean appendToExisting = false; - - if (left instanceof SBoxSubSuperfix) - { - - SBoxSubSuperfix sbox = (SBoxSubSuperfix)left; - - if (!sbox.hasSuperfix()) - appendToExisting = true; - } - - if (appendToExisting) - { - - SBoxSubSuperfix sbox = (SBoxSubSuperfix)left; - sbox.setSuperfix(right); - push(sbox); - } - else - { - push(new SBoxSubSuperfix(left, right, null)); - } - } - else if (aType.equals("_")) - { - - SBox right = pop(); - SBox left = pop(); - - if (left instanceof SBoxSubSuperfix) - { - - SBoxSubSuperfix sbox = (SBoxSubSuperfix)left; - sbox.setSubfix(right); - push(sbox); - } - else - { - push(new SBoxSubSuperfix(left, null, right)); - } - } - else if (aType.equals("[sqrt]")) - { - - SBox left = pop(); - push(new SBoxSquareRoot(left)); - } - else if (aType.equals("[sum]")) - { - push(new SBoxSum()); - } - else if (aType.equals("[int]")) - { - push(new SBoxInt()); - } - else if (aType.equals("[roundBracket]")) - { - - SBox left = pop(); - push(new SBoxBracket(left, "(", ")")); - } - else if (aType.equals("[squareBracket]")) - { - - SBox left = pop(); - push(new SBoxBracket(left, "[", "]")); - } - else if (aType.equals("[accoBracket]")) - { - - SBox left = pop(); - push(new SBoxBracket(left, "{", "}")); - } - else if (aType.equals("[grid]")) - { - - SBox widthBox = pop(); - SBox heightBox = pop(); - int width = Integer.parseInt(((SBoxSymbolName)widthBox).iSymbol); - int height = Integer.parseInt(((SBoxSymbolName)heightBox).iSymbol); - SBoxGrid grid = new SBoxGrid(width, height); - int i; - int j; - - for (j = height - 1; j >= 0; j--) - { - - for (i = width - 1; i >= 0; i--) - { - - SBox value = pop(); - grid.SetSBox(i, j, value); - } - } - - push(grid); - } - else - { - push(new SBoxSymbolName(aType)); - } - } - - public void processLiteral(String aExpression) - { - push(new SBoxSymbolName(aExpression)); - } - - class SBoxSymbolName - extends SBox - { - - public String iSymbol; - - SBoxSymbolName(String aSymbol) - { - iSymbol = aSymbol; - - if (iSymbol.indexOf("\\") == 0) - { - - if (iSymbol.equals("\\pi")) - { - } - else if (iSymbol.equals("\\infty")) - { - } - else if (iSymbol.equals("\\cdot")) - { - } - else if (iSymbol.equals("\\wedge")) - { - } - else if (iSymbol.equals("\\vee")) - { - } - else if (iSymbol.equals("\\neq")) - { - } - else - { - iSymbol = iSymbol.substring(1); - } - } - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - - int height = SBoxBuilder.fontForSize(aSize); - g.setFontSize(height); - iSize = aSize; - iPosition = aPosition; - - if (iSymbol.equals("\\pi") || iSymbol.equals("\\wedge") || iSymbol.equals("\\vee")) - { - iDimension = new Dimension(g.textWidth("M"), height); - iAscent = g.getAscent(); - } - else if (iSymbol.equals("\\neq")) - { - iDimension = new Dimension(g.textWidth("="), height); - iAscent = g.getAscent(); - } - else if (iSymbol.equals("\\infty")) - { - iDimension = new Dimension(g.textWidth("oo"), height); - iAscent = g.getAscent(); - } - else if (iSymbol.equals("\\cdot")) - { - iDimension = new Dimension(g.textWidth("."), height); - iAscent = g.getAscent(); - } - else - { - iAscent = g.getAscent(); - iDimension = new Dimension(g.textWidth(iSymbol), height); - } - } - - public void render(GraphicsPrimitives g) - { - - if (iSymbol.equals("\\pi")) - { - - double deltax = 0.15 * iDimension.width; - double deltay = 0.2 * iDimension.height; - g.drawLine((int)(iPosition.x + 1 * deltax), (int)(iPosition.y - iAscent + 2 * deltay), (int)(iPosition.x + iDimension.width - 1 * deltax), (int)(iPosition.y - iAscent + 2 * deltay)); - g.drawLine((int)(iPosition.x + 2 * deltax), (int)(iPosition.y - iAscent + 2 * deltay), (int)(iPosition.x + 2 * deltax), (int)(iPosition.y - iAscent + iDimension.height + 0 * deltay)); - g.drawLine((int)(iPosition.x + iDimension.width - 2 * deltax), (int)(iPosition.y - iAscent + 2 * deltay), (int)(iPosition.x + iDimension.width - 2 * deltax), (int)(iPosition.y - iAscent + iDimension.height + 0 * deltay)); - } - else if (iSymbol.equals("\\wedge") || iSymbol.equals("\\vee")) - { - - double deltax = 0.15 * iDimension.width; - double deltay = 0.2 * iDimension.height; - int ytip = (int)(iPosition.y - iAscent + iDimension.height + 0 * deltay); - int ybase = (int)(iPosition.y - iAscent + 2 * deltay); - - if (iSymbol.equals("\\wedge")) - { - - int swap = ytip; - ytip = ybase; - ybase = swap; - } - - g.drawLine((int)(iPosition.x + 1 * deltax), ybase, iPosition.x + iDimension.width / 2, ytip); - g.drawLine((int)(iPosition.x + iDimension.width - 1 * deltax), ybase, iPosition.x + iDimension.width / 2, ytip); - } - else if (iSymbol.equals("\\neq")) - { - g.setFontSize(SBoxBuilder.fontForSize(iSize)); - g.drawText("=", iPosition.x, iPosition.y); - g.drawLine(iPosition.x + (2 * iDimension.width) / 3, iPosition.y - iAscent + (2 * iDimension.height) / 6, iPosition.x + (1 * iDimension.width) / 3, iPosition.y - iAscent + (6 * iDimension.height) / 6); - } - else if (iSymbol.equals("\\infty")) - { - g.setFontSize(SBoxBuilder.fontForSize(iSize)); - g.drawText("o", iPosition.x + 1, iPosition.y); - g.drawText("o", iPosition.x + g.textWidth("o") - 2, iPosition.y); - } - else if (iSymbol.equals("\\cdot")) - { - - int height = SBoxBuilder.fontForSize(iSize); - g.setFontSize(height); - g.drawText(".", iPosition.x, iPosition.y - height / 3); - } - else - { - g.setFontSize(SBoxBuilder.fontForSize(iSize)); - g.drawText(iSymbol, iPosition.x, iPosition.y); - } - } - } - - abstract class SBoxCompoundExpression - extends SBox - { - - SBox[] iExpressions; - - SBoxCompoundExpression(int aNrSubExpressions) - { - iExpressions = new SBox[aNrSubExpressions]; - } - - public void render(GraphicsPrimitives g) - { - - //drawBoundingBox(g); - int i; - - for (i = 0; i < iExpressions.length; i++) - { - - if (iExpressions[i] != null) - { - iExpressions[i].render(g); - } - } - } - - public void drawBoundingBox(GraphicsPrimitives g) - { - g.setLineThickness(0); - - int x0 = iPosition.x; - int y0 = iPosition.y - getCalculatedAscent(); - int x1 = x0 + iDimension.width; - int y1 = y0 + iDimension.height; - g.drawLine(x0, y0, x1, y0); - g.drawLine(x1, y0, x1, y1); - g.drawLine(x1, y1, x0, y1); - g.drawLine(x0, y1, x0, y0); - - int i; - - for (i = 0; i < iExpressions.length; i++) - { - - if (iExpressions[i] != null) - iExpressions[i].drawBoundingBox(g); - } - } - } - - class SBoxSubSuperfix - extends SBoxCompoundExpression - { - - int iExtent = 0; - int iSubOffset = 0; - int iSuperOffset = 0; - - SBoxSubSuperfix(SBox aExpr, SBox aSuperfix, SBox aSubfix) - { - super(3); - iExpressions[0] = aExpr; - iExpressions[1] = aSuperfix; - iExpressions[2] = aSubfix; - } - - void setSuperfix(SBox aExpression) - { - iExpressions[1] = aExpression; - } - - void setSubfix(SBox aExpression) - { - iExpressions[2] = aExpression; - } - - boolean hasSuperfix() - { - - return (iExpressions[1] != null); - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - iSize = aSize; - iPosition = aPosition; - - // Get dimensions first - if (iDimension == null) - { - - Dimension dsfix = new Dimension(0, 0); - Dimension dlfix = new Dimension(0, 0); - iExpressions[0].calculatePositions(g, aSize, null); - - if (iExpressions[1] != null) - iExpressions[1].calculatePositions(g, aSize - 1, null); - - if (iExpressions[2] != null) - iExpressions[2].calculatePositions(g, aSize - 1, null); - - Dimension dexpr = iExpressions[0].getDimension(); - - if (iExpressions[1] != null) - dsfix = iExpressions[1].getDimension(); - - if (iExpressions[2] != null) - dlfix = iExpressions[2].getDimension(); - - if (iExpressions[0] instanceof SBoxSum || iExpressions[0] instanceof SBoxInt) - { - iSuperOffset = 0; - iSubOffset = 0; - - if (iExpressions[1] != null) - iExtent = iExtent + iExpressions[1].iAscent; - - if (iExpressions[2] != null) - iExtent = iExtent + iExpressions[2].iAscent; - - int fixMaxWidth = dsfix.width; - - if (dlfix.width > fixMaxWidth) - fixMaxWidth = dlfix.width; - - if (dexpr.width > fixMaxWidth) - fixMaxWidth = dexpr.width; - - iDimension = new Dimension(fixMaxWidth, dexpr.height + iExtent); - } - else - { - - if (iExpressions[1] != null) - { - iSuperOffset = iExpressions[1].getDimension().height - iExpressions[1].iAscent - iExpressions[0].getDimension().height / 4; - iExtent = iExtent + iSuperOffset + iExpressions[1].iAscent; - } - - if (iExpressions[2] != null) - { - iSubOffset = iExpressions[2].iAscent; - - int delta = iSubOffset + (iExpressions[2].getDimension().height - iExpressions[2].iAscent) - (iExpressions[0].getDimension().height - iExpressions[0].iAscent); - iExtent = iExtent + delta; - } - - int fixMaxWidth = dsfix.width; - - if (dlfix.width > fixMaxWidth) - fixMaxWidth = dlfix.width; - - iDimension = new Dimension(dexpr.width + fixMaxWidth, dexpr.height + iExtent); - } - - iAscent = iExpressions[0].getCalculatedAscent() + iExtent; - - if (iExpressions[2] != null) - { - iAscent = iAscent - iExpressions[2].getDimension().height; - } - } - - if (aPosition != null) - { - - Dimension dsfix = new Dimension(0, 0); - Dimension dlfix = new Dimension(0, 0); - Dimension dexpr = iExpressions[0].getDimension(); - - if (iExpressions[1] != null) - dsfix = iExpressions[1].getDimension(); - - if (iExpressions[2] != null) - dlfix = iExpressions[2].getDimension(); - - iExpressions[0].calculatePositions(g, aSize, new Point(aPosition.x, aPosition.y)); - - if (iExpressions[0] instanceof SBoxSum || iExpressions[0] instanceof SBoxInt) - { - - if (iExpressions[1] != null) - iExpressions[1].calculatePositions(g, aSize - 1, new Point(aPosition.x, aPosition.y - iExpressions[0].iAscent - dsfix.height)); - - if (iExpressions[2] != null) - iExpressions[2].calculatePositions(g, aSize - 1, new Point(aPosition.x, aPosition.y + iExpressions[2].iAscent + dlfix.height)); - } - else - { - - if (iExpressions[1] != null) - iExpressions[1].calculatePositions(g, aSize - 1, new Point(aPosition.x + dexpr.width, aPosition.y - iExpressions[0].iAscent - iSuperOffset)); - - if (iExpressions[2] != null) - iExpressions[2].calculatePositions(g, aSize - 1, new Point(aPosition.x + dexpr.width, aPosition.y + iSubOffset)); - } - } - } - } - - class SBoxGrid - extends SBoxCompoundExpression - { - - int iHeight; - int[] iHeights; - int iWidth; - int[] iWidths; - - SBoxGrid(int aWidth, int aHeight) - { - super(aWidth * aHeight); - iWidth = aWidth; - iHeight = aHeight; - } - - void SetSBox(int x, int y, SBox aExpression) - { - iExpressions[x + iWidth * y] = aExpression; - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - - int spacing = 12; - iSize = aSize; - iPosition = aPosition; - - // Get dimensions first - if (iDimension == null) - { - - int i; - int j; - - for (i = 0; i < iWidth * iHeight; i++) - { - iExpressions[i].calculatePositions(g, aSize, null); - } - - iWidths = new int[iWidth]; - iHeights = new int[iHeight]; - - for (i = 0; i < iWidth; i++) - iWidths[i] = 0; - - for (i = 0; i < iHeight; i++) - iHeights[i] = 0; - - for (i = 0; i < iWidth; i++) - { - - for (j = 0; j < iHeight; j++) - { - - Dimension d = iExpressions[i + iWidth * j].getDimension(); - - if (iWidths[i] < d.width) - iWidths[i] = d.width; - - if (iHeights[j] < d.height) - iHeights[j] = d.height; - } - } - - int totalWidth = 0; - - for (i = 0; i < iWidth; i++) - { - totalWidth = totalWidth + iWidths[i]; - } - - int totalHeight = 0; - - for (j = 0; j < iHeight; j++) - { - totalHeight = totalHeight + iHeights[j]; - } - - iDimension = new Dimension(totalWidth + spacing * (iWidth), totalHeight + spacing * (iHeight)); - iAscent = iDimension.height / 2; - } - - if (aPosition != null) - { - - int i; - int j; - int h = -iAscent; - - for (j = 0; j < iHeight; j++) - { - - int maxAscent = -10000; - - for (i = 0; i < iWidth; i++) - { - - if (maxAscent < iExpressions[i + j * iWidth].iAscent) - maxAscent = iExpressions[i + j * iWidth].iAscent; - } - - h = h + maxAscent; - - int w = 0; - - for (i = 0; i < iWidth; i++) - { - iExpressions[i + j * iWidth].calculatePositions(g, aSize, new Point(aPosition.x + w, aPosition.y + h)); - w += iWidths[i] + spacing; - } - - h = h - maxAscent; - h = h + iHeights[j] + spacing; - } - } - } - } - - class SBoxPrefixOperator - extends SBoxCompoundExpression - { - SBoxPrefixOperator(SBox aLeft, SBox aRight) - { - super(2); - iExpressions[0] = aLeft; - iExpressions[1] = aRight; - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - iSize = aSize; - iPosition = aPosition; - - // Get dimensions first - if (iDimension == null) - { - iExpressions[0].calculatePositions(g, aSize, null); - iExpressions[1].calculatePositions(g, aSize, null); - - Dimension dleft = iExpressions[0].getDimension(); - Dimension dright = iExpressions[1].getDimension(); - int height = dleft.height; - - if (height < dright.height) - height = dright.height; - - iDimension = new Dimension(dleft.width + dright.width + 2, height); - iAscent = iExpressions[0].getCalculatedAscent(); - - if (iAscent < iExpressions[1].getCalculatedAscent()) - iAscent = iExpressions[1].getCalculatedAscent(); - } - - if (aPosition != null) - { - - Dimension dleft = iExpressions[0].getDimension(); - Dimension dright = iExpressions[1].getDimension(); - iExpressions[0].calculatePositions(g, aSize, new Point(aPosition.x, aPosition.y)); /*+(iAscent-iExpressions[0].getCalculatedAscent())*/ - iExpressions[1].calculatePositions(g, aSize, new Point(aPosition.x + dleft.width + 2, aPosition.y)); /*+(iAscent-iExpressions[1].getCalculatedAscent())*/ - } - } - } - - class SBoxInfixOperator - extends SBoxCompoundExpression - { - SBoxInfixOperator(SBox aLeft, SBox aInfix, SBox aRight) - { - super(3); - iExpressions[0] = aLeft; - iExpressions[1] = aInfix; - iExpressions[2] = aRight; - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - iSize = aSize; - iPosition = aPosition; - - // Get dimensions first - if (iDimension == null) - { - iExpressions[0].calculatePositions(g, aSize, null); - iExpressions[1].calculatePositions(g, aSize, null); - iExpressions[2].calculatePositions(g, aSize, null); - - Dimension dleft = iExpressions[0].getDimension(); - Dimension dinfix = iExpressions[1].getDimension(); - Dimension dright = iExpressions[2].getDimension(); - int height = dleft.height; - - if (height < dinfix.height) - height = dinfix.height; - - if (height < dright.height) - height = dright.height; - - iDimension = new Dimension(dleft.width + dinfix.width + dright.width + 4, height); - iAscent = iExpressions[0].getCalculatedAscent(); - - if (iAscent < iExpressions[1].getCalculatedAscent()) - iAscent = iExpressions[1].getCalculatedAscent(); - - if (iAscent < iExpressions[2].getCalculatedAscent()) - iAscent = iExpressions[2].getCalculatedAscent(); - } - - if (aPosition != null) - { - - Dimension dleft = iExpressions[0].getDimension(); - Dimension dinfix = iExpressions[1].getDimension(); - Dimension dright = iExpressions[2].getDimension(); - iExpressions[0].calculatePositions(g, aSize, new Point(aPosition.x, aPosition.y)); - iExpressions[1].calculatePositions(g, aSize, new Point(aPosition.x + dleft.width + 2, aPosition.y)); - iExpressions[2].calculatePositions(g, aSize, new Point(aPosition.x + dleft.width + dinfix.width + 4, aPosition.y)); - } - } - } - - class SBoxDivisor - extends SBoxCompoundExpression - { - - int iDashheight = 0; - - SBoxDivisor(SBox aNumerator, SBox aDenominator) - { - super(2); - iExpressions[0] = aNumerator; - iExpressions[1] = aDenominator; - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - iSize = aSize; - iPosition = aPosition; - iDashheight = SBoxBuilder.fontForSize(iSize); - - if (iDimension == null) - { - iExpressions[0].calculatePositions(g, aSize, null); - iExpressions[1].calculatePositions(g, aSize, null); - - Dimension ndim = iExpressions[0].getDimension(); - Dimension ddim = iExpressions[1].getDimension(); - int width = ndim.width; - - if (width < ddim.width) - width = ddim.width; - - iDimension = new Dimension(width, ndim.height + ddim.height + iDashheight); - iAscent = ndim.height + iDashheight; - } - - if (aPosition != null) - { - - Dimension ndim = iExpressions[0].getDimension(); - Dimension ddim = iExpressions[1].getDimension(); - int ynumer = aPosition.y - ndim.height + iExpressions[0].getCalculatedAscent() - iDashheight; - int ydenom = aPosition.y + iExpressions[1].getCalculatedAscent(); - iExpressions[0].calculatePositions(g, aSize, new java.awt.Point(aPosition.x + (iDimension.width - ndim.width) / 2, ynumer)); - iExpressions[1].calculatePositions(g, aSize, new java.awt.Point(aPosition.x + (iDimension.width - ddim.width) / 2, ydenom)); - } - } - - public void render(GraphicsPrimitives g) - { - super.render(g); - - java.awt.Dimension ndim = iExpressions[0].getDimension(); - java.awt.Dimension ddim = iExpressions[1].getDimension(); - int width = ndim.width; - - if (width < ddim.width) - width = ddim.width; - - g.setLineThickness(1); - g.drawLine(iPosition.x, iPosition.y - iDashheight / 2 + 2, iPosition.x + width, iPosition.y - iDashheight / 2 + 2); - } - } - - class SBoxSum - extends SBox - { - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - - int height = SBoxBuilder.fontForSize(aSize); - g.setFontSize(height); - iSize = aSize; - iPosition = aPosition; - iAscent = height / 2 + g.getAscent(); - iDimension = new Dimension((4 * height) / 3, 2 * height); - } - - public void render(GraphicsPrimitives g) - { - - int height = SBoxBuilder.fontForSize(iSize); - g.setLineThickness(2); - - int x0 = iPosition.x; - int y0 = iPosition.y - iAscent; - int x1 = x0 + iDimension.width; - int y1 = y0 + iDimension.height; - g.drawLine(x1, y0, x0, y0); - g.drawLine(x0, y0, x0 + (2 * height) / 4, (int)(y0 + y1) / 2); - g.drawLine(x0 + (2 * height) / 4, (int)(y0 + y1) / 2, x0, y1); - g.drawLine(x0, y1, x1, y1); - } - } - - class SBoxInt - extends SBox - { - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - - int height = SBoxBuilder.fontForSize(aSize); - g.setFontSize(height); - iSize = aSize; - iPosition = aPosition; - iAscent = height / 2 + g.getAscent(); - iDimension = new Dimension((1 * height) / 2, 2 * height); - } - - public void render(GraphicsPrimitives g) - { - - int height = SBoxBuilder.fontForSize(iSize); - g.setLineThickness(2); - - int x0 = iPosition.x; - int y0 = iPosition.y - iAscent; - int x1 = x0 + iDimension.width; - int y1 = y0 + iDimension.height; - g.drawLine(x1, y0, x1 - iDimension.width / 4, y0); - g.drawLine(x1 - iDimension.width / 4, y0, x1 - (2 * iDimension.width) / 4, y0 + iDimension.width / 4); - g.drawLine(x1 - (2 * iDimension.width) / 4, y0 + iDimension.width / 4, x1 - (2 * iDimension.width) / 4, y0 + iDimension.height - iDimension.width / 4); - g.drawLine(x1 - (2 * iDimension.width) / 4, y0 + iDimension.height - iDimension.width / 4, x1 - (3 * iDimension.width) / 4, y0 + iDimension.height); - g.drawLine(x1 - (3 * iDimension.width) / 4, y0 + iDimension.height, x0, y0 + iDimension.height); - } - } - - class SBoxSquareRoot - extends SBoxCompoundExpression - { - SBoxSquareRoot(SBox aExpression) - { - super(1); - iExpressions[0] = aExpression; - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - iSize = aSize; - iPosition = aPosition; - - if (iDimension == null) - { - iExpressions[0].calculatePositions(g, aSize, null); - - Dimension dim = iExpressions[0].getDimension(); - iDimension = new Dimension((int)(dim.width + 6), dim.height + 3); - iAscent = iExpressions[0].getCalculatedAscent() + 3; - } - - if (aPosition != null) - { - - Dimension dim = iExpressions[0].getDimension(); - iExpressions[0].calculatePositions(g, aSize, new java.awt.Point((int)(aPosition.x + 6), aPosition.y)); - } - } - - public void render(GraphicsPrimitives g) - { - super.render(g); - g.setLineThickness(1); - - Dimension dim = iExpressions[0].getDimension(); - int x0 = iPosition.x; - int y0 = iPosition.y - iAscent; - int x1 = x0 + dim.width + 6; - int y1 = y0 + dim.height + 6; - g.drawLine(x0, y0 + 1, x0 + 3, y1 - 1); - g.drawLine(x0 + 3, y1 - 1, x0 + 6, y0 + 2); - g.drawLine(x0 + 6, y0 + 1, x1, y0 + 1); - } - } - - class SBoxBracket - extends SBoxCompoundExpression - { - - int iBracketWidth; - String iClose; - int iFontSize; - String iOpen; - - SBoxBracket(SBox aExpression, String aOpen, String aClose) - { - super(1); - iOpen = aOpen; - iClose = aClose; - iExpressions[0] = aExpression; - } - - public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition) - { - iSize = aSize; - iPosition = aPosition; - - if (iDimension == null) - { - iExpressions[0].calculatePositions(g, aSize, null); - - Dimension dim = iExpressions[0].getDimension(); - iFontSize = dim.height; - g.setFontSize(dim.height); - iBracketWidth = SBoxBuilder.fontForSize(aSize) / 2; - iDimension = new Dimension(dim.width + 2 * iBracketWidth, dim.height); - iAscent = iExpressions[0].getCalculatedAscent(); - } - - if (aPosition != null) - { - - Dimension dim = iExpressions[0].getDimension(); - iExpressions[0].calculatePositions(g, aSize, new java.awt.Point(aPosition.x + iBracketWidth, aPosition.y)); - } - } - - public void render(GraphicsPrimitives g) - { - super.render(g); - - Dimension dim = iExpressions[0].getDimension(); - drawBracket(g, iOpen, iPosition.x, iPosition.y - getCalculatedAscent()); - drawBracket(g, iClose, iPosition.x + dim.width + iBracketWidth, iPosition.y - getCalculatedAscent()); - } - - void drawBracket(GraphicsPrimitives g, String bracket, int x, int y) - { - - Dimension dim = iExpressions[0].getDimension(); - - if (bracket.equals("[") || bracket.equals("]")) - { - - int margin = 2; - g.setLineThickness(2); - - if (bracket.equals("[")) - { - g.drawLine(x + margin, y, x + margin, y + dim.height); - } - else - { - g.drawLine(x + iBracketWidth - margin, y, x + iBracketWidth - margin, y + dim.height); - } - - g.setLineThickness(1); - g.drawLine(x + iBracketWidth - margin, y, x + margin, y); - g.drawLine(x + margin, y + dim.height, x + iBracketWidth - margin, y + dim.height); - } - else if (bracket.equals("(") || bracket.equals(")")) - { - - int xstart; - int xend; - - if (bracket.equals("(")) - { - xstart = x + iBracketWidth; - xend = x; - } - else - { - xstart = x; - xend = x + iBracketWidth; - } - - int delta = xend - xstart; - float[] steps = new float[3]; - steps[0] = 0.2f; - steps[1] = 0.6f; - steps[2] = 0.8f; - g.setLineThickness(1f); - g.drawLine((int)(xstart + (delta * steps[0])), y + (0 * dim.height) / 6, (int)(xstart + (delta * steps[1])), y + (1 * dim.height) / 6); - g.setLineThickness(1.3f); - g.drawLine((int)(xstart + (delta * steps[1])), y + (1 * dim.height) / 6, (int)(xstart + (delta * steps[2])), y + (2 * dim.height) / 6); - g.setLineThickness(1.6f); - g.drawLine((int)(xstart + (delta * steps[2])), y + (2 * dim.height) / 6, (int)(xstart + (delta * steps[2])), y + (4 * dim.height) / 6); - g.setLineThickness(1.3f); - g.drawLine((int)(xstart + (delta * steps[2])), y + (4 * dim.height) / 6, (int)(xstart + (delta * steps[1])), y + (5 * dim.height) / 6); - g.setLineThickness(1f); - g.drawLine((int)(xstart + (delta * steps[1])), y + (5 * dim.height) / 6, (int)(xstart + (delta * steps[0])), y + (6 * dim.height) / 6); - } - else - { - g.setFontSize(iFontSize); - - int offset = (iFontSize - iAscent) / 2; - g.drawText(bracket, x, y + offset); - } - } - } -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/SBox.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/SBox.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/SBox.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/SBox.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - -public abstract class SBox -{ - java.awt.Dimension iDimension; - java.awt.Point iPosition; - int iSize; - int iAscent; - - abstract public void calculatePositions(GraphicsPrimitives g, int aSize, java.awt.Point aPosition); - abstract public void render(GraphicsPrimitives g); - - public java.awt.Dimension getDimension() - { - return iDimension; - } - - public java.awt.Point getCalculatedPosition() - { - return iPosition; - } - - public int getSetSize() - { - return iSize; - } - - public int getCalculatedAscent() - { - return iAscent; - } - - public void drawBoundingBox(GraphicsPrimitives g) - { - g.setLineThickness(0); - int x0 = iPosition.x; - int y0 = iPosition.y-getCalculatedAscent(); - int x1 = x0+iDimension.width; - int y1 = y0+iDimension.height; - g.drawLine(x0,y0,x1,y0); - g.drawLine(x1,y0,x1,y1); - g.drawLine(x1,y1,x0,y1); - g.drawLine(x0,y1,x0,y0); - } - -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ScreenCapturePanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ScreenCapturePanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ScreenCapturePanel.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ScreenCapturePanel.java 2010-12-29 01:32:10.000000000 +0000 @@ -0,0 +1,66 @@ + +package org.mathpiper.ui.gui.worksheets; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import org.mathpiper.ui.gui.Utility; + + +public class ScreenCapturePanel extends JPanel implements MouseListener{ + + public ScreenCapturePanel() + { + this.addMouseListener(this); + this.setBackground(Color.white); + } + + + public void mousePressed(MouseEvent e) { + //eventOutput("Mouse pressed (# of clicks: " + e.getClickCount() + ")", e); + } + + + public void mouseReleased(MouseEvent e) { + //eventOutput("Mouse released (# of clicks: " + e.getClickCount() + ")", e); + } + + + public void mouseEntered(MouseEvent e) { + //eventOutput("Mouse entered", e); + } + + + public void mouseExited(MouseEvent e) { + //eventOutput("Mouse exited", e); + } + + + public void mouseClicked(MouseEvent e) { + //eventOutput("Mouse clicked (# of clicks: " + e.getClickCount() + ")", e); + + int buttonNumber = e.getButton(); + + if (buttonNumber == MouseEvent.BUTTON3) { + JPopupMenu popup = new JPopupMenu(); + JMenuItem menuItem = new JMenuItem("Save image to file"); + menuItem.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Utility.saveImageOfComponent(ScreenCapturePanel.this); + } + + }); + + popup.add(menuItem); + popup.show(ScreenCapturePanel.this, 10, 10); + + + } + }//end method. +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/StringLine.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/StringLine.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/StringLine.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/StringLine.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.ui.gui.worksheets; - -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; - -class StringLine extends MathOutputLine { - - StringLine(String aText, Font aFont, Color aColor) { - iText = aText; - iFont = aFont; - iColor = aColor; - } - - public void draw(Graphics g, int x, int y) { - g.setColor(iColor); - g.setFont(iFont); - FontMetrics fontMetrics = g.getFontMetrics(); - g.drawString(iText, x, y + fontMetrics.getHeight()); - } - - public int height(Graphics g) { - g.setFont(iFont); - FontMetrics fontMetrics = g.getFontMetrics(); - return fontMetrics.getHeight(); - } - private String iText; - private Font iFont; - private Color iColor; -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bounds.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bounds.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bounds.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bounds.java 2010-03-04 23:33:18.000000000 +0000 @@ -0,0 +1,75 @@ + +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +import java.awt.Dimension; + + +public class Bounds { + + + public double top; + + public double bottom; + + public double left; + + public double right; + + + + + public Bounds() { + this(0, 0, 0, 0); + } + + + public Bounds(double top, double bottom, double left, double right) { + this.top = top; + this.bottom = bottom; + this.left = left; + this.right = right; + } + + public double getBottom() { + return bottom; + } + + public void setBottom(double bottom) { + this.bottom = bottom; + } + + public double getLeft() { + return left; + } + + public void setLeft(double left) { + this.left = left; + } + + public double getRight() { + return right; + } + + public void setRight(double right) { + this.right = right; + } + + public double getTop() { + return top; + } + + public void setTop(double top) { + this.top = top; + } + + + public Dimension getScaledDimension(double scale) + { + return new Dimension((int)( (right - left)*scale), (int)( (bottom - top)*scale) ); + } + + + public String toString() { + return "[top=" + top + ",bottom=" + bottom + ",left=" + left + ",right=" + right + "]"; + } +} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bracket.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bracket.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bracket.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Bracket.java 2010-04-02 06:35:47.000000000 +0000 @@ -0,0 +1,143 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +public class Bracket extends CompoundExpression { + + double iBracketWidth; + String iClose; + double iFontSize; + String iOpen; + + private SymbolBox iExpression; + + public Bracket(SymbolBox aExpression, String aOpen, String aClose) { + //super(1); + iOpen = aOpen; + iClose = aClose; + iExpression = aExpression; + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + iSize = aSize; + iPosition = aPosition; + + if (iDimension == null) { + iExpression.calculatePositions(sg, aSize, null); + + Dimensions dim = iExpression.getDimension(); + iFontSize = dim.height; + sg.setFontSize( dim.height); + iBracketWidth = ScaledGraphics.fontForSize(aSize) / 2; + iDimension = new Dimensions(dim.width + 2 * iBracketWidth, dim.height); + iAscent = iExpression.getCalculatedAscent(); + } + + if (aPosition != null) { + + Dimensions dim = iExpression.getDimension(); + iExpression.calculatePositions(sg, aSize, new Position(aPosition.x + iBracketWidth, aPosition.y)); + } + } + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg); + + iExpression.render(sg); + + Dimensions dim = iExpression.getDimension(); + drawBracket(sg, iOpen, iPosition.x, iPosition.y - getCalculatedAscent()); + drawBracket(sg, iClose, iPosition.x + dim.width + iBracketWidth, iPosition.y - getCalculatedAscent()); + } + + void drawBracket(ScaledGraphics sg, String bracket, double x, double y) { + + Dimensions dim = iExpression.getDimension(); + + if (bracket.equals("[") || bracket.equals("]")) { + + int margin = 2; + sg.setLineThickness(2); + + if (bracket.equals("[")) { + sg.drawLine(x + margin, y, x + margin, y + dim.height); + } else { + sg.drawLine(x + iBracketWidth - margin, y, x + iBracketWidth - margin, y + dim.height); + } + + sg.setLineThickness(1); + sg.drawLine(x + iBracketWidth - margin, y, x + margin, y); + sg.drawLine(x + margin, y + dim.height, x + iBracketWidth - margin, y + dim.height); + } else if (bracket.equals("(") || bracket.equals(")")) { + + double xstart; + double xend; + + if (bracket.equals("(")) { + xstart = x + iBracketWidth; + xend = x; + } else { + xstart = x; + xend = x + iBracketWidth; + } + + double delta = xend - xstart; + + double[] steps = new double[3]; + + double verticalOffset = 2; + + steps[0] = 0.2; + steps[1] = 0.6; + steps[2] = 0.8; + + sg.setLineThickness(1.1); + sg.drawLine( (xstart + (delta * steps[0])), y + verticalOffset + (0 * dim.height) / 6, xstart + (delta * steps[1]), y + verticalOffset + (1 * dim.height) / 6); + + sg.setLineThickness(1.3); + sg.drawLine( (xstart + (delta * steps[1])), y + verticalOffset + (1 * dim.height) / 6, xstart + (delta * steps[2]), y + verticalOffset + (2 * dim.height) / 6); + + sg.setLineThickness(1.5); + sg.drawLine( (xstart + (delta * steps[2])), y + verticalOffset + (2 * dim.height) / 6, xstart + (delta * steps[2]), y + verticalOffset + (4 * dim.height) / 6); + + sg.setLineThickness(1.3); + sg.drawLine( (xstart + (delta * steps[2])), y + verticalOffset + (4 * dim.height) / 6, xstart + (delta * steps[1]), y + verticalOffset + (5 * dim.height) / 6); + + sg.setLineThickness(1.1); + sg.drawLine( (xstart + (delta * steps[1])), y + verticalOffset + (5 * dim.height) / 6, xstart + (delta * steps[0]), y + verticalOffset + (6 * dim.height) / 6); + + + /* sg.setColor(Color.RED); + sg.setLineThickness(1.6); + sg.drawLine( (xstart + (delta * steps[2])), y + (2 * dim.getTextHeight) / 6, xstart + (delta * steps[2]), y + (4 * dim.getTextHeight) / 6); + + sg.drawArc(xstart + (delta * .8), y + (0 * dim.getTextHeight)/6,30, 30, 180, -60); + sg.setColor(Color.black);*/ + + } else { + sg.setFontSize(iFontSize); + + double offset = (iFontSize - iAscent) / 2; + sg.drawText(bracket, x, y + offset); + } + }//end method. + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[] {this.iExpression}; + }//end method. + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/CompoundExpression.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/CompoundExpression.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/CompoundExpression.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/CompoundExpression.java 2010-04-02 06:35:47.000000000 +0000 @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +import java.awt.Color; + +abstract class CompoundExpression extends SymbolBox { + + //SymbolBox[] iExpressions; + + /* CompoundExpression(int aNrSubExpressions) { + iExpressions = new SymbolBox[aNrSubExpressions]; + }*/ + + public void render(ScaledGraphics sg) { + + } + + + public void drawBoundingBox(ScaledGraphics sg) { + + drawBoundingBox(sg, Color.BLUE); + /*sg.setColor(Color.blue); + sg.setLineThickness(0); + + double x0 = iPosition.x; + double y0 = iPosition.y - getCalculatedAscent(); + double x1 = x0 + iDimension.getTextWidth; + double y1 = y0 + iDimension.getTextHeight; + sg.drawLine(x0, y0, x1, y0); + sg.drawLine(x1, y0, x1, y1); + sg.drawLine(x1, y1, x0, y1); + sg.drawLine(x0, y1, x0, y0); + + sg.drawscaledText("" + sequence++, x0, y0 + 3, .2); + + sg.setColor(Color.black);*/ + + + + } + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Dimensions.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Dimensions.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Dimensions.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Dimensions.java 2010-02-24 02:58:08.000000000 +0000 @@ -0,0 +1,82 @@ + +package org.mathpiper.ui.gui.worksheets.symbolboxes; + + +public class Dimensions { + + + public double width; + + + public double height; + + + + + public Dimensions() { + this(0, 0); + } + + + public Dimensions(Dimensions d) { + this(d.width, d.height); + } + + + public Dimensions(double width, double height) { + this.width = width; + this.height = height; + } + + + public double getWidth() { + return width; + } + + + public double getHeight() { + return height; + } + + + public void setSize(double width, double height) { + this.width = width; + this.height = height; + } + + + public Dimensions getSize() { + return new Dimensions(width, height); + } + + + public void setSize(Dimensions d) { + setSize(d.width, d.height); + } + + + public void setSize(int width, int height) { + this.width = width; + this.height = height; + } + + + public boolean equals(Object obj) { + if (obj instanceof Dimensions) { + Dimensions d = (Dimensions)obj; + return (width == d.width) && (height == d.height); + } + return false; + } + + + public int hashCode() { + double sum = width + height; + return (int) (sum * (sum + 1)/2 + width); + } + + + public String toString() { + return getClass().getName() + "[width=" + width + ",height=" + height + "]"; + } +} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Fraction.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Fraction.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Fraction.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Fraction.java 2010-02-26 02:36:14.000000000 +0000 @@ -0,0 +1,87 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +public class Fraction extends CompoundExpression { + + private int iDashheight = 0; + + private SymbolBox iNumerator; + + private SymbolBox iDenominator; + + public Fraction(SymbolBox aNumerator, SymbolBox aDenominator) { + + iNumerator = aNumerator; + + iDenominator = aDenominator; + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + iSize = aSize; + iPosition = aPosition; + iDashheight = ScaledGraphics.fontForSize(iSize); + + if (iDimension == null) { + iNumerator.calculatePositions(sg, aSize, null); + iDenominator.calculatePositions(sg, aSize, null); + + Dimensions ndim = iNumerator.getDimension(); + Dimensions ddim = iDenominator.getDimension(); + double width = ndim.width; + + if (width < ddim.width) { + width = ddim.width; + } + + iDimension = new Dimensions(width, ndim.height + ddim.height + iDashheight); + iAscent = ndim.height + iDashheight; + } + + if (aPosition != null) { + + Dimensions ndim = iNumerator.getDimension(); + Dimensions ddim = iDenominator.getDimension(); + double ynumer = aPosition.y - ndim.height + iNumerator.getCalculatedAscent() - iDashheight; + double ydenom = aPosition.y + iDenominator.getCalculatedAscent(); + iNumerator.calculatePositions(sg, aSize, new Position( (aPosition.x + (iDimension.width - ndim.width) / 2), ynumer)); + iDenominator.calculatePositions(sg, aSize, new Position( (aPosition.x + (iDimension.width - ddim.width) / 2), ydenom)); + } + } + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg); + + iNumerator.render(sg); + + iDenominator.render(sg); + + Dimensions ndim = iNumerator.getDimension(); + Dimensions ddim = iDenominator.getDimension(); + double width = ndim.width; + + if (width < ddim.width) { + width = ddim.width; + } + + sg.setLineThickness(1); + sg.drawLine(iPosition.x, iPosition.y - iDashheight / 2 + 2, iPosition.x + width, iPosition.y - iDashheight / 2 + 2); + } + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[] {this.iNumerator, this.iDenominator}; + }//end method. + + + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Grid.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Grid.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Grid.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Grid.java 2010-02-26 02:36:14.000000000 +0000 @@ -0,0 +1,146 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + + + +public class Grid extends CompoundExpression { + + int iHeight; + double[] iHeights; + int iWidth; + double[] iWidths; + + private SymbolBox iExpressions[]; + + public Grid(int aWidth, int aHeight) { + //super(aWidth * aHeight); + iExpressions = new SymbolBox[aWidth * aHeight]; + iWidth = aWidth; + iHeight = aHeight; + } + + public void setSBox(int x, int y, SymbolBox aExpression) { + iExpressions[x + iWidth * y] = aExpression; + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + + int spacing = 12; + iSize = aSize; + iPosition = aPosition; + + // Get dimensions first + if (iDimension == null) { + + int i; + int j; + + for (i = 0; i < iWidth * iHeight; i++) { + iExpressions[i].calculatePositions(sg, aSize, null); + } + + iWidths = new double[iWidth]; + iHeights = new double[iHeight]; + + for (i = 0; i < iWidth; i++) { + iWidths[i] = 0; + } + + for (i = 0; i < iHeight; i++) { + iHeights[i] = 0; + } + + for (i = 0; i < iWidth; i++) { + + for (j = 0; j < iHeight; j++) { + + Dimensions d = iExpressions[i + iWidth * j].getDimension(); + + if (iWidths[i] < d.width) { + iWidths[i] = d.width; + } + + if (iHeights[j] < d.height) { + iHeights[j] = d.height; + } + } + } + + double totalWidth = 0; + + for (i = 0; i < iWidth; i++) { + totalWidth = totalWidth + iWidths[i]; + } + + double totalHeight = 0; + + for (j = 0; j < iHeight; j++) { + totalHeight = totalHeight + iHeights[j]; + } + + iDimension = new Dimensions(totalWidth + spacing * (iWidth), totalHeight + spacing * (iHeight)); + iAscent = iDimension.height / 2; + } + + if (aPosition != null) { + + int i; + int j; + double h = -iAscent; + + for (j = 0; j < iHeight; j++) { + + double maxAscent = -10000; + + for (i = 0; i < iWidth; i++) { + + if (maxAscent < iExpressions[i + j * iWidth].iAscent) { + maxAscent = iExpressions[i + j * iWidth].iAscent; + } + } + + h = h + maxAscent; + + double w = 0; + + for (i = 0; i < iWidth; i++) { + iExpressions[i + j * iWidth].calculatePositions(sg, aSize, new Position( (aPosition.x + w), (aPosition.y + h))); + w += iWidths[i] + spacing; + } + + h = h - maxAscent; + h = h + iHeights[j] + spacing; + } + } + }//end calculatePositions. + + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg); + + int i; + + for (i = 0; i < iExpressions.length; i++) { + + if (iExpressions[i] != null) { + iExpressions[i].render(sg); + } + }//end for. + + }//end render. + + + public SymbolBox[] getChildren() + { + return this.iExpressions; + }//end method. + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/InfixOperator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/InfixOperator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/InfixOperator.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/InfixOperator.java 2010-02-26 08:35:35.000000000 +0000 @@ -0,0 +1,92 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + + +public class InfixOperator extends CompoundExpression { + + private SymbolBox iLeft; + + private SymbolBox iInfix; + + private SymbolBox iRight; + + public InfixOperator(SymbolBox aLeft, SymbolBox aInfix, SymbolBox aRight) { + iLeft = aLeft; + iInfix = aInfix; + iRight = aRight; + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + iSize = aSize; + iPosition = aPosition; + + // Get dimensions first + if (iDimension == null) { + iLeft.calculatePositions(sg, aSize, null); + iInfix.calculatePositions(sg, aSize, null); + iRight.calculatePositions(sg, aSize, null); + + Dimensions dleft = iLeft.getDimension(); + Dimensions dinfix = iInfix.getDimension(); + Dimensions dright = iRight.getDimension(); + double height = dleft.height; + + if (height < dinfix.height) { + height = dinfix.height; + } + + if (height < dright.height) { + height = dright.height; + } + + iDimension = new Dimensions(dleft.width + dinfix.width + dright.width + 4, height); + iAscent = iLeft.getCalculatedAscent(); + + if (iAscent < iInfix.getCalculatedAscent()) { + iAscent = iInfix.getCalculatedAscent(); + } + + if (iAscent < iRight.getCalculatedAscent()) { + iAscent = iRight.getCalculatedAscent(); + } + } + + if (aPosition != null) { + + Dimensions dleft = iLeft.getDimension(); + Dimensions dinfix = iInfix.getDimension(); + Dimensions dright = iRight.getDimension(); + iLeft.calculatePositions(sg, aSize, new Position(aPosition.x, aPosition.y)); + iInfix.calculatePositions(sg, aSize, new Position( (aPosition.x + dleft.width + 2), aPosition.y) ); + iRight.calculatePositions(sg, aSize, new Position( (aPosition.x + dleft.width + dinfix.width + 4), aPosition.y)); + } + }//end calculatePositions. + + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg); + + iLeft.render(sg); + + iInfix.render(sg); + + iRight.render(sg); + }//end render. + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[] {this.iLeft, this.iInfix, this.iRight}; + }//end method. + + + + + public String toString() + { + String returnString = ""; //this.iInfix.toString(); + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Integral.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Integral.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Integral.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Integral.java 2010-02-28 09:23:26.000000000 +0000 @@ -0,0 +1,51 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +import java.awt.Color; + +public class Integral extends SymbolBox { + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + + int height = ScaledGraphics.fontForSize(aSize); + sg.setFontSize(height); + iSize = aSize; + iPosition = aPosition; + iAscent = height / 2 + sg.getAscent(); + iDimension = new Dimensions((1 * height) / 2, 2 * height); + } + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg, Color.RED); + + int height = ScaledGraphics.fontForSize(iSize); + sg.setLineThickness(2); + + double x0 = iPosition.x; + double y0 = iPosition.y - iAscent; + double x1 = x0 + iDimension.width; + double y1 = y0 + iDimension.height; + sg.drawLine(x1, y0, x1 - iDimension.width / 4, y0); + sg.drawLine(x1 - iDimension.width / 4, y0, x1 - (2 * iDimension.width) / 4, y0 + iDimension.width / 4); + sg.drawLine(x1 - (2 * iDimension.width) / 4, y0 + iDimension.width / 4, x1 - (2 * iDimension.width) / 4, y0 + iDimension.height - iDimension.width / 4); + sg.drawLine(x1 - (2 * iDimension.width) / 4, y0 + iDimension.height - iDimension.width / 4, x1 - (3 * iDimension.width) / 4, y0 + iDimension.height); + sg.drawLine(x1 - (3 * iDimension.width) / 4, y0 + iDimension.height, x0, y0 + iDimension.height); + } + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[0]; + }//end method. + + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Position.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Position.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Position.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Position.java 2010-02-24 06:57:58.000000000 +0000 @@ -0,0 +1,87 @@ + + +package org.mathpiper.ui.gui.worksheets.symbolboxes; + + + + +public class Position { + + public double x; + + + public double y; + + + public Position() { + this(0, 0); + } + + + public Position(Position p) { + this(p.x, p.y); + } + + + public Position(double x, double y) { + this.x = x; + this.y = y; + } + + + public double getX() { + return x; + } + + + public double getY() { + return y; + } + + + public Position getLocation() { + return new Position(x, y); + } + + + public void setLocation(Position p) { + setLocation(p.x, p.y); + } + + + public void setLocation(int x, int y) { + move(x, y); + } + + + public void setLocation(double x, double y) { + this.x = x; + this.y = y; + } + + + public void move(double x, double y) { + this.x = x; + this.y = y; + } + + + public void translate(double dx, double dy) { + this.x += dx; + this.y += dy; + } + + + public boolean equals(Object obj) { + if (obj instanceof Position) { + Position pt = (Position)obj; + return (x == pt.x) && (y == pt.y); + } + return super.equals(obj); + } + + + public String toString() { + return getClass().getName() + "[x=" + x + ",y=" + y + "]"; + } +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/PrefixOperator.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/PrefixOperator.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/PrefixOperator.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/PrefixOperator.java 2010-02-26 02:36:14.000000000 +0000 @@ -0,0 +1,77 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + + + +public class PrefixOperator extends CompoundExpression { + + private SymbolBox iLeft; + + private SymbolBox iRight; + + public PrefixOperator(SymbolBox aLeft, SymbolBox aRight) { + //super(2); + iLeft = aLeft; + iRight = aRight; + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + iSize = aSize; + iPosition = aPosition; + + // Get dimensions first + if (iDimension == null) { + iLeft.calculatePositions(sg, aSize, null); + iRight.calculatePositions(sg, aSize, null); + + Dimensions dleft = iLeft.getDimension(); + Dimensions dright = iRight.getDimension(); + double height = dleft.height; + + if (height < dright.height) { + height = dright.height; + } + + iDimension = new Dimensions(dleft.width + dright.width + 2, height); + iAscent = iLeft.getCalculatedAscent(); + + if (iAscent < iRight.getCalculatedAscent()) { + iAscent = iRight.getCalculatedAscent(); + } + } + + if (aPosition != null) { + + Dimensions dleft = iLeft.getDimension(); + Dimensions dright = iRight.getDimension(); + iLeft.calculatePositions(sg, aSize, new Position(aPosition.x, aPosition.y)); /*+(iAscent-iLeft.getCalculatedAscent())*/ + iRight.calculatePositions(sg, aSize, new Position( (aPosition.x + dleft.width + 2), aPosition.y)); /*+(iAscent-iRight.getCalculatedAscent())*/ + } + }//end calculatePositions. + + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg); + + iLeft.render(sg); + + iRight.render(sg); + }//end render. + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[] {this.iLeft, this.iRight}; + }//end method. + + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/ScaledGraphics.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/ScaledGraphics.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/ScaledGraphics.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/ScaledGraphics.java 2010-03-04 23:25:19.000000000 +0000 @@ -0,0 +1,170 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +import java.awt.*; + +public class ScaledGraphics { + + private double viewScale = 1.0; + private Graphics iG = null; + private Graphics2D iG2D = null; + int prevGray = -1; + int prevSetFontSize = -1; + FontMetrics metrics = null; + + public ScaledGraphics(Graphics g) { + iG = g; + if (g instanceof Graphics2D) { + iG2D = (Graphics2D) g; + } + } + + public void setLineThickness(double aThickness) { + if (iG2D != null) { + iG2D.setStroke(new BasicStroke((float) (aThickness * viewScale), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + } + } + + public void drawLine(double x0, double y0, double x1, double y1) { + iG.drawLine((int) (x0 * viewScale), (int) (y0 * viewScale), (int) (x1 * viewScale), (int) (y1 * viewScale)); + } + + + public void drawArc(double x,double y,double width,double height,int startAngle,int arcAngle) { + //iG.drawLine((int) (x0 * viewScale), (int) (y0 * viewScale), (int) (x1 * viewScale), (int) (y1 * viewScale)); + iG.drawArc((int) (x * viewScale), (int) (y * viewScale), (int) (width * viewScale), (int) (height * viewScale), startAngle, arcAngle); + } + + public void drawRectangle(double x, double y, double width, double height) { + iG.drawRect((int) (x * viewScale), (int) (y * viewScale), (int) (width * viewScale), (int) (height * viewScale)); + } + + public void setGray(int aGray) { + if (prevGray != aGray) { + prevGray = aGray; + iG.setColor(new Color(aGray, aGray, aGray)); + } + } + + public void drawText(String text, double x, double y) { + iG.drawString(text, (int) (x * viewScale), (int) (y * viewScale)); + } + + public void drawscaledText(String text, double x, double y, double scale) { + double normalFontSize = getFontSize(); + + double scaledFontSize = normalFontSize * scale; + + setFontSize(scaledFontSize); + + iG.drawString(text, (int) (x * viewScale), (int) (y * viewScale)); + + setFontSize(normalFontSize); + + } + + + public void setFontSize(double aSize) { + int newFontSize = (int) (viewScale * aSize); + if (prevSetFontSize != newFontSize) { + prevSetFontSize = newFontSize; + Font f = new Font("Verdana", Font.PLAIN, newFontSize); + if (f != null) { + iG.setFont(f); + metrics = iG.getFontMetrics(); + } + } + } + + public double getFontSize() { + return (prevSetFontSize / viewScale); + } + + public double getScaledTextWidth(String text) { + java.awt.geom.Rectangle2D textBoundingRectangle = metrics.getStringBounds(text, iG); + return (textBoundingRectangle.getWidth() / viewScale); + } + + public double getScaledTextHeight(String text) { + java.awt.geom.Rectangle2D textBoundingRectangle = metrics.getStringBounds(text, iG); + return (textBoundingRectangle.getHeight() / viewScale); + } + + public double getTextWidth(String text) { + java.awt.geom.Rectangle2D textBoundingRectangle = metrics.getStringBounds(text, iG); + return textBoundingRectangle.getWidth(); + } + + public double getTextHeight(String text) { + java.awt.geom.Rectangle2D textBoundingRectangle = metrics.getStringBounds(text, iG); + return textBoundingRectangle.getHeight(); + } + + public double getAscent() { + return (metrics.getAscent() / viewScale); + } + + public double getDescent() { + return (metrics.getDescent() / viewScale); + } + + public void setViewScale(double aViewScale) { + viewScale = aViewScale; + } + + public void setColor(Color color) { + if (iG2D != null) { + iG2D.setColor(color); + } else if (iG != null) { + iG.setColor(color); + } + + }//end method. + + public static int fontForSize(int aSize) { + + if (aSize > 3) { + aSize = 3; + } + + if (aSize < 0) { + aSize = 0; + } + + switch (aSize) { + + case 0: + return 6; + + case 1: + return 8; + + case 2: + return 12; + + case 3: + return 16; + + default: + return 16; + }//end switch. + + }//end method. + + +}//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SquareRoot.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SquareRoot.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SquareRoot.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SquareRoot.java 2010-02-26 02:36:14.000000000 +0000 @@ -0,0 +1,64 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +public class SquareRoot extends CompoundExpression { + + private SymbolBox iExpression; + + public SquareRoot(SymbolBox aExpression) { + iExpression = aExpression; + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + iSize = aSize; + iPosition = aPosition; + + if (iDimension == null) { + iExpression.calculatePositions(sg, aSize, null); + + Dimensions dim = iExpression.getDimension(); + iDimension = new Dimensions( (dim.width + 6), dim.height + 3); + iAscent = iExpression.getCalculatedAscent() + 3; + } + + if (aPosition != null) { + + Dimensions dim = iExpression.getDimension(); + iExpression.calculatePositions(sg, aSize, new Position( (aPosition.x + 6), aPosition.y)); + } + } + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg); + + iExpression.render(sg); + + sg.setLineThickness(1); + + Dimensions dim = iExpression.getDimension(); + double x0 = iPosition.x; + double y0 = iPosition.y - iAscent; + double x1 = x0 + dim.width + 6; + double y1 = y0 + dim.height + 6; + sg.drawLine(x0, y0 + 1, x0 + 3, y1 - 1); + sg.drawLine(x0 + 3, y1 - 1, x0 + 6, y0 + 2); + sg.drawLine(x0 + 6, y0 + 1, x1, y0 + 1); + } + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[] {this.iExpression}; + }//end method. + + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Sum.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Sum.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Sum.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/Sum.java 2010-02-27 10:33:43.000000000 +0000 @@ -0,0 +1,50 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +import java.awt.Color; + +public class Sum extends SymbolBox { + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + + int height = ScaledGraphics.fontForSize(aSize); + sg.setFontSize(height); + iSize = aSize; + iPosition = aPosition; + iAscent = height / 2 + sg.getAscent(); + iDimension = new Dimensions((4 * height) / 3, 2 * height); + } + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg, Color.RED); + + int height = ScaledGraphics.fontForSize(iSize); + sg.setLineThickness(2); + + double x0 = iPosition.x; + double y0 = iPosition.y - iAscent; + double x1 = x0 + iDimension.width; + double y1 = y0 + iDimension.height; + sg.drawLine(x1, y0, x0, y0); + sg.drawLine(x0, y0, x0 + (2 * height) / 4, (y0 + y1) / 2); + sg.drawLine(x0 + (2 * height) / 4, (y0 + y1) / 2, x0, y1); + sg.drawLine(x0, y1, x1, y1); + } + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[0]; + }//end method. + + + + + public String toString() + { + String returnString = ""; + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SuperSubFix.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SuperSubFix.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SuperSubFix.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SuperSubFix.java 2010-02-27 10:33:43.000000000 +0000 @@ -0,0 +1,214 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + + +public class SuperSubFix extends CompoundExpression { + + double iExtent = 0; + double iSubOffset = 0; + double iSuperOffset = 0; + + private SymbolBox iExpr; + + private SymbolBox iSuperfix; + + private SymbolBox iSubfix; + + public SuperSubFix(SymbolBox aExpr, SymbolBox aSuperfix, SymbolBox aSubfix) { + + iExpr = aExpr; + iSuperfix = aSuperfix; + iSubfix = aSubfix; + } + + public void setSuperfix(SymbolBox aExpression) { + iSuperfix = aExpression; + } + + public void setSubfix(SymbolBox aExpression) { + iSubfix = aExpression; + } + + public boolean hasSuperfix() { + + return (iSuperfix != null); + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + iSize = aSize; + iPosition = aPosition; + + // Get dimensions first + if (iDimension == null) { + + Dimensions dsfix = new Dimensions(0, 0); + Dimensions dlfix = new Dimensions(0, 0); + iExpr.calculatePositions(sg, aSize, null); + + if (iSuperfix != null) { + iSuperfix.calculatePositions(sg, aSize - 1, null); + } + + if (iSubfix != null) { + iSubfix.calculatePositions(sg, aSize - 1, null); + } + + Dimensions dexpr = iExpr.getDimension(); + + if (iSuperfix != null) { + dsfix = iSuperfix.getDimension(); + } + + if (iSubfix != null) { + dlfix = iSubfix.getDimension(); + } + + if (iExpr instanceof Sum || iExpr instanceof Integral) { + iSuperOffset = 0; + iSubOffset = 0; + + if (iSuperfix != null) { + iExtent = iExtent + iSuperfix.iAscent; + } + + if (iSubfix != null) { + iExtent = iExtent + iSubfix.iAscent; + } + + double fixMaxWidth = dsfix.width; + + if (dlfix.width > fixMaxWidth) { + fixMaxWidth = dlfix.width; + } + + if (dexpr.width > fixMaxWidth) { + fixMaxWidth = dexpr.width; + } + + iDimension = new Dimensions(fixMaxWidth, (dexpr.height + iExtent)); + } else { + + if (iSuperfix != null) { + iSuperOffset = iSuperfix.getDimension().height - iSuperfix.iAscent - iExpr.getDimension().height / 4; + iExtent = iExtent + iSuperOffset + iSuperfix.iAscent; + } + + if (iSubfix != null) { + iSubOffset = iSubfix.iAscent; + + double delta = iSubOffset + (iSubfix.getDimension().height - iSubfix.iAscent) - (iExpr.getDimension().height - iExpr.iAscent); + iExtent = iExtent + delta; + } + + double fixMaxWidth = dsfix.width; + + if (dlfix.width > fixMaxWidth) { + fixMaxWidth = dlfix.width; + } + + iDimension = new Dimensions(dexpr.width + fixMaxWidth, (dexpr.height + iExtent)); + } + + iAscent = iExpr.getCalculatedAscent() + iExtent; + + if (iSubfix != null) { + iAscent = iAscent - iSubfix.getDimension().height; + } + } + + if (aPosition != null) { + + Dimensions dsfix = new Dimensions(0, 0); + Dimensions dlfix = new Dimensions(0, 0); + Dimensions dexpr = iExpr.getDimension(); + + if (iSuperfix != null) { + dsfix = iSuperfix.getDimension(); + } + + if (iSubfix != null) { + dlfix = iSubfix.getDimension(); + } + + iExpr.calculatePositions(sg, aSize, new Position(aPosition.x, aPosition.y)); + + if (iExpr instanceof Sum || iExpr instanceof Integral) { + + if (iSuperfix != null) { + iSuperfix.calculatePositions(sg, aSize - 1, new Position(aPosition.x, (aPosition.y - iExpr.iAscent - dsfix.height))); + } + + if (iSubfix != null) { + iSubfix.calculatePositions(sg, aSize - 1, new Position(aPosition.x, (aPosition.y + iSubfix.iAscent + dlfix.height))); + } + } else { + + if (iSuperfix != null) { + iSuperfix.calculatePositions(sg, aSize - 1, new Position( (aPosition.x + dexpr.width), (aPosition.y - iExpr.iAscent - iSuperOffset))); + } + + if (iSubfix != null) { + iSubfix.calculatePositions(sg, aSize - 1, new Position( (aPosition.x + dexpr.width), (aPosition.y + iSubOffset))); + } + } + } + }//end calculate positions. + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg); + + iExpr.render(sg); + + if(iSuperfix != null) + { + iSuperfix.render(sg); + } + + if(iSubfix != null) + { + iSubfix.render(sg); + } + } + + + + public SymbolBox[] getChildren() + { + if(this.iSuperfix == null) + { + return new SymbolBox[] {this.iExpr, this.iSubfix}; + } + else if(this.iSubfix == null) + { + return new SymbolBox[] {this.iExpr, this.iSuperfix}; + } + else + { + return new SymbolBox[] {this.iExpr, this.iSuperfix, this.iSubfix}; + } + + }//end method. + + + + + public String toString() + { + String returnString = ""; + + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolBox.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolBox.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolBox.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolBox.java 2010-04-02 07:38:34.000000000 +0000 @@ -0,0 +1,149 @@ +/* {{{ License. + * 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 any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ //}}} +// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +import java.awt.Color; +import java.util.List; + +public abstract class SymbolBox { + + static boolean drawBoundingBox = false; + static int sequence = 0; + + protected Dimensions iDimension; + + protected Position iPosition; + int iSize; + double iAscent; + + private boolean endOfLevel = false; + + private int treeX; + + private int treeY; + + public static int getSequence() { + return sequence; + } + + public static void setSequence(int sequence) { + SymbolBox.sequence = sequence; + } + + + abstract public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition); + + abstract public void render(ScaledGraphics sg); + + public Dimensions getDimension() { + return iDimension; + } + + public Position getCalculatedPosition() { + return iPosition; + } + + public int getSetSize() { + return iSize; + } + + public double getCalculatedAscent() { + return iAscent; + } + + public void drawBoundingBox(ScaledGraphics sg, Color color) { + sg.setColor(color); + sg.setLineThickness(0); + double x0 = iPosition.x; + double y0 = iPosition.y - getCalculatedAscent(); + double x1 = x0 + iDimension.width; + double y1 = y0 + iDimension.height; + + sg.drawLine(x0, y0, x1, y0); + sg.drawLine(x1, y0, x1, y1); + sg.drawLine(x1, y1, x0, y1); + sg.drawLine(x0, y1, x0, y0); + + sg.drawscaledText("" + sequence++, x0, y0 + 3, .2); + + + + sg.setColor(Color.black); + }//end method. + + public static void setDrawBoundingBox(boolean drawBoundingBox) { + SymbolBox.drawBoundingBox = drawBoundingBox; + } + + public static boolean isDrawBoundingBox() { + return drawBoundingBox; + } + + public Bounds getScaledBounds(double scale) + { + scale = 1; + double x0 = iPosition.x * scale; + double y0 = (iPosition.y - getCalculatedAscent()) * scale; + double x1 = (x0 + iDimension.width) * scale; + double y1 = (y0 + iDimension.height) * scale; + + return new Bounds(y0, y1, x0, x1); + } + + + public abstract SymbolBox[] getChildren(); + + + + public boolean isEndOfLevel() { + return endOfLevel; + } + + public void setEndOfLevel(boolean endOfLevel) { + this.endOfLevel = endOfLevel; + } + + + public int getTextWidth(ScaledGraphics sg) + { + return (int) sg.getScaledTextWidth(toString()); + } + + public int getTextHeight(ScaledGraphics sg) + { + return (int) sg.getScaledTextHeight(toString()); + } + + public int getTreeX() { + return treeX; + } + + public void setTreeX(int treeX) { + this.treeX = treeX; + } + + public int getTreeY() { + return treeY; + } + + public void setTreeY(int treeY) { + this.treeY = treeY; + } + + +}//end class. + diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolName.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolName.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolName.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/symbolboxes/SymbolName.java 2010-02-27 10:33:43.000000000 +0000 @@ -0,0 +1,114 @@ +package org.mathpiper.ui.gui.worksheets.symbolboxes; + +import java.awt.Color; + +public class SymbolName extends SymbolBox { + + public String iSymbol; + + public SymbolName(String aSymbol) { + iSymbol = aSymbol; + + if (iSymbol.indexOf("\\") == 0) { + + if (iSymbol.equals("\\pi")) { + } else if (iSymbol.equals("\\infty")) { + } else if (iSymbol.equals("\\cdot")) { + } else if (iSymbol.equals("\\wedge")) { + } else if (iSymbol.equals("\\vee")) { + } else if (iSymbol.equals("\\neq")) { + } else { + iSymbol = iSymbol.substring(1); + } + } + } + + public void calculatePositions(ScaledGraphics sg, int aSize, Position aPosition) { + + int height = ScaledGraphics.fontForSize(aSize); + sg.setFontSize(height); + iSize = aSize; + iPosition = aPosition; + + if (iSymbol.equals("\\pi") || iSymbol.equals("\\wedge") || iSymbol.equals("\\vee")) { + iDimension = new Dimensions(sg.getScaledTextWidth("M"), height); + iAscent = sg.getAscent(); + } else if (iSymbol.equals("\\neq")) { + iDimension = new Dimensions(sg.getScaledTextWidth("="), height); + iAscent = sg.getAscent(); + } else if (iSymbol.equals("\\infty")) { + iDimension = new Dimensions(sg.getScaledTextWidth("oo"), height); + iAscent = sg.getAscent(); + } else if (iSymbol.equals("\\cdot")) { + iDimension = new Dimensions(sg.getScaledTextWidth("."), height); + iAscent = sg.getAscent(); + } else { + iAscent = sg.getAscent(); + iDimension = new Dimensions(sg.getScaledTextWidth(iSymbol), height); + } + } + + public void render(ScaledGraphics sg) { + + if(drawBoundingBox) drawBoundingBox(sg, Color.RED); + + if (iSymbol.equals("\\pi")) { + + double deltax = 0.15 * iDimension.width; + double deltay = 0.2 * iDimension.height; + sg.drawLine( (iPosition.x + 1 * deltax), (iPosition.y - iAscent + 2 * deltay), (iPosition.x + iDimension.width - 1 * deltax), (iPosition.y - iAscent + 2 * deltay)); + sg.drawLine( (iPosition.x + 2 * deltax), (iPosition.y - iAscent + 2 * deltay), (iPosition.x + 2 * deltax), (iPosition.y - iAscent + iDimension.height + 0 * deltay)); + sg.drawLine( (iPosition.x + iDimension.width - 2 * deltax), (iPosition.y - iAscent + 2 * deltay), (iPosition.x + iDimension.width - 2 * deltax), (iPosition.y - iAscent + iDimension.height + 0 * deltay)); + } else if (iSymbol.equals("\\wedge") || iSymbol.equals("\\vee")) { + + double deltax = 0.15 * iDimension.width; + double deltay = 0.2 * iDimension.height; + double ytip = (iPosition.y - iAscent + iDimension.height + 0 * deltay); + double ybase = (iPosition.y - iAscent + 2 * deltay); + + if (iSymbol.equals("\\wedge")) { + + double swap = ytip; + ytip = ybase; + ybase = swap; + } + + sg.drawLine( (iPosition.x + 1 * deltax), ybase, iPosition.x + iDimension.width / 2, ytip); + sg.drawLine( (iPosition.x + iDimension.width - 1 * deltax), ybase, iPosition.x + iDimension.width / 2, ytip); + } else if (iSymbol.equals("\\neq")) { + sg.setFontSize(ScaledGraphics.fontForSize(iSize)); + sg.drawText("=", iPosition.x, iPosition.y); + sg.drawLine(iPosition.x + (2 * iDimension.width) / 3, iPosition.y - iAscent + (2 * iDimension.height) / 6, iPosition.x + (1 * iDimension.width) / 3, iPosition.y - iAscent + (6 * iDimension.height) / 6); + } else if (iSymbol.equals("\\infty")) { + sg.setFontSize(ScaledGraphics.fontForSize(iSize)); + sg.drawText("o", iPosition.x + 1, iPosition.y); + sg.drawText("o", iPosition.x + sg.getScaledTextWidth("o") - 2, iPosition.y); + } else if (iSymbol.equals("\\cdot")) { + + int height = ScaledGraphics.fontForSize(iSize); + sg.setFontSize(height); + sg.drawText(".", iPosition.x, iPosition.y - height / 3); + } else { + sg.setFontSize(ScaledGraphics.fontForSize(iSize)); + sg.drawText(iSymbol, iPosition.x, iPosition.y); + } + } + + + + public SymbolBox[] getChildren() + { + return new SymbolBox[0]; + }//end method. + + + + + public String toString() + { + String returnString = ""; + + return returnString; + }//end method. + +}//end class diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TempPanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TempPanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TempPanel.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TempPanel.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -package org.mathpiper.ui.gui.worksheets; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import javax.swing.JPanel; - -public class TempPanel extends JPanel implements KeyListener{ - - public TempPanel() { - - System.out.println("Initializing."); - this.setSize(400, 400); //todo:tk: - - setBackground(Color.WHITE); - setLayout(null); - this.setPreferredSize(new Dimension(400,400)); - this.setFocusable(true); - requestFocus(); - addKeyListener(this); - - - }//end constructor. - - - public void keyPressed(KeyEvent e) - { - System.out.println("KeyPressed."); - //processKeyEvent(e); - } - - public void keyTyped(KeyEvent e) - { - System.out.println("KeyPressed."); - // processKeyEvent(e); - } - - public void keyReleased(KeyEvent e) - { - System.out.println("KeyPressed."); - // processKeyEvent(e); - } - -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TexParser.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TexParser.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TexParser.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TexParser.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,475 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -//}}} -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: -package org.mathpiper.ui.gui.worksheets; - -import org.mathpiper.ui.gui.worksheets.SBoxBuilder; -import org.mathpiper.ui.gui.worksheets.SBox; - - -public class TexParser -{ - - static String singleOps = "^_+=,"; - int currentPos; - String iCurrentExpression; - String nextToken; - - private void showToken() - { - System.out.println("[" + nextToken + "]"); - } - - void nextToken() - { - nextToken = ""; - - if (currentPos == iCurrentExpression.length()) - { - - //showToken(); - return; - } - - while (currentPos < iCurrentExpression.length() && isSpace(iCurrentExpression.charAt(currentPos))) - currentPos++; - - if (currentPos == iCurrentExpression.length()) - { - - //showToken(); - return; - } - else if (isAlNum(iCurrentExpression.charAt(currentPos))) - { - - int startPos = currentPos; - - while (currentPos < iCurrentExpression.length() && isAlNum(iCurrentExpression.charAt(currentPos))) - { - currentPos++; - } - - nextToken = iCurrentExpression.substring(startPos, currentPos); - - //showToken(); - return; - } - - int c = iCurrentExpression.charAt(currentPos); - - if (c == '{') - { - nextToken = "{"; - currentPos++; - - //showToken(); - return; - } - else if (c == '}') - { - nextToken = "}"; - currentPos++; - - //showToken(); - return; - } - else if (singleOps.indexOf(c) >= 0) - { - nextToken = "" + (char)c; - currentPos++; - - //showToken(); - return; - } - else if (c == '\\') - { - - int startPos = currentPos; - - while (currentPos < iCurrentExpression.length() && (isAlNum(iCurrentExpression.charAt(currentPos)) || iCurrentExpression.charAt(currentPos) == '\\')) - { - currentPos++; - } - - nextToken = iCurrentExpression.substring(startPos, currentPos); - - //showToken(); - return; - } - - //showToken(); - } - - boolean matchToken(String token) - { - - if (nextToken.equals(token)) - - return true; - - System.out.println("Found " + nextToken + ", expected " + token); - - return false; - } - - public SBox parse(String aExpression) - { - iCurrentExpression = aExpression; - currentPos = 0; - nextToken(); - - return parseTopExpression(); - } - - SBox parseTopExpression() - { - - SBoxBuilder builder = new SBoxBuilder(); - parseOneExpression10(builder); - - SBox expression = builder.pop(); - - return expression; - } - - void parseOneExpression10(SBoxBuilder builder) - { - parseOneExpression20(builder); - - // = , - while (nextToken.equals("=") || nextToken.equals("\\neq") || nextToken.equals(",")) - { - - String token = nextToken; - nextToken(); - parseOneExpression20(builder); - builder.process(token); - } - } - - void parseOneExpression20(SBoxBuilder builder) - { - parseOneExpression25(builder); - - // +, - - while (nextToken.equals("+") || nextToken.equals("-") || nextToken.equals("\\wedge") || nextToken.equals("\\vee") || nextToken.equals("<") || nextToken.equals(">") || nextToken.equals("\\leq") || nextToken.equals("\\geq")) - { - - String token = nextToken; - - if (token.equals("-")) - token = "-/2"; - else if (token.equals("\\leq")) - token = "<="; - else if (token.equals("\\geq")) - token = ">="; - - nextToken(); - parseOneExpression25(builder); - builder.process(token); - } - } - - void parseOneExpression25(SBoxBuilder builder) - { - parseOneExpression30(builder); - - // implicit * - while (nextToken.length() > 0 && !nextToken.equals("+") && !nextToken.equals("-") && !nextToken.equals("=") && !nextToken.equals("\\neq") && !nextToken.equals("}") && !nextToken.equals("&") && !nextToken.equals("\\wedge") && !nextToken.equals("\\vee") && !nextToken.equals("<") && !nextToken.equals(">") && !nextToken.equals("\\leq") && !nextToken.equals("\\geq") && !nextToken.equals("\\end") && !nextToken.equals("\\\\") && !nextToken.equals("\\right)") && !nextToken.equals("\\right]") && !nextToken.equals(",")) - { - - //System.out.println("nextToken = "+nextToken); - String token = "*"; - parseOneExpression30(builder); - - //System.out.println("After: nextToken = "+nextToken); - builder.process(token); - } - } - - void parseOneExpression30(SBoxBuilder builder) - { - parseOneExpression40(builder); - - // _, ^ - while (nextToken.equals("_") || nextToken.equals("^") || nextToken.equals("!")) - { - - if (nextToken.equals("!")) - { - builder.process(nextToken); - nextToken(); - } - else - { - - String token = nextToken; - nextToken(); - parseOneExpression40(builder); - builder.process(token); - } - } - } - - void parseOneExpression40(SBoxBuilder builder) - { - - // atom - if (nextToken.equals("{")) - { - nextToken(); - parseOneExpression10(builder); - - if (!nextToken.equals("}")) - { - System.out.println("Got " + nextToken + ", expected }"); - - return; - } - } - else if (nextToken.equals("\\left(")) - { - nextToken(); - parseOneExpression10(builder); - - if (!nextToken.equals("\\right)")) - { - System.out.println("Got " + nextToken + ", expected \\right)"); - - return; - } - - builder.process("[roundBracket]"); - } - else if (nextToken.equals("\\left[")) - { - nextToken(); - parseOneExpression10(builder); - - if (!nextToken.equals("\\right]")) - { - System.out.println("Got " + nextToken + ", expected \\right]"); - - return; - } - - builder.process("[squareBracket]"); - } - else if (nextToken.equals("\\sqrt")) - { - nextToken(); - parseOneExpression25(builder); - builder.process("[sqrt]"); - - return; - } - else if (nextToken.equals("\\exp")) - { - nextToken(); - builder.process("e"); - parseOneExpression40(builder); - builder.process("^"); - - return; - } - else if (nextToken.equals("\\imath")) - { - builder.process("i"); - } - else if (nextToken.equals("\\mathrm")) - { - nextToken(); - - if (!matchToken("{")) - - return; - - int startPos = currentPos; - - while (currentPos < iCurrentExpression.length() && iCurrentExpression.charAt(currentPos) != '}') - currentPos++; - - String literal = iCurrentExpression.substring(startPos, currentPos); - currentPos++; - builder.processLiteral(literal); - nextToken(); - - return; - } - else if (nextToken.equals("-")) - { - nextToken(); - parseOneExpression30(builder); - builder.process("-/1"); - - return; - } - else if (nextToken.equals("\\neg")) - { - nextToken(); - parseOneExpression30(builder); - builder.process("~"); - - return; - } - else if (nextToken.equals("\\sum")) - { - builder.process("[sum]"); - } - else if (nextToken.equals("\\int")) - { - builder.process("[int]"); - } - else if (nextToken.equals("\\frac")) - { - nextToken(); - parseOneExpression40(builder); - parseOneExpression40(builder); - builder.process("/"); - - return; - } - else if (nextToken.equals("\\begin")) - { - nextToken(); - - if (!matchToken("{")) - - return; - - nextToken(); - - String name = nextToken; - nextToken(); - - if (!matchToken("}")) - - return; - - if (name.equals("array")) - { - - int nrColumns = 0; - int nrRows = 0; - nextToken(); - - if (!matchToken("{")) - - return; - - nextToken(); - - String coldef = nextToken; - nextToken(); - - if (!matchToken("}")) - - return; - - nrColumns = coldef.length(); - nrRows = 1; - nextToken(); - - while (!nextToken.equals("\\end")) - { - parseOneExpression10(builder); - - if (nextToken.equals("\\\\")) - { - nrRows++; - nextToken(); - } - else if (nextToken.equals("&")) - { - nextToken(); - } - else - { - - // System.out.println("END? "+nextToken); - } - } - - nextToken(); - - if (!matchToken("{")) - - return; - - nextToken(); - - String name2 = nextToken; - nextToken(); - - if (!matchToken("}")) - - return; - - if (name2.equals("array")) - { - builder.process("" + nrRows); - builder.process("" + nrColumns); - builder.process("[grid]"); - } - } - } - else - { - builder.process(nextToken); - } - - nextToken(); - } - - boolean isSpace(int c) - { - - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - - return true; - - return false; - } - - boolean isAlNum(int c) - { - - if (isSpace(c)) - - return false; - - if (c == '{') - - return false; - - if (c == '}') - - return false; - - if (c == '\\') - - return false; - - if (singleOps.indexOf(c) >= 0) - - return false; - - return true; - } -} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TreePanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TreePanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TreePanel.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TreePanel.java 2010-04-02 07:38:34.000000000 +0000 @@ -0,0 +1,237 @@ +package org.mathpiper.ui.gui.worksheets; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.util.LinkedList; +import java.util.Queue; +import javax.swing.JPanel; +import org.mathpiper.ui.gui.worksheets.symbolboxes.Position; +import org.mathpiper.ui.gui.worksheets.symbolboxes.ScaledGraphics; +import org.mathpiper.ui.gui.worksheets.symbolboxes.SymbolBox; + +public class TreePanel extends JPanel implements ViewPanel { + + protected SymbolBox symbolBox; + protected double viewScale = 1; + private Queue queue = new LinkedList(); + private int[] lastOnRasterArray = new int[10000]; + private int maxTreeY = 0; + private boolean paintedOnce = false; + + public TreePanel(SymbolBox symbolBox, double viewScale) { + this.symbolBox = symbolBox; + this.setOpaque(true); + this.viewScale = viewScale; + this.setBackground(Color.white); + + for(int index = 0; index < lastOnRasterArray.length; index++) + { + lastOnRasterArray[index] = -1; + }//end for. + + } + + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + + g2d.setStroke(new BasicStroke((float) (2), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + g2d.setColor(Color.black); + g2d.setBackground(Color.white); + ScaledGraphics sg = new ScaledGraphics(g2d); + sg.setLineThickness(0); + sg.setViewScale(viewScale); + + int x = 0; + int y = 0; + symbolBox.calculatePositions(sg, 3, new Position(x , y)); + + + for(int index = 0; index < lastOnRasterArray.length; index++) + { + lastOnRasterArray[index] = -1; + }//end for. + + maxTreeY = 0; + + layoutTree(symbolBox, 50/*yPosition*/, -20/*position*/, null, sg); + + + queue.add(symbolBox); + + SymbolBox currentNode; + + + while (!queue.isEmpty()) { + currentNode = queue.remove(); + + if (currentNode != null) { + String nodeString = currentNode.toString(); + + sg.drawText(nodeString, currentNode.getTreeX(), currentNode.getTreeY() );//xPosition, yPosition); + + SymbolBox[] children = currentNode.getChildren(); + + if (children != null) { + for (SymbolBox child : children) { + if (child != null) { + queue.add(child); + + sg.setColor(Color.BLACK); + sg.setLineThickness(1.5); + sg.drawLine(currentNode.getTreeX() + currentNode.getTextWidth(sg)/2, currentNode.getTreeY() + 4, child.getTreeX() + child.getTextWidth(sg)/2, child.getTreeY() - child.getTextHeight(sg) + 3); + + } + } + + }//end if. + + + } else { + System.out.print(""); + } + + if(paintedOnce == false) + { + super.revalidate(); + paintedOnce = true; + } + + }//end while. + + } + + public Dimension getPreferredSize() { + + if(paintedOnce == false) + { + return new Dimension(0,0); + } + + int maxWidth = 0; + + int index = 0; + + for(; index < lastOnRasterArray.length; index++) + { + if(lastOnRasterArray[index] > maxWidth) + { + maxWidth = lastOnRasterArray[index]; + }//end if. + + }//end for. + + maxWidth = (int) ((maxWidth + 100) * viewScale); + + int maxHeight = (int) ((maxTreeY) * viewScale); + + return(new Dimension(maxWidth, maxHeight)); + + }//end method. + + + public void setViewScale(double viewScale) { + this.viewScale = viewScale; + this.revalidate(); + this.repaint(); + } + + + //Layout algorithm from "Aesthetic Layout of Generalized Trees" by Anthony Bloesch. + private int layoutTree(SymbolBox tree, int yPosition, int position, SymbolBox parent, ScaledGraphics sg) + { + int Y_SEPARATION = 35; + int MIN_X_SEPARATION = 20; + + int branchPosition; + int i; + int leftPosition; + int rightPosition; + int width; + + int interBranchSpace = 75; + + + if(tree == null) + { + return position; + } + else /* Place subtree. */ + { + /* Ensure the nominal position of the node is to the right of any other node. */ + for(i = yPosition - Y_SEPARATION; i < yPosition+tree.getTextHeight(sg); i++) + { + int lastOnRaster = lastOnRasterArray[i]; + + int possibleNewPosition = (lastOnRaster + MIN_X_SEPARATION + tree.getTextWidth(sg)/2); + + if(possibleNewPosition > position) + { + position = possibleNewPosition; + }//end if. + + }//end for. + + + if(tree.getChildren().length >= 1){ /* Place branches if they exist. */ + + if(tree.getChildren().length > 1) { + + width = (tree.getChildren()[0].getTextWidth(sg) + + tree.getChildren()[tree.getChildren().length-1].getTextWidth(sg))/2 + + (tree.getChildren().length-1)*MIN_X_SEPARATION; + + for(i=1; i < tree.getChildren().length-1; i++) + width += tree.getChildren()[i].getTextWidth(sg);} + + else + width = 0; + + branchPosition = position - width/2; + /* Position far left branch. */ + leftPosition = layoutTree(tree.getChildren()[0], yPosition + tree.getTextHeight(sg) + Y_SEPARATION, + branchPosition, tree, sg); + + /* Position the other branches if they exist. */ + rightPosition = leftPosition; + for(i = 1; i < tree.getChildren().length; i++){ + branchPosition += MIN_X_SEPARATION + + (tree.getChildren()[i-1].getTextWidth(sg) + + tree.getChildren()[i].getTextWidth(sg))/2; + rightPosition = layoutTree(tree.getChildren()[i], yPosition + tree.getTextHeight(sg) + Y_SEPARATION, + branchPosition, tree, sg); + } /* for */ + + position = (leftPosition+rightPosition)/2; + + }//end if tree -> nrBranches >= 1 */ + + /* Add node to list. */ + for(i = yPosition - Y_SEPARATION; i < yPosition+tree.getTextHeight(sg); i++) + { + lastOnRasterArray[i] = position + ((tree.getTextWidth(sg) + interBranchSpace) + 1)/2; + if(i > maxTreeY) + { + maxTreeY = i; + }//end if. + }//end for. + + + tree.setTreeX(position); + + tree.setTreeY(yPosition); + + return position; + + + }//end else. + + + }//end method. + +}//end class. diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TResult.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TResult.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/TResult.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/TResult.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -/* {{{ License. - * 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 any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ //}}} - -// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: - -package org.mathpiper.ui.gui.worksheets; - - -public interface TResult -{ - public int nrLines(MathPiperGraphicsContext aGraphicsContext, int width) ; - public void draw(MathPiperGraphicsContext aGraphicsContext, int current_word, int width, int height, int red, int green, int blue); -}; - diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ViewPanel.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ViewPanel.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/gui/worksheets/ViewPanel.java 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/gui/worksheets/ViewPanel.java 2010-02-26 08:35:35.000000000 +0000 @@ -0,0 +1,11 @@ + +package org.mathpiper.ui.gui.worksheets; + + +public interface ViewPanel { + + void setViewScale(double viewScale); + + void repaint(); + +} diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/ui/text/consoles/Console.java mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/text/consoles/Console.java --- mathpiper-0.0.svn2556/src/org/mathpiper/ui/text/consoles/Console.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/ui/text/consoles/Console.java 2010-12-07 07:11:02.000000000 +0000 @@ -13,7 +13,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //}}} - // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper.ui.text.consoles; @@ -25,12 +24,15 @@ import org.mathpiper.interpreters.Interpreter; import org.mathpiper.interpreters.Interpreters; + /** * Provides a command line console which can be used to interact with a mathpiper instance. */ public class Console { - Interpreter interpreter; + private Interpreter interpreter; + private boolean suppressOutput = false; + public Console() { //MathPiper needs an output stream to send "side effect" output to. @@ -38,10 +40,12 @@ interpreter = Interpreters.getSynchronousInterpreter(); } + void addDirectory(String directory) { interpreter.addScriptsDirectory(directory); } + String readLine(InputStreamReader aStream) { StringBuffer line = new StringBuffer(); try { @@ -56,10 +60,19 @@ return line.toString(); } + String evaluate(String input) { //return (String) interpreter.evaluate(input); EvaluationResponse response = interpreter.evaluate(input, true); - String responseString = "Result> " + response.getResult() + "\n"; + + String responseString = ""; + + if (suppressOutput == false) { + responseString = "Result> " + response.getResult() + "\n"; + } else { + responseString = "Result> " + "OUTPUT SUPPRESSED\n"; + this.suppressOutput = false; + } if (!response.getSideEffects().equalsIgnoreCase("")) { @@ -67,7 +80,11 @@ } if (!response.getExceptionMessage().equalsIgnoreCase("")) { - responseString = responseString + response.getExceptionMessage() + " Source file name: " + response.getSourceFileName() + " Near line number: " + response.getLineNumber() + "\n"; + responseString = responseString + response.getExceptionMessage() + " Source file name: " + response.getSourceFileName() + ", Near line number: " + response.getLineNumber() + "\n"; + } + else if (response.getException() != null) + { + response.getException().printStackTrace(); } @@ -75,7 +92,6 @@ }//end evaluate. - /** * A Read Evaluate Print Loop for implementing text consoles. * @@ -84,7 +100,7 @@ */ public void repl(InputStream inputStream, PrintStream out) { out.println("\nMathPiper version '" + Version.version + "'."); - out.println("See http://mathrider.org for more information and documentation on MathPiper."); + out.println("See http://mathpiper.org for more information and documentation on MathPiper."); out.println("Place a backslash at the end of a line to enter multiline input."); out.println("To exit MathPiper, enter \"Exit()\" or \"exit\" or \"quit\" or Ctrl-c.\n"); /*TODO fixme @@ -103,17 +119,19 @@ input = readLine(new InputStreamReader(inputStream)); input = input.trim(); - if(input.endsWith("\\")) - { - oneOrMoreLineInput += input.substring(0,input.length()-1); + if (input.endsWith("\\")) { + oneOrMoreLineInput += input.substring(0, input.length() - 1); continue; - } - else - { + } else { oneOrMoreLineInput += input; } + oneOrMoreLineInput = oneOrMoreLineInput.trim(); + if(oneOrMoreLineInput.endsWith(";;")) + { + this.suppressOutput = true; + } String responseString = evaluate(oneOrMoreLineInput); oneOrMoreLineInput = ""; @@ -127,6 +145,7 @@ } }//end repl. + /** * The normal entry point for running mathpiper from a command line. It processes command line arguments, * sets mathpiper's standard output to System.out, then enters a REPL (Read, Evaluate, Print Loop). Currently, @@ -155,15 +174,20 @@ } i++; } - int scriptsToRun = i; - //Change the default directory. tk. if (defaultDirectory != null) { console.addDirectory(defaultDirectory); } - console.repl(System.in, System.out); + if (i < argv.length) { + for (; i < argv.length; ++i) { + String cmd = "LoadScript(\"".concat(argv[i]).concat("\");"); + System.out.println(console.evaluate(cmd)); + } + } else { + console.repl(System.in, System.out); + } diff -Nru mathpiper-0.0.svn2556/src/org/mathpiper/Version.java mathpiper-0.81f+dfsg1/src/org/mathpiper/Version.java --- mathpiper-0.0.svn2556/src/org/mathpiper/Version.java 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/src/org/mathpiper/Version.java 2011-04-24 07:45:56.000000000 +0000 @@ -17,9 +17,11 @@ // :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0: package org.mathpiper; +//$Revision: 4053 $ +//$Id: Version.java 4053 2011-04-24 07:45:56Z ted.kosan $ public class Version { -//"$Id$" - public static final String version = ".76j"; + + public static final String version = ".81f"; }//end class. diff -Nru mathpiper-0.0.svn2556/storage/scripts/array.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/array.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/array.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/array.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - - -ArrayCreateFromList(list):= -[ - Local(result,i); - result:=ArrayCreate(Length(list),0); - i:=1; - While (list != {}) - [ - result[i]:=Head(list); - i++; - list:=Tail(list); - ]; - result; -]; - -ArrayToList(array):= (array[1 .. ArraySize(array) ]); - diff -Nru mathpiper-0.0.svn2556/storage/scripts/array.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/array.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/array.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/array.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - -ArrayCreateFromList -ArrayToList -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/assoc.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/assoc.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/assoc.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/assoc.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ - -/* Assoc : given an assoc list like for example l:={{a,2},{b,3}}, - Assoc(b,l) will return {b,3}. if the key is not in the list, - it will return the atom Empty. -*/ - -Function("Assoc",{key,list}) Builtin'Assoc(key,list); - - -AssocIndices(associndiceslist_IsList) <-- - DestructiveReverse(MapSingle("Head",associndiceslist)); - -/// Delete an element of an associative list. -LocalSymbols(hash, key, element, hash'expr) -[ - -/// AssocDelete(hash,{"key", value}) -10 # AssocDelete(hash_IsList, element_IsList) <-- -[ - Local(index); - index := Find(hash, element); - If( - index > 0, - DestructiveDelete(hash, index) - ); - index>0; // return False if nothing found - -]; - - -/// AssocDelete(hash, "key") -20 # AssocDelete(hash_IsList, key_IsString) <-- -[ - AssocDelete(hash, Builtin'Assoc(key, hash)); -]; - -30 # AssocDelete(hash_IsList, Empty) <-- False; - -//HoldArg("AssocDelete", hash); -//UnFence("AssocDelete", 1); -//UnFence("AssocDelete", 2); - -]; // LocalSymbols(hash, ...) - diff -Nru mathpiper-0.0.svn2556/storage/scripts/assoc.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/assoc.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/assoc.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/assoc.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -Assoc -AssocIndices -AssocDelete -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/base.rep/math.mpi mathpiper-0.81f+dfsg1/storage/scripts/base.rep/math.mpi --- mathpiper-0.0.svn2556/storage/scripts/base.rep/math.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/base.rep/math.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,225 +0,0 @@ - -/* This file contains some math functions that can be defined based on the - BigNumber API. This file should only use the features supported by the - compiler, as it gets compiled to a plugin for speed. - */ - - -// first define the binary exponentiation algorithm, MathIntPower. -// Later, the PowerN function will be defined through IntPower and MathLn/ExpN. Note that ExpN uses IntPower. - -// power x^n only for non-negative integer n -Defun("PositiveIntPower", {x,n}) -[ - Local(result,unit); - If(LessThan(n,0), False, - [ - Set(unit,1); // this is a constant, initial value of the power - Set(result, unit); - If(Equals(n,0),unit, - If(Equals(n,1),x, - [ - While(GreaterThan(n,0)) - [ - If( - Equals(BitAnd(n,1), 1), -// If( -// Equals(result,unit), // if result is already assigned -// Set(result, x), // avoid multiplication - Set(result, MultiplyN(result,x)) -// ) - ); - Set(x, MultiplyN(x,x)); - Set(n,ShiftRight(n,1)); - ]; - result; - ] - ) - ); - ]); -]; - -// power x^y only for integer y (perhaps negative) -Defun("MathIntPower", {x,y}) - If(Equals(x,0),0,If(Equals(x,1),1, - If(IsInteger(y),If(LessThan(y,0), // negative power, need to convert x to float to save time, since x^(-n) is never going to be integer anyway - DivideN(1, PositiveIntPower(AddN(x,0.),MathNegate(y))), - // now the positive integer y calculation - note that x might still be integer - PositiveIntPower(x,y) - ), // floating-point calculation is absent, return False - False) - )); - - -Defun("Trigonometry",{x,i,sum,term}) -[ - Local(x2,orig,eps,previousPrec,newPrec); - Set(previousPrec,BuiltinPrecisionGet()); - Set(newPrec,AddN(BuiltinPrecisionGet(),2)); - Set(x2,MultiplyN(x,x)); - BuiltinPrecisionSet(newPrec); - Set(eps,MathIntPower(10,MathNegate(previousPrec))); - While(GreaterThan(AbsN(term),eps)) - [ - Set(term,MultiplyN(term,x2)); - Set(i,AddN(i,1.0)); - Set(term,DivideN(term,i)); - Set(i,AddN(i,1.0)); - Set(term,DivideN(MathNegate(term),i)); - BuiltinPrecisionSet(previousPrec); - Set(sum, AddN(sum, term)); - BuiltinPrecisionSet(newPrec); - ]; - BuiltinPrecisionSet(previousPrec); - sum; -]; - -Defun("SinN",{x})Trigonometry(x,1.0,x,x); -Defun("CosN",{x})Trigonometry(x,0.0,1.0,1.0); -Defun("TanN",{x})DivideN(SinN(x),CosN(x)); - -Defun("ArcSinN",{int1}) -[ - Local(result,eps); - Set(result,FastArcSin(int1)); - Local(x,q,s,c); - Set(q,SubtractN(SinN(result),int1)); - Set(eps,MathIntPower(10,MathNegate(BuiltinPrecisionGet()))); - While(GreaterThan(AbsN(q),eps)) - [ - Set(s,SubtractN(int1,SinN(result))); - Set(c,CosN(result)); - Set(q,DivideN(s,c)); - Set(result,AddN(result,q)); - ]; - result; -]; - - -// simple Taylor expansion, use only for 0<=x<1 -Defun("MathExpTaylor0",{x}) -[ - Local(i,aResult,term,eps); - // Exp(x)=Sum(i=0 to Inf) x^(i) /(i)! - // Which incrementally becomes the algorithm: - // - // i <- 0 - Set(i,0); - // sum <- 1 - Set(aResult,1.0); - // term <- 1 - Set(term,1.0); - Set(eps,MathIntPower(10,MathNegate(BuiltinPrecisionGet()))); - // While (term>epsilon) - While(GreaterThan(AbsN(term),eps)) - [ - // i <- i+1 - Set(i,AddN(i,1)); - // term <- term*x/(i) - Set(term,DivideN(MultiplyN(term,x),i)); - // sum <- sum+term - Set(aResult,AddN(aResult,term)); - ]; - aResult; -]; - -/// Identity transformation, compute Exp(x) from value=Exp(x/2^n) by squaring the value n times -Defun("MathExpDoubling", {value, n}) -[ - Local(shift, result); - Set(shift, n); - Set(result, value); - While (GreaterThan(shift,0)) // will lose 'shift' bits of precision here - [ - Set(result, MultiplyN(result, result)); - Set(shift, AddN(shift,MathNegate(1))); - ]; - result; -]; - -// MathMul2Exp: multiply x by 2^n quickly (for integer n) -// this should really be implemented in the core as a call to BigNumber::ShiftRight or ShiftLeft -Defun("MathMul2Exp", {x,n}) // avoid roundoff by not calculating 1/2^n separately - If(GreaterThan(n,0), MultiplyN(x, MathIntPower(2,n)), DivideN(x, MathIntPower(2,MathNegate(n)))); -// this doesn't work because ShiftLeft/Right don't yet work on floats -// If(GreaterThan(n,0), ShiftLeft(x,n), ShiftRight(x,n) -// ); - -/// ExpN(x). Algorithm: for x<0, divide 1 by ExpN(-x); for x>1, compute ExpN(x/2)^2 recursively; for 0="," >= "}, {"<"," < "}, {">"," > "}, - {"And"," && "}, {"Or"," || "}, {">>", " >> "}, - { "<<", " << " }, { "&", " & " }, { "|", " | " }, - { "%", " % " }, { "^", " ^ " }, - }; - - CFormRegularOps() := cformRegularOps; -]; // LocalSymbols(cformRegularOps) - - /* This is the template for "regular" binary infix operators: -100 # CForm(_x + _y, _p) <-- CFormBracketIf(p>1); -20 # (II^_n)_(IsOdd(n) = True) <-- II*(-1)^(n>>1); - -LocalSymbols(complexReduce) [ - - Set(complexReduce, - Hold( - { - Exp(x_IsComplexII) <- Exp(ReII(x))*(Cos(ImII(x))+II*Sin(ImII(x))) - })); - - NN(_c) <-- - [ - Local(result); - c := (c /:: complexReduce); - result := Coef(Expand(c,II),II,{0,1}); - result; - ]; - -]; //LocalSymbols(complexReduce) - - -ReII(_c) <-- NN(c)[1]; -ImII(_c) <-- NN(c)[2]; -IsComplexII(_c) <-- (ImII(c) != 0); - - - -0 # Complex(_r,i_IsZero) <-- r; -2 # Complex(Complex(_r1,_i1),_i2) <-- Complex(r1,i1+i2); -2 # Complex(_r1,Complex(_r2,_i2)) <-- Complex(r1-i2,r2); - -6 # Complex(Undefined,_x) <-- Undefined; -6 # Complex(_x,Undefined) <-- Undefined; - -/*Real parts */ -110 # Re(Complex(_r,_i)) <-- r; -120 # Re(Undefined) <-- Undefined; -300 # Re(_x) <-- x; - -/* Imaginary parts */ -110 # Im(Complex(_r,_i)) <-- i; -120 # Im(Undefined) <-- Undefined; -300 # Im(_x) <-- 0; - -/* All things you can request a real and imaginary part for are complex */ -1 # IsComplex(x_IsRationalOrNumber) <-- True; -2 # IsComplex(Complex(_r,_i)) <-- True; -3 # IsComplex(_x) <-- False; - -IsNotComplex(x) := Not(IsComplex(x)); -/* Addition */ - -110 # Complex(_r1,_i1) + Complex(_r2,_i2) <-- Complex(r1+r2,i1+i2); -300 # Complex(_r,_i) + x_IsConstant <-- Complex(r+x,i); -300 # x_IsConstant + Complex(_r,_i) <-- Complex(r+x,i); - -110 # - Complex(_r,_i) <-- Complex(-r,-i); - -300 # Complex(_r,_i) - x_IsConstant <-- Complex(r-x,i); -300 # x_IsConstant - Complex(_r,_i) <-- Complex((-r)+x,-i); -111 # Complex(_r1,_i1) - Complex(_r2,_i2) <-- Complex(r1-r2,i1-i2); - -/* Multiplication */ -110 # Complex(_r1,_i1) * Complex(_r2,_i2) <-- Complex(r1*r2-i1*i2,r1*i2+r2*i1); -/* right now this is slower than above -110 # Complex(_r1,_i1) * Complex(_r2,_i2) <-- -[ // the Karatsuba trick - Local(A,B); - A:=r1*r2; - B:=i1*i2; - Complex(A-B,(r1+i1)*(r2+i2)-A-B); -]; -*/ - - -// Multiplication in combination with complex numbers in the light of infinity -250 # Complex(r_IsZero,_i) * x_IsInfinity <-- Complex(0,i*x); -250 # Complex(_r,i_IsZero) * x_IsInfinity <-- Complex(r*x,0); -251 # Complex(_r,_i) * x_IsInfinity <-- Complex(r*x,i*x); - -250 # x_IsInfinity * Complex(r_IsZero,_i) <-- Complex(0,i*x); -250 # x_IsInfinity * Complex(_r,i_IsZero) <-- Complex(r*x,0); -251 # x_IsInfinity * Complex(_r,_i) <-- Complex(r*x,i*x); - - -300 # Complex(_r,_i) * y_IsConstant <-- Complex(r*y,i*y); -300 # y_IsConstant * Complex(_r,_i) <-- Complex(r*y,i*y); - -330 # Complex(_r,_i) * (y_IsConstant / _z) <-- (Complex(r*y,i*y))/z; -330 # (y_IsConstant / _z) * Complex(_r,_i) <-- (Complex(r*y,i*y))/z; - - -110 # x_IsConstant / Complex(_r,_i) <-- (x*Conjugate(Complex(r,i)))/(r^2+i^2); - - -300 # Complex(_r,_i) / y_IsConstant <-- Complex(r/y,i/y); - -110 # (_x ^ Complex(_r,_i)) <-- Exp(Complex(r,i)*Ln(x)); - -110 # Sqrt(Complex(_r,_i)) <-- Exp(Ln(Complex(r,i))/2); -110 # (Complex(_r,_i) ^ x_IsRationalOrNumber)_(Not(IsInteger(x))) <-- Exp(x*Ln(Complex(r,i))); - -// This is commented out because it used PowerN so (2*I)^(-10) became a floating-point number. Now everything is handled by binary algorithm below -//120 # Complex(r_IsZero,_i) ^ n_IsInteger <-- {1,I,-1,-I}[1+Mod(n,4)] * i^n; - -123 # Complex(_r, _i) ^ n_IsNegativeInteger <-- 1/Complex(r, i)^(-n); - -124 # Complex(_r, _i) ^ (p_IsZero) <-- 1; // cannot have Complex(0,0) here - -125 # Complex(_r, _i) ^ n_IsPositiveInteger <-- -[ - // use binary method - Local(result, x); - x:=Complex(r,i); - result:=1; - While(n > 0) - [ - if ((n&1) = 1) - [ - result := result*x; - ]; - x := x*x; - n := n>>1; - ]; - result; -]; - - -/*[ // this method is disabled b/c it suffers from severe roundoff errors - Local(rr,ii,count,sign); - rr:=r^n; - ii:=0; - For(count:=1,count<=n,count:=count+2) [ - sign:=If(IsZero(Mod(count-1,4)),1,-1); - ii:=ii+sign*Bin(n,count)*i^count*r^(n-count); - If(count>> ",CustomEval'Expression()); - While(debugging) - [ - Echo("DebugOut> ",Eval(FromString(ReadCmdLineString("Debug> "):";")Read())); - // If(debugging,Echo("DebugOut> ",debugRes)); - If(IsExitRequested(),debugging:=False); - ]; - ]); - debugging:=nextdebugging; - - If(IsExitRequested(),debugstopped:=True); - -]; -Macro(DebugLeave,{}) -[ - If(debugging = False And debugstopdepth >= 0 And Length(debugcallstack) = debugstopdepth, - [ - debugstepoverline := -1; - debugging := True; - debugstopdepth := -1; - ]); - - debugcallstack := Tail(debugcallstack); - If(debugverbose,Echo(CustomEval'Result()," <-- ",CustomEval'Expression())); -]; -Macro(Debug,{expression}) -ToStdout() -[ - DebugStart(); - CustomEval(DebugEnter(),DebugLeave(),If(debugstopped,Check(False,""),[debugging:=True;debugcallstack := Tail(debugcallstack);]),@expression); -]; - - -ProfileStart():= -[ - profilefn:={}; -]; -10 # ProfileEnter()_(IsFunction(CustomEval'Expression())) <-- -[ - Local(fname); - fname:=Type(CustomEval'Expression()); - If(profilefn[fname]=Empty,profilefn[fname]:=0); - profilefn[fname] := profilefn[fname]+1; -]; -Macro(Profile,{expression}) -[ - ProfileStart(); - CustomEval(ProfileEnter(),True,CustomEval'Stop(),@expression); - ForEach(item,profilefn) - Echo("Function ",item[1]," called ",item[2]," times"); -]; - -/// Measure the time taken by evaluation and print results. -Macro(Time,{expression}) -[ - Local(result); - Echo(GetTime(Set(result, @expression)), "seconds taken"); - result; -]; - - - - -// ClearScreenString : the ascii escape codes to clear the screen -ClearScreenString := CharString(27):"[2J":CharString(27):"[1;1H"; - -// WriteLines: do the actual outputting of lines of a file to screen -WriteLines(filename,lines,from,nrlines,breakpoints,current):= -[ - Local(i,nr); - nr:=Length(lines); - WriteString(ClearScreenString); - Echo("File ",filename," at line ",current); - For(i:=from,i") - else - WriteString(" "); - if (Contains(breakpoints,i)) - WriteString("*") - else - WriteString(" "); - WriteString("| "); - Echo(lines[i][1]); - ]; -]; -Debug'FileLoaded := ""; -Debug'FileLines := {}; -Debug'NrLines:=20; - -// -// DebugShowCode: show the part of the file we are currently executing (based on the -// value returned by CustomEval'Expression() ). -// -// Currently unimplemented, should we remove? -// -DebugShowCode():= -[ - False; -]; - -]; //LocalSymbols - - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/debug.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/debug.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/debug.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/debug.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -TraceExp -Debug -Profile -DebugRun -DebugStep -DebugStepOver -DebugBreakAt -DebugRemoveBreakAt -DebugStop -DebugVerbose -DebugAddBreakpoint -BreakpointsClear -DebugCallstack -DebugBreakIf -DebugLocals -Time -DebugShowCode -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/deffunc.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/deffunc.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/deffunc.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/deffunc.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,255 +0,0 @@ - -/* Defining a macro-like function that declares a function - * with only one rule. - */ -RuleBase("Function",{oper,args,body}); -HoldArg("Function",oper); -HoldArg("Function",args); -HoldArg("Function",body); - -RuleBase("Macro",{oper,args,body}); -HoldArg("Macro",oper); -HoldArg("Macro",args); -HoldArg("Macro",body); - -// function with variable number of arguments: Function("func",{x,y, ...})body; -Rule("Function",3,2047, - And(GreaterThan(Length(args), 1), Equals( MathNth(args, Length(args)), Atom("...") )) -) -[ - DestructiveDelete(args,Length(args)); // remove trailing "..." - Retract(oper,Length(args)); - MacroRuleBaseListed(oper,args); - MacroRule(oper,Length(args),1025,True) body; // at precedence 1025, for flexibility -]; - -// function with a fixed number of arguments -Rule("Function",3,2048,True) -[ - Retract(oper,Length(args)); - MacroRuleBase(oper,args); - MacroRule(oper,Length(args),1025,True) body; -]; - - -// macro with variable number of arguments: Macro("func",{x,y, ...})body; -Rule("Macro",3,2047, - And(GreaterThan(Length(args), 1), Equals( MathNth(args, Length(args)), Atom("...") )) -) -[ - DestructiveDelete(args,Length(args)); // remove trailing "..." - Retract(oper,Length(args)); - `DefMacroRuleBaseListed(@oper,@args); - MacroRule(oper,Length(args),1025,True) body; // at precedence 1025, for flexibility -]; - -// macro with a fixed number of arguments -Rule("Macro",3,2048,True) -[ - Retract(oper,Length(args)); - `DefMacroRuleBase(@oper,@args); - MacroRule(oper,Length(args),1025,True) body; -]; - - -/// shorthand function declarations -RuleBase("Function",{oper}); -// function with variable number of arguments: Function() f(x,y, ...) -Rule("Function",1,2047, - And(IsFunction(oper), GreaterThan(Length(oper), 1), Equals( MathNth(oper, Length(oper)), Atom("...") )) -) -[ - Local(args); - Set(args,Tail(Listify(oper))); - DestructiveDelete(args,Length(args)); // remove trailing "..." - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - MacroRuleBaseListed(Type(oper),args) - ); -]; -// function with a fixed number of arguments -Rule("Function",1,2048, - And(IsFunction(oper)) -) -[ - Local(args); - Set(args,Tail(Listify(oper))); - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - MacroRuleBase(Type(oper),args) - ); -]; - - -RuleBase("Macro",{oper}); -// macro with variable number of arguments: Macro() f(x,y, ...) -Rule("Macro",1,2047, - And(IsFunction(oper), GreaterThan(Length(oper), 1), Equals( MathNth(oper, Length(oper)), Atom("...") )) -) -[ - Local(args,name); - Set(args,Tail(Listify(oper))); - DestructiveDelete(args,Length(args)); // remove trailing "..." - Set(name,Type(oper)); - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - `DefMacroRuleBaseListed(@name,@args) - ); -]; -// macro with a fixed number of arguments -Rule("Macro",1,2048, - And(IsFunction(oper)) -) -[ - Local(args,name); - Set(args,Tail(Listify(oper))); - Set(name,Type(oper)); - If(RuleBaseDefined(Type(oper),Length(args)), - False, // do nothing - [ - `DefMacroRuleBase(@name,@args); - ] - ); -]; - - -RuleBase("TemplateFunction",{oper,args,body}); -Bodied("TemplateFunction",60000); -HoldArg("TemplateFunction",oper); -HoldArg("TemplateFunction",args); -HoldArg("TemplateFunction",body); -Rule("TemplateFunction",3,2047,True) -[ - Retract(oper,Length(args)); - Local(arglist); - arglist:=FlatCopy(args); - - DestructiveAppend(arglist,{args,UnList({Hold,body})}); - arglist:=ApplyPure("LocalSymbols",arglist); - - MacroRuleBase(oper,arglist[1]); - MacroRule(oper,Length(args),1025,True) arglist[2]; - -]; - -Function("HoldArgNr",{function,arity,index}) -[ - Local(args); - args:=RuleBaseArgList(function,arity); -/* Echo({"holdnr ",args}); */ - ApplyPure("HoldArg",{function,args[index]}); -]; - - - -/* := assignment. */ -RuleBase(":=",{aLeftAssign,aRightAssign}); -UnFence(":=",2); -HoldArg(":=",aLeftAssign); -HoldArg(":=",aRightAssign); - -/* := assignment. */ -// assign a variable -Rule(":=",2,0,IsAtom(aLeftAssign)) -[ - MacroSet(aLeftAssign,Eval(aRightAssign)); - Eval(aLeftAssign); -]; - -// assign lists -Rule(":=",2,0,IsList(aLeftAssign)) -[ - Map(":=",{aLeftAssign,Eval(aRightAssign)}); -]; - -// auxiliary function to help assign arrays using := -RuleBase("AssignArray",{setlistterm,setlistindex,setlistresult}); -UnFence("AssignArray",3); -Rule("AssignArray",3,1,IsString(setlistindex)) -[ - Local(item); - item:=Assoc(setlistindex,setlistterm); - If(item = Empty, - DestructiveInsert(setlistterm,1,{setlistindex,setlistresult}), - DestructiveReplace(item,2,setlistresult) - ); - True; -]; -// assign generic arrays -Rule("AssignArray",3,1, - And( - Equals(IsGeneric(setlistterm),True), - Equals(GenericTypeName(setlistterm),"Array") - ) - ) -[ - ArraySet(setlistterm,setlistindex,setlistresult); -]; - - -Rule("AssignArray",3,2,True) -[ - DestructiveReplace(setlistterm ,setlistindex, setlistresult); - True; -]; - -// a[x] := ... assigns to an array element -Rule(":=",2,10,IsFunction(aLeftAssign) And (Head(Listify(aLeftAssign)) = Nth)) -[ - Local(frst,scnd); - - Local(lst); - Set(lst,(Listify(aLeftAssign))); - Set(lst,Tail(lst)); - Set(frst, Eval(Head(lst))); - Set(lst,Tail(lst)); - Set(scnd, Eval(Head(lst))); - - AssignArray(frst,scnd,Eval(aRightAssign)); -]; - -// f(x):=... defines a new function -Rule(":=",2,30,IsFunction(aLeftAssign) And Not(Equals(aLeftAssign[0], Atom(":=")))) -[ - Local(oper,args,arity); - Set(oper,String(aLeftAssign[0])); - Set(args,Tail(Listify(aLeftAssign))); - If( - And(GreaterThan(Length(args), 1), Equals( MathNth(args, Length(args)), Atom("...") )), - // function with variable number of arguments - [ - DestructiveDelete(args,Length(args)); // remove trailing "..." - Set(arity,Length(args)); - Retract(oper,arity); - MacroRuleBaseListed(oper, args); - ], - // function with a fixed number of arguments - [ - Set(arity,Length(args)); - Retract(oper,arity); - MacroRuleBase(oper, args); - ] - ); - UnHoldable(aRightAssign); - MacroRule(oper,arity,1025,True) aRightAssign; -]; - -// this will "unhold" a variable - used to make sure that := with Eval() -// immediately on the right hand side evaluates its argument -RuleBase("UnHoldable",{var}); -HoldArg("UnHoldable",var); -UnFence("UnHoldable",1); -Rule("UnHoldable",1,10,Equals(Type(Eval(var)),"Eval")) -[ - MacroSet(var,Eval(Eval(var))); -/* Echo({"unheld",var,Eval(var)}); */ -]; -Rule("UnHoldable",1,20,True) -[ -/* Echo({"held"}); */ - True; -]; - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/deffunc.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/deffunc.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/deffunc.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/deffunc.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -Function -Macro -TemplateFunction -HoldArgNr -:= -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/deriv.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/deriv.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/deriv.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/deriv.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ - - - -RuleBase("D",{aVar,aFunc}); -RuleBase("D",{aVar,aCount,aFunc}); - -Rule("D",2,1,IsList(aVar) And Not(IsList(aFunc))) - Map("D",{aVar,FillList(aFunc, Length(aVar))}); -Rule("D",2,1,IsList(aVar) And IsList(aFunc)) - Map("D",{aVar,aFunc}); - -Rule("D",2,3,True) -[ - MacroLocal(aVar); - Apply("Deriv",{aVar,1,aFunc}); -]; - -Rule("D",3,1,IsList(aVar) And Not(IsList(aFunc))) - Map("D",{aVar, - FillList(aCount, Length(aVar)), - FillList(aFunc, Length(aVar))}); -Rule("D",3,1,IsList(aVar) And IsList(aFunc)) - Map("D",{aVar, - FillList(aCount, Length(aVar)), - aFunc}); -Rule("D",3,3,True) -[ - MacroLocal(aVar); - Apply("Deriv",{aVar,aCount,aFunc}); -]; - - -HoldArg("D",aVar); -HoldArg("D",aFunc); - -5 # (Deriv(_var,1)_func) <-- Deriv(var)func; -5 # (Deriv(_var,0)_func) <-- func; -10 # (Deriv(_var,n_IsPositiveInteger)_func) <-- Deriv(var)Deriv(var,n-1)func; -10 # (Deriv(_var,n_IsNegativeInteger)_func) <-- Check(0,"Negative derivative"); - - -// Need to clean out Sec(x) and friends -0 # (Deriv(_var) (_var)) <-- 1; -1 # (Deriv(_var)func_IsAtom) <-- 0; -2 # (Deriv(_var)_x + _y) <-- (Deriv(var)x) + (Deriv(var)y); -2 # (Deriv(_var)- (_x) ) <-- -Deriv(var)x; -2 # (Deriv(_var)_x - _y) <-- (Deriv(var)x) - (Deriv(var)y); -2 # (Deriv(_var)_x * _y) <-- (x*Deriv(var)y) + (Deriv(var)x)*y; -2 # (Deriv(_var)Sin(_x)) <-- (Deriv(var)x)*Cos(x); -2 # (Deriv(_var)Sinh(_x))<-- (Deriv(var)x)*Cosh(x); -2 # (Deriv(_var)Cosh(_x))<-- (Deriv(var)x)*Sinh(x); -2 # (Deriv(_var)Cos(_x)) <-- -(Deriv(var)x)*Sin(x); -2 # (Deriv(_var)Csc(_x)) <-- -(Deriv(var)x)*Csc(x)*Cot(x); -2 # (Deriv(_var)Csch(_x)) <-- -(Deriv(var)x)*Csch(x)*Coth(x); -2 # (Deriv(_var)Sec(_x)) <-- (Deriv(var)x)*Sec(x)*Tan(x); -2 # (Deriv(_var)Sech(_x)) <-- -(Deriv(var)x)*Sech(x)*Tanh(x); -2 # (Deriv(_var)Cot(_x)) <-- -(Deriv(var)x)*Csc(x)^2; -2 # (Deriv(_var)Coth(_x)) <-- (Deriv(var)x)*Csch(x)^2; - -2 # (Deriv(_var)Tan(_x)) <-- ((Deriv(var) x) / (Cos(x)^2)); -2 # (Deriv(_var)Tanh(_x)) <-- (Deriv(var)x)*Sech(x)^2; - -2 # (Deriv(_var)Exp(_x)) <-- (Deriv(var)x)*Exp(x); - -// When dividing by a constant, this is faster -2 # (Deriv(_var)(_x / _y))_(IsFreeOf(var,y)) <-- (Deriv(var) x) / y; -3 # (Deriv(_var)(_x / _y)) <-- - (y* (Deriv(var) x) - x* (Deriv(var) y))/ (y^2); - -2 # (Deriv(_var)Ln(_x)) <-- ((Deriv(var) x) / x); -2 # (Deriv(_var)(_x ^ _n))_(IsRationalOrNumber(n) Or IsFreeOf(var, n)) <-- - n * (Deriv(var) x) * (x ^ (n - 1)); - -2 # (Deriv(_var)(Abs(_x))) <-- Sign(x)*(Deriv(var)x); -2 # (Deriv(_var)(Sign(_x))) <-- 0; - -2 # (Deriv(_var)(if(_cond)(_body))) <-- - UnList({Atom("if"),cond,Deriv(var)body}); -2 # (Deriv(_var)((_left) else (_right))) <-- - UnList({Atom("else"), (Deriv(var)left), (Deriv(var)right) } ); - -3 # (Deriv(_var)(_x ^ _n)) <-- (x^n)*Deriv(var)(n*Ln(x)); - -2 # (Deriv(_var)ArcSin(_x)) <-- (Deriv(var) x )/Sqrt(1 -(x ^ 2)); -2 # (Deriv(_var)ArcCos(_x)) <-- -(Deriv(var)x)/Sqrt(1 -(x^2)); -2 # (Deriv(_var)ArcTan(_x)) <-- (Deriv(var) x)/(1 + x^2); -2 # (Deriv(_var)Sqrt(_x)) <-- ((Deriv(var)x)/(2*Sqrt(x))); -2 # (Deriv(_var)Complex(_r,_i)) <-- Complex(Deriv(var)r,Deriv(var)i); - -LocalSymbols(var,var2,a,b,y)[ - 2 # (Deriv(_var)Integrate(_var)(_y)) <-- y; - 2 # (Deriv(_var)Integrate(_var2,_a,_b)(y_IsFreeOf(var))) <-- - (Deriv(var)b)*(y Where var2 == b) - - (Deriv(var)a)*(y Where var2 == a); - 3 # (Deriv(_var)Integrate(_var2,_a,_b)(_y)) <-- - (Deriv(var)b)*(y Where var2 == b) - - (Deriv(var)a)*(y Where var2 == a) + - Integrate(var2,a,b) Deriv(var) y; - ]; - - - -2 # (Deriv(_var)func_IsList)_(Not(IsList(var))) <-- - Map("Deriv",{FillList(var,Length(func)),func}); - - -2 # (Deriv(_var)UniVariate(_var,_first,_coefs)) <-- -[ - Local(result,m,i); - result:=FlatCopy(coefs); - m:=Length(result); - For(i:=1,i<=m,i++) - [ - result[i] := result[i] * (first+i-1); - ]; - UniVariate(var,first-1,result); -]; - - -RuleBase("Diverge", {aFunc, aBasis}); -Rule("Diverge", 2, 1, IsList(aBasis) And IsList(aFunc) And Length(aBasis) = Length(aFunc)) - Add(Map("D", {aBasis,aFunc})); - -RuleBase("Curl", {aFunc, aBasis}); - -Rule("Curl", 2, 1, Length(aBasis)=Length(aFunc)) - { - Apply("D",{aBasis[2],aFunc[3]})-Apply("D",{aBasis[3],aFunc[2]}), - Apply("D",{aBasis[3],aFunc[1]})-Apply("D",{aBasis[1],aFunc[3]}), - Apply("D",{aBasis[1],aFunc[2]})-Apply("D",{aBasis[2],aFunc[1]}) - }; - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/deriv.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/deriv.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/deriv.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/deriv.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -D -Deriv -Diverge -Curl -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/example.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/example.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/example.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/example.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ - - -examplelist:= -Hold( -{ - {40!, -"Simple factorial of a number. -" - }, - {D(x)Sin(x), -"Taking the derivative of a function (the derivative of Sin(x) with -respect to x in this case). -" - }, - {Taylor(x,0,5)Sin(x), -"Expanding a function into a taylor series. -" - }, - {Integrate(x,a,b)Sin(x), -"Integrate a function. -" - }, - {Solve(a+x*y==z,x), -"Solve a function for a variable. -" - }, - {Limit(x,0) Sin(x)/x, -"Take a limit. -" - }, - {Subst(x,Cos(a)) x+x, -"Substitute an expression with another in the main expression. -" - }, - {Expand((1+x)^3), -"Expand into a polynomial. -" - }, - {2^40, -"Big numbers. -" - }, - {1<<40, -"Bitwise operations -" - }, - {1 .. 4, -"Generating a list of numbers. -" - }, - {a:b:c:{}, -"Generating a list of items. -" - }, - {[Local(x);x:={a,b,c};Sin(x)^2;], -"Threading: Sin(..)^2 will be performed on all elements of the list -passed in. -" - }, - {[Local(list);list:={a,b,c,d,e,f}; list[2 .. 4];], -"Selecting a sublist from a list. -" - }, - {Permutations({a,b,c}), -"Generate all permutations of a list. -" - }, - {VarList(a+b*x), -"Show all variables that occur in an expression. -" - }, - {TrigSimpCombine(Cos(a)*Cos(a)+Sin(a)*Sin(a)), -"Convert factors between trigonometric functions to addition of -trigonometric functions. -" - } -} -); -exampleindex:=0; - -Example():= -[ - exampleindex++; - If (exampleindex>Length(examplelist),exampleindex:=1); - - Local(example); - example:=examplelist[exampleindex]; - WriteString("Current example : "); - Write(example[1]);WriteString(";");NewLine(); - NewLine(); - WriteString(example[2]); - NewLine(); - Eval(example[1]); -]; - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/example.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/example.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/example.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/example.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -Example -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/factors.rep/binaryfactors.mpi mathpiper-0.81f+dfsg1/storage/scripts/factors.rep/binaryfactors.mpi --- mathpiper-0.0.svn2556/storage/scripts/factors.rep/binaryfactors.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/factors.rep/binaryfactors.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,295 +0,0 @@ - - -LocalSymbols(lastcoef,OrdBuild, AddFoundSolutionSingle , AddFoundSolution, Fct, MkfactD) -[ - -LastCoef(_vector,_p) <-- -[ - Local(n); - n:=Length(vector); - Add(vector*p^(0 .. (n-1))); -]; - -/* -Ord(vector,q):= -[ - Local(n); - n:=Length(vector); - q*Coef(Simplify(LastCoef(vector,p+q)-LastCoef(vector,p)),q,1); -]; -*/ - -OrdBuild(vector,q):= -[ - Local(i,result,n); - Set(i,2); - Set(result, 0); - Set(n, Length(vector)); - While (i<=n) - [ - Set(result,result+(i-1)*vector[i]*p^(i-2)); - Set(i, i+2); - ]; - q*result; -]; - - -Function(AddFoundSolutionSingle,{p}) -[ - Local(calc); -// If ( Not Contains(result,p), -// [ - Set(calc, Eval(lastcoef)); - If (Equals(calc, 0), - [ - Local(newlist,count,root); - count:=0; - root := p; - Local(rem); - - rem:={-root,1}; - {testpoly,rem}:=MkfactD(testpoly,rem); - - rem:={-root,1}; - {newlist,rem}:=MkfactD(poly,rem); - While (rem = {}) - [ - count++; - Set(poly,newlist); - rem:={-root,1}; - {newlist,rem}:=MkfactD(poly,rem); - ]; - - Local(lgcd,lc); - Set(lgcd,Gcd({andiv,an,root})); - Set(lc,Div(an,lgcd)); - Set(result,{var+ (-(Div(root,lgcd)/lc)),count}:result); - Set(andiv,Div(andiv,lgcd^count)); - Set(anmul,anmul*lc^count); - -// factor:=(x-root); -// Set(result,{factor,count}:result); - - Local(p,q); - Set(lastcoef, LastCoef(testpoly,p)); - Set(ord, OrdBuild(testpoly,q)); - ]); -// ]); -]; -UnFence(AddFoundSolutionSingle,1); - -Function(AddFoundSolution,{p}) -[ - AddFoundSolutionSingle(p); - AddFoundSolutionSingle(-2*q+p); -]; -UnFence(AddFoundSolution,1); - -Function(Fct,{poly,var}) -[ - Local(maxNrRoots,result,ord,p,q,accu,calc,twoq,mask); - - Local(gcd); - [ - Set(gcd,Gcd(poly)); - If(poly[Length(poly)] < 0,Set(gcd, gcd * -1)); - Set(poly,poly/gcd); - ]; - - Local(unrat); - Set(unrat,Lcm(MapSingle("Denom",poly))); - Set(poly,unrat*poly); - - Local(origdegree); - Set(origdegree,Length(poly)-1); - - Local(an,andiv,anmul); - Set(an,poly[Length(poly)]); - Set(poly,poly* (an^((origdegree-1) .. -1))); - Set(andiv,an^(origdegree-1)); - Set(anmul,1); - - Local(leadingcoef,lowestcoef); - Set(leadingcoef,poly[Length(poly)]); - [ - Local(i); - Set(i,1); - Set(lowestcoef,Abs(poly[i])); - While (lowestcoef = 0 And i<=Length(poly)) - [ - Set(i,i+1); - Set(lowestcoef,Abs(poly[i])); - ]; - ]; - // testpoly is the square-free version of the polynomial, used for finding - // the factors. the original polynomials is kept around to find the - // multiplicity of the factor. - Local(testpoly); -// Set(testpoly,Mkc(Div(polynom,Monic(Gcd(polynom,Deriv(var)polynom))),var)); - Local(deriv); - // First determine a derivative of the original polynomial - deriv:=Tail(poly); - [ - Local(i); - For (i:=1,i<=Length(deriv),i++) - [ - deriv[i] := deriv[i]*i; - ]; -// Echo("POLY = ",poly); -// Echo("DERIV = ",deriv); - ]; - [ - Local(q,r,next); - q:=poly; - r:=deriv; - While(r != {}) - [ -//Echo(q,r); - next := MkfactD(q,r)[2]; - q:=r; - r:=next; - ]; - // now q is the gcd of the polynomial and its first derivative. - - // Make it monic - q:=q/q[Length(q)]; - testpoly:=MkfactD(poly,q)[1]; -//Echo("TESTPOLY = ",testpoly); - ]; - -// Set(testpoly,poly); //@@@ - - Set(maxNrRoots,Length(testpoly)-1); - Set(result, {}); - - Set(lastcoef, LastCoef(testpoly,p)); - Set(ord, OrdBuild(testpoly,q)); - - Set(accu,{}); - Set(q,1); - Set(twoq,MultiplyN(q,2)); - Set(mask,AddN(twoq,MathNegate(1))); - if (IsEven(testpoly[1])) - [ - Set(accu,0:accu); - AddFoundSolutionSingle(0); - ]; - Set(p,1); - Set(calc, Eval(lastcoef)); - If (IsEven(calc), - [ - Set(accu,1:accu); - AddFoundSolution(1); - ]); - Set(q,twoq); - Set(twoq,MultiplyN(q,2)); - Set(mask,AddN(twoq,MathNegate(1))); - While(Length(result)0 And q<=Abs(testpoly[1])) - [ - Local(newaccu); - Set(newaccu,{}); - ForEach(p,accu) - [ - Set(calc,Eval(lastcoef)); - If (LessThan(calc,0), - Set(calc, AddN(calc,MultiplyN(twoq,DivN(AddN(MathNegate(calc),twoq),twoq)))) - ); - Set(calc, BitAnd(calc, mask)); - If ( Equals(calc, 0), - [ - Set(newaccu, p:newaccu); - AddFoundSolutionSingle(-2*q+p); - ]); - Set(calc, AddN(calc, Eval(ord))); - If (LessThan(calc,0), - Set(calc, AddN(calc,MultiplyN(twoq,DivN(AddN(MathNegate(calc),twoq),twoq)))) - ); - Set(calc, BitAnd(calc, mask)); - If ( Equals(calc, 0), - [ - Set(newaccu, AddN(p,q):newaccu); - AddFoundSolution(AddN(p,q)); - ]); - ]; - Set(accu, newaccu); - Set(q,twoq); - Set(twoq,MultiplyN(q,2)); - Set(mask,AddN(twoq,MathNegate(1))); - -//Echo("q = ",q); -//Echo("Length is",Length(accu),"accu = ",accu); -//Echo("result = ",result); - ]; - - // If the polynom is not one, it is a polynomial which is not reducible any further - // with this algorithm, return as is. - Set(poly,poly*an^(0 .. (Length(poly)-1))); - Set(poly,gcd*anmul*poly); - //TODO had to add this if statement, what was andiv again, and why would it become zero? This happens with for example Factor(2*x^2) - If(Not IsZero(unrat * andiv ),Set(poly,poly/(unrat * andiv ))); - If(poly != {1}, - [ - result:={(Add(poly*var^(0 .. (Length(poly)-1)))),1}:result; - ]); - result; -]; - - - -BinaryFactors(expr):= -[ - Local(result,uni,coefs); - uni:=MakeUni(expr,VarList(expr)[1]); - uni:=Listify(uni); - coefs:=uni[4]; - coefs:=Concat(ZeroVector(uni[3]),coefs); - result:=Fct(coefs,uni[2]); -// Echo(result,list); -// Echo((Add(list*x^(0 .. (Length(list)-1))))); -// Factorize(x-result)*(Add(list*x^(0 .. (Length(list)-1)))); - result; -]; - - - -MkfactD(numer,denom):= -[ - Local(q,r,i,j,ln,ld,nq); - DropEndZeroes(numer); - DropEndZeroes(denom); - Set(numer,Reverse(numer)); - Set(denom,Reverse(denom)); - Set(ln,Length(numer)); - Set(ld,Length(denom)); - Set(q,FillList(0,ln)); - Set(r,FillList(0,ln)); - - Set(i,1); - If(ld>0, - [ - While(Length(numer)>=Length(denom)) - [ - Set(nq,numer[1]/denom[1]); - q[ln-(Length(numer)-ld)] := nq; - For(j:=1,j<=Length(denom),j++) - [ - numer[j] := (numer[j] - nq*denom[j]); - ]; - r[i] := r[1] + numer[1]; - - Set(numer, Tail(numer)); - i++; - ]; - ]); - For(j:=0,j 1, // if this is > 1, we need to separate some factors. Gcd() is very fast - small'powers := TrialFactorize(n, 257), // value is {n1, {p1,q1}, {p2,q2}, ...} and n1=1 if completely factorized into these factors, and the remainder otherwise - small'powers := {n} // pretend we had run TrialFactorize without success - ); - n := small'powers[1]; // remainder - If(n=1, Tail(small'powers), - // if n!=1, need to factorize the remainder with Pollard Rho algorithm - [ - If(InVerboseMode(), Echo({"FactorizeInt: Info: remaining number ", n})); - SortFactorList( - PollardCombineLists(Tail(small'powers), PollardRhoFactorize(n)) - ); - ] - ); -]; - -/// Sort the list of prime factors using HeapSort() -LocalSymbols(a,b, list) [ - -SortFactorList(list) := HeapSort(list, {{a,b}, a[1] 1,000,000. -/// Try all prime factors up to Sqrt(n). -/// Resulting factors are automatically sorted. -/// This function is not used any more. -/* -2# TrialFactorize(n_IsPrimePower) <-- {GetPrimePower(n)}; -3# TrialFactorize(n_IsInteger) <-- -[ - Local(factorization); - factorization := TrialFactorize(n, n); // TrialFactorize will limit to Sqrt(n) automatically - If( - Head(factorization) = 1, // all factors were smaller than Sqrt(n) - Tail(factorization), - // the first element needs to be replaced - Concat(Tail(factorization), {{Head(factorization),1}}) - ); -]; -*/ - -/// Auxiliary function. Return the power of a given prime contained in a given integer and remaining integer. -/// E.g. FindPrimeFactor(63, 3) returns {7, 2} and FindPrimeFactor(42,17) returns {42, 0} -// use variable step loops, like in IntLog() -FindPrimeFactor(n, prime) := -[ - Local(power, factor, old'factor, step); - power := 1; - old'factor := 1; // in case the power should be 0 - factor := prime; - // first loop: increase step - While(Mod(n, factor)=0) // avoid division, just compute Mod() - [ - old'factor := factor; // save old value here, avoid sqrt - factor := factor^2; - power := power*2; - ]; - power := Div(power,2); - factor := old'factor; - n := Div(n, factor); - // second loop: decrease step - step := Div(power,2); - While(step>0 And n > 1) - [ - factor := prime^step; - If( - Mod(n, factor)=0, - [ - n := Div(n, factor); - power := power + step; - ] - ); - step := Div(step, 2); - ]; - {n, power}; -]; - -/* simpler method but slower on worstcase such as p^n or n! */ -FindPrimeFactorSimple(n, prime) := -[ - Local(power, factor); - power := 0; - factor := prime; - While(Mod(n, factor)=0) - [ - factor := factor*prime; - power++; - ]; - {n/(factor/prime), power}; -]; -/**/ - -/// Auxiliary function. Factorizes by trials. Return prime factors up to given limit and the remaining number. -/// E.g. TrialFactorize(42, 2) returns {21, {{2, 1}}} and TrialFactorize(37, 4) returns {37} -TrialFactorize(n, limit) := -[ - Local(power, prime, result); - result := {n}; // first element of result will be replaced by the final value of n - prime := 2; // first prime - While(prime <= limit And n>1 And prime*prime <= n) - [ // find the max power of prime which divides n - {n, power} := FindPrimeFactor(n, prime); - If( - power>0, - DestructiveAppend(result, {prime,power}) - ); - prime := NextPseudoPrime(prime); // faster than NextPrime and we don't need real primes here - ]; - // replace the first element which was n by the new n - DestructiveReplace(result, 1, n); -]; - -/* This is Pollard's Rho method of factorizing, as described in - * "Modern Computer Algebra". It is a rather fast algorithm for - * factoring, but doesn't scale to polynomials regrettably. - * - * It acts 'by chance'. This is the Floyd cycle detection trick, where - * you move x(i+1) = f(x(i)) and y(i+1) = f(f(y(i))), so the y goes twice - * as fast as x, and for a certain i x(i) will be equal to y(i). - * - * "Modern Computer Algebra" reasons that if f(x) = (x^2+1) mod n for - * the value n to be factored, then chances are good that gcd(x-y,n) - * is a factor of n. The function x^2+1 is arbitrary, a higher order - * polynomial could have been chosen also. - * - */ - -/* -Warning: The Pollard Rho algorithm cannot factor some numbers, e.g. 703, and -can enter an infinite loop. This currently results in an error message: "failed to factorize". -Hopefully the TrialFactorize() step will avoid these situations by excluding -small prime factors. -This problem could also be circumvented by trying a different random initial value for x when a loop is encountered -- hopefully another initial value will not get into a loop. (currently this is not implemented) -*/ - -RandomInteger(n) := FloorN(Random()*n); -/// Polynomial for the Pollard Rho iteration -PollardRhoPolynomial(_x) <-- x^2+1; - -2# PollardRhoFactorize(n_IsPrimePower) <-- {GetPrimePower(n)}; -3# PollardRhoFactorize(_n) <-- -[ - Local(x,y,restarts,gcd,repeat); - gcd:=1; - restarts := 100; // allow at most this many restartings of the algorithm - While(gcd = 1 And restarts>=0) // outer loop: this will be typically executed only once but it is needed to restart the iteration if it "stalls" - [ - restarts--; - /* Pick a random value between 1 and n-1 */ - x:= RandomInteger(n-1)+1; - - /* Initialize loop */ - gcd:=1; y:=x; - repeat := 4; // allow at most this many repetitions -// Echo({"debug PollardRho: entering gcd loop, n=", n}); - - /* loop until failure or success found */ - While(gcd = 1 And repeat>=0) - [ - x:= Mod( PollardRhoPolynomial(x), n); - y:= Mod( PollardRhoPolynomial( - Mod( PollardRhoPolynomial(y), n) // this is faster for large numbers - ), n); - If(x-y = 0, - [ - gcd := 1; - repeat--; // guard against "stalling" in an infinite loop but allow a few repetitions - ], - gcd:=Gcd(x-y,n) - ); -// Echo({"debug PollardRho: gcd=",gcd," x=", x," y=", y}); - ]; - If(InVerboseMode() And repeat<=0, Echo({"PollardRhoFactorize: Warning: stalled while factorizing ", n, "; counters ", x, y})); - ]; - Check(restarts>0, "PollardRhoFactorize: Error: failed to factorize " : String(n)); - If(InVerboseMode() And gcd > 1, Echo({"PollardRhoFactorize: Info: while factorizing ", n, " found factor ", gcd})); - /* Return result found */ - PollardCombineLists(PollardRhoFactorize(gcd), PollardRhoFactorize(Div(n,gcd))); -]; - -/* PollardCombineLists combines two assoc lists used for factoring. - the first element in each item list is the factor, and the second - the exponent. Thus, an assoc list of {{2,3},{3,5}} means 2^3*3^5. -*/ - -5 # PollardMerge(_list,{1,_n}) <-- True; -10 # PollardMerge(_list,_item)_(Assoc(item[1],list) = Empty) <-- - DestructiveInsert(list,1,item); - -20 # PollardMerge(_list,_item) <-- -[ - Local(assoc); - assoc := Assoc(item[1],list); - assoc[2]:=assoc[2]+item[2]; -]; - -PollardCombineLists(_left,_right) <-- -[ - ForEach(item,right) - [ - PollardMerge(left,item); - ]; - left; -]; - - - - -/* New factorization : split between integers and polynomials. */ -10 # Factors(p_IsInteger) <-- FactorizeInt(p); -20 # Factors(p_CanBeUni)_(Length(VarList(p)) = 1) <-- BinaryFactors(p); -30 # Factors(p_IsGaussianInteger) <-- GaussianFactors(p); - - -// This is so Factor(Sin(x)) doesn't return FWatom(Sin(x)) -//Factor(_p) <-- FW(Factors(p)); -10 # Factor(p_CanBeUni) <-- FW(Factors(p)); - - -/* FW: pass FW the result of Factors, and it will show it in the - * form of p0^n0*p1^n1*... - */ - -10 # FWatom({_a,1}) <-- a; -20 # FWatom({_a,_n}) <-- UnList({Atom("^"),a, n}); -5 # FW(_list)_(Length(list) = 0) <-- 1; -10 # FW(_list)_(Length(list) = 1) <-- FWatom(list[1]); -20 # FW(_list) <-- -[ - Local(result); - result:=FWatom(Head(list)); - ForEach(item,Tail(list)) - [ - result := UnList({ Atom("*"),result,FWatom(item)}); - ]; - result; -]; - -10 # Roots(poly_CanBeUni) <-- -[ - Local(factors,result,uni,root,i,deg); - factors:=Factors(poly); - result:={}; - ForEach(item,factors) - [ - uni:=MakeUni(item[1]); - deg:=Degree(uni); - If(deg > 0 And deg < 3, - [ - root:= PSolve(uni); - If(Not IsList(root),root:={root}); - For(i:=0,i 0 And deg < 3, - [ - root:= PSolve(uni); - If(Not IsList(root),root:={root}); - For(i:=1,i<=Length(root),i++) - result:= Concat({{root[i],item[2]}}, result); - ] - ); - ]; - result; -]; - -// The bud of an Quadratic Seive algorithm -// congruence solving code must be written first -Function("FactorQS",{n})[ - Local(x,k,fb,j); - // optimal number of primes in factor base - // according to Fundamental Number Theory with Applications - Mollin, p130 - k:=Round(N(Sqrt(Exp(Sqrt(Ln(n)*Ln(Ln(n))))))); - fb:=ZeroVector(k); - For(j:=1,j<=k,j++)[ - fb[j]:=NextPrime(j); - ]; -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/factors.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/factors.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/factors.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/factors.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -FindPrimeFactor -FindPrimeFactorSimple -Factors -Factor -TrialFactorize -FW -Roots -RootsWithMultiples -FactorQS -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/functional.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/functional.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/functional.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/functional.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ - -/* Operators for functional programming. - * Examples: - * a:b:c:{} -> {a,b,c} - * "Sin" @ a -> Sin(a) - * "Sin" @ {a,b} -> Sin(a,b) - * "Sin" /@ {a,b} -> {Sin(a),Sin(b)} - * 1 .. 4 -> {1,2,3,4} - */ - - -/* a : b will now return unevaluated (rather than cause error of invalid argument in Concat) if neither a nor b is a list and if one of them is not a string -*/ -RuleBase(":",{head,tail}); -Rule(":",2,20,IsList(head) And Not IsList(tail) ) Concat(head,{tail}); -Rule(":",2,30,IsList(tail) ) Concat({head},tail); -Rule(":",2,10,IsString(tail) And IsString(head)) ConcatStrings(head,tail); -UnFence(":",2); - - -RuleBase("@",{func,arg}); -Rule("@",2,1,IsList(arg)) Apply(func,arg); -Rule("@",2,2,True ) Apply(func,{arg}); - -Function("/@",{func,lst}) Apply("MapSingle",{func,lst}); - -/* -.. operator is implemented with the Table function. -*/ -10 # (count'from_IsInteger .. count'to_IsInteger)_(count'from <= count'to) - <-- Table(i,i,count'from,count'to,1); -20 # (count'from_IsInteger .. count'to_IsInteger) - <-- Table(i,i,count'from,count'to,-1); - -/* NFunction("new'func", "old'func" {arg'list}) will define a wrapper function -around "old'func", called "new'func", which will return "old'func(arg'list)" -only when all arguments are numbers and will return unevaluated -"new'func(arg'list)" otherwise. */ -LocalSymbols(NFunction'Numberize) -[ -NFunction(new'name_IsString, old'name_IsString, arg'list_IsList) <-- [ - MacroRuleBase(new'name, arg'list); - MacroRule(new'name, Length(arg'list), 0, // check whether all args are numeric - UnList({IsNumericList, arg'list}) - ) - - /* this is the rule defined for the new function. - // this expression should evaluate to the body of the rule. - // the body looks like this: - // NFunction'Numberize(old'name(arg'list)) - */ - NFunction'Numberize(UnList({Atom("@"), old'name, arg'list})); - // cannot use bare '@' b/c get a syntax error - -]; - -// this function is local to NFunction. -// special handling for numerical errors: return Undefined unless given a number. -10 # NFunction'Numberize(x_IsNumber) <-- x; -20 # NFunction'Numberize(x_IsAtom) <-- Undefined; -// do nothing unless given an atom - -]; // LocalSymbols() - diff -Nru mathpiper-0.0.svn2556/storage/scripts/functional.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/functional.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/functional.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/functional.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -: -@ -/@ -.. -NFunction -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/functional.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/functional.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/functional.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/functional.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -// From code.mpi.def: -OMDef( ":" , "mathpiper","prepend" ); -OMDef( "@" , "mathpiper","apply" ); -OMDef( "/@" , "mathpiper","list_apply" ); -OMDef( ".." , "interval1","integer_interval" ); -OMDef( "NFunction", "mathpiper","NFunction" ); diff -Nru mathpiper-0.0.svn2556/storage/scripts/html.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/html.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/html.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/html.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,222 +0,0 @@ - -/* code to generate html */ - - -/* Global defines */ -anchor:={}; -anchor["0"]:="a"; -anchor["name"]:=""; - -link:={}; -link["0"]:="a"; -link["href"]:=""; - -frameset:={}; -frameset["0"]:="frameset"; -frameset["border"]:="0"; - -frame:={}; -frame["0"]:="frame"; - -caption:={}; -caption["0"]:="caption"; - -table:={}; -table["0"]:="table"; - -form:={}; -form["0"]:="form"; - -textarea:={}; -textarea["0"]:="textarea"; - -textfield:={}; -textfield["0"]:="input"; -textfield["TYPE"]:="text"; - -button:={}; -button["0"]:="input"; -button["TYPE"]:="submit"; - -bullets:={}; -bullets["0"]:="ul"; - -bullet:={}; -bullet["0"]:="li"; - -newline:=" -"; -Gt():=">"; -Lt():="<"; - - - - -HtmlNewParagraph():= (newline : "

    " : newline); - -HtmlTitle(title):= -[ -" - " : title : " - -"; -]; - -HtmlAnchor(name):= -[ - anchor["name"]:=name; - HtmlTag(anchor,""); -]; -Bodied("HtmlAnchor",60000); - -HtmlTable(cellpadding,width,body):= -[ - table["cellpadding"]:=String(cellpadding); - table["width"]:=width; - HtmlTag(table,body); -]; - -Bullets(list):=HtmlTag(bullets,list); -Bullet (list):=HtmlTag(bullet ,list); - - -HtmlCaption(title):= -[ - HtmlTag(caption,title); -]; - -HtmlForm(action,body):= -[ - form["method"]:="get"; - form["action"]:=action; - HtmlTag(form,body); -]; - - -HtmlTextArea(name,width,height,body) := -[ - textarea["name"]:=name; - textarea["cols"]:=String(width); - textarea["rows"]:=String(height); - HtmlTag(textarea,body); -]; - -HtmlTextField(name,size,value):= -[ - textfield["name"]:=name; - textfield["size"]:=String(size); - textfield["value"]:=value; - HtmlTag(textfield,""); -]; - -HtmlSubmitButton(name,value):= -[ - button["name"]:=name; - button["value"]:=value; - HtmlTag(button,""); -]; - - -HtmlLink(description,file,tag,target):= -[ - If(tag != "", - link["href"]:= file : "#" : tag, - link["href"]:= file); - - If(target != "",link["target"] :=target); - HtmlTag(link,description); -]; - -HtmlFrameSetRows(columns,body):= -[ - frameset["cols"]:=""; - frameset["rows"]:=columns; - HtmlTag(frameset,body); -]; - -HtmlFrameSetCols(columns,body):= -[ - frameset["cols"]:=columns; - frameset["rows"]:=""; - HtmlTag(frameset,body); -]; - -HtmlFrame(source,name):= -[ - frame["src"]:=source; - frame["name"]:=name; - HtmlTag(frame,""); -]; - - -/* export a html tag type, using the specifications in the - tags assoc list. - */ -HtmlTag(tags,content):= -[ - Local(result,tag,analytics); - result:="<" : tags["0"]; - ForEach(tag,AssocIndices(tags)) - [ - If (tag != "0" And tags[tag] != "", - result:= result : " " : tag : "=" : "\"" : tags[tag] : "\"" - ); - ]; - - analytics:=""; - If(tags["0"] = "body", - analytics:=" - -"); - - - result:= result : ">" : newline : - content : newline : - analytics : "" : newline; - - result; -]; - -/* output directory management */ -htmldir:=""; -SetHtmlDirectory(dir):= [htmldir:=dir;]; -HtmlFile(file) := [htmldir : file;]; - - -/* loading and saving site info */ -site:={}; -ClearSite() := [site:={};]; -LoadSite():= -[ - FromFile("siteall") - [ - site:=Read(); - ]; -]; - -SaveSite():= -[ - ToFile("siteall") - [ - Write(site); - WriteString(";"); - ]; -]; - -MySQLQuery(pidstr,string):= -[ - Local(result); - ToFile("sqlin":pidstr) WriteString(string); - SystemCall("mysql mysql < ":"sqlin":pidstr:" > sqlout":pidstr); - SystemCall(FindFile("tools/mysqlstubs"):" sqlout":pidstr:" sqlout_":pidstr); - result:= FromFile("sqlout_":pidstr)Read(); - SystemCall("rm -rf sqlin":pidstr); - SystemCall("rm -rf sqlout":pidstr); - SystemCall("rm -rf sqlout_":pidstr); - result; -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/html.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/html.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/html.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/html.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -HtmlNewParagraph -HtmlAnchor -HtmlLink -HtmlTable -HtmlCaption -HtmlTitle -HtmlFrameSetRows -HtmlFrameSetCols -HtmlFrame -HtmlTag -HtmlForm -Bullets -Bullet -HtmlTextArea -HtmlTextField -HtmlSubmitButton -SetHtmlDirectory -HtmlFile -ClearSite -LoadSite -SaveSite -MySQLQuery -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/initialization.rep/mathpiperinit.mpi mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/mathpiperinit.mpi --- mathpiper-0.0.svn2556/storage/scripts/initialization.rep/mathpiperinit.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/mathpiperinit.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ - - -/* This is the basic initialization file for MathPiper. It gets loaded - * each time MathPiper is started. All the basic files are loaded. - */ - -/* Set up drivers, configurable in the .mpiperrc - * Set(MultiNomialDriver,"org/mathpiper/scripts/multivar.rep/sparsenomial.mpi"); - * or - * Set(MultiNomialDriver,"org/mathpiper/scripts/multivar.rep/partialdensenomial.mpi"); - */ - -/* The truly required files (MathPiper NEEDS to load). */ -// syntax must be loaded first -Use("org/mathpiper/scripts/initialization.rep/stdopers.mpi"); - -/* Set of functions to define very simple functions. There are scripts that can - be compiled to plugins. So MathPiper either loads the plugin, or loads the - scripts at this point. The functions in these plugins need to be defined with - these "Defun" functions. - */ -DefMacroRuleBase("Defun",{func,args,body}); -Rule("Defun",3,0,True) -[ - Local(nrargs); - Set(nrargs,Length(@args)); - Retract(@func, `(@nrargs)); - RuleBase(@func,@args); - Local(fn,bd); - Set(fn,Hold(@func)); Set(bd,Hold(@body)); - `Rule(@fn, @nrargs, 0,True)(@bd); -]; - -//TODO remove? Use("org/mathpiper/scripts/base.rep/math.mpi"); - -Use("org/mathpiper/scripts/patterns.rep/code.mpi"); -// at this point <-- can be used - -Use("org/mathpiper/scripts/deffunc.rep/code.mpi"); - -// at this point := and Function() can be used - -Use("org/mathpiper/scripts/constants.rep/code.mpi"); -Use("org/mathpiper/scripts/initialization.rep/standard.mpi"); -Use("org/mathpiper/scripts/initialization.rep/stdarith.mpi"); - -// at this point arithmetic can be used - -/* Load the def files for the other modules. The def files contain lists - * of functions defined in that file. So, in solve.def you can find the - * functions defined in the file solve. Each time a function is invoked - * for which the interpreter can not find a definition, the file is loaded. - */ - -RuleBase(LoadPackages,{packages}); -Rule(LoadPackages, 1, 1, True) -[ - If(Equals(packages,{}), True, - [ - DefLoad(Head(packages)); - LoadPackages(Tail(packages)); - ]); -]; - -Use("org/mathpiper/scripts/initialization.rep/packages.mpi"); -LoadPackages(DefFileList()); - - -/* The read-eval-print loop */ -RuleBase("REP",{}); -LocalSymbols(input,stringOut,result,errorString) -Rule("REP",0,1,True) -[ - Local(input,stringOut,result); - While(Not(IsExitRequested())) - [ - Set(errorString, ""); - If(And(IsString(PrettyReader'Get()),Not(PrettyReader'Get() = "")), - TrapError(Set(input, FromString(ReadCmdLineString("In> "))ApplyPure(PrettyReader'Get(),{})),Set(errorString,GetCoreError())), - TrapError(Set(input, FromString(ConcatStrings(ReadCmdLineString("In> "),";"))Read()),Set(errorString,GetCoreError()))); - If(Not(errorString = ""), WriteString(errorString)); - If (Not(IsExitRequested()) And errorString="", - [ - Set(stringOut,""); - Set(result,False); - Set(stringOut,ToString()[TrapError(Set(result,Eval(input)),Set(errorString,GetCoreError()));]); - If(Not(stringOut = ""), WriteString(stringOut)); - If(Not(errorString = ""), WriteString(errorString)); - SetGlobalLazyVariable(%,result); - If(PrettyPrinter'Get()="", - [ - Write(Atom("Out> "),result); - NewLine(); - ], - Apply(PrettyPrinter'Get(),{result})); - ]); - ]; -]; - \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/initialization.rep/packages.mpi mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/packages.mpi --- mathpiper-0.0.svn2556/storage/scripts/initialization.rep/packages.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/packages.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -/// This file is generated by a script. -/// It lists all {.def} files in the library. -Defun(DefFileList,{}) { -"org/mathpiper/scripts/array.rep/code.mpi", -"org/mathpiper/scripts/assoc.rep/code.mpi", -"org/mathpiper/scripts/base.rep/math.mpi", -"org/mathpiper/scripts/c_form.rep/code.mpi", -"org/mathpiper/scripts/complex.rep/code.mpi", -"org/mathpiper/scripts/constants.rep/code.mpi", -"org/mathpiper/scripts/controlflow.rep/code.mpi", -"org/mathpiper/scripts/debug.rep/code.mpi", -"org/mathpiper/scripts/deffunc.rep/code.mpi", -"org/mathpiper/scripts/deriv.rep/code.mpi", -"org/mathpiper/scripts/example.rep/code.mpi", -"org/mathpiper/scripts/factors.rep/binaryfactors.mpi", -"org/mathpiper/scripts/factors.rep/code.mpi", -"org/mathpiper/scripts/functional.rep/code.mpi", -"org/mathpiper/scripts/html.rep/code.mpi", -"org/mathpiper/scripts/integrate.rep/code.mpi", -"org/mathpiper/scripts/io.rep/code.mpi", -"org/mathpiper/scripts/io.rep/defaultprint.mpi", -"org/mathpiper/scripts/limit.rep/code.mpi", -"org/mathpiper/scripts/linalg.rep/code.mpi", -"org/mathpiper/scripts/lists.rep/code.mpi", -"org/mathpiper/scripts/lists.rep/scopestack.mpi", -"org/mathpiper/scripts/localrules.rep/code.mpi", -"org/mathpiper/scripts/logic.rep/code.mpi", -"org/mathpiper/scripts/multivar.rep/code.mpi", -"org/mathpiper/scripts/multivar.rep/sparsetree.mpi", -"org/mathpiper/scripts/newly.rep/code.mpi", -"org/mathpiper/scripts/numbers.rep/GaussianIntegers.mpi", -"org/mathpiper/scripts/numbers.rep/NumberTheory.mpi", -"org/mathpiper/scripts/numbers.rep/code.mpi", -"org/mathpiper/scripts/numbers.rep/nthroot.mpi", -"org/mathpiper/scripts/odesolver.rep/code.mpi", -"org/mathpiper/scripts/openmath.rep/code.mpi", -"org/mathpiper/scripts/orthopoly.rep/code.mpi", -"org/mathpiper/scripts/padic.rep/code.mpi", -"org/mathpiper/scripts/patterns.rep/code.mpi", -"org/mathpiper/scripts/plots.rep/code.mpi", -"org/mathpiper/scripts/plots.rep/plot2d.mpi", -"org/mathpiper/scripts/plots.rep/plot3d.mpi", -"org/mathpiper/scripts/predicates.rep/code.mpi", -"org/mathpiper/scripts/probability.rep/code.mpi", -"org/mathpiper/scripts/pslq.rep/code.mpi", -"org/mathpiper/scripts/rabinmiller.rep/code.mpi", -"org/mathpiper/scripts/radsimp.rep/code.mpi", -"org/mathpiper/scripts/random.rep/code.mpi", -"org/mathpiper/scripts/simplify.rep/code.mpi", -"org/mathpiper/scripts/simplify.rep/factorial.mpi", -"org/mathpiper/scripts/solve.rep/code.mpi", -"org/mathpiper/scripts/specfunc.rep/bernou.mpi", -"org/mathpiper/scripts/specfunc.rep/bessel.mpi", -"org/mathpiper/scripts/specfunc.rep/code.mpi", -"org/mathpiper/scripts/specfunc.rep/gamma.mpi", -"org/mathpiper/scripts/specfunc.rep/gammaconst.mpi", -"org/mathpiper/scripts/specfunc.rep/zeta.mpi", -"org/mathpiper/scripts/initialization.rep/standard.mpi", -"org/mathpiper/scripts/statistics.rep/distributions.mpi", -"org/mathpiper/scripts/statistics.rep/hypothesystest.mpi", -"org/mathpiper/scripts/statistics.rep/incompletegamma.mpi", -"org/mathpiper/scripts/statistics.rep/regression.mpi", -"org/mathpiper/scripts/statistics.rep/statistics.mpi", -"org/mathpiper/scripts/stats.rep/code.mpi", -"org/mathpiper/scripts/initialization.rep/stdarith.mpi", -"org/mathpiper/scripts/stdfuncs.rep/code.mpi", -"org/mathpiper/scripts/stdfuncs.rep/elemfuncs.mpi", -"org/mathpiper/scripts/stdfuncs.rep/numerical.mpi", -"org/mathpiper/scripts/stdfuncs.rep/nummethods.mpi", -"org/mathpiper/scripts/stubs.rep/code.mpi", -"org/mathpiper/scripts/substitute.rep/code.mpi", -"org/mathpiper/scripts/sums.rep/code.mpi", -"org/mathpiper/scripts/sums.rep/taylor.mpi", -"org/mathpiper/scripts/sums.rep/taylor3.mpi", -"org/mathpiper/scripts/tensor.rep/code.mpi", -"org/mathpiper/scripts/testers.rep/code.mpi", -"org/mathpiper/scripts/texform.rep/code.mpi", -"org/mathpiper/scripts/transforms.rep/code.mpi", -"org/mathpiper/scripts/trigsimp.rep/code.mpi", -"org/mathpiper/scripts/univar.rep/Cyclotomic.mpi", -"org/mathpiper/scripts/univar.rep/code.mpi", -"org/mathpiper/scripts/univar.rep/sparse.mpi", -"org/mathpiper/scripts/univar.rep/sturm.mpi", -}; diff -Nru mathpiper-0.0.svn2556/storage/scripts/initialization.rep/standard.mpi mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/standard.mpi --- mathpiper-0.0.svn2556/storage/scripts/initialization.rep/standard.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/standard.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,200 +0,0 @@ - -/* See the documentation on the assignment of the precedence of the rules. - */ - -/* Some very basic functions that are used always any way... */ - - -/* Implementation of Nth that allows extending. */ -RuleBase("Nth",{alist,aindex}); -Rule("Nth",2,10, - And(Equals(IsFunction(alist),True), - Equals(IsInteger(aindex),True), - Not(Equals(Head(Listify(alist)),Nth)) - )) - MathNth(alist,aindex); - - - - -Rule("Nth",2,14, - And(Equals(IsString(alist),True),IsList(aindex)) - ) -[ - Local(result); - result:=""; - ForEach(i,aindex) [ result := result : StringMidGet(i,1,alist); ]; - result; -]; - -Rule("Nth",2,15,Equals(IsString(alist),True)) -[ - StringMidGet(aindex,1,alist); -]; - - -Rule("Nth",2,20,Equals(IsList(aindex),True)) -[ - Map({{ii},alist[ii]},{aindex}); -]; - -Rule("Nth",2,30, - And( - Equals(IsGeneric(alist),True), - Equals(GenericTypeName(alist),"Array"), - Equals(IsInteger(aindex),True) - ) - ) -[ - ArrayGet(alist,aindex); -]; - - - -Rule("Nth",2,40,Equals(IsString(aindex),True)) -[ - Local(as); - as := Assoc(aindex,alist); - If (Not(Equals(as,Empty)),Set(as,Nth(as,2))); - as; -]; - -Function("NrArgs",{aLeft}) Length(Listify(aLeft))-1; - -10 # IsNonObject(Object(_x)) <-- False; -20 # IsNonObject(_x) <-- True; - -1 # Numer(_x / _y) <-- x; -2 # Numer(x_IsNumber) <-- x; -1 # Denom(_x / _y) <-- y; -2 # Denom(x_IsNumber) <-- 1; - -/* Implementation of numeric mode */ -LocalSymbols(Numeric) [ - Set(Numeric,False); - - - - // evaluate numerically with given precision - LocalSymbols(prev'Numeric, previousNumericMode, numeric'result) Macro("N",{expr,digits}) - [ // we were in non-numeric mode - Local(prev'Numeric, previousNumericMode, numeric'result,errorString); - Set(previousNumericMode, BuiltinPrecisionGet()); - BuiltinPrecisionSet(@digits); - AssignCachedConstantsN(); - Set(prev'Numeric,Numeric); - Set(Numeric, True); - Set(errorString,""); - TrapError(Set(numeric'result, Eval(@expr)),Set(errorString,GetCoreError())); - Set(Numeric,prev'Numeric); - If(Not Numeric,[ - // clear constants - ClearCachedConstantsN(); - ]); - BuiltinPrecisionSet(previousNumericMode); - Check(errorString="",errorString); - numeric'result; - ]; - - LocalSymbols(dig,ex) Macro("N",{expr}) - [ - Local(dig,ex); - Set(dig,BuiltinPrecisionGet()); - Set(ex,Hold(@expr)); - `N(@ex,@dig); - ]; - - - - - - - LocalSymbols(result) Macro("NonN",{expr}) - [ - Local(result); - GlobalPush(Numeric); - Numeric := False; - result := (@expr); - Numeric := GlobalPop(); - result; - ]; - - Function("InNumericMode",{}) Numeric; - -]; //LocalSymbols(Numeric) - -LocalSymbols(Verbose) [ - Set(Verbose,False); - Function("V",{aNumberBody}) - [ - Local(prevVerbose,result); - Set(prevVerbose,Verbose); - Set(Verbose,True); - Set(result,Eval(aNumberBody)); - Set(Verbose,prevVerbose); - result; - ]; - Function("InVerboseMode",{}) Verbose; - -]; // LocalSymbols(Verbose) -HoldArg("V",aNumberBody); -UnFence("V",1); - -Function("++",{aVar}) -[ - MacroSet(aVar,AddN(Eval(aVar),1)); -]; -UnFence("++",1); -HoldArg("++",aVar); - - -Function("--",{aVar}) -[ - MacroSet(aVar,SubtractN(Eval(aVar),1)); -]; -UnFence("--",1); -HoldArg("--",aVar); - - -Function("TableForm",{list}) -[ - Local(i); - ForEach(i,list) - [ - Write(i); - NewLine(); - ]; - True; -]; - -RuleBase("NormalForm",{expression}); -Rule("NormalForm",1,1000,True) expression; - - - - -RuleBase("==",{left,right}); -RuleBase("!==",{left,right}); - - -a_IsNonNegativeInteger & b_IsNonNegativeInteger <-- BitAnd(a,b); -a_IsNonNegativeInteger | b_IsNonNegativeInteger <-- BitOr(a,b); -a_IsNonNegativeInteger % b_IsPositiveInteger <-- Mod(a,b); - -RuleBase("if",{predicate,body}); -(if(True) _body) <-- Eval(body); -HoldArg("if",body); -UnFence("if",2); - -RuleBase("else",{ifthen,otherwise}); -0 # (if (_predicate) _body else _otherwise)_(Eval(predicate) = True) <-- - Eval(body); -0 # (if (_predicate) _body else _otherwise)_(Eval(predicate) = False) <-- - Eval(otherwise); -1 # (if (_predicate) _body else _otherwise) <-- - UnList({Atom("else"), - UnList({Atom("if"), (Eval(predicate)), body}), - otherwise}); -HoldArg("else",ifthen); -HoldArg("else",otherwise); -UnFence("else",2); \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/initialization.rep/standard.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/standard.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/initialization.rep/standard.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/standard.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Nth -NrArgs -IsNonObject -Numer -Denom -NormalForm -== -!== -+- -/- -*- -^- -:=- -:=+ -& -| -% -if -else -N -NonN -InNumericMode -V -InVerboseMode -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/initialization.rep/stdarith.mpi mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/stdarith.mpi --- mathpiper-0.0.svn2556/storage/scripts/initialization.rep/stdarith.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/stdarith.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,382 +0,0 @@ -/* Standard arithmetic */ - - -/* Addition */ - -100 # + _x <-- x; - -50 # x_IsNumber + y_IsNumber <-- AddN(x,y); - -100 # 0 + _x <-- x; -100 # _x + 0 <-- x; -100 # _x + _x <-- 2*x; -100 # _x + n_IsConstant*(_x) <-- (n+1)*x; -100 # n_IsConstant*(_x) + _x <-- (n+1)*x; -101 # _x + - _y <-- x-y; -101 # _x + (- _y)/(_z) <-- x-(y/z); -101 # (- _y)/(_z) + _x <-- x-(y/z); -101 # (- _x) + _y <-- y-x; -102 # _x + y_IsNegativeNumber <-- x-(-y); -102 # _x + y_IsNegativeNumber * _z <-- x-((-y)*z); -102 # _x + (y_IsNegativeNumber)/(_z) <-- x-((-y)/z); -102 # (y_IsNegativeNumber)/(_z) + _x <-- x-((-y)/z); -102 # (x_IsNegativeNumber) + _y <-- y-(-x); -// fractions -150 # _n1 / _d + _n2 / _d <-- (n1+n2)/d; - -200 # (x_IsNumber + _y)_Not(IsNumber(y)) <-- y+x; -200 # ((_y + x_IsNumber) + _z)_Not(IsNumber(y) Or IsNumber(z)) <-- (y+z)+x; -200 # ((x_IsNumber + _y) + z_IsNumber)_Not(IsNumber(y)) <-- y+(x+z); -200 # ((_x + y_IsNumber) + z_IsNumber)_Not(IsNumber(x)) <-- x+(y+z); -// fractions -210 # x_IsNumber + (y_IsNumber / z_IsNumber) <--(x*z+y)/z; -210 # (y_IsNumber / z_IsNumber) + x_IsNumber <--(x*z+y)/z; -210 # (x_IsNumber / v_IsNumber) + (y_IsNumber / z_IsNumber) <--(x*z+y*v)/(v*z); - - -// 220 # + x_IsList <-- MapSingle("+",x); // this rule is never active - -220 # (xlist_IsList + ylist_IsList)_(Length(xlist)=Length(ylist)) <-- Map("+",{xlist,ylist}); - -SumListSide(_x, y_IsList) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x + y[i]); ]; - result; -]; - -240 # (x_IsList + _y)_Not(IsList(y)) <-- SumListSide(y,x); -241 # (_x + y_IsList)_Not(IsList(x)) <-- SumListSide(x,y); - -250 # z_IsInfinity + Complex(_x,_y) <-- Complex(x+z,y); -250 # Complex(_x,_y) + z_IsInfinity <-- Complex(x+z,y); - -251 # z_IsInfinity + _x <-- z; -251 # _x + z_IsInfinity <-- z; - - -250 # Undefined + _y <-- Undefined; -250 # _x + Undefined <-- Undefined; - - - -/* Subtraction arity 1 */ - -//50 # -0 <-- 0; -51 # -Undefined <-- Undefined; -54 # - (- _x) <-- x; -55 # (- (x_IsNumber)) <-- SubtractN(0,x); -100 # _x - n_IsConstant*(_x) <-- (1-n)*x; -100 # n_IsConstant*(_x) - _x <-- (n-1)*x; - -110 # - (_x - _y) <-- y-x; -111 # - (x_IsNumber / _y) <-- (-x)/y; -LocalSymbols(x) -[ - 200 # - (x_IsList) <-- MapSingle("-",x); -]; - -/* Subtraction arity 2 */ -50 # x_IsNumber - y_IsNumber <-- SubtractN(x,y); -50 # x_IsNumber - y_IsNumber <-- SubtractN(x,y); -60 # Infinity - Infinity <-- Undefined; -100 # 0 - _x <-- -x; -100 # _x - 0 <-- x; -100 # _x - _x <-- 0; - -110 # _x - (- _y) <-- x + y; -110 # _x - (y_IsNegativeNumber) <-- x + (-y); -111 # (_x + _y)- _x <-- y; -111 # (_x + _y)- _y <-- x; -112 # _x - (_x + _y) <-- - y; -112 # _y - (_x + _y) <-- - x; -113 # (- _x) - _y <-- -(x+y); -113 # (x_IsNegativeNumber) - _y <-- -((-x)+y); -113 # (x_IsNegativeNumber)/_y - _z <-- -((-x)/y+z); - - -/* TODO move to this precedence everywhere? */ -LocalSymbols(x,y,xarg,yarg) -[ - 10 # ((x_IsList) - (y_IsList))_(Length(x)=Length(y)) <-- - [ - Map({{xarg,yarg},xarg-yarg},{x,y}); - ]; -]; - -240 # (x_IsList - y_IsNonObject)_Not(IsList(y)) <-- -(y-x); - -241 # (x_IsNonObject - y_IsList)_Not(IsList(x)) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x - y[i]); ]; - result; -]; - -250 # z_IsInfinity - Complex(_x,_y) <-- Complex(-x+z,-y); -250 # Complex(_x,_y) - z_IsInfinity <-- Complex(x-z,y); - -251 # z_IsInfinity - _x <-- z; -251 # _x - z_IsInfinity <-- -z; - -250 # Undefined - _y <-- Undefined; -250 # _x - Undefined <-- Undefined; -// fractions -210 # x_IsNumber - (y_IsNumber / z_IsNumber) <--(x*z-y)/z; -210 # (y_IsNumber / z_IsNumber) - x_IsNumber <--(y-x*z)/z; -210 # (x_IsNumber / v_IsNumber) - (y_IsNumber / z_IsNumber) <--(x*z-y*v)/(v*z); - - -/* Multiplication */ - -50 # x_IsNumber * y_IsNumber <-- MultiplyN(x,y); -100 # 1 * _x <-- x; -100 # _x * 1 <-- x; -100 # (_f * _x)_(f= -1) <-- -x; -100 # (_x * _f)_(f= -1) <-- -x; - -95 # x_IsMatrix * y_IsMatrix <-- -[ - Local(i,j,k,row,result); - result:=ZeroMatrix(Length(x),Length(y[1])); - For(i:=1,i<=Length(x),i++) - For(j:=1,j<=Length(y),j++) - For(k:=1,k<=Length(y[1]),k++) - [ - row:=result[i]; - row[k]:= row[k]+x[i][j]*y[j][k]; - ]; - result; -]; - - -96 # x_IsMatrix * y_IsList <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(x),i++) - [ DestructiveInsert(result,i,x[i] . y); ]; - result; -]; - - -97 # (x_IsList * y_IsNonObject)_Not(IsList(y)) <-- y*x; -98 # (x_IsNonObject * y_IsList)_Not(IsList(x)) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x * y[i]); ]; - result; -]; - - -50 # _x * Undefined <-- Undefined; -50 # Undefined * _y <-- Undefined; - - -100 # 0 * Infinity <-- Undefined; -100 # Infinity * 0 <-- Undefined; - -101 # 0 * (_x) <-- 0; -101 # (_x) * 0 <-- 0; - -100 # x_IsNumber * (y_IsNumber * _z) <-- (x*y)*z; -100 # x_IsNumber * (_y * z_IsNumber) <-- (x*z)*y; - -100 # (_x * _y) * _y <-- x * y^2; -100 # (_x * _y) * _x <-- y * x^2; -100 # _y * (_x * _y) <-- x * y^2; -100 # _x * (_x * _y) <-- y * x^2; -100 # _x * (_y / _z) <-- (x*y)/z; -// fractions -100 # (_y / _z) * _x <-- (x*y)/z; -100 # (_x * y_IsNumber)_Not(IsNumber(x)) <-- y*x; - -100 # (_x) * (_x) ^ (n_IsConstant) <-- x^(n+1); -100 # (_x) ^ (n_IsConstant) * (_x) <-- x^(n+1); -100 # (_x * _y)* _x ^ n_IsConstant <-- y * x^(n+1); -100 # (_y * _x)* _x ^ n_IsConstant <-- y * x^(n+1); - -105 # x_IsNumber * -(_y) <-- (-x)*y; -105 # (-(_x)) * (y_IsNumber) <-- (-y)*x; - -106 # _x * -(_y) <-- -(x*y); -106 # (- _x) * _y <-- -(x*y); - -107 # -( (-(_x))/(_y)) <-- x/y; -107 # -( (_x)/(-(_y))) <-- x/y; - - -250 # x_IsNumber * y_IsInfinity <-- Sign(x)*y; -250 # x_IsInfinity * y_IsNumber <-- Sign(y)*x; - - -/* Note: this rule MUST be past all the transformations on - * matrices, since they are lists also. - */ -230 # (aLeft_IsList * aRight_IsList)_(Length(aLeft)=Length(aRight)) <-- - Map("*",{aLeft,aRight}); -// fractions -242 # (x_IsInteger / y_IsInteger) * (v_IsInteger / w_IsInteger) <-- (x*v)/(y*w); -243 # x_IsInteger * (y_IsInteger / z_IsInteger) <-- (x*y)/z; -243 # (y_IsInteger / z_IsInteger) * x_IsInteger <-- (x*y)/z; - -400 # (_x) * (_x) <-- x^2; - -/* Division */ - -50 # 0 / 0 <-- Undefined; - -52 # x_IsPositiveNumber / 0 <-- Infinity; -52 # x_IsNegativeNumber / 0 <-- -Infinity; -55 # (_x / y_IsNumber)_(IsZero(y)) <-- Undefined; -55 # 0 / _x <-- 0; -60 # (x_IsNumber / y_IsNumber)_(InNumericMode() /* Sorry, Serge Or - Not(IsInteger(x) And IsInteger(y)) */ ) <-- - DivideN(x,y); - -// unnecessary rule (see #100 below). TODO: REMOVE -//55 # x_IsNumber / y_IsNegativeNumber <-- (-x)/(-y); - -56 # (x_IsNonZeroInteger / y_IsNonZeroInteger)_(GcdN(x,y) > 1) <-- - [ - Local(gcd); - Set(x,x); - Set(y,y); - Set(gcd,GcdN(x,y)); - DivN(x,gcd)/DivN(y,gcd); - ]; - - -90 # x_IsInfinity / y_IsInfinity <-- Undefined; -95 # x_IsInfinity / y_IsNumber <-- Sign(y)*x; -95 # x_IsInfinity / y_IsComplex <-- Infinity; - -90 # Undefined / _y <-- Undefined; -90 # _y / Undefined <-- Undefined; - - -100 # _x / _x <-- 1; -100 # _x / 1 <-- x; -100 # (_x / y_IsNegativeNumber) <-- -x/(-y); -100 # (_x / - _y) <-- -x/y; -// fractions -200 # (_x / _y)/ _z <-- x/(y*z); -230 # _x / (_y / _z) <-- (x*z)/y; - -240 # (xlist_IsList / ylist_IsList)_(Length(xlist)=Length(ylist)) <-- - Map("/",{xlist,ylist}); - - -250 # (x_IsList / _y)_(Not(IsList(y))) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(x),i++) - [ DestructiveInsert(result,i,x[i] / y); ]; - result; -]; - -250 # (_x / y_IsList)_(Not(IsList(x))) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=Length(y),i++) - [ DestructiveInsert(result,i,x/y[i]); ]; - result; -]; - -250 # _x / Infinity <-- 0; -250 # _x / (-Infinity) <-- 0; - - -400 # 0 / _x <-- 0; - -/* Faster version of raising power to 0.5 */ -50 # _x ^ (1/2) <-- Sqrt(x); -50 # (x_IsPositiveNumber ^ (1/2))_IsInteger(SqrtN(x)) <-- SqrtN(x); -58 # 1 ^ n_IsInfinity <-- Undefined; -59 # _x ^ 1 <-- x; -59 # 1 ^ _n <-- 1; -59 # x_IsZero ^ y_IsZero <-- Undefined; -60 # (x_IsZero ^ n_IsRationalOrNumber)_(n>0) <-- 0; -60 # (x_IsZero ^ n_IsRationalOrNumber)_(n<0) <-- Infinity; -// This is to fix: -// In> 0.0000^2 -// Out> 0.0000^2; -// In> 0.0^2/2 -// Out> 0.0^2/2; -//60 # (x_IsNumber ^ n_IsRationalOrNumber)_(x+1=1) <-- 0; - -59 # _x ^ Undefined <-- Undefined; -59 # Undefined ^ _x <-- Undefined; - -/* Regular raising to the power. */ -61 # Infinity ^ (y_IsNegativeNumber) <-- 0; -61 # (-Infinity) ^ (y_IsNegativeNumber) <-- 0; -//61 # x_IsPositiveNumber ^ y_IsPositiveNumber <-- PowerN(x,y); -//61 # x_IsPositiveNumber ^ y_IsNegativeNumber <-- (1/PowerN(x,-y)); -// integer powers are very fast -61 # x_IsPositiveNumber ^ y_IsPositiveInteger <-- MathIntPower(x,y); -61 # x_IsPositiveNumber ^ y_IsNegativeInteger <-- 1/MathIntPower(x,-y); -65 # (x_IsPositiveNumber ^ y_IsNumber)_InNumericMode() <-- Exp(y*Ln(x)); - -90 # (-_x)^m_IsEven <-- x^m; -91 # (x_IsConstant ^ (m_IsOdd / p_IsOdd))_(IsNegativeNumber(Re(N(Eval(x))))) <-- - -((-x)^(m/p)); -92 # (x_IsNegativeNumber ^ y_IsNumber)_InNumericMode() <-- Exp(y*Ln(x)); - - -70 # (_x ^ m_IsRationalOrNumber) ^ n_IsRationalOrNumber <-- x^(n*m); - -80 # (x_IsNumber/y_IsNumber) ^ n_IsPositiveInteger <-- x^n/y^n; -80 # (x_IsNumber/y_IsNumber) ^ n_IsNegativeInteger <-- y^(-n)/x^(-n); -80 # x_IsNegativeNumber ^ n_IsEven <-- (-x)^n; -80 # x_IsNegativeNumber ^ n_IsOdd <-- -((-x)^n); - - -100 # ((_x)*(_x ^ _m)) <-- x^(m+1); -100 # ((_x ^ _m)*(_x)) <-- x^(m+1); -100 # ((_x ^ _n)*(_x ^ _m)) <-- x^(m+n); - -100 # ((x_IsNumber)^(n_IsInteger/(_m)))_(n>1) <-- MathIntPower(x,n)^(1/m); - -100 # Sqrt(_n)^(m_IsEven) <-- n^(m/2); - - -200 # x_IsMatrix ^ n_IsPositiveInteger <-- x*(x^(n-1)); -204 # (xlist_IsList ^ nlist_IsList)_(Length(xlist)=Length(nlist)) <-- - Map("^",{xlist,nlist}); -205 # (xlist_IsList ^ n_IsConstant)_(Not(IsList(n))) <-- - Map({{xx},xx^n},{xlist}); -206 # (_x ^ n_IsList)_(Not(IsList(x))) <-- Map({{xx},x^xx},{n}); -249 # x_IsInfinity ^ 0 <-- Undefined; -250 # Infinity ^ (_n) <-- Infinity; -250 # Infinity ^ (_x_IsComplex) <-- Infinity; -250 # ((-Infinity) ^ (n_IsNumber))_(IsEven(n)) <-- Infinity; -250 # ((-Infinity) ^ (n_IsNumber))_(IsOdd(n)) <-- -Infinity; - -250 # (x_IsNumber ^ Infinity)_(x> -1 And x < 1) <-- 0; -250 # (x_IsNumber ^ Infinity)_(x> 1) <-- Infinity; - -// these Magnitude(x)s should probably be changed to Abs(x)s - -250 # (x_IsComplex ^ Infinity)_(Magnitude(x) > 1) <-- Infinity; -250 # (x_IsComplex ^ Infinity)_(Magnitude(x) < -1) <-- -Infinity; -250 # (x_IsComplex ^ Infinity)_(Magnitude(x) > -1 And Magnitude(x) < 1) <-- 0; - -250 # (x_IsNumber ^ -Infinity)_(x> -1 And x < 1) <-- Infinity; -250 # (x_IsNumber ^ -Infinity)_(x< -1) <-- 0; -250 # (x_IsNumber ^ -Infinity)_(x> 1) <-- 0; - -255 # (x_IsComplex ^ Infinity)_(Abs(x) = 1) <-- Undefined; -255 # (x_IsComplex ^ -Infinity)_(Abs(x) = 1) <-- Undefined; - - - -400 # _x ^ 0 <-- 1; diff -Nru mathpiper-0.0.svn2556/storage/scripts/initialization.rep/stdarith.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/stdarith.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/initialization.rep/stdarith.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/stdarith.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -+ -- -* -/ -^ -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/initialization.rep/stdopers.mpi mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/stdopers.mpi --- mathpiper-0.0.svn2556/storage/scripts/initialization.rep/stdopers.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/initialization.rep/stdopers.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ - -/* stdopers is loaded immediately after MathPiper is started. It contains - * the definitions of the infix operators, so the parser can already - * parse expressions containing these operators, even though the - * function hasn't been defined yet. - */ - -Infix("=",90); -Infix("And",1000); -RightAssociative("And"); -Infix("Or", 1010); -Prefix("Not", 100); -Infix("<",90); -Infix(">",90); -Infix("<=",90); -Infix(">=",90); -Infix("!=",90); - -Infix(":=",10000); -RightAssociative(":="); - -Infix("+",70); -Infix("-",70); -RightPrecedence("-",40); -Infix("/",30); -Infix("*",40); -Infix("^",20); -RightAssociative("^"); -Prefix("+",50); -Prefix("-",50); -RightPrecedence("-",40); -Bodied("For",60000); -Bodied("Until",60000); -Postfix("++",5); -Postfix("--",5); -Bodied("ForEach",60000); -Infix("<<",10); -Infix(">>",10); -Bodied("D",60000); -Bodied("Deriv",60000); -Infix("X",30); -Infix(".",30); -Infix("o",30); -Postfix("!", 30); -Postfix("!!", 30); -Infix("***", 50); -Bodied("Integrate",60000); - -Bodied("Limit",60000); - -/* functional operators */ -Infix(":",70); -RightAssociative(":"); -Infix("@",600); -Infix("/@",600); -Infix("..",600); - -Bodied("Taylor",60000); -Bodied("Taylor1",60000); -Bodied("Taylor2",60000); -Bodied("Taylor3",60000); -Bodied("InverseTaylor",60000); - -Infix("<--",10000); -Infix("#",9900); - -Bodied("TSum",60000); -Bodied("TExplicitSum",60000); -Bodied("TD",5); /* Tell the MathPiper interpreter that TD is to be used as TD(i)f */ - -/* Operator to be used for non-evaluating comparisons */ -Infix("==",90); -Infix("!==",90); - -/* Operators needed for propositional logic theorem prover */ -Infix("=>",10000); /* implication, read as 'implies' */ - - -Bodied("if",5); -Infix("else",60000); -RightAssociative("else"); -/* Bitwise operations we REALLY need. Perhaps we should define them - also as MathPiper operators? - */ -Infix("&",50); -Infix("|",50); -Infix("%",50); - -/* local pattern replacement operators */ -Infix("/:",20000); -Infix("/::",20000); -Infix("<-",10000); - -/* Operators used for manual layout */ -Infix("<>", OpPrecedence("=")); -Infix("<=>", OpPrecedence("=")); - -/* Operators for Solve: Where and AddTo */ -Infix("Where", 11000); -Infix("AddTo", 2000); - -Bodied("Function",60000); -Bodied("Macro",60000); - -Bodied(Assert, 60000); - -// Defining very simple functions, in scripts that can be converted to plugin. -Bodied("Defun",0); - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/integrate.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/integrate.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/integrate.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/integrate.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,355 +0,0 @@ - -RuleBase("IntegrateMultiplicative",{var,from,a,b}); -UnFence("IntegrateMultiplicative",4); - -10# (Integrate(_var)(expr_IsList)) - <-- Map("Integrate",{FillList(var,Length(expr)),expr}); -20 # (Integrate(_var)(_expr)) <-- IntSub(var,expr,AntiDeriv(var,IntClean(var,expr))); - - -10 # IntSub(_var,_expr,Integrate(_var)(_expr2)) <-- - `Hold(Integrate(@var)(@expr)); -20 # IntSub(_var,_expr,_result) <-- result; // + UniqueConstant(); - -//////////////////////////////////////////////// -// -// Integrate over a range -// -//////////////////////////////////////////////// -10# (Integrate(_var,_from,_to)(expr_IsList)) - <-- Map("Integrate",{FillList(var,Length(expr)), - FillList(from,Length(expr)), - FillList(to,Length(expr)), - expr}); - -20 # (Integrate(_var,_from,_to)(_expr)) - <-- indefIntegrate(var,from,to,expr,a,b); - -//////////////////////////////////////////////// -// -// separate rules can be added here for specific integrals -// to indefIntegrate -// -//////////////////////////////////////////////// - -10 # indefIntegrate(_var,_from,_to,_expr,_a,_b)_(from = -to And IsOddFunction(expr,var)) <-- 0; - -// We need to define this case (integrating from 0 to 0 over an even function) explicitly, otherwise -// the integration ends up going in to infinite recursion. Extended it a little bit more, since if -// you are integrating from A to A, then the result is obviously zero. There are perhaps situations -// where this does not work, where we need to simplify (to-from) first. A naive implementation caused -// a test to fail. -10 # indefIntegrate(_var,_from,_from,_expr,_a,_b) <-- 0; - -12 # indefIntegrate(_var,_from,_to,_expr,_a,_b)_(from = -to And IsEvenFunction(expr,var)) <-- - 2*indefIntegrate(var,0,to,expr,a,b); - -100 # indefIntegrate(_var,_from,_to,_expr,_a,_b)_(Type(AntiDeriv(var,IntClean(var,expr))) != "AntiDeriv") - <-- - IntegrateRange(var,expr,from,to,AntiDeriv(var,IntClean(var,expr))); -101 # indefIntegrate(_var,_from,_to,_expr,_a,_b) - <-- `Hold(Integrate(@var,@from,@to)(@expr)); -// <-- IntegrateRange(var,expr,from,to,AntiDeriv(var,expr)); - - - -//////////////////////////////////////////////// -// -// No anti-derivative found, return unavaluated. -// -//////////////////////////////////////////////// -10 # IntegrateRange(_var,_expr,_from,_to,Integrate(_var)_expr2) - <-- `Hold(Integrate(@var,@from,@to)@expr); - -//////////////////////////////////////////////// -// -// Anti-derivative found, return result. -// -//////////////////////////////////////////////// -20 # IntegrateRange(_var,_expr,_from,_to,_antideriv) - <-- `(@antideriv Where @var == @to) - `(@antideriv Where @var == @from); - -//////////////////////////////////////////////// -// -// IntClean cleans up an expression before passing -// it on to integration. This function normalizes -// an expression in a way desirable for integration. -// TrigSimpCombine, for instance, expands expressions -// containing trigonometric functions so that they are -// additive as opposed to multiplicative. -// -// If the expression doesn't contain the variable, -// just return it as-is. This fixes: -// In> Integrate(x) z^100 -//////////////////////////////////////////////// -10 # IntClean(_var,_expr) <-- -[ - if( IsFreeOf(var,expr))[ - expr; - ] else if ( HasFunc(expr,Sin) Or HasFunc(expr,Cos) )[ - Simplify(TrigSimpCombine(expr)); - ] else [ - Simplify(expr); - ]; -]; - -//////////////////////////////////////////////// -// -// Anti-derivative of a univariate polynomial -// -//////////////////////////////////////////////// -5 # AntiDeriv(_var, poly_CanBeUni(var) ) - <-- NormalForm(AntiDeriv(var,`MakeUni(@poly,@var))); -5 # AntiDeriv(_var,UniVariate(_var,_first,_coefs)) <-- -[ - Local(result,i); - result:=FlatCopy(coefs); - For(i:=1,i<=Length(result),i++) - [ - result[i]:= result[i]/(first+i); - ]; - UniVariate(var,first+1,result); -]; - - - -//////////////////////////////////////////////// -// -// Standard additive properties of integration. -// -//////////////////////////////////////////////// -10 # AntiDeriv(_var,_x + _y) <-- AntiDeriv(var,x) + AntiDeriv(var,y); -10 # AntiDeriv(_var,_x - _y) <-- AntiDeriv(var,x) - AntiDeriv(var,y); -10 # AntiDeriv(_var, - _y) <-- - AntiDeriv(var,y); - -10 # AntiDeriv(_var,_x/c_IsFreeOf(var) )_(HasExpr(x,var)) <-- AntiDeriv(var,x)/c; -10 # AntiDeriv(_var,c_IsFreeOf(var)/_x )_(HasExpr(x,var) And c!= 1) - <-- c*AntiDeriv(var,1/x); - - -//////////////////////////////////////////////// -// -// Multiplying a polynomial with another (integrable) -// function, Integrate by parts. -// -//////////////////////////////////////////////// -1570 # IntegrateMultiplicative(_var,(exy_CanBeUni(var)) * _exx,_dummy1,_dummy2) - <-- IntByParts(var,exy*exx,AntiDeriv(var,exx)); -1570 # IntegrateMultiplicative(_var,_exx * (exy_CanBeUni(var)),_dummy1,_dummy2) - <-- IntByParts(var,exy*exx,AntiDeriv(var,exx)); -10 # IntByParts(_var,_exy * _exx,Integrate(_var)(_something)) <-- - `Hold(AntiDeriv(@var,((@exy)*(@exx)))); -20 # IntByParts(_var,_exy * _exx,_anti)_(Not IsFreeOf(anti,exx)) <-- - `Hold(AntiDeriv(@var,((@exy)*(@exx)))); -30 # IntByParts(_var,_exy * _exx,_anti) <-- - [ - Local(cf); - cf:=anti*Deriv(var)exy; -// Echo({exy*anti,exy*exx,cf}); - exy*anti - `(AntiDeriv(@var,@cf)); - ]; - -//////////////////////////////////////////////// -// -// Rational functions: f(x)/g(x) where f and g are -// polynomials. -// -//////////////////////////////////////////////// -1570 # IntegrateMultiplicative(_var,(exy_CanBeUni(var)) / (exx_CanBeUni(var)),_dummy1,_dummy2) <-- - IntRat(var,exy/exx,MakeUni(exy,var),MakeUni(exx,var)); - -10 # IntRat(_var,_exy / _exx,_exyu,_exxu)_ - (Degree(exyu) > Degree(exxu) Or Degree(Gcd(exyu,exxu)) > 0) <-- - [ - Local(gcd); - gcd:=Gcd(exxu,exyu); - exyu:=Div(exyu,gcd); - exxu:=Div(exxu,gcd); - AntiDeriv(var,NormalForm(Div(exyu,exxu))) + - AntiDeriv(var,NormalForm(Mod(exyu,exxu))/NormalForm(exxu)); - ]; - -11 # IntRat(_var,_exy / _exx,_exyu,_exxu)_ - (Degree(exxu,var) > 1 And LeadingCoef(exxu)=1 And - IsNumericList(Coef(exxu,var,0 .. Degree(exxu)))) <-- -[ - Local(ee); - ee:=Apart(exy/exx,var); - `AntiDeriv(@var,@ee); -]; - - -20 # IntRat(_var,_exy / _exx,_exyu,_exxu) <-- - `Hold(AntiDeriv(@var,((@exy)/(@exx)))); - - -30 # AntiDeriv(_var,Deriv(_var)(_expr)) <-- expr; - -//////////////////////////////////////////////// -// -// No simple form, try something else -// -//////////////////////////////////////////////// -100 # AntiDeriv(_var,_exp) <-- -[ - IntegrateMultiplicative(var,exp,a,b); -]; - - -//////////////////////////////////////////////// -// -// Special anti-derivatives can be added here. -// -//////////////////////////////////////////////// - -// integrating expressions containing if: -10 # IntegrateMultiplicative(_var,if(_cond)(_body),_a,_b) - <-- - [ - body := AntiDeriv(var,body); - `Hold(if(@cond)(@body)); - ]; -// integrating expressions containing else -10 # IntegrateMultiplicative(_var,(_left) else (_right),_a,_b) - <-- - [ - left := AntiDeriv(var,left); - right := AntiDeriv(var,right); - `Hold( (@left) else (@right) ); - ]; - - -//////////////////////////////////////////////// -// -// Could not find anti-derivative, return unsimplified -// -//////////////////////////////////////////////// -1600 # IntegrateMultiplicative(_var,_exp,_a,_b) <-- `Hold(Integrate(@var)(@exp)); - -//////////////////////////////////////////////// -// -// IntFunc declares the anti-derivative of a function -// that has one argument. -// Calling sequence: IntFunc(variable,from,to); -// Example: IntFunc(x,Cos(_x),Sin(x)); -// -//////////////////////////////////////////////// -LocalSymbols(intpred) -[ - intpred := 50; - IntFunc(_vr,_from,_to) <-- - [ - `((@intpred) # IntegrateMultiplicative(_var,@from,_dummy1,_dummy2)_MatchLinear(var,@vr) <-- (@to)/Matched'a()); - intpred++; - ]; -]; - - -IntPureSquare(_vr,_from,_sign2,_sign0,_to) <-- -[ - `(50 # IntegrateMultiplicative(_var,@from,_dummy1,_dummy2)_MatchPureSquared(var,@sign2,@sign0,@vr) <-- (@to)); -]; - - - - -//////////////////////////////////////////////// -// -// Declaration of the anti-derivatives of a few analytic functions -// -//////////////////////////////////////////////// - - -IntFunc(x,Sqrt(_x),(2*Sqrt(x)^(3))/3); -IntFunc(x,1/_x^(_n),x^(1-n)/(1-n) ); -IntFunc(x,Sin(_x),-Cos(x)); -IntFunc(x,1/Sin(_x), Ln( 1/Sin(x) - Cos(x)/Sin(x) ) ); -IntFunc(x,Cos(_x),Sin(x)); -IntFunc(x,1/Cos(_x),Ln(1/Cos(x)+Tan(x))); -IntFunc(x,Tan(_x),-Ln(Cos(x))); -IntFunc(x,1/Tan(_x),Ln(Sin(x)) ); -IntFunc(x,Cos(_x)/Sin(_x),Ln(Sin(x))); -IntFunc(x,Exp(_x),Exp(x)); -IntFunc(x,(C_IsFreeOf(var))^(_x),C^x/Ln(C)); -// we don't need Ln(Abs(x)) -IntFunc(x,num_IsFreeOf(var) / (_x),num*Ln(x)); -IntFunc(x,Ln(_x),x*Ln(x)-x); -// where did these 1+1's come from? -IntFunc(x,(_x)*Ln(_x),(1/(1+1))*x^(1+1)*Ln(x) - (1/(1+1)^2)*x^(1+1) ); -IntFunc(x,Ln(_x)*(_x),(1/(1+1))*x^(1+1)*Ln(x) - (1/(1+1)^2)*x^(1+1) ); - -IntFunc(x,1/Sin(_x)^2,-Cos(x)/Sin(x) ); -IntFunc(x,1/Cos(_x)^2,Tan(x) ); -IntFunc(x,1/(Sin(_x)*Tan(_x)),-1/Sin(x)); -IntFunc(x,Tan(_x)/Cos(_x),1/Cos(x)); -IntFunc(x,1/Sinh(_x)^2,-1/Tanh(x)); -IntFunc(x,1/Cosh(_x)^2,Tanh(x)); -IntFunc(x,1/(Sinh(_x)*Tan(_x)),-1/Sinh(x)); -IntFunc(x,Tanh(_x)/Cosh(_x),-1/Cosh(x)); - -IntFunc(x,1/Sqrt(m_IsFreeOf(x)-_x^2),ArcSin(x/Sqrt(m)) ); - -IntFunc(x,Exp(n_IsNumber*_x)*Sin(m_IsNumber*_x),Exp(n*x)*(n*Sin(m*x)- m*Cos(m*x))/(m^2+n^2) ); - -// n>0 -IntFunc(x,Ln(_x)*(_x)^n_IsNumber,(1/(n+1))*x^(n+1)*Ln(x) - (1/(n+1)^2)*x^(n+1) ); - -// n>0 -IntFunc(x,Ln(A_IsNumber*_x)*(_x)^n_IsNumber,(1/(n+1))*x^(n+1)*Ln(A*x) - (1/(n+1)^2)*x^(n+1) ); - -IntFunc(x,Sin(Ln(_x)),x*Sin(Ln(x))/2 - x*Cos(Ln(x))/2 ); -IntFunc(x,Cos(Ln(_x)),x*Sin(Ln(x))/2 - x*Cos(Ln(x))/2 ); - -IntFunc(x,1/((_x)*Ln(_x)),Ln(Ln(x))); - -IntFunc(x,(_x)^(-1),Ln(x)); - -IntFunc(x,(_x)^(n_IsFreeOf(x)),x^(n+1)/(n+1)); -IntFunc(x,Sinh(_x),Cosh(x)); -IntFunc(x,Sinh(_x)^2,Sinh(2*x)/4 - x/2); -IntFunc(x,1/Sinh(_x),Ln(Tanh(x/2))); -IntFunc(x,Cosh(_x),Sinh(x)); -IntFunc(x,Cosh(_x)^2,Sinh(2*x)/4 + x/2); -IntFunc(x,1/Cosh(_x),ArcTan(Sinh(x))); -IntFunc(x,Tanh(_x),Ln(Cosh(x))); -IntFunc(x,Tanh(_x)/Cosh(_x),-1/Cosh(x)); -IntFunc(x,1/Cosh(_x)^2,Tanh(x)); -//IntFunc(x,1/Sech(_x)*Coth(_x),-1/Sinh(x)); -IntFunc(x,1/Tanh(_x),Ln(Sinh(x))); - -IntFunc(x,Abs(_x),Abs(x)*x/2); // not 2*a - -IntFunc(x,ArcTan(_x),x*ArcTan(x) - Ln(x^2 + 1)/2); -//IntFunc(x,ArcSin(_x),(x*ArcSin(x)) + Sqrt(1-x^2) ); -IntFunc(x,ArcCos(_x),x*ArcCos(x) - Sqrt(1-x^2) ); - -IntFunc(x,ArcTanh(_x),x*ArcTanh(x) + Ln(1-x^2)/2 ); -IntFunc(x,ArcSinh(_x),x*ArcSinh(x) - Sqrt(x^2 + 1) ); -IntFunc(x,ArcCosh(_x),x*ArcCosh(x) - Sqrt(x-1)*Sqrt(x+1) ); - - -// n^2 > x^2 -//IntFunc(x,num_IsFreeOf(var)/(-(_x)^2 + n_IsNumber),num*ArcTanh(x/Sqrt(n))/n); - -// x^2 > n^2 -//IntFunc(x,num_IsFreeOf(var)/((_x)^2 - n_IsNumber),num * -ArcCoth(x/Sqrt(n))/Sqrt(n)); - -// n^2 > x^2 -//IntFunc(x,num_IsFreeOf(var)/Sqrt(n_IsNumber - (_x)^2),num*ArcSin(x/Sqrt(n))); - -// previous code is killing this.... -IntFunc(x,num_IsFreeOf(var)/(A_IsNumber + B_IsNumber*(_x))^2,-num/(A*b + B^2*x)); - -// Code works now? -IntFunc(x,num_IsFreeOf(var)/(n_IsNumber + m_IsNumber*Exp(p_IsNumber*(_x))),num*x/n - num*Ln(n + m*Exp(p*x))/(n*p)); -IntFunc(x,num_IsFreeOf(var)/(m_IsNumber*Exp(p_IsNumber*(_x)) + n_IsNumber),num*x/n - num*Ln(n + m*Exp(p*x))/(n*p)); - -IntPureSquare(x,num_IsFreeOf(var)/(_x),1,1,(num/(a*Sqrt(Matched'b()/Matched'a())))*ArcTan(var/Sqrt(Matched'b()/Matched'a()))); - - - -///// Integrating Special Functions -IntFunc(x,Erf(_x), x*Erf(x)+ 1/(Exp(x^2)*Sqrt(Pi)) ); - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/integrate.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/integrate.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/integrate.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/integrate.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -Integrate -AntiDeriv -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/integrate.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/integrate.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/integrate.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/integrate.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -// From code.mpi.def: -OMDef( "Integrate", "calculus1","defint", // Same argument reordering as Sum. - { $, _2 .. _3, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }, - { $, _{2,2,1}, _{1,1}, _{1,2}, _{2,3} } - ); -OMDef( "AntiDeriv", "piper","AntiDeriv" ); diff -Nru mathpiper-0.0.svn2556/storage/scripts/io.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/io.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/io.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/io.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -/// stuff related to input-output during interactive sessions - -/// simple prettyprinter -Use("org/mathpiper/scripts/io.rep/print.mpi"); - -/// global error reporting and handling -Use("org/mathpiper/scripts/io.rep/errors.mpi"); - -/// ascii formula prettyprinter -Use("org/mathpiper/scripts/io.rep/formula.mpi"); diff -Nru mathpiper-0.0.svn2556/storage/scripts/io.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/io.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/io.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/io.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -Print -IsError -Assert -GetErrorTableau -ClearErrors -DumpErrors -ClearError -PrettyForm -EvalFormula -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/io.rep/defaultprint.mpi mathpiper-0.81f+dfsg1/storage/scripts/io.rep/defaultprint.mpi --- mathpiper-0.0.svn2556/storage/scripts/io.rep/defaultprint.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/io.rep/defaultprint.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -/// The new default pretty-printer: DefaultPrint -Function("DefaultPrint", {x}) -[ - DumpErrors(); - WriteString("Out> "); - Write(x); - WriteString("; -"); -]; -HoldArg("DefaultPrint", x); - diff -Nru mathpiper-0.0.svn2556/storage/scripts/io.rep/defaultprint.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/io.rep/defaultprint.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/io.rep/defaultprint.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/io.rep/defaultprint.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -DefaultPrint -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/io.rep/errors.mpi mathpiper-0.81f+dfsg1/storage/scripts/io.rep/errors.mpi --- mathpiper-0.0.svn2556/storage/scripts/io.rep/errors.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/io.rep/errors.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -////////////////////////////////////////////////// -/// ErrorTableau, Assert, IsError --- global error reporting -////////////////////////////////////////////////// - -LocalSymbols(ErrorTableau) [ - - /// global error tableau. Its entries do not have to be lists. - Set(ErrorTableau, {}); - - GetErrorTableau() := ErrorTableau; - - ClearErrors() <-- Set(ErrorTableau, {}); - - /// aux function to check for corrupt tableau - CheckErrorTableau() <-- - If( - Not IsList(ErrorTableau), - Set(ErrorTableau, {{"general", "corrupted ErrorTableau"}}) - ); - -]; // LocalSymbols(ErrorTableau) - -/// check for errors -IsError() <-- -[ - CheckErrorTableau(); - Length(GetErrorTableau())>0; -]; - -/// check for errors of a given kind -IsError(error'class_IsString) <-- -[ - CheckErrorTableau(); - GetErrorTableau()[error'class] != Empty; -]; - -/// post an error if assertion fails -(Assert(_error'class, _error'object) _predicate) <-- -[ - CheckErrorTableau(); - If(Equals(predicate, True), // if it does not evaluate to True, it's an error - True, - [ // error occurred, need to post error'object - DestructiveAppend(GetErrorTableau(), {error'class, error'object}); - False; - ] - ); -]; - -/// interface -(Assert(_error'class) _predicate) <-- Assert(error'class, True) predicate; - -/// interface -(Assert() _predicate) <-- Assert("generic", True) predicate; - -/// print all errors and clear the tableau -DumpErrors() <-- -[ - Local(error'object, error'word); - CheckErrorTableau(); - ForEach(error'object, GetErrorTableau()) - [ // error'object might be e.g. {"critical", {"bad bad", -1000}} - If( - IsList(error'object), - [ - If( // special case: error class "warning" - Length(error'object) > 0 And error'object[1] = "warning", - [ - error'word := "Warning"; - error'object[1] := ""; // don't print the word "warning" again - ], - error'word := "Error: " // important hack: insert ": " here but not after "Warning" - ); - - If( // special case: {"error'class", True} - Length(error'object)=2 And error'object[2]=True, - Echo(error'word, error'object[1]), - [ - Echo(error'word, error'object[1], ": ", - PrintList(Tail(error'object))); - ] - ); - ], - // error'object is not a list: just print it - Echo("Error: ", error'object) - ); - ]; - ClearErrors(); -]; - -/// obtain error object -GetError(error'class_IsString) <-- -[ - Local(error); - error := GetErrorTableau()[error'class]; - If( - error != Empty, - error, - False - ); -]; - -/// delete error -ClearError(error'class_IsString) <-- AssocDelete(GetErrorTableau(), error'class); - - -////////////////////////////////////////////////// - diff -Nru mathpiper-0.0.svn2556/storage/scripts/io.rep/formula.mpi mathpiper-0.81f+dfsg1/storage/scripts/io.rep/formula.mpi --- mathpiper-0.0.svn2556/storage/scripts/io.rep/formula.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/io.rep/formula.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,439 +0,0 @@ - -/* -TODO: -- Func(a=b) prematurely evaluates a=b -- clean up the code! - - document the code!!! -- prefix/postfix currently not used!!! -- some rules for rendering the formula are slooooww.... - -- bin, derivative, sqrt, integral, summation, limits, - ___ - / a | - \ / - - \/ b - - / - | - | - | - / - - d - --- f( x ) - d x - - 2 - d - ---- f( x ) - 2 - d x - - Infinity - ___ - \ - \ n - / x - /__ - n = 0 - Sin(x) - lim ------ - x -> Infinity x - - - -*/ - -/* -NLog(str):= -[ - WriteString(str); - NewLine(); -]; -*/ - -CharList(length,item):= -[ - Local(line,i); - line:=""; - For(Set(i,0),LessThan(i,length),Set(i,AddN(i,1))) - Set(line, line:item); - line; -]; - -CharField(width,height) := ArrayCreate(height,CharList(width," ")); - -WriteCharField(charfield):= -[ - Local(i,len); - len:=Length(charfield); - For(Set(i,1),i<=len,Set(i,AddN(i,1))) - [ - WriteString(charfield[i]); - NewLine(); - ]; - True; -]; - -ColumnFilled(charfield,column):= -[ - Local(i,result,len); - result:=False; - len:=Length(charfield); - For(Set(i, 1),(result = False) And (i<=len),Set(i,AddN(i,1))) - [ - If(StringMidGet(column,1,charfield[i]) != " ",result:=True); - ]; - result; -]; -WriteCharField(charfield,width):= -[ - Local(pos,length,len); - Set(length, Length(charfield[1])); - Set(pos, 1); - While(pos<=length) - [ - Local(i,thiswidth); - Set(thiswidth, width); - If(thiswidth>(length-pos)+1, - [ - Set(thiswidth, AddN(SubtractN(length,pos),1)); - ], - [ - While (thiswidth>1 And ColumnFilled(charfield,pos+thiswidth-1)) - [ - Set(thiswidth,SubtractN(thiswidth,1)); - ]; - If(thiswidth = 1, Set(thiswidth, width)); - ] - ); - len:=Length(charfield); - For(Set(i, 1),i<=len,Set(i,AddN(i,1))) - [ - WriteString(StringMidGet(pos,thiswidth,charfield[i])); - NewLine(); - ]; - Set(pos, AddN(pos, thiswidth)); - NewLine(); - ]; - True; -]; - - - -PutString(charfield,x,y,string):= -[ - cf[y] := StringMidSet(x,string,cf[y]); - True; -]; - -MakeOper(x,y,width,height,oper,args,base):= -[ - Local(result); - Set(result,ArrayCreate(7,0)); - ArraySet(result,1,x); - ArraySet(result,2,y); - ArraySet(result,3,width); - ArraySet(result,4,height); - ArraySet(result,5,oper); - ArraySet(result,6,args); - ArraySet(result,7,base); - result; -]; - - -MoveOper(f,x,y):= -[ - f[1]:=AddN(f[1], x); /* move x */ - f[2]:=AddN(f[2], y); /* move y */ - f[7]:=AddN(f[7], y); /* move base */ -]; - -AlignBase(i1,i2):= -[ - Local(base); - Set(base, Max(i1[7],i2[7])); - MoveOper(i1,0,SubtractN(base,(i1[7]))); - MoveOper(i2,0,SubtractN(base,(i2[7]))); -]; - -10 # BuildArgs({}) <-- Formula(Atom(" ")); -20 # BuildArgs({_head}) <-- head; -30 # BuildArgs(_any) <-- - [ - Local(item1,item2,comma,base,newitem); - Set(item1, any[1]); - Set(item2, any[2]); - Set(comma, Formula(Atom(","))); - Set(base, Max(item1[7],item2[7])); - MoveOper(item1,0,SubtractN(base,(item1[7]))); - MoveOper(comma,AddN(item1[3],1),base); - - MoveOper(item2,comma[1]+comma[3]+1,SubtractN(base,(item2[7]))); - Set(newitem, MakeOper(0,0,AddN(item2[1],item2[3]),Max(item1[4],item2[4]),"Func",{item1,comma,item2},base)); - BuildArgs(newitem:Tail(Tail(any))); - ]; - - - -FormulaBracket(f):= -[ - Local(left,right); - Set(left, Formula(Atom("("))); - Set(right, Formula(Atom(")"))); - left[4]:=f[4]; - right[4]:=f[4]; - MoveOper(left,f[1],f[2]); - MoveOper(f,2,0); - MoveOper(right,f[1]+f[3]+1,f[2]); - MakeOper(0,0,right[1]+right[3],f[4],"Func",{left,f,right},f[7]); -]; - - -/* RuleBase("Formula",{f}); */ - -1 # Formula(f_IsAtom) <-- - MakeOper(0,0,Length(String(f)),1,"Atom",String(f),0); - -2 # Formula(_xx ^ _yy) <-- -[ - Local(l,r); - Set(l, BracketOn(Formula(xx),xx,OpLeftPrecedence("^"))); - Set(r, BracketOn(Formula(yy),yy,OpRightPrecedence("^"))); - MoveOper(l,0,r[4]); - MoveOper(r,l[3],0); - MakeOper(0,0,AddN(l[3],r[3]),AddN(l[4],r[4]),"Func",{l,r},l[2]+l[4]-1); -]; - - - -10 # FormulaArrayItem(xx_IsList) <-- -[ - Local(sub,height); - sub := {}; - height := 0; - ForEach(item,xx) - [ - Local(made); - made := FormulaBracket(Formula(item)); - If(made[4] > height,Set(height,made[4])); - DestructiveAppend(sub,made); - ]; - MakeOper(0,0,0,height,"List",sub,height>>1); -]; - - -20 # FormulaArrayItem(_item) <-- Formula(item); - -2 # Formula(xx_IsList) <-- -[ - Local(sub,width,height); - sub:={}; - width := 0; - height := 1; - - ForEach(item,xx) - [ - Local(made); - made := FormulaArrayItem(item); - - If(made[3] > width,Set(width,made[3])); - MoveOper(made,0,height); - Set(height,AddN(height,AddN(made[4],1))); - DestructiveAppend(sub,made); - ]; - - Local(thislength,maxlength); - maxlength:=0; - ForEach(item,xx) - [ - thislength:=0; - if(IsList(item)) [thislength:=Length(item);]; - if (maxlength0, - [ - Local(i,j); - width:=0; - For(j:=1,j<=maxlength,j++) - [ - Local(w); - w := 0; - For(i:=1,i<=Length(sub),i++) - [ - if (IsList(xx[i]) And j<=Length(xx[i])) - If(sub[i][6][j][3] > w,w := sub[i][6][j][3]); - ]; - - For(i:=1,i<=Length(sub),i++) - [ - if (IsList(xx[i]) And j<=Length(xx[i])) - MoveOper(sub[i][6][j],width,0); - ]; - width := width+w+1; - ]; - For(i:=1,i<=Length(sub),i++) - [ - sub[i][3] := width; - ]; - ] - ); - - sub := MakeOper(0,0,width,height,"List",sub,height>>1); - FormulaBracket(sub); -]; - -2 # Formula(_xx / _yy) <-- -[ - Local(l,r,dash,width); -/* - Set(l, BracketOn(Formula(xx),xx,OpLeftPrecedence("/"))); - Set(r, BracketOn(Formula(yy),yy,OpRightPrecedence("/"))); -*/ - Set(l, Formula(xx)); - Set(r, Formula(yy)); - Set(width, Max(l[3],r[3])); - Set(dash, Formula(Atom(CharList(width,"-")))); - MoveOper(dash,0,l[4]); - MoveOper(l,(SubtractN(width,l[3])>>1),0); - MoveOper(r,(SubtractN(width,r[3])>>1),AddN(dash[2], dash[4])); - MakeOper(0,0,width,AddN(r[2], r[4]),"Func",{l,r,dash},dash[2]); -]; - -RuleBase("BracketOn",{op,f,prec}); -Rule("BracketOn",3,1,IsFunction(f) And NrArgs(f) = 2 - And IsInfix(Type(f)) And OpPrecedence(Type(f)) > prec) -[ - FormulaBracket(op); -]; -Rule("BracketOn",3,2,True) -[ - op; -]; - -10 # Formula(f_IsFunction)_(NrArgs(f) = 2 And IsInfix(Type(f))) <-- -[ - Local(l,r,oper,width,height,base); - Set(l, Formula(f[1])); - Set(r, Formula(f[2])); - - Set(l, BracketOn(l,f[1],OpLeftPrecedence(Type(f)))); - Set(r, BracketOn(r,f[2],OpRightPrecedence(Type(f)))); - - Set(oper, Formula(f[0])); - Set(base, Max(l[7],r[7])); - MoveOper(oper,AddN(l[3],1),SubtractN(base,(oper[7]))); - MoveOper(r,oper[1] + oper[3]+1,SubtractN(base,(r[7]))); - MoveOper(l,0,SubtractN(base,(l[7]))); - Set(height, Max(AddN(l[2], l[4]),AddN(r[2], r[4]))); - - MakeOper(0,0,AddN(r[1], r[3]),height,"Func",{l,r,oper},base); -]; - -11 # Formula(f_IsFunction) <-- -[ - Local(head,args,all); - Set(head, Formula(f[0])); - Set(all, Tail(Listify(f))); - - Set(args, FormulaBracket(BuildArgs(MapSingle("Formula",Apply("Hold",{all}))))); - AlignBase(head,args); - MoveOper(args,head[3],0); - - MakeOper(0,0,args[1]+args[3],Max(head[4],args[4]),"Func",{head,args},head[7]); -]; - - - -RuleBase("RenderFormula",{cf,f,x,y}); - -/* -/ / / -\ | | - \ | - \ -*/ - -Rule("RenderFormula",4,1,f[5] = "Atom" And f[6] = "(" And f[4] > 1) -[ - Local(height,i); - Set(x, AddN(x,f[1])); - Set(y, AddN(y,f[2])); - Set(height, SubtractN(f[4],1)); - - cf[y] := StringMidSet(x, "/", cf[y]); - cf[AddN(y,height)] := StringMidSet(x, "\\", cf[AddN(y,height)]); - For (Set(i,1),LessThan(i,height),Set(i,AddN(i,1))) - cf[AddN(y,i)] := StringMidSet(x, "|", cf[AddN(y,i)]); -]; - -Rule("RenderFormula",4,1,f[5] = "Atom" And f[6] = ")" And f[4] > 1) -[ - Local(height,i); - Set(x, AddN(x,f[1])); - Set(y, AddN(y,f[2])); - Set(height, SubtractN(f[4],1)); - cf[y] := StringMidSet(x, "\\", cf[y]); - cf[y+height] := StringMidSet(x, "/", cf[y+height]); - For (Set(i,1),LessThan(i,height),Set(i,AddN(i,1))) - cf[AddN(y,i)] := StringMidSet(x, "|", cf[AddN(y,i)]); -]; - -Rule("RenderFormula",4,5,f[5] = "Atom") -[ - cf[AddN(y, f[2]) ]:= - StringMidSet(AddN(x,f[1]),f[6],cf[AddN(y, f[2]) ]); -]; - -Rule("RenderFormula",4,6,True) -[ - ForEach(item,f[6]) - [ - RenderFormula(cf,item,AddN(x, f[1]),AddN(y, f[2])); - ]; -]; - -LocalSymbols(formulaMaxWidth) [ - SetFormulaMaxWidth(width):= - [ - formulaMaxWidth := width; - ]; - FormulaMaxWidth() := formulaMaxWidth; - SetFormulaMaxWidth(60); -]; // LocalSymbols(formulaMaxWidth) - -Function("PrettyForm",{ff}) -[ - Local(cf,f); - - f:=Formula(ff); - - cf:=CharField(f[3],f[4]); - RenderFormula(cf,f,1,1); - - NewLine(); - WriteCharField(cf,FormulaMaxWidth()); - - DumpErrors(); - True; -]; -/* -HoldArg("PrettyForm",ff); -*/ - -EvalFormula(f):= -[ - Local(result); - result:= UnList({Atom("="),f,Eval(f)}); - PrettyForm(result); - True; -]; -HoldArg("EvalFormula",f); - -/* -{x,y,width,height,oper,args,base} -*/ - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/io.rep/print.mpi mathpiper-0.81f+dfsg1/storage/scripts/io.rep/print.mpi --- mathpiper-0.0.svn2556/storage/scripts/io.rep/print.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/io.rep/print.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ - -/* A reference print implementation. Expand at own leisure. - * - * This file implements Print, a scripted expression printer. - */ - - -/* 60000 is the maximum precedence allowed for operators */ -10 # Print(_x) <-- -[ - Print(x,60000); - NewLine(); - DumpErrors(); -]; - -/* Print an argument within an environment of precedence n */ -10 # Print(x_IsAtom,_n) <-- Write(x); -10 # Print(_x,_n)_(IsInfix(Type(x))And NrArgs(x) = 2) <-- -[ - Local(bracket); - bracket:= (OpPrecedence(Type(x)) > n); - If(bracket,WriteString("(")); - Print(x[1],OpLeftPrecedence(Type(x))); - Write(x[0]); - Print(x[2],OpRightPrecedence(Type(x))); - If(bracket,WriteString(")")); -]; - -10 # Print(_x,_n)_(IsPrefix(Type(x)) And NrArgs(x) = 1) <-- -[ - Local(bracket); - bracket:= (OpPrecedence(Type(x)) > n); - Write(x[0]); - If(bracket,WriteString("(")); - Print(x[1],OpRightPrecedence(Type(x))); - If(bracket,WriteString(")")); -]; - -10 # Print(_x,_n)_(IsPostfix(Type(x))And NrArgs(x) = 1) <-- -[ - Local(bracket); - bracket:= (OpPrecedence(Type(x)) > n); - If(bracket,WriteString("(")); - Print(x[1],OpLeftPrecedence(Type(x))); - Write(x[0]); - If(bracket,WriteString(")")); -]; - -20 # Print(_x,_n)_(Type(x) = "List") <-- -[ - WriteString("{"); - PrintArg(x); - WriteString("}"); -]; - -20 # Print(_x,_n)_(Type(x) = "Prog") <-- -[ - WriteString("["); - PrintArgProg(Tail(Listify(x))); - WriteString("]"); -]; -20 # Print(_x,_n)_(Type(x) = "Nth") <-- -[ - Print(x[1],0); - WriteString("["); - Print(x[2],60000); - WriteString("]"); -]; - -100 # Print(x_IsFunction,_n) <-- - [ - Write(x[0]); - WriteString("("); - PrintArg(Tail(Listify(x))); - WriteString(")"); - ]; - - -/* Print the arguments of an ordinary function */ -10 # PrintArg({}) <-- True; - -20 # PrintArg(_list) <-- -[ - Print(Head(list),60000); - PrintArgComma(Tail(list)); -]; -10 # PrintArgComma({}) <-- True; -20 # PrintArgComma(_list) <-- -[ - WriteString(","); - Print(Head(list),60000); - PrintArgComma(Tail(list)); -]; - - -18 # Print(Complex(0,1),_n) <-- [WriteString("I");]; -19 # Print(Complex(0,_y),_n) <-- [WriteString("I*");Print(y,4);]; -19 # Print(Complex(_x,1),_n) <-- [Print(x,7);WriteString("+I");]; -20 # Print(Complex(_x,_y),_n) <-- [Print(x,7);WriteString("+I*");Print(y,4);]; - - -/* Tail-recursive printing the body of a compound statement */ -10 # PrintArgProg({}) <-- True; -20 # PrintArgProg(_list) <-- -[ - Print(Head(list),60000); - WriteString(";"); - PrintArgProg(Tail(list)); -]; - - - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/limit.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/limit.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/limit.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/limit.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -/* */ -/* Limit operator rule base */ -/* */ - - -/* Exponentiation rules */ - -/* Special limit #1: 0 ^ 0; #2: 1 ^ Infinity; #3: Infinity ^ 0 */ -200 # Lim(_var, _tar, _dir, _x ^ _y)_ -( [ - Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); - ((IsZero(lx) And IsZero(ly)) Or ((lx = 1) And IsInfinity(ly)) Or (IsInfinity(lx) And IsZero(ly))); -] ) -<-- Exp(Lim(var, tar, dir, y * Ln(x))); - -/* Default rule */ -210 # Lim(_var, _tar, _dir, _x ^ _y) -<-- Lim(var, tar, dir, x)^Lim(var, tar, dir, y); - - -/* Division rules */ - -/* Special limit #4: 0 / 0; #5: Infinity / Infinity */ -300 # Lim(_var, _tar, _dir, _x / _y)_ -( [ - Local(lx,ly,infx,infy); - lx := Lim(var, tar, dir, x); - ly := Lim(var, tar, dir, y); - infx := (IsInfinity(lx) Or (IsZero(Re(lx)) And IsInfinity(Im(lx)))); - infy := (IsInfinity(ly) Or (IsZero(Re(ly)) And IsInfinity(Im(ly)))); - ((IsZero(lx) And IsZero(ly)) Or - (infx And infy) - ); -] ) -<-- Lim(var, tar, dir, ApplyPure("D", {var, x})/ApplyPure("D", {var, y})); - -/* Special limit #6: null denominator */ -/* Probably there are still some problems. */ - -Dir(Right) <-- 1; -Dir(Left) <-- -1; - -/* To get the sign of the denominator on one side: */ -Sign(_var, _tar, _dir, _exp, _n) -<-- [ - Local(der, coef); der := ApplyPure("D", {var, exp}); - coef := Eval(ApplyPure("Subst", {var, tar, der})); - If ( coef = 0, - Sign(var, tar, dir, der, n+1), - (Sign(coef)*Dir(dir)) ^ n - ); -]; - -/* To avoid infinite recursion (with 1/Exp(-x) for instance) */ -310 # Lim(_var, _tar, _dir, _x / _y)_ -(IsInfinity(tar) And IsZero(Lim(var, tar, dir, y))) -<-- Sign(Lim(var, tar, dir, x))*Sign(Lim(var, tar, dir, ApplyPure("D", {var, y})))*tar; - -320 # Lim(_var, _tar, _dir, _x / _y)_IsZero(Lim(var, tar, dir, y)) -<-- Sign(Lim(var, tar, dir, x))*Sign(var, tar, dir, y, 1)*Infinity; - - -/* Default rule */ -330 # Lim(_var, _tar, _dir, _x / _y) -<-- Lim(var, tar, dir, x)/Lim(var, tar, dir, y); ]; - - -/* Multiplication rules */ - -/* To avoid some infinite recursions */ -400 # Lim(_var, _tar, _dir, _x * Exp(_y))_ -(IsInfinity(Lim(var, tar, dir, x)) And (Lim(var, tar, dir, y) = -Infinity)) -<-- Lim(var, tar, dir, x/Exp(-y)); -400 # Lim(_var, _tar, _dir, Exp(_x) * _y)_ -((Lim(var, tar, dir, x) = -Infinity) And IsInfinity(Lim(var, tar, dir, y))) -<-- Lim(var, tar, dir, y/Exp(-x)); -400 # Lim(_var, _tar, _dir, Ln(_x) * _y)_ -(IsZero(Lim(var, tar, dir, x)) And IsZero(Lim(var, tar, dir, y))) -<-- Lim(var, tar, dir, y*Ln(x)); - -/* Special limit #7: 0 * Infinity */ -410 # Lim(_var, _tar, _dir, _x * _y)_ -((IsZero(Lim(var, tar, dir, x)) And IsInfinity(Lim(var, tar, dir, y))) - Or (IsInfinity(Lim(var, tar, dir, x)) And IsZero(Lim(var, tar, dir, y)))) -<-- Lim(var, tar, dir, Simplify(ApplyPure("D", {var, y})/ApplyPure("D", -{var, 1/x}))); - -/* Default rule */ -420 # Lim(_var, _tar, _dir, _x * _y) -<-- Lim(var, tar, dir, x) * Lim(var, tar, dir, y); - - -/* Substraction rules */ - -/* Special limit #8: Infinity - Infinity */ -500 # Lim(_var, _tar, _dir, _x - _y)_ -( [ - Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); - ((lx = Infinity) And (ly = Infinity)) Or ((lx = -Infinity) And (ly = -Infinity)); -] ) -<-- Lim(var, tar, dir, x*(1-y/x)); - -/* Default rule */ -510 # Lim(_var, _tar, _dir, _x - _y) -<-- Lim(var, tar, dir, x)-Lim(var, tar, dir, y); - -/* Unary minus */ -520 # Lim(_var, _tar, _dir, - _x) -<-- - Lim(var, tar, dir, x); - - -/* Addition rules */ - -/* Special limit #9: Infinity + (-Infinity) */ -600 # Lim(_var, _tar, _dir, _x + _y)_ -( [ - Local(lx,ly); lx := Lim(var, tar, dir, x); ly := Lim(var, tar, dir, y); - ((lx = Infinity) And (ly = -Infinity)) Or ((lx = -Infinity) And (ly = Infinity)); -] ) -<-- Lim(var, tar, dir, x*(1+y/x)); - -/* Default rule */ -610 # Lim(_var, _tar, _dir, _x + _y) -<-- Lim(var, tar, dir, x)+Lim(var, tar, dir, y); - -/* Global default rule : evaluate expression */ - -700 # Lim(_var, _tar, _dir, exp_IsFunction) -<-- Eval(MapArgs(exp,"LimitArgs")); - -LimitArgs(_arg) <-- Lim(var,tar,dir,arg); -UnFence("LimitArgs",1); /* Allow LimitArgs to have access to the local variables of the caller. */ - -701 # Lim(_var, _tar, _dir, _exp) -<-- Eval(ApplyPure("Subst", {var, tar, exp})); - - -/* Limit without direction */ - -10 # Lim(_var, tar_IsInfinity, _exp) <-- Lim(var, tar, None, exp); - -20 # Lim(_var, _tar, _exp) -<-- [ - Local(l); l := Lim(var, tar, Left, exp); - If ( l = Lim(var, tar, Right, exp), - l, - Undefined - ); -]; - - - - -/* User-callable function */ - -(Limit(_var,_lim)(_fie)) <-- Lim(var,lim,fie); -(Limit(_var,_lim,_direction)(_fie)) <-- Lim(var,lim,direction,fie); -UnFence("Limit",3); - - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/limit.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/limit.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/limit.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/limit.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -Limit -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/limit.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/limit.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/limit.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/limit.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -// From code.mpi.def: -OMDef("Limit", "limit1","limit", - { _0, _2, OMS("limit1", "under"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) - |{ _0, _2, OMS("limit1", "above"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) - |{ _0, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, - { _0, _{3,2,1}, _1, Left, _{3,3}}_(_2=OMS("limit1", "below")) - |{_0, _{3,2,1}, _1, Right, _{3,3}}_(_2=OMS("limit1", "above")) - |{_0, _{3,2,1}, _1, _{3,3}} - ); -// Test [result Limit(x,0,Right)1/x]: FromString(ToString()OMForm(Limit(x,0,Right) 1/x))OMRead() - -// As explained in the manual, "limit1:both_sides" and "fns1:lambda" will -// be handled as OMS("limit1", "both_sides") and OMS("fns1", "lambda"), so -// we don't need to define bogus mappings for them: -// OMDef("OMSymbolLimit1BothSides", "limit1", "both_sides"); -// OMDef("OMSymbolLambda", "fns1", "lambda"); -// The same applies to "Left" and "Right", which are undefined symbols -// that are used only inside limit expressions, so they don't need a mapping -// of their own. -// We could define them as follows: -//OMDef("Left", "limit1","below"); -//OMDef("Right", "limit1","above"); -// and then use the following rules instead: -// { _0, _2, Left, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Left) -// |{ _0, _2, Right, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }_(_3=Right) -// |{ _0, _2, OMS("limit1", "both_sides"), OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _3) }, -// { _0, _{3,2,1}, _1, _2, _{3,3}}_(_2=Left Or _2=Right) -// |{_0, _{3,2,1}, _1, _{3,3}} -// The result is exactly the same. The only difference is when producing the -// OMForm of the symbols themselves, outside the limit expression. diff -Nru mathpiper-0.0.svn2556/storage/scripts/linalg.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/linalg.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/linalg.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/linalg.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,904 +0,0 @@ - -/* Levi-civita symbol */ -Function("LeviCivita",{indices}) -[ - Local(i,j,length,left,right,factor); - length:=Length(indices); - factor:=1; - - For (j:=length,j>1,j--) - [ - For(i:=1,i0,i--) - [ - DestructiveInsert(newresult,1,Insert(item,i,head)); - ]; - ]; - newresult:=DestructiveReverse(newresult); - Permutations(newresult,Tail(list)); - ]); -]; - - -Function("Permutations",{list}) -[ - Permutations({{}},list); -]; - -Function("InProduct",{aLeft,aRight}) -[ - Local(length); - length:=Length(aLeft); - Check(length = Length(aRight),"InProduct: error, vectors not of the same dimension"); - - Local(result); - result:=0; - Local(i); - For(i:=1,i<=length,i++) - [ - result := result + aLeft[i] * aRight[i]; - ]; - result; -]; - - -Function("CrossProduct",{aLeft,aRight}) -[ - Local(length); - length:=Length(aLeft); - Check(length = 3,"OutProduct: error, vectors not of dimension 3"); - Check(length = Length(aRight),"OutProduct: error, vectors not of the same dimension"); - - Local(perms); - perms := Permutations({1,2,3}); - - Local(result); - result:=ZeroVector(3); - - Local(term); - ForEach(term,perms) - [ - result[ term[1] ] := result[ term[1] ] + - LeviCivita(term) * aLeft[ term[2] ] * aRight[ term[3] ] ; - ]; - result; -]; - - -_x o _y <-- Outer(x,y); - -// outer product of vectors -Outer(t1_IsVector, t2_IsVector) <-- -[ - Local(i,j,n,m,result); - n:=Length(t1); - m:=Length(t2); - result:=ZeroMatrix(n,m); - For(i:=1,i<=n,i++) - For(j:=1,j<=m,j++) - result[i][j]:=t1[i]*t2[j]; - result; -]; - - - -Function("ZeroVector",{n}) -[ - Local(i,result); - result:={}; - For(i:=1,i<=n,i++) - [ - DestructiveInsert(result,1,0); - ]; - result; -]; - - -Function("BaseVector",{row,n}) -[ - Local(i,result); - result:=ZeroVector(n); - result[row] := 1; - result; -]; - -RandomIntegerVector(_count,_coefmin,_coefmax) <-- - Table(FloorN(coefmin+Random()*(coefmax+1-coefmin)),i,1,count,1); - -RandomIntegerMatrix(_rows,_cols,_coefmin,_coefmax) <-- - GenMatrix({{i,j}, FloorN(coefmin+Random()*(coefmax+1-coefmin))}, rows, cols ); - - -Identity(n_IsNonNegativeInteger) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=n,i++) - [ - DestructiveAppend(result,BaseVector(i,n)); - ]; - result; -]; - -// -// Diagonal: return a vector with the diagonal elements of the matrix -// -Function("Diagonal",{A}) -[ - Local(result,i,n); - n:=Length(A); - result:=ZeroVector(n); - For(i:=1,i<=n,i++) - [ - result[i] := A[i][i]; - ]; - result; -]; - -Function("DiagonalMatrix",{list}) -[ - Local(result,i,n); - n:=Length(list); - result:=Identity(n); - For(i:=1,i<=n,i++) - [ - result[i][i] := list[i]; - ]; - result; -]; - -Function("Normalize",{vector}) -[ - Local(norm); - norm:=0; - ForEach(item,vector) - [ - norm:=norm+item*item; - ]; - (1/(norm^(1/2)))*vector; -]; - -5 # ZeroMatrix(n_IsNonNegativeInteger) <-- ZeroMatrix(n,n); -10 # ZeroMatrix(n_IsNonNegativeInteger,m_IsNonNegativeInteger) <-- -[ - Local(i,result); - result:={}; - For(i:=1,i<=n,i++) - DestructiveInsert(result,i,ZeroVector(m)); - result; -]; - - -Transpose(matrix_IsList)_(Length(Dimensions(matrix))>1) <-- -[ - Local(i,j,result); - result:=ZeroMatrix(Length(matrix[1]),Length(matrix)); - For(i:=1,i<=Length(matrix),i++) - For(j:=1,j<=Length(matrix[1]),j++) - result[j][i]:=matrix[i][j]; - result; -]; - -FrobeniusNorm(matrix_IsMatrix) <-- -[ - Local(i,j,result); - result:=0; - For(i:=1,i<=Length(matrix),i++) - For(j:=1,j<=Length(matrix[1]),j++) - result:=result+Abs(matrix[i][j])^2; - - Sqrt(result); - -]; - - -10 # Determinant(_matrix)_(IsUpperTriangular(matrix) Or IsLowerTriangular(matrix)) <-- -[ - Local(result); - result:=1; - ForEach(i, Diagonal(matrix) ) - result:=result*i; - result; -]; - -// -// The fast determinant routine that does the determinant numerically, rule 20, -// divides things by the elements on the diagonal of the matrix. So if one of these -// elements happens to be zero, the result is something like Infinity or Undefined. -// Use the symbolic determinant in that case, as it is slower but much more robust. -// -15 # Determinant(_matrix)_(Length(Select("IsZero",Diagonal(matrix))) > 0) <-- SymbolicDeterminant(matrix); - -// Not numeric entries, so lets treat it symbolically. -16 # Determinant(_matrix)_(VarList(matrix) != {}) <-- SymbolicDeterminant(matrix); - -20 # Determinant(_matrix) <-- GaussianDeterminant(matrix); - -GaussianDeterminant(matrix):= -[ - Local(n,s,result); - n:=Length(matrix); - result:=1; - - [ - matrix:=FlatCopy(matrix); - Local(i); - For(i:=1,i<=n,i++) - [ - matrix[i]:=FlatCopy(matrix[i]); - ]; - ]; - - // gaussian elimination - ForEach(i, 1 .. (n-1) ) - [ - ForEach(k, (i+1) .. n ) - [ - s:=matrix[k][i]; - ForEach(j, i .. n ) - [ - matrix[k][j] := matrix[k][j] - (s/matrix[i][i])*matrix[i][j]; - //Echo({"matrix[",k,"][",j,"] =", aug[k][j]," - ", - // matrix[k][i],"/",matrix[i][i],"*",matrix[i][j]," k i =", k,i }); - ]; - ]; - ]; - -//Echo("mat: ",matrix); -//Echo("diagmat: ",Diagonal(matrix)); - // now upper triangular - ForEach(i, Diagonal(matrix) ) - result:=result*i; - result; -]; - -/* Recursive calculation of determinant, provided by Sebastian Ferraro - */ -20 # RecursiveDeterminant(_matrix) <-- -[ - /* - Computes a determinant recursively by summing the product of each (nonzero) element on the first row of the matrix - by +/- the determinant of the submatrix with the corresponding row and column deleted. - */ - Local(result); - If(Equals(Length(matrix),1),matrix[1][1],[ - result:=0; - ForEach(i,1 .. Length(matrix)) - //Consider only non-zero entries - If(Not(Equals(matrix[1][i],0)), - //Transpose and Drop eliminate row 1, column i - result:=result+matrix[1][i]*(-1)^(i+1)* RecursiveDeterminant(Transpose(Drop(Transpose(Drop(matrix,{1,1})),{i,i})))); - result; - ]); -]; - - -20 # SymbolicDeterminant(_matrix) <-- -[ - Local(perms,indices,result); - Check((IsMatrix(matrix)),"Determinant: Argument must be a matrix"); - indices:=Table(i,i,1,Length(matrix),1); - perms:=Permutations(indices); - result:=0; - ForEach(item,perms) - result:=result+Factorize(i,1,Length(matrix),matrix[i][item[i] ])* - LeviCivita(item); - result; -]; - - - -Function("Sparsity",{matrix}) -[ - Local(rows,cols,nonzero); - nonzero:=0; - rows:=Length(matrix); - cols:=Length(matrix[1]); - ForEach(i, 1 .. rows ) - ForEach(j, 1 .. cols ) - If(matrix[i][j] != 0, nonzero:=nonzero+1 ); - - N(1 - nonzero/(rows*cols)); -]; - -Function("CoFactor",{matrix,ii,jj}) -[ - Local(perms,indices,result); - indices:=Table(i,i,1,Length(matrix),1); - perms:=Permutations(indices); - result:=0; - ForEach(item,perms) - If(item[ii] = jj, - result:=result+ - Factorize(i,1,Length(matrix), - If(ii=i,1,matrix[i][item[i] ]) - )*LeviCivita(item)); - result; -]; - - - -Minor(matrix,i,j) := CoFactor(matrix,i,j)*(-1)^(i+j); - -Function("Inverse",{matrix}) -[ - Local(perms,indices,inv,det,n); - n:=Length(matrix); - indices:=Table(i,i,1,n,1); - perms:=Permutations(indices); - inv:=ZeroMatrix(n,n); - det:=0; - ForEach(item,perms) - [ - Local(i,lc); - lc := LeviCivita(item); - det:=det+Factorize(i,1,n,matrix[i][item[i] ])* lc; - For(i:=1,i<=n,i++) - [ - inv[item[i] ][i] := inv[item[i] ][i]+ - Factorize(j,1,n, - If(j=i,1,matrix[j][item[j] ]))*lc; - ]; - ]; - Check(det != 0, "Zero determinant"); - (1/det)*inv; -]; - -Tr(x_IsList) <-- -[ - Local(i,j,n,d,r,aux,result); - d:=Dimensions(x); - r:=Length(d); // tensor rank - n:=Min(d); // minimal dim - result:=0; - For(i:=1,i<=n,i++) - [ - aux:=x[i]; - For(j:=2,j<=r,j++) - aux:=aux[i]; - result:=result+aux; - ]; - result; -]; - - -Trace(matrix_IsList) <-- Tr(matrix); - - -x X y := CrossProduct(x,y); - -Function("VandermondeMatrix",{vector})[ - Local(len,i,j,item,matrix); - len:=Length(vector); - matrix:=ZeroMatrix(len,len); - - For(i:=1,i<=Length(matrix),i++)[ - For(j:=1,j<=Length(matrix[1]),j++)[ - matrix[j][i]:=vector[i]^(j-1); - ]; - ]; - - matrix; -]; - -/* SylvesterMatrix */ - -Function("SylvesterMatrix",{poly1, poly2, var}) -[ - Local(i,m,p,q,y,z,result); - y:=Degree(poly1,var); - z:=Degree(poly2,var); - m:=y+z; - p:={}; - q:={}; - result:=ZeroMatrix(m,m); - - For(i:=y,i>=0,i--) - DestructiveAppend(p,Coef(poly1,var,i)); - For(i:=z,i>=0,i--) - DestructiveAppend(q,Coef(poly2,var,i)); - - For(i:=1,i<=z,i++) - [ - Local(j,k); - k:=1; - For(j:=i,k<=Length(p),j++) - [ - result[i][j]:=p[k]; - k++; - ]; - ]; - - For(i:=1,i<=y,i++) - [ - Local(j,k); - k:=1; - For(j:=i,k<=Length(q),j++) - [ - result[i+z][j]:=q[k]; - k++; - ]; - ]; - result; -]; - - - -Function("MatrixRow",{matrix,row}) -[ - Check(row > 0, "MatrixRow: row index out of range"); - Check(row <= Length(matrix), "MatrixRow: row index out of range"); - - Local(result); - result:=matrix[row]; - - result; -]; - -Function("MatrixColumn",{matrix,col}) -[ - Local(m); - m:=matrix[1]; - - Check(col > 0, "MatrixColumn: column index out of range"); - Check(col <= Length(m), "MatrixColumn: column index out of range"); - - Local(i,result); - result:={}; - For(i:=1,i<=Length(matrix),i++) - DestructiveAppend(result,matrix[i][col]); - - result; -]; - -Function("GenMatrix",{func,m,n}) -[ - Local(i,j,result); - result:=ZeroMatrix(m,n); - - For(i:=1,i<=m,i++) - For(j:=1,j<=n,j++) - result[i][j]:=ApplyPure(func,{i,j}); - - result; -]; -HoldArg("GenMatrix",func); -UnFence("GenMatrix",3); - -// The arguments of the following functions -// should be checked - -// this takes N funcs in N vars -JacobianMatrix(f,v):=GenMatrix({{i,j},Deriv(v[j])f[i]},Length(f),Length(f)); - -// this takes 1 func in N vars -HessianMatrix(f,v):=GenMatrix({{i,j}, Deriv(v[i]) Deriv(v[j]) f},Length(v),Length(v)); - -// this takes N funcs in 1 var -WronskianMatrix(f,v):=GenMatrix({{i,j}, Deriv(v,i-1) f[j]}, Length(f), Length(f) ); - -// notoriously hard to manipulate numerically -HilbertMatrix(n):=GenMatrix({{i,j}, 1/(i+j-1)}, n,n ); -HilbertMatrix(m,n):=GenMatrix({{i,j}, 1/(i+j-1)}, m,n ); -HilbertInverseMatrix(n):=GenMatrix({{i,j}, - (-1)^(i+j)*(i+j-1)*Bin(n+i-1,n-j)*Bin(n+j-1,n-i)*Bin(i+j-2,i-1)^2},n,n); - -HankelMatrix(n):=GenMatrix({{i,j}, If(i+j-1>n,0,i+j-1) }, n,n ); -HankelMatrix(m,n):=GenMatrix({{i,j}, If(i+j-1>n,0,i+j-1)}, m,n ); - -ToeplitzMatrix(N):=GenMatrix({{i,j},N[Abs(i-j)+1]}, Length(N), Length(N) ); - -// Used to test numerical eigenvalue algorithms, because it -// has eigenvalues extremely close to each other. -// WilkinsonMatrix(21) has 2 eigenvalues near 10.7 that agree -// to 14 decimal places -// Leto: I am not going to document this until we actually have -// numerical eigenvalue algorithms -WilkinsonMatrix(N):=GenMatrix({{i,j}, - If( Abs(i-j)=1,1, - [ If(i=j,Abs( (N-1)/2 - i+1 ),0 ); ] )}, N,N ); - -10 # Norm(_v) <-- PNorm(v,2); - -// p-norm, reduces to euclidean norm when p = 2 -Function("PNorm",{v,p}) -[ - Local(result,i); - Check(p>=1,"PNorm: p must be >= 1"); - - result:=0; - For(i:=1,i<=Length(v),i++)[ - result:=result+Abs(v[i])^p; - ]; - - // make it look nicer when p = 2 - If(p=2,Sqrt(result),(result)^(1/p) ); -]; - -// This is the standard textbook definition of the Gram-Schmidt -// Orthogonalization process, from: -// Friedberg,Insel,Spence "Linear Algebra" (1997) -// TODO: This function does not check if the input vectors are LI, it -// only checks for zero vectors -Function("OrthogonalBasis",{W})[ - Local(V,j,k); - - V:=ZeroMatrix(Length(W),Length(W[1]) ); - - V[1]:=W[1]; - For(k:=2,k<=Length(W),k++)[ - Check(Not IsZero(Norm(W[k])) , - "OrthogonalBasis: Input vectors must be linearly independent"); - V[k]:=W[k]-Sum(j,1,k-1,InProduct(W[k],V[j])*V[j]/Norm(V[j])^2); - ]; - V; -]; -// Like orthogonalization, only normalize all vectors -Function("OrthonormalBasis",{W})[ - Local(i); - W:=OrthogonalBasis(W); - For(i:=1,i<=Length(W),i++)[ - W[i]:=W[i]/Norm(W[i]); - ]; - W; -]; - - -/* Code that returns the list of the dimensions of a tensor - Code submitted by Dirk Reusch. - */ - -LocalSymbols(x,i,n,m,aux,dim,result) -[ -1 # Dimensions(x_IsList) <-- - [ - Local(i,n,m,aux,dim,result); - result:=List(Length(x)); -//Echo("GETTING ",x); -//Echo(Length(Select(IsList,x))); -//Echo("END"); - If(Length(x)>0 And Length(Select(IsList,x))=Length(x), - [ - n:=Length(x); - dim:=MapSingle(Dimensions,x); - m:=Min(MapSingle(Length,dim)); - - For(i:=1,i<=m,i++) - [ - aux:=Table(dim[j][i],j,1,n,1); - If(Min(aux)=Max(aux), - result:=DestructiveAppend(result,dim[1][i]), - i:=m+1); - ]; - ]); -//Echo(x,result); - result; - ]; - -2 # Dimensions(_x) <-- List(); -]; - -////// -////// - -////// -// dot product for vectors and matrices (dr) -////// - -_x . _y <-- Dot(x,y); - -LocalSymbols(Dot0,Dot1) -[ -// vector . vector -Dot(t1_IsVector,t2_IsVector)_(Length(t1)=Length(t2)) <-- - Dot0(t1,t2,Length(t1)); - -// matrix . vector -Dot(t1_IsMatrix,t2_IsVector)_(Length(t1[1])=Length(t2)) <-- -[ - Local(i,n,m,result); - n:=Length(t1); - m:=Length(t2); - result:=List(); - For(i:=1,i<=n,i++) - DestructiveInsert(result,1,Dot0(t1[i],t2,m)); - DestructiveReverse(result); -]; - -// vector . matrix -Dot(t1_IsVector,t2_IsMatrix)_(Length(t1)=Length(t2) - And Length(t2[1])>0) <-- - Dot1(t1,t2,Length(t1),Length(t2[1])); - -// matrix . matrix -Dot(t1_IsMatrix,t2_IsMatrix)_(Length(t1[1])=Length(t2) - And Length(t2[1])>0) <-- -[ - Local(i,n,k,l,result); - n:=Length(t1); - k:=Length(t2); - l:=Length(t2[1]); - result:=List(); - For(i:=1,i<=n,i++) - DestructiveInsert(result,1,Dot1(t1[i],t2,k,l)); - DestructiveReverse(result); -]; - -// vector . vector -Dot0(_t1,_t2,_n) <-- -[ - Local(i,result); - result:=0; - For(i:=1,i<=n,i++) - result:=result+t1[i]*t2[i]; - result; -]; - -// vector . matrix -// m vector length -// n number of matrix cols -Dot1(_t1,_t2,_m,_n) <-- -[ - Local(i,j,result); - result:=ZeroVector(n); - For(i:=1,i<=n,i++) - For(j:=1,j<=m,j++) - result[i]:=result[i]+t1[j]*t2[j][i]; - result; -]; - -]; // LocalSymbols(Dot0,Dot1) - -////// -////// - -////// -// power of a matrix (dr) -////// - -MatrixPower(x_IsSquareMatrix, n_IsNonNegativeInteger) <-- -[ - Local(result); - result:=Identity(Length(x)); - While(n != 0) - [ - If(IsOdd(n), - result:=Dot(result,x)); - x:=Dot(x,x); - n:=n>>1; - ]; - result; -]; - -MatrixPower(x_IsSquareMatrix, n_IsNegativeInteger) <-- - MatrixPower(Inverse(x),-n); - -////// -////// -10 # MatrixSolve(matrix_IsDiagonal,b_IsVector) <-- -[ - Local(rowsm,rowsb,x); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - x:=ZeroVector(rowsb); - ForEach(i,1 .. rowsb) - x[i]:=b[i]/matrix[i][i]; - x; -]; - -// Backward Substitution -15 # MatrixSolve(matrix_IsUpperTriangular,b_IsVector) <-- -[ - Local(rowsm,rowsb,x,s); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - x:=ZeroVector(rowsb); - - x[rowsb]:=b[rowsb]/matrix[rowsb][rowsb]; - If(InVerboseMode(),Echo({"set x[",rowsb,"] = ",b[rowsb]/matrix[rowsb][rowsb]})); - - ForEach(i,(rowsb-1) .. 1 )[ - s:=b[i]; - ForEach(j,i+1 .. rowsb )[ - s:= s - matrix[i][j]*x[j]; - ]; - x[i]:= s/matrix[i][i]; - If(InVerboseMode(),Echo({"set x[",i,"] = ",s/matrix[i][i]})); - ]; - x; -]; - -// Forward Substitution -15 # MatrixSolve(matrix_IsLowerTriangular,b_IsVector) <-- -[ - Local(rowsm,rowsb,x,s); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - x:=ZeroVector(rowsb); - - x[1]:=b[1]/matrix[1][1]; - If(InVerboseMode(),Echo({"set x[1] = ",b[1]/matrix[1][1]})); - - ForEach(i,2 .. rowsb )[ - s:=b[i]; - ForEach(j,1 .. (i-1) )[ - s:= s - matrix[i][j]*x[j]; - ]; - x[i]:= s/matrix[i][i]; - If(InVerboseMode(),Echo({"set x[",i,"] = ",s/matrix[i][i]})); - ]; - x; -]; -// Gaussian Elimination and Back Substitution -// pivoting not implemented yet -20 # MatrixSolve(matrix_IsMatrix,b_IsVector) <-- -[ - Local(aug,rowsm,rowsb,x,s); - rowsm:=Length(matrix); - rowsb:=Length(b); - Check(rowsm=rowsb,"MatrixSolve: Matrix and vector must have same number of rows"); - aug:=ZeroMatrix(rowsb,rowsb+1); - x:=ZeroVector(rowsb); - - // create augmented matrix - ForEach(i, 1 .. rowsb ) - ForEach(j, 1 .. rowsb ) - aug[i][j] := matrix[i][j]; - ForEach(i, 1 .. rowsb ) - aug[i][rowsb+1] := b[i]; - - // gaussian elimination - ForEach(i, 1 .. (rowsb-1) )[ - // If our pivot element is 0 we need to switch - // this row with a row that has a nonzero element - If(aug[i][i] = 0, [ - Local(p,tmp); - p:=i+1; - While( aug[p][p] = 0 )[ p++; ]; - If(InVerboseMode(), Echo({"switching row ",i,"with ",p}) ); - tmp:=aug[i]; - aug[i]:=aug[p]; - aug[p]:=tmp; - ]); - - - ForEach(k, (i+1) .. rowsb )[ - s:=aug[k][i]; - ForEach(j, i .. (rowsb+1) )[ - aug[k][j] := aug[k][j] - (s/aug[i][i])*aug[i][j]; - //Echo({"aug[",k,"][",j,"] =", aug[k][j]," - ", - // aug[k][i],"/",aug[i][i],"*",aug[i][j]," k i =", k,i }); - ]; - ]; - ]; - //PrettyForm(aug); - x[rowsb]:=aug[rowsb][rowsb+1]/aug[rowsb][rowsb]; - If(InVerboseMode(),Echo({"set x[",rowsb,"] = ",x[rowsb] })); - - ForEach(i,(rowsb-1) .. 1 )[ - s:=aug[i][rowsb+1]; - ForEach(j,i+1 .. rowsb)[ - s := s - aug[i][j]*x[j]; - ]; - x[i]:=s/aug[i][i]; - If(InVerboseMode(),Echo({"set x[",i,"] = ",x[i] })); - ]; - x; - -]; - -// Cholesky Decomposition, adapted from: -// Fundamentals Of Matrix Computation (2nd), David S. Watkins, pp38 -// This algorithm performs O(n^3) flops where A is nxn -// Given the positive definite matrix A, a matrix R is returned such that -// A = Transpose(R) * R - -10 # Cholesky(A_IsMatrix) <-- -[ - Local(matrix,n,k,j); - n:=Length(A); - matrix:=ZeroMatrix(n); - - // copy entries of A into matrix - ForEach(i,1 .. n) - ForEach(j,1 .. n) - matrix[i][j] := A[i][j]; - - // in place algorithm for cholesky decomp - ForEach(i,1 .. n)[ - For(k:=1,k<=(i-1),k++) - matrix[i][i] := matrix[i][i] - matrix[k][i]^2; - Check( matrix[i][i] > 0, "Cholesky: Matrix is not positive definite"); - matrix[i][i] := Sqrt(matrix[i][i]); - //Echo({"matrix[",i,"][",i,"] = ", matrix[i][i] }); - For(j:=i+1,j<=n,j++)[ - For(k:=1,k<=(i-1),k++) - matrix[i][j]:= matrix[i][j] - matrix[k][i]*matrix[k][j]; - matrix[i][j] := matrix[i][j]/matrix[i][i]; - //Echo({"matrix[",i,"][",j,"] = ", matrix[i][j] }); - ]; - ]; - // cholesky factorization is upper triangular - ForEach(i,1 .. n) - ForEach(j,1 .. n) - If(i>j,matrix[i][j] := 0); - matrix; -]; - -// In place LU decomposition -// Pivotting is not implemented -// Adapted from Numerical Methods with Matlab -// Gerald Recktenwald, Sec 8.4 -10 # LU(A_IsSquareMatrix) <-- -[ - Local(n,matrix,L,U); - n:=Length(A); - L:=ZeroMatrix(n,n); - U:=ZeroMatrix(n,n); - matrix:=ZeroMatrix(n,n); - - ForEach(i,1 .. n) - ForEach(j,1 .. n) - matrix[i][j] := A[i][j]; - - // loop over pivot rows - ForEach(i,1 ..(n-1))[ - // loop over column below the pivot - ForEach(k,i+1 .. n)[ - // compute multiplier and store it in L - matrix[k][i] := matrix[k][i] / matrix[i][i]; - // loop over elements in row k - ForEach(j,i+1 .. n)[ - matrix[k][j] := matrix[k][j] - matrix[k][i]*matrix[i][j]; - ]; - ]; - ]; - ForEach(i,1 .. n)[ - ForEach(j,1 .. n)[ - If(i<=j,U[i][j]:=matrix[i][j],L[i][j]:=matrix[i][j]); - ]; - // diagonal of L is always 1's - L[i][i]:=1; - ]; - - {L,U}; -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/linalg.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/linalg.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/linalg.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/linalg.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -LeviCivita -Permutations -InProduct -CrossProduct -Outer -o -ZeroVector -BaseVector -Identity -DiagonalMatrix -Normalize -ZeroMatrix -Transpose -Determinant -CoFactor -Minor -Inverse -Trace -Tr -X -. -SylvesterMatrix -VandermondeMatrix -MatrixRow -MatrixColumn -GenMatrix -RandomIntegerVector -RandomIntegerMatrix -JacobianMatrix -HessianMatrix -WronskianMatrix -HilbertMatrix -HilbertInverseMatrix -HankelMatrix -ToeplitzMatrix -FrobeniusNorm -PNorm -Norm -OrthogonalBasis -OrthonormalBasis -Dimensions -Dot -MatrixPower -Diagonal -Sparsity -MatrixSolve -Cholesky -LU -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/lists.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/lists.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,629 +0,0 @@ - - -Function("Contains",{list,element}) -[ - Local(result); - Set(result,False); - While(And(Not(result), Not(Equals(list, {})))) - [ - If(Equals(Head(list),element), - Set(result, True), - Set(list, Tail(list)) - ); - ]; - result; -]; - -Function("Find",{list,element}) -[ - Local(result,count); - Set(result, -1); - Set(count, 1); - While(And(result<0, Not(Equals(list, {})))) - [ - If(Equals(Head(list), element), - Set(result, count) - ); - Set(list,Tail(list)); - Set(count,AddN(count,1)); - ]; - result; -]; - -// Find the first thingy that matches a predicate -Function("FindPredicate",{list,predicate}) -[ - Local(result,count); - Set(result, -1); - Set(count, 1); - While(And(result<0, Not(Equals(list, {})))) - [ - If(Apply(predicate,{Head(list)}), - Set(result, count) - ); - Set(list,Tail(list)); - Set(count,AddN(count,1)); - ]; - result; -]; - - - - -Function("Append",{list,element}) -[ - Insert(list,Length(list)+1,element); -]; -Function("DestructiveAppend",{list,element}) -[ - DestructiveInsert(list,Length(list)+1,element); -]; - -Function("DestructiveAppendList",{list,toadd}) -[ - Local(i,nr); - nr:=Length(toadd); - For(i:=1,i<=nr,i++) - [ - DestructiveAppend(list,toadd[i]); - ]; - True; -]; - - -Function("RemoveDuplicates",{list}) -[ - Local(result); - Set(result,{}); - ForEach(item,list) - If(Not(Contains(result,item)),DestructiveAppend(result,item)); - result; -]; - -Function("Union",{list1,list2}) -[ - RemoveDuplicates(Concat(list1,list2)); -]; - -Function("Intersection",{list1,list2}) -[ - Local(l2,index,result); - l2:=FlatCopy(list2); - result:={}; - ForEach(item,list1) - [ - Set(index, Find(l2,item)); - If(index>0, - [ - DestructiveDelete(l2,index); - DestructiveInsert(result,1,item); - ] - ); - ]; - DestructiveReverse(result); -]; - -Function("Difference",{list1,list2}) -[ - Local(l2,index,result); - l2:=FlatCopy(list2); - result:=FlatCopy(list1); - ForEach(item,list1) - [ - Set(index,Find(l2,item)); - If(index>0, - [ - DestructiveDelete(l2,index); - DestructiveDelete(result,Find(result,item)); - ] - ); - ]; - result; -]; - -Function("Push",{stack,element}) -[ - DestructiveInsert(stack,1,element); -]; - -Function("Pop",{stack,index}) -[ - Local(result); - result:=stack[index]; - DestructiveDelete(stack,index); - result; -]; - -Function("PopFront",{stack}) Pop(stack,1); -Function("PopBack",{stack}) Pop(stack,Length(stack)); - -Function("Swap",{list,index1,index2}) -[ - Local(item1,item2); - item1:=list[index1]; - item2:=list[index2]; - list[index1] := item2; - list[index2] := item1; -]; - - -Function("Count",{list,element}) -[ - Local(result); - Set(result,0); - ForEach(item,list) If(Equals(item, element), Set(result,AddN(result,1))); - result; -]; - -Function("BubbleSort",{list,compare}) -[ - Local(i,j,length,left,right); - - list:=FlatCopy(list); - length:=Length(list); - - For (j:=length,j>1,j--) - [ - For(i:=1,iy, z - ); - // xx 1, 2, 3 - list[last] := list[first+1]; - list[first+1] := list[first]; - list[first] := temp; - ] - ); - list; -]; - -HeapSort(list, compare) := HeapSort(list, ArrayCreate(Length(list), 0), 1, Length(list), compare); - -// this will sort "list" and mangle "tmplist" -1 # HeapSort(_list, _tmplist, _first, _last, _compare) _ (last - first <= 2) <-- SmallSort(list, first, last, compare); -2 # HeapSort(_list, _tmplist, _first, _last, _compare) <-- -[ // See: J. W. J. Williams, Algorithm 232 (Heapsort), Com. of ACM, vol. 7, no. 6, p. 347 (1964) - // sort two halves recursively, then merge two halves - // cannot merge in-place efficiently, so need a second list - Local(mid, ileft, iright, pleft); - mid := first+((last-first)>>1); - HeapSort(list, tmplist, first, mid, compare); - HeapSort(list, tmplist, mid+1, last, compare); - // copy the lower part to temporary array - For(ileft := first, ileft <= mid, ileft++) - tmplist[ileft] := list[ileft]; - For( - [ileft := first; pleft := first; iright := mid+1;], - ileft <= mid, // if the left half is finished, we don't have to do any more work - pleft++ // one element is stored at each iteration - ) // merge two halves - // elements before pleft have been stored - // the smallest element of the right half is at iright - // the smallest element of the left half is at ileft, access through tmplist - If( // we copy an element from ileft either if it is smaller or if the right half is finished; it is unnecessary to copy the remainder of the right half since the right half stays in the "list" - iright>last Or Apply(compare,{tmplist[ileft],list[iright]}), - [ // take element from ileft - list[pleft] := tmplist[ileft]; - ileft++; - ], - [ // take element from iright - list[pleft] := list[iright]; - iright++; - ] - ); - - list; -]; - -LocalSymbols(max,f,low,high,mid,current) -[ -FindIsq(max,f) := -[ - Local(low,high,mid,current); - low:=1; - high:=max+1; - Set(mid,((high+low)>>1)); - While(high>low And mid>1) - [ - Set(mid,((high+low)>>1)); - Set(current,Apply(f,{mid})); -//Echo({low,high,current}); - If(current = 0, - high:=low-1, - If(current > 0, - Set(high,mid), - Set(low,mid+1) - ) - ); - ]; - mid; -]; -]; -UnFence("FindIsq",2); -LocalSymbols(max,f,result) -[ - BSearch(max,f) := - [ - Local(result); - Set(result, FindIsq(max,f)); - If(Apply(f,{result})!=0,Set(result,-1)); - result; - ]; -]; -UnFence("BSearch",2); - - -/* VarList: return the variables this expression depends on. */ -VarList(_expr) <-- VarList(expr,"IsVariable"); - -Function("VarList",{expr,filter}) -[ - RemoveDuplicates(VarListAll(expr,filter)); -]; - - - -/* - * RuleBase for VarListAll: recursively traverse an expression looking - * up all variables the expression depends on. - */ -/* Accept any variable. */ - -VarListAll(_expr) <-- VarListAll(expr,"IsVariable"); - -10 # VarListAll(_expr,_filter)_(Apply(filter,{expr}) = True) <-- - {expr}; - -/* Otherwise check all leafs of a function. */ -20 # VarListAll(expr_IsFunction,_filter) <-- -[ - Local(item,result, flatlist); - Set(flatlist,Tail(Listify(expr))); - Set(result,{}); - ForEach(item,flatlist) - Set(result,Concat(result,VarListAll(item,filter))); - result; -]; - -/* Else it doesn't depend on any variable. */ -30 # VarListAll(_expr,_filter) <-- {}; - - - - -/* Juan: TemplateFunction (as defined in the file "deffunc") - * also makes the arguments to the function local symbols. - * Use HoldArgNr to specify the index of a variable to hold - * (since they are defined as local symbols). - */ - -TemplateFunction("Table",{body,var,count'from,count'to,step}) - LocalSymbols(result,nr,ii) - [ - MacroLocal(var); - result:={}; - nr := (count'to - count'from) / step; - ii := 0; - While( ii <= nr ) - [ - MacroSet( var, count'from + ii * step ); - DestructiveInsert( result,1,Eval(body) ); - Set(ii,AddN(ii,1)); - ]; - DestructiveReverse(result); - ]; -HoldArgNr("Table",5,1); /* body */ -HoldArgNr("Table",5,2); /* var */ -UnFence("Table",5); - - - -TemplateFunction("MapSingle",{func,list}) -[ - Local(mapsingleresult); - mapsingleresult:={}; - - ForEach(mapsingleitem,list) - [ - DestructiveInsert(mapsingleresult,1, - Apply(func,{mapsingleitem})); - ]; - DestructiveReverse(mapsingleresult); -]; -UnFence("MapSingle",2); -HoldArg("MapSingle",func); - -/* Another Macro... hack for /: to work. */ -TemplateFunction("MacroMapSingle",{func,list}) -[ - Local(mapsingleresult); - mapsingleresult:={}; - - ForEach(mapsingleitem,list) - [ - DestructiveInsert(mapsingleresult,1, - `ApplyPure(func,{Hold(Hold(@mapsingleitem))})); - ]; - DestructiveReverse(mapsingleresult); -]; -UnFence("MacroMapSingle",2); -HoldArg("MacroMapSingle",func); -HoldArg("MacroMapSingle",list); - -LocalSymbols(func,lists,mapsingleresult,mapsingleitem) -[ - Function("Map",{func,lists}) - [ - Local(mapsingleresult,mapsingleitem); - mapsingleresult:={}; - lists:=Transpose(lists); - ForEach(mapsingleitem,lists) - [ - DestructiveInsert(mapsingleresult,1,Apply(func,mapsingleitem)); - ]; - DestructiveReverse(mapsingleresult); - ]; - UnFence("Map",2); - HoldArg("Map",func); -]; - -TemplateFunction("MapArgs",{expr,oper}) -[ - Set(expr,Listify(expr)); - UnList(Concat({expr[1]}, - Apply("MapSingle",{oper,Tail(expr)}) - ) ); -]; -UnFence("MapArgs",2); -HoldArg("MapArgs",oper); - -/* Another Macro... hack for /: to work. */ -Macro("MacroMapArgs",{expr,oper}) -[ - Local(ex,tl,op); - Set(op,@oper); - Set(ex,Listify(@expr)); - Set(tl,Tail(ex)); - - UnList(Concat({ex[1]}, - `MacroMapSingle(@op,Hold(@tl))) - ); -]; -UnFence("MapArgs",2); -HoldArg("MapArgs",oper); - - - -Function("FillList", {aItem, aLength}) -[ - Local(i, aResult); - aResult:={}; - For(i:=0, i= 0) - If( range = 0 Or lst = {}, lst, Drop( Tail(lst), range-1 )); - -Rule("Drop", 2, 2, range < 0) - Take( lst, Length(lst) + range ); - - -/* ���� Take ���� */ - -/* Needs to check the parameters */ - -/* - * Take( list, n ) gives the first n elements of 'list' - * Take( list, -n ) gives the last n elements of 'list' - * Take( list, {m,n} ) elements m through n of 'list' - */ - -RuleBase("Take", {lst, range}); - -Rule("Take", 2, 1, IsList(range)) - Take( Drop(lst, range[1] -1), range[2] - range[1] + 1); - -Rule("Take", 2, 2, range >= 0) - If( Length(lst)=0 Or range=0, {}, - Concat({Head(lst)}, Take(Tail(lst), range-1))); - -Rule("Take", 2, 2, range < 0) - Drop( lst, Length(lst) + range ); - - -/* ���� Partition ���� */ - -/* Partition( list, n ) partitions 'list' into non-overlapping sublists of length n */ - -Partition(lst, len):= - If( Length(lst) < len Or len = 0, {}, - Concat( {Take(lst,len)}, Partition(Drop(lst,len), len) )); - - -////////////////////////////////////////////////// -/// Print a list using a padding string -////////////////////////////////////////////////// - -10 # PrintList(list_IsList) <-- PrintList(list, ", "); -10 # PrintList({}, padding_IsString) <-- ""; -20 # PrintList(list_IsList, padding_IsString) <-- ToString() [ - Local(i); - ForEach(i, list) [ - If(Not(Equals(i, Head(list))), WriteString(padding)); - If (IsString(i), WriteString(i), If(IsList(i), WriteString("{" : PrintList(i, padding) : "}"), Write(i))); - ]; -]; - -////////////////////////////////////////////////// -/// FuncList --- list all function atoms used in an expression -////////////////////////////////////////////////// -/// like VarList except collects functions - -10 # FuncList(expr_IsAtom) <-- {}; -20 # FuncList(expr_IsFunction) <-- -RemoveDuplicates( - Concat( - {Head(Listify(expr))}, - Apply("Concat", - MapSingle("FuncList", Tail(Listify(expr))) - ) - ) -); - -/* -This is like FuncList except only looks at arguments of a given list of functions. All other functions become "opaque". -FuncListArith() is defined to only look at arithmetic operations +, -, *, /. -*/ -10 # FuncList(expr_IsAtom, look'list_IsList) <-- {}; -// a function not in the looking list - return its type -20 # FuncList(expr_IsFunction, look'list_IsList)_(Not Contains(look'list, Atom(Type(expr)))) <-- {Atom(Type(expr))}; -// a function in the looking list - traverse its arguments -30 # FuncList(expr_IsFunction, look'list_IsList) <-- -RemoveDuplicates( - Concat( - {Head(Listify(expr))}, - [ // gave up trying to do it using Map and MapSingle... so writing a loop now. - // obtain a list of functions, considering only functions in look'list - Local(item, result); - result := {}; - ForEach(item, expr) result := Concat(result, FuncList(item, look'list)); - result; - ] - ) -); - -FuncListArith(expr) := FuncList(expr, {Atom("+"), Atom("-"), *, /}); - -HoldArgNr("FuncList", 1, 1); -HoldArgNr("FuncList", 2, 1); -HoldArgNr("FuncListArith", 1, 1); - -/// VarListArith --- obtain arithmetic variables -// currently the VarList(x,y) semantic is convoluted so let's introduce a new name; but in principle this needs to be cleaned up -VarListArith(expr) := VarListSome(expr, {Atom("+"), Atom("-"), *, /}); - -/// VarListSome is just like FuncList(x,y) - -10 # VarListSome({}, _look'list) <-- {}; -// an atom should be a variable to qualify -10 # VarListSome(expr_IsVariable, _look'list) <-- {expr}; -15 # VarListSome(expr_IsAtom, _look'list) <-- {}; -// a function not in the looking list - return it whole -20 # VarListSome(expr_IsFunction, look'list_IsList)_(Not Contains(look'list, Atom(Type(expr)))) <-- {expr}; -// a function in the looking list - traverse its arguments -30 # VarListSome(expr_IsFunction, look'list_IsList) <-- -RemoveDuplicates( - [ // obtain a list of functions, considering only functions in look'list - Local(item, result); - result := {}; - ForEach(item, expr) result := Concat(result, VarListSome(item, look'list)); - result; - ] -); - -////////////////////////////////////////////////// -/// Global stack operations on variables -////////////////////////////////////////////////// - - -LocalSymbols(GlobalStack, x) -[ - GlobalStack := {}; - - GlobalPop(x_IsAtom) <-- - [ - Check(Length(GlobalStack)>0, "GlobalPop: Error: empty GlobalStack"); - MacroSet(x, PopFront(GlobalStack)); - Eval(x); - ]; - - HoldArgNr("GlobalPop", 1, 1); - - GlobalPop() <-- - [ - Check(Length(GlobalStack)>0, "GlobalPop: Error: empty GlobalStack"); - PopFront(GlobalStack); - ]; - - GlobalPush(_x) <-- - [ - Push(GlobalStack, x); - x; - ]; -]; - - - -// Non-destructive Reverse operation -Reverse(list):=DestructiveReverse(FlatCopy(list)); - diff -Nru mathpiper-0.0.svn2556/storage/scripts/lists.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/lists.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -Contains -Find -FindPredicate -Append -DestructiveAppend -DestructiveAppendList -RemoveDuplicates -Union -Intersection -Difference -Push -Pop -PopFront -PopBack -Swap -Count -BubbleSort -HeapSort -FindIsq -BSearch -VarList -VarListAll -Table -MacroMapSingle -MapSingle -Map -MacroMapArgs -MapArgs -FillList -Drop -Take -Partition -PrintList -FuncList -FuncListSome -FuncListArith -VarListArith -VarListSome -GlobalPop -GlobalPush -Reverse -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/lists.rep/scopestack.mpi mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/scopestack.mpi --- mathpiper-0.0.svn2556/storage/scripts/lists.rep/scopestack.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/scopestack.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ - -/* - Stack simulator. Api: - - NewStack() - creates a stack simulation - PushStackFrame(stack,unfenced) - push frame on stack, (un)fenced - PushStackFrame(stack,fenced) - PopStackFrame(stack) - pop stack frame - StackDepth(_stack) - return stack depth - AddToStack(stack,element) - add element to top stack frame - - IsOnStack(stack,element) - returns True if element is accessible - on current stack, False otherwise - FindOnStack(stack,element) - return assoc list for element. - Check first with IsOnStack that it is available! - -*/ - -NewStack() := {{},{}}; - -10 # PushStackFrame(_stack,unfenced) - <-- - [ - DestructiveInsert(stack[1],1,{}); - DestructiveInsert(stack[2],1,True); - ]; -10 # PushStackFrame(_stack,fenced) - <-- - [ - DestructiveInsert(stack[1],1,{}); - DestructiveInsert(stack[2],1,False); - ]; -PopStackFrame(stack):= -[ - DestructiveDelete(stack[1],1); - DestructiveDelete(stack[2],1); -]; -StackDepth(_stack) <-- Length(stack[1]); - -AddToStack(stack,element) := -[ - DestructiveInsert(stack[1][1],1,{element,{}}); -]; - -DropOneFrame(_stack) <-- {Tail(stack[1]),Tail(stack[2])}; - -10 # IsOnStack({{},{}},_element) <-- False; -11 # IsOnStack(_stack,_element)_(stack[1][1][element] != Empty) <-- True; -20 # IsOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) - <-- IsOnStack(DropOneFrame(stack),element); -30 # IsOnStack(_stack,_element) <-- -[ -//Echo("stack depth = ",StackDepth(stack)); -//Echo(stack[2][1]); -False; -]; -10 # FindOnStack(_stack,_element)_(stack[1][1][element] != Empty) - <-- stack[1][1][element]; -20 # FindOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) - <-- FindOnStack(DropOneFrame(stack),element); -30 # FindOnStack(_stack,_element) <-- Check(False,"Illegal stack access! Use IsOnStack."); - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/lists.rep/scopestack.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/scopestack.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/lists.rep/scopestack.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/lists.rep/scopestack.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -NewStack -PushStackFrame -PopStackFrame -StackDepth -AddToStack -IsOnStack -FindOnStack -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/localrules.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/localrules.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/localrules.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/localrules.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,164 +0,0 @@ - -RuleBase("<-",{left,right}); -HoldArg("<-",left); -HoldArg("<-",right); - -LocalSymbols(LocResult) [ - - Set(LocResult,True); - 10 # LocPredicate(exp_IsAtom) <-- - [ - Local(tr,result); - tr:=patterns; - result:=False; - While (tr != {}) - [ - If (Head(Head(tr)) = exp, - [ - Set(LocResult,Eval(Head(Tail(Head(tr))))); - result := True; - tr:={}; - ], - [ - tr := Tail(tr); - ]); - ]; - result; - ]; - - 10 # LocPredicate(exp_IsFunction) <-- - [ - Local(tr,result,head); - tr:=patterns; - result:=False; - While (tr != {}) - [ - Set(head, Head(Head(tr))); - If (Not(IsAtom(head)) And exp[0]=head[1] And Pattern'Matches(head[2], exp), - [ - Set(LocResult,Eval(Head(Tail(Head(tr))))); - Set(result, True); - Set(tr,{}); - ], - [ - Set(tr, Tail(tr)); - ]); - ]; - result; - ]; - 20 # LocPredicate(_exp) <-- False; - - LocChange(_exp) <-- LocResult; -]; // LocalSymbols(LocResult) - -UnFence("LocPredicate",1); -UnFence("LocChange",1); - -10 # LocProcessSingle({_pat,_post,_exp}) <-- { {pat[0],Pattern'Create(pat,post)},exp }; -20 # LocProcessSingle({pat_IsFunction,_exp}) <-- { {pat[0],Pattern'Create(pat,True)},exp }; -30 # LocProcessSingle({pat_IsAtom,_exp}) <-- { pat,exp }; -40 # LocProcessSingle(pat_IsFunction <- _exp) <-- { {pat[0],Pattern'Create(pat,True)},exp }; -50 # LocProcessSingle(pat_IsAtom <- _exp) <-- { pat,exp }; - -LocProcess(patterns) := -[ - MapSingle("LocProcessSingle",patterns); -]; - -CompilePatterns(patterns) := LocPatterns(LocProcess(patterns)); - - -5 # (_expression /: LocPatterns(_patterns)) <-- -[ - MacroSubstitute(expression,"LocPredicate","LocChange"); -]; -10 # (_expression /: _patterns) <-- -[ - Set(patterns, LocProcess(patterns)); - MacroSubstitute(expression,"LocPredicate","LocChange"); -]; - -5 # (_expression /:: LocPatterns(_patterns)) <-- -[ - MacroSubstitute(expression,"LocPredicate","LocChange"); -]; -10 # (_expression /:: _patterns) <-- -[ - Local(old); - Set(patterns, LocProcess(patterns)); - Set(old, expression); - Set(expression, MacroSubstitute(expression,"LocPredicate","LocChange")); - While (expression != old) - [ - Set(old, expression); - Set(expression, MacroSubstitute(expression,"LocPredicate","LocChange")); - ]; - expression; -]; - - -RuleBase("Where",{left,right}); -//HoldArg("Where",left); -//HoldArg("Where",right); -UnFence("Where",2); -10 # (_body Where var_IsAtom == _value) - <-- `[Local(@var);@var := @value;@body;]; -20 # (_body Where (_a And _b)) - <-- -[ - Set(body,`(@body Where @a)); - `(@body Where @b); -]; - -30 # (_body Where {}) <-- {}; -40 # (_body Where list_IsList)_IsList(list[1]) - <-- - [ - Local(head,rest); - head:=Head(list); - rest:=Tail(list); - rest:= `(@body Where @rest); - `(@body Where @head) : rest; - ]; - -50 # (_body Where list_IsList) - <-- - [ - Local(head,rest); - While (list != {}) - [ - head:=Head(list); - body := `(@body Where @head); - list:=Tail(list); - ]; - body; - ]; - - -60 # (_body Where _var == _value) <-- Subst(var,value)body; - - - -// (a or b) and (c or d) -> (a and c) or (a and d) or (b and c) or (b and d) -20 # (list_IsList AddTo _rest) <-- -[ - Local(res); - res:={}; - ForEach(item,list) - [ - res := Concat(res,item AddTo rest); - ]; - res; -]; -30 # (_a'item AddTo list_IsList) <-- -[ - MapSingle({{orig},a'item And orig},list); -]; -40 # (_a'item AddTo _b) <-- a'item And b; - - - - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/localrules.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/localrules.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/localrules.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/localrules.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -/: -/:: -CompilePatterns -Where -AddTo -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/logic.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/logic.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/logic.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/logic.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,361 +0,0 @@ -/* Tests on logic */ - -/* Small theorem prover for propositional logic, based on the - * resolution principle. - * Written by Ayal Pinkus, based on the simple theorem prover from "Prolog, Ivan Bratko, chapter 20" - * Version 0.1 initial implementation. - * - * - * Examples: -CanProve(( (a=>b) And (b=>c)=>(a=>c) )) <-- True -CanProve(a Or Not a) <-- True -CanProve(True Or a) <-- True -CanProve(False Or a) <-- a -CanProve(a And Not a) <-- False -CanProve(a Or b Or (a And b)) <-- a Or b - */ - -RuleBase("=>",{a,b}); - - -/* - Simplify a boolean expression. CNF is responsible - for converting an expression to the following form: - (p1 Or p2 Or ...) And (q1 Or q2 Or ...) And ... - That is, a conjunction of disjunctions. -*/ - - -// Trivial simplifications -10 # CNF( Not True) <-- False; -11 # CNF( Not False) <-- True; -12 # CNF(True And (_x)) <-- CNF(x); -13 # CNF(False And (_x)) <-- False; -14 # CNF(_x And True) <-- CNF(x); -15 # CNF(_x And False) <-- False; -16 # CNF(True Or (_x)) <-- True; -17 # CNF(False Or (_x)) <-- CNF(x); -18 # CNF((_x) Or True ) <-- True; -19 # CNF((_x) Or False) <-- CNF(x); - -// A bit more complext -21 # CNF(_x Or _x) <-- CNF(x); -22 # CNF(_x And _x) <-- CNF(x); -23 # CNF(_x Or Not (_x)) <-- True; -14 # CNF(Not (_x) Or _x) <-- True; -25 # CNF(_x And Not (_x)) <-- False; -26 # CNF(Not (_x) And _x) <-- False; - -// Simplifications that deal with (in)equalities -25 # CNF(((_x) == (_y)) Or ((_x) !== (_y))) <-- True; -25 # CNF(((_x) !== (_y)) Or ((_x) == (_y))) <-- True; -26 # CNF(((_x) == (_y)) And ((_x) !== (_y))) <-- False; -26 # CNF(((_x) !== (_y)) And ((_x) == (_y))) <-- False; - -27 # CNF(((_x) >= (_y)) And ((_x) < (_y))) <-- False; -27 # CNF(((_x) < (_y)) And ((_x) >= (_y))) <-- False; -28 # CNF(((_x) >= (_y)) Or ((_x) < (_y))) <-- True; -28 # CNF(((_x) < (_y)) Or ((_x) >= (_y))) <-- True; - -// some things that are more complex -120 # CNF((_x) Or (_y)) <-- LogOr(x, y, CNF(x), CNF(y)); -10 # LogOr(_x,_y,_x,_y) <-- x Or y; -20 # LogOr(_x,_y,_u,_v) <-- CNF(u Or v); - -130 # CNF( Not (_x)) <-- LogNot(x, CNF(x)); -10 # LogNot(_x, _x) <-- Not (x); -20 # LogNot(_x, _y) <-- CNF(Not (y)); - -40 # CNF( Not ( Not (_x))) <-- CNF(x); // eliminate double negation -45 # CNF((_x)=>(_y)) <-- CNF((Not (x)) Or (y)); // eliminate implication - -50 # CNF( Not ((_x) And (_y))) <-- CNF((Not x) Or (Not y)); // De Morgan's law -60 # CNF( Not ((_x) Or (_y))) <-- CNF(Not (x)) And CNF(Not (y)); // De Morgan's law - -/* -70 # CNF((_x) And ((_y) Or (_z))) <-- CNF(x And y) Or CNF(x And z); -70 # CNF(((_x) Or (_y)) And (_z)) <-- CNF(x And z) Or CNF(y And z); - -80 # CNF((_x) Or ((_y) And (_z))) <-- CNF(x Or y) And CNF(x Or z); -80 # CNF(((_x) And (_y)) Or (_z)) <-- CNF(x Or z) And CNF(y Or z); -*/ - -70 # CNF(((_x) And (_y)) Or (_z)) <-- CNF(x Or z) And CNF(y Or z); // Distributing Or over And -80 # CNF((_x) Or ((_y) And (_z))) <-- CNF(x Or y) And CNF(x Or z); - -90 # CNF((_x) And (_y)) <-- CNF(x) And CNF(y); // Transform subexpression - -101 # CNF( (_x) < (_y) ) <-- Not CNFInEq(x >= y); -102 # CNF( (_x) > (_y) ) <-- CNFInEq(x > y); -103 # CNF( (_x) >= (_y) ) <-- CNFInEq(x >= y); -104 # CNF( (_x) <= (_y) ) <-- Not CNFInEq(x > y); -105 # CNF( (_x) == (_y) ) <-- CNFInEq(x == y); -106 # CNF( (_x) !== (_y) ) <-- Not CNFInEq(x == y); - -111 # CNF( Not((_x) < (_y)) ) <-- CNFInEq( x >= y ); -113 # CNF( Not((_x) <= (_y)) ) <-- CNFInEq( x > y ); -116 # CNF( Not((_x) !== (_y)) ) <-- CNFInEq( x == y ); - -/* Accept as fully simplified, fallthrough case */ -200 # CNF(_x) <-- x; - -20 # CNFInEq((_xex) == (_yex)) <-- (CNFInEqSimplify(xex-yex) == 0); -20 # CNFInEq((_xex) > (_yex)) <-- (CNFInEqSimplify(xex-yex) > 0); -20 # CNFInEq((_xex) >= (_yex)) <-- (CNFInEqSimplify(xex-yex) >= 0); -30 # CNFInEq(_exp) <-- (CNFInEqSimplify(exp)); - -10 # CNFInEqSimplify((_x) - (_x)) <-- 0; // strictly speaking, this is not always valid, i.e. 1/0 - 1/0 != 0... -100# CNFInEqSimplify(_x) <-- [/*Echo({"Hit the bottom of CNFInEqSimplify with ", x, Nl()});*/ x;]; - // former "Simplify"; - -// Some shortcuts to match prev interface -CanProveAux(_proposition) <-- LogicSimplify(proposition, 3); -10 # LogicSimplify(_proposition, _level)_(level<2) <-- CNF(proposition); - -20 # LogicSimplify(_proposition, _level) <-- -[ - Local(cnf, list, clauses); - Check(level > 1, "Wrong level"); - // First get the CNF version of the proposition - Set(cnf, CNF(proposition)); - - If(level <= 1, cnf, [ - Set(list, Flatten(cnf, "And")); - Set(clauses, {}); - ForEach(clause, list) - [ - Local(newclause); - //newclause := BubbleSort(LogicRemoveTautologies(Flatten(clause, "Or")), LessThan); - Set(newclause, LogicRemoveTautologies(Flatten(clause, "Or"))); - If(newclause != {True}, DestructiveAppend(clauses, newclause)); - ]; - - /* - Note that we sort each of the clauses so that they look the same, - i.e. if we have (A And B) And ( B And A), only the first one will - persist. - */ - Set(clauses, RemoveDuplicates(clauses)); - - If(Equals(level, 3) And (Length(clauses) != 0), [ - Set(clauses, DoUnitSubsumptionAndResolution(clauses)); - Set(clauses, LogicCombine(clauses)); - ]); - - Set(clauses, RemoveDuplicates(clauses)); - - If(Equals(Length(clauses), 0), True, [ - /* assemble the result back into a boolean expression */ - Local(result); - Set(result, True); - ForEach(item,clauses) - [ - Set(result, result And UnFlatten(item, "Or", False)); - ]; - - result; - ]); - ]); -]; - -/* CanProve tries to prove that the negation of the negation of - the proposition is true. Negating twice is just a trick to - allow all the simplification rules a la De Morgan to operate - */ -/*CanProve(_proposition) <-- CanProveAux( Not CanProveAux( Not proposition));*/ - -CanProve(_proposition) <-- CanProveAux( proposition ); - -1 # SimpleNegate(Not (_x)) <-- x; -2 # SimpleNegate(_x) <-- Not(x); - -/* LogicRemoveTautologies scans a list representing e1 Or e2 Or ... to find - if there are elements p and Not p in the list. This signifies p Or Not p, - which is always True. These pairs are removed. Another function that is used - is RemoveDuplicates, which converts p Or p into p. -*/ - -/* this can be optimized to walk through the lists a bit more efficiently and also take -care of duplicates in one pass */ -LocalCmp(_e1, _e2) <-- LessThan(ToString() Write(e1), ToString() Write(e2)); - -// we may want to add other expression simplifers for new expression types -100 # SimplifyExpression(_x) <-- x; - -// Return values: -// {True} means True -// {} means False -LogicRemoveTautologies(_e) <-- -[ - Local(i, len, negationfound); Set(len, Length(e)); - Set(negationfound, False); - - //Echo(e); - e := BubbleSort(e, "LocalCmp"); - - For(Set(i, 1), (i <= len) And (Not negationfound), i++) - [ - Local(x, n, j); - // we can register other simplification rules for expressions - //e[i] := MathNth(e,i) /:: {gamma(_y) <- SimplifyExpression(gamma(y))}; - Set(x, MathNth(e,i)); - Set(n, SimpleNegate(x)); /* this is all we have to do because of - the kind of expressions we can have coming in */ - - For(Set(j, i+1), (j <= len) And (Not negationfound), j++) [ - Local(y); - Set(y, MathNth(e,j)); - - If(Equals(y, n), - [ - //Echo({"Deleting from ", e, " i=", i, ", j=", j, Nl()}); - - Set(negationfound, True); - //Echo({"Removing clause ", i, Nl()}); - ], - If(Equals(y, x), - [ - //Echo({"Deleting from ", e, " j=", j, Nl()}); - DestructiveDelete(e, j); - Set(len,SubtractN(len,1)); - ]) - ); - ]; - Check(len = Length(e), "The length computation is incorrect"); - ]; - - If(negationfound, {True}, e); /* note that a list is returned */ -]; - -10 # Contradict((_x) - (_y) == 0, (_x) - (_z) == 0)_(y != z) <-- True; -12 # Contradict((_x) == (_y), (_x) == (_z))_(y != z) <-- True; -13 # Contradict((_x) - (_y) == 0, (_x) - (_z) >= 0)_(z > y) <-- True; -14 # Contradict((_x) - (_y) == 0, (_x) - (_z) > 0)_(z > y) <-- True; -14 # Contradict(Not (_x) - (_y) >= 0, (_x) - (_z) > 0)_(z > y) <-- True; -15 # Contradict(_a, _b) <-- Equals(SimpleNegate(a), b); - -/* find the number of the list that contains n in it, a pointer to a list of lists in passed */ -LogicFindWith(_list, _i, _n) <-- -[ - Local(result, index, j); - Set(result, -1); Set(index, -1); - - For(j := i+1, (result<0) And (j <= Length(list)), j++) - [ - Local(k, len); Set(len, Length(list[j])); - For(k := 1, (result<0) And (k<=len), k++) - [ - Local(el); Set(el, list[j][k]); - - If(Contradict(n, el), - [Set(result, j); Set(index, k);]); - ]; - ]; - {result, index}; -]; - -/* LogicCombine is responsible for scanning a list of lists, which represent - a form (p1 Or p2 Or ...) And (q1 Or q2 Or ...) And ... by scanning the lists - for combinations x Or Y And Not x Or Z <-- Y Or Z . If Y Or Z is empty then this clause - is false, and thus the entire proposition is false. -*/ -LogicCombine(_list) <-- -[ - Local(i, j); - For(Set(i,1), i<=Length(list), Set(i,AddN(i,1))) - [ - //Echo({"list[", i, "/", Length(list), "]: ", list[i], Nl()}); - - For(j := 1, (j<=Length(list[i])), j++) - [ - Local(tocombine, n, k); - Set(n, list[i][j]); - - {tocombine, k} := LogicFindWith(list, i, n);// search forward for n, tocombine is the list we - // will combine the current one with - If(tocombine != -1, - [ - Local(combination); - Check(k != -1, "k is -1"); - - Set(combination, LogicRemoveTautologies(Concat(list[i], list[tocombine]))); - If(combination = {}, // the combined clause is false, so the whole thing is false - [Set(list, {{}}); Set(i, Length(list)+1);], [/*Set(i, 0);*/]); - ]); - ]; - ]; - list; -]; - -10 # Subsumes((_x) - (_y) == 0, Not ((_x) - (_z)==0))_(y!=z) <-- True; -// suif_tmp0_127_1-72==0 And 78-suif_tmp0_127_1>=0 -20 # Subsumes((_x) - (_y) == 0, (_z) - (_x) >= 0)_(z>=y) <-- True; -20 # Subsumes((_x) - (_y) == 0, (_z) - (_x) > 0)_(z>y) <-- True; -// suif_tmp0_127_1-72==0 And suif_tmp0_127_1-63>=0 -30 # Subsumes((_x) - (_y) == 0, (_x) - (_z) >= 0)_(y>=z) <-- True; -30 # Subsumes((_x) - (_y) == 0, (_x) - (_z) > 0)_(y>z) <-- True; - -90 # Subsumes((_x), (_x)) <-- True; - -100# Subsumes((_x), (_y)) <-- False; - - -// perform unit subsumption and resolutiuon for a unit clause # i -// a boolean indicated whether there was a change is returned -DoUnitSubsumptionAndResolution(_list) <-- -[ - Local(i, j, k, isFalse, isTrue, changed); - Set(isFalse, False); - Set(isTrue, False); - Set(changed, True); - - //Echo({"In DoUnitSubsumptionAndResolution", Nl()}); - - While(changed) [ - Set(changed, False); - - For(i:=1, (Not isFalse And Not isTrue) And i <= Length(list), i++) - [ - If(Length(list[i]) = 1, [ - Local(x); Set(x, list[i][1]); //n := SimpleNegate(x); - //Echo({"Unit clause ", x, Nl()}); - - // found a unit clause, {x}, not use it to modify other clauses - For(j:=1, (Not isFalse And Not isTrue) And j <= Length(list), j++) - [ - If(i !=j, [ - Local(deletedClause); Set(deletedClause, False); - For(k:=1, (Not isFalse And Not isTrue And Not deletedClause) And k <= Length(list[j]), k++) - [ - // In both of these, if a clause becomes empty, the whole thing is False - - //Echo({" ", x, " subsumes ", list[j][k], i,j, Subsumes(x, list[j][k]), Nl()}); - - // unit subsumption -- this kills clause j - If(Subsumes(x, list[j][k]), [ - // delete this clause - DestructiveDelete(list, j); - j--; - If(i>j, i--); // i also needs to be decremented - Set(deletedClause, True); - Set(changed, True); - If(Length(list) = 0, [Set(isTrue, True);]); - ], - // else, try unit resolution - If(Contradict(x, list[j][k]), [ - //Echo({x, " contradicts", list[j][k], Nl()}); - DestructiveDelete(list[j], k); - k--; - Set(changed, True); - If(Length(list[j]) = 0, [Set(isFalse, True);]); - ]) - ); - ]; - ]); - ]; - ]); - ]; - ]; - - list; -]; \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/logic.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/logic.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/logic.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/logic.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -CNF // former LogicSimplify -LogicSimplify // (expression, level=1..3 -CanProve // <==> LogicSimplify(expr, 3) -LogicRemoveTautologies // not clear is this will stay, but it is eq. to LogicSimplify(expr, 2) -Subsumes -//~ -//| -//& -=> -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/logic.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/logic.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/logic.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/logic.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -// From code.mpi.def: -OMDef( "=>" , "logic1","implies" ); -OMDef( "CNF" , "piper","cnf" ); -OMDef( "LogicSimplify", "piper","logic_simplify" ); -OMDef( "CanProve" , "piper","can_prove" ); -OMDef( "LogicRemoveTautologies", "piper","logic_remove_tautologies" ); -OMDef( "Subsumes" , "piper","subsumes" ); -// The following appear in the def file, but commented out: -// "~", "piper", "Not" -// "|", "piper", "Or" -// "&", "piper", "And" diff -Nru mathpiper-0.0.svn2556/storage/scripts/multivar.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/multivar.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/multivar.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/multivar.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,338 +0,0 @@ - -// The basic container for multivariates -RuleBase("MultiNomial",{vars,terms}); - -// using the sparse tree driver for multivariate polynomials -//Use("org/mathpiper/scripts/multivar.rep/sparsenomial.mpi"); -//Use("org/mathpiper/scripts/multivar.rep/partialdensenomial.mpi"); - -If(IsBound(MultiNomialDriver), - `Use(@MultiNomialDriver), - Use("org/mathpiper/scripts/multivar.rep/sparsenomial.mpi")); - -// Code that can build the internal representation of a multivariate polynomial -Use("org/mathpiper/scripts/multivar.rep/makemulti.mpi"); - - -MM(_expr) <-- MM(expr,MultiExpressionList(expr)); -MM(_expr,_vars) <-- MakeMultiNomial(expr,vars); - -MultiSimp(_expr) <-- -[ - Local(vars); - vars:=MultiExpressionList(expr); -//Echo({"step1 ",MM(expr,vars)}); - MultiSimp2(MM(expr,vars)); -]; - -10 # MultiSimp2(_a / _b) <-- -[ - Local(c1,c2,gcd,cmn,vars); - - - c1 := MultiContentTerm(a); - c2 := MultiContentTerm(b); - gcd:=Gcd(c1[2],c2[2]); - c1[2] := c1[2]/gcd; - c2[2] := c2[2]/gcd; - - cmn:=Min(c1[1],c2[1]); - c1[1] := c1[1] - cmn; - c2[1] := c2[1] - cmn; - - vars:=MultiVars(a); - Check(vars = MultiVars(a),"incompatible Multivars to simplify"); - - (NormalForm(CreateTerm(vars,c1))/NormalForm(CreateTerm(vars,c2))) - *(NormalForm(MultiPrimitivePart(a))/NormalForm(MultiPrimitivePart(b))); -]; - -20 # MultiSimp2(expr_IsMulti) <-- -[ - NormalForm(MultiContent(expr))*NormalForm(MultiPrimitivePart(expr)); -]; -30 # MultiSimp2(_expr) <-- expr; - -MultiContent(multi_IsMulti) -<-- -[ - Local(least,gcd); - Set(least, MultiDegree(multi)); - Set(gcd,MultiLeadingCoef(multi)); - ScanMultiNomial("MultiContentScan",multi); - CreateTerm(MultiVars(multi),MultiContentTerm(multi)); -]; - -MultiContentTerm(multi_IsMulti) -<-- -[ - Local(least,gcd); - Set(least, MultiDegree(multi)); - Set(gcd,MultiLeadingCoef(multi)); - ScanMultiNomial("MultiContentScan",multi); - {least,gcd}; -]; - -MultiContentScan(_coefs,_fact) <-- -[ - Set(least,Min({least,coefs})); - Set(gcd,Gcd(gcd,fact)); -]; -UnFence("MultiContentScan",2); - -MultiPrimitivePart(MultiNomial(vars_IsList,_terms)) -<-- -[ - Local(cont); - Set(cont,MultiContentTerm(MultiNomial(vars,terms))); - Set(cont,CreateTerm(vars,{-cont[1],1/(cont[2])})); - MultiNomialMultiply(MultiNomial(vars,terms), cont); -]; - -10 # MultiRemoveGcd(x_IsMulti/y_IsMulti) <-- -[ - Local(gcd); - Set(gcd,MultiGcd(x,y)); - Set(x,MultiDivide(x,{gcd})[1][1]); - Set(y,MultiDivide(y,{gcd})[1][1]); - x/y; -]; -20 # MultiRemoveGcd(_x) <-- x; - - - -5 # MultiDegree(MultiNomial(_vars,_term))_(Not(IsList(term))) <-- {}; -10 # MultiDegree(MultiNomial(_vars,{})) <-- FillList(-Infinity,Length(vars)); -20 # MultiDegree(MultiNomial(_vars,_terms)) - <-- (MultiLeadingTerm(MultiNomial(vars,terms))[1]); - - -10 # MultiLeadingCoef(MultiNomial(_vars,_terms)) - <-- (MultiLeadingTerm(MultiNomial(vars,terms))[2]); - -10 # MultiLeadingMono(MultiNomial(_vars,{})) <-- 0; -20 # MultiLeadingMono(MultiNomial(_vars,_terms)) - <-- Factorize(vars^(MultiDegree(MultiNomial(vars,terms)))); - -20 # MultiLeadingTerm(_m) <-- MultiLeadingCoef(m) * MultiLeadingMono(m); - -MultiVars(MultiNomial(_vars,_terms)) <-- vars; - -20 # MultiLT(multi_IsMulti) - <-- CreateTerm(MultiVars(multi),MultiLeadingTerm(multi)); - -10 # MultiLM(multi_IsMulti) <-- MultiDegree(multi); - -10 # MultiLC(MultiNomial(_vars,{})) <-- 0; -20 # MultiLC(multi_IsMulti) <-- MultiLeadingCoef(multi); - -DropZeroLC(multi_IsMulti) <-- MultiDropLeadingZeroes(multi); - - - - - - - - - - - - -/************************************************************* - MultiDivide : - input - f - a multivariate polynomial - g[1 .. n] - a list of polynomials to divide by - output - {q[1 .. n],r} such that f = q[1]*g[1] + ... + q[n]*g[n] + r - - Basically quotient and remainder after division by a group of - polynomials. -**************************************************************/ -20 # MultiDivide(_f,g_IsList) <-- -[ - Local(i,v,q,r,nr); - v:=MultiExpressionList(f+Sum(g)); - f:=MakeMultiNomial(f,v); - nr := Length(g); - For(i:=1,i<=nr,i++) - [ - g[i] := MakeMultiNomial(g[i],v); - ]; - {q,r}:=MultiDivide(f,g); - q:=MapSingle("NormalForm",q); - r:=NormalForm(r); - {q,r}; -]; - -10 # MultiDivide(f_IsMulti,g_IsList) <-- -[ - Local(i,nr,q,r,p,v,finished); - Set(nr, Length(g)); - Set(v, MultiVars(f)); - Set(q, FillList(0,nr)); - Set(r, 0); - Set(p, f); - Set(finished,MultiZero(p)); - Local(plt,glt); - While (Not finished) - [ - Set(plt, MultiLT(p)); - For(i:=1,i<=nr,i++) - [ - Set(glt, MultiLT(g[i])); - - if (MultiLM(glt) = MultiLM(plt) Or MultiTermLess({MultiLM(glt),1}, {MultiLM(plt),1})) - if (Select({{n},n<0},MultiLM(plt)-MultiLM(glt)) = {}) - [ - Local(ff); - Set(ff, CreateTerm(v,{MultiLM(plt)-MultiLM(glt),MultiLC(plt)/MultiLC(glt)})); - q[i] := q[i] + ff; - Local(ltbefore,ltafter); - Set(ltbefore,MultiLeadingTerm(p)); -// Echo(ltbefore,MultiLeadingTerm(p)); - Set(p, p - ff*g[i]); - Set(ltafter,MultiLeadingTerm(p)); -// Echo(ltbefore,MultiLeadingTerm(p)); - if (ltbefore[1] = ltafter[1]) - [ - Set(ltafter,MultiLT(p)); - Set(p,p-ltafter); - ]; -// Echo(ltbefore,MultiLeadingTerm(p)); - Set(i,nr+2); - ]; - ]; - - If (i = nr+1, - [ - Set(r, r + LocalSymbols(a,b)(Subst(a,b)plt)); - Set(p, p - LocalSymbols(a,b)(Subst(a,b)plt)); - ]); -//Echo(p); - Set(finished,MultiZero(p)); - ]; - {q,r}; -]; - - -//TODO optimize this! keeps on converting to and from internal format! - -10 # MultiGcd( 0,_g) <-- g; -10 # MultiGcd(_f, 0) <-- f; - -20 # MultiGcd(_f,_g) <-- -[ - Local(v); - v:=MultiExpressionList(f+g); //hier - NormalForm(MultiGcd(MakeMultiNomial(f,v),MakeMultiNomial(g,v))); -]; - - -5 # MultiGcd(f_IsMulti,g_IsMulti)_(MultiTermLess({MultiLM(f),1},{MultiLM(g),1})) <-- -[ -//Echo("lesser"); - MultiGcd(g,f); -]; - -5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(MultiLM(MultiNomial(vars,terms)) = MultiLM(g)) - <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); - -5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(Select({{n},n<0},MultiLM(MultiNomial(vars,terms))-MultiLM(g)) != {}) - <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); - -5 # MultiGcd(MultiNomial(_vars,_terms),g_IsMulti)_(NormalForm(g) = 0) - <-- CreateTerm(vars,{FillList(0,Length(vars)),1}); -10 # MultiGcd(f_IsMulti,g_IsMulti) <-- -[ - LocalSymbols(a) - [ - Set(f,Subst(a,a)f); - Set(g,Subst(a,a)g); - ]; - Local(new); - While(g != 0) - [ -//Echo("before f",f,NormalForm(f)); -//Echo("before g",g,NormalForm(g)); - Set(new, MultiDivide(f,{g})); -//Echo("new g",NormalForm(new[1][1]),NormalForm(new[2])); -If(new[1][1]=0, -[ - g:=MakeMultiNomial(1,MultiVars(f)); -//Echo("PRIM ",MultiPrimitivePart(g)); - new[2]:=0; -]); - Set(new, new[2]); - Set(f,g); - Set(g,new); - -//Echo("after f",f,NormalForm(f)); -//Echo("after g",g,NormalForm(g)); - ]; - MultiPrimitivePart(f); -]; - - - -MultiDivTerm(MultiNomial(_vars,_term1),MultiNomial(_vars,_term2)) <-- -[ - Local(lm1,lm2); - Set(lm1,MultiLeadingTerm(MultiNomial(vars,term1)) ); - Set(lm2,MultiLeadingTerm(MultiNomial(vars,term2)) ); - CreateTerm(vars,{lm1[1]-lm2[1],lm1[2] / lm2[2]}); -]; -MultiS(_g,_h,MultiNomial(_vars,_terms)) <-- -[ - Local(gamma); - - gamma :=Max(MultiDegree(g),MultiDegree(h)); - Local(result,topterm); - topterm := MM(Factorize(vars^gamma)); - - result := - MultiDivTerm(topterm,MultiLT(g))*g - - MultiDivTerm(topterm,MultiLT(h))*h; - - result; -]; - - -/* - Groebner : Calculate the Groebner basis of a set of polynomials. - Nice example of its power is - -In> TableForm(Groebner({x*(y-1),y*(x-1)})) - x*y-x - x*y-y - y-x - y^2-y -In> Factor(y^2-y) -Out> y*(y-1); - -From which you can see that x = y, and x^2 = x so x is 0 or 1. - -*/ - -Groebner(f_IsList) <-- -[ - Local(vars,i,j,S,nr,r); - nr:=Length(f); - vars:=VarList(f); - For(i:=1,i<=nr,i++) - [ - f[i] := MakeMultiNomial(f[i],vars); - ]; - S:={}; - For(i:=1,i0) - [ - If(n&1 != 0, Set(result, MultiNomialMultiply(result,mult))); - Set(n,n>>1); - If(n!=0,Set(mult,MultiNomialMultiply(mult,mult))); - ]; - result; - ]; - - 15 # MakeMultiNomial(_x ^ _n,vars_IsList)_(Not(IsInteger(n)) And IsInteger(Simplify(n))) <-- - MakeMultiNomial( x ^ Simplify(n),vars); - - 50 # MakeMultiNomial(_x ^ (_n),vars_IsList)_(Contains(vars,x)) <-- - [ - Set(n,Simplify(n)); - If(IsInteger(n), - MultiSingleFactor(vars,x,n), - MultiSingleFactor(vars,x^n,1) - ); - ]; -]; - - -x_IsMulti + (y_IsMulti/z_IsMulti) <-- ((x*z+y)/z); -(y_IsMulti/z_IsMulti) + x_IsMulti <-- ((x*z+y)/z); -(y_IsMulti/z_IsMulti) + (x_IsMulti/w_IsMulti) <-- ((y*w+x*z)/(z*w)); -(y_IsMulti/z_IsMulti) - (x_IsMulti/w_IsMulti) <-- ((y*w-x*z)/(z*w)); -(y_IsMulti/z_IsMulti) * (x_IsMulti/w_IsMulti) <-- ((y*x)/(z*w)); -(y_IsMulti/z_IsMulti) / (x_IsMulti/w_IsMulti) <-- ((y*w)/(z*x)); -x_IsMulti - (y_IsMulti/z_IsMulti) <-- ((x*z-y)/z); -(y_IsMulti/z_IsMulti) - x_IsMulti <-- ((y-x*z)/z); -(a_IsMulti/(c_IsMulti/b_IsMulti)) <-- ((a*b)/c); -((a_IsMulti/c_IsMulti)/b_IsMulti) <-- (a/(b*c)); -((a_IsMulti/b_IsMulti) * c_IsMulti) <-- ((a*c)/b); -(a_IsMulti * (c_IsMulti/b_IsMulti)) <-- ((a*c)/b); -- ((a_IsMulti)/(b_IsMulti)) <-- (-a)/b; - - -MultiNomialMultiply( - MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2), - MultiNomial(_vars,_terms3)/MultiNomial(_vars,_terms4)) <-- -[ - MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ - MultiNomialMultiply(MultiNomial(vars,terms2),MultiNomial(vars,terms4)); -]; -MultiNomialMultiply( - MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2), - MultiNomial(_vars,_terms3)) <-- -[ - MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ - MultiNomial(vars,terms2); -]; -MultiNomialMultiply( - MultiNomial(_vars,_terms3), - MultiNomial(_vars,_terms1)/MultiNomial(_vars,_terms2)) <-- -[ - MultiNomialMultiply(MultiNomial(vars,terms1),MultiNomial(vars,terms3))/ - MultiNomial(vars,terms2); -]; - -10 # MultiNomialMultiply(_a,_b) <-- -[ - Echo({"ERROR!",a,b}); - Echo({"ERROR!",Type(a),Type(b)}); -]; - - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/multivar.rep/sparsenomial.mpi mathpiper-0.81f+dfsg1/storage/scripts/multivar.rep/sparsenomial.mpi --- mathpiper-0.0.svn2556/storage/scripts/multivar.rep/sparsenomial.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/multivar.rep/sparsenomial.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ - -/* Implementation of MultiNomials based on sparse representation - in the sparsetree.mpi code. This is the real driver, using - the sparse trees just for representation. - */ -Use("org/mathpiper/scripts/multivar.rep/sparsetree.mpi"); - -LocalSymbols(NormalMultiNomial) [ - -CreateTerm(_vars,{_coefs,_fact}) - <-- MultiNomial(vars,CreateSparseTree(coefs,fact)); - -/************************************************************ - -Adding and multiplying multivariate polynomials - -************************************************************/ -MultiNomialAdd(MultiNomial(_vars,_x), MultiNomial(_vars,_y)) - <-- MultiNomial(vars,AddSparseTrees(Length(vars),x,y)); -MultiNomialMultiplyAdd(MultiNomial(_vars,_x), MultiNomial(_vars,_y),_coefs,_fact) - <-- MultiNomial(vars,MultiplyAddSparseTrees(Length(vars),x,y,coefs,fact)); -MultiNomialNegate(MultiNomial(_vars,_terms)) - <-- - [ - SparseTreeMap(Hold({{coefs,list},-list}),Length(vars),terms); - MultiNomial(vars,terms); - ]; -MultiNomialMultiply(MultiNomial(_vars,_x),_multi2) - <-- - [ - Local(result); - Set(result,MakeMultiNomial(0,vars)); - SparseTreeScan("muadm",Length(vars),x); - result; - ]; -muadm(_coefs,_fact) <-- -[ - Set(result,MultiNomialMultiplyAdd(result, multi2,coefs,fact)); -]; -UnFence("muadm",2); - - -/* NormalForm: done as an explicit loop in stead of using SparseTreeScan - for speed. This routine is a lot faster! - */ -10 # NormalForm(x_IsMulti/y_IsMulti) <-- NormalForm(x)/NormalForm(y); -20 # NormalForm(MultiNomial(_vars,_list) ) - <-- NormalMultiNomial(vars,list,1); -10 # NormalMultiNomial({},_term,_prefact) <-- prefact*term; -20 # NormalMultiNomial(_vars,_list,_prefact) - <-- - [ - Local(first,rest,result); - Set(first,Head(vars)); - Set(rest,Tail(vars)); - Set(result,0); - ForEach(item,list) - [ - Set(result,result+NormalMultiNomial(rest,item[2],prefact*first^(item[1]))); - ]; - result; - ]; - -]; // LocalSymbols - -MultiLeadingTerm(MultiNomial(_vars,_terms)) - <-- - [ - Local(coefs,fact); - Set(coefs,MultiDegreeScanHead(terms,Length(vars))); - {coefs,fact}; - ]; -10 # MultiDegreeScanHead(_tree,0) - <-- - [ - Set(fact,tree); - {}; - ]; -10 # MultiDegreeScanHead(_tree,1) - <-- - [ - Set(fact,tree[1][2]); - {tree[1][1]}; - ]; -20 # MultiDegreeScanHead(_tree,_depth) - <-- - [ - (tree[1][1]):MultiDegreeScanHead(tree[1][2],depth-1); - ]; -UnFence("MultiDegreeScanHead",2); - -ScanMultiNomial(_op,MultiNomial(vars_IsList,_terms)) - <-- SparseTreeScan(op,Length(vars),terms); -UnFence("ScanMultiNomial",2); - - -MultiDropLeadingZeroes(MultiNomial(_vars,_terms)) - <-- - [ - MultiDropScan(terms,Length(vars)); - MultiNomial(vars,terms); - ]; -10 # MultiDropScan(0,0) <-- True; -10 # MultiDropScan({_n,0},0) <-- True; -20 # MultiDropScan(_n,0) - <-- - [ - False; - ]; -30 # MultiDropScan(_tree,_depth) - <-- - [ - Local(i); - For(i:=1,i<=Length(tree),i++) - [ - if (MultiDropScan(tree[i][2],depth-1)) - [ - DestructiveDelete(tree,i); - i--; - ] - else - [ - i:=Length(tree); - ]; - ]; - (tree = {}); - ]; -UnFence("MultiDropScan",2); - - -MultiTermLess({_deg1,_fact1},{_deg2,_fact2}) <-- - [ - Local(deg); - Set(deg, deg1-deg2); - While(deg != {} And Head(deg) = 0) [ Set(deg, Tail(deg));]; - - ((deg = {}) And (fact1-fact2 < 0)) Or - ((deg != {}) And (deg[1] < 0)); - ]; - -20 # MultiZero(multi_IsMulti) <-- -[ - CheckMultiZero(DropZeroLC(multi)); -]; -10 # CheckMultiZero(MultiNomial(_vars,{})) <-- True; -20 # CheckMultiZero(MultiNomial(_vars,_terms)) <-- False; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/multivar.rep/sparsetree.mpi mathpiper-0.81f+dfsg1/storage/scripts/multivar.rep/sparsetree.mpi --- mathpiper-0.0.svn2556/storage/scripts/multivar.rep/sparsetree.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/multivar.rep/sparsetree.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,207 +0,0 @@ - -/* Implementation of a sparse tree of Multidimensional matrix elements. -*/ - -10 # SparseTreeGet({},_tree) <-- tree; -20 # SparseTreeGet(_key,_tree) <-- -[ - SparseTreeGet2(Tail(key),Assoc(Head(key),tree)); -]; -10 # SparseTreeGet2(_key,Empty) <-- 0; -20 # SparseTreeGet2(_key,_item) <-- SparseTreeGet(key,Head(Tail(item))); - -10 # SparseTreeSet({_i},_tree,_newvalue) - <-- -[ - Local(Current,assoc,result); - Set(assoc,Assoc(i,tree)); - if(assoc=Empty) - [ - Set(Current,0); - Set(result,Eval(newvalue)); - AddSparseTrees(1,tree,CreateSparseTree({i},result)); - ] - else - [ - Set(Current,assoc[2]); - Set(result,Eval(newvalue)); - assoc[2] := result; - ]; - result; -]; -20 # SparseTreeSet(_key,_tree,_newvalue) <-- -[ - SparseTreeSet2(Tail(key),Assoc(Head(key),tree)); -]; -10 # SparseTreeSet2(_key,Empty) <-- 0; -20 # SparseTreeSet2(_key,_item) - <-- SparseTreeSet(key,Head(Tail(item)),newvalue); -UnFence("SparseTreeSet",3); -UnFence("SparseTreeSet2",2); - - -LocalSymbols(SparseTreeMap2,SparseTreeScan2,Muaddterm,MuMuaddterm, - meradd,meraddmap) [ - -10 # CreateSparseTree({},_fact) <-- fact; - -20 # CreateSparseTree(_coefs,_fact) - <-- CreateSparseTree(Head(coefs),Tail(coefs),fact); -10 # CreateSparseTree(_first,{},_fact) <-- {{first,fact}}; -20 # CreateSparseTree(_first,_coefs,_fact) - <-- {{first,CreateSparseTree(Head(coefs),Tail(coefs),fact)}}; - -10 # SparseTreeMap(_op,_depth,_list) <-- SparseTreeMap2(list,depth,{}); -10 # SparseTreeMap2(_list,1,_coefs) - <-- - ForEach(item,list) - [ - item[2] := ApplyPure(op,{Concat(coefs,{item[1]}),item[2]}); - ]; -20 # SparseTreeMap2(_list,_depth,_coefs) - <-- - ForEach(item,list) - [ - SparseTreeMap2(item[2],AddN(depth,-1),Concat(coefs,{item[1]})); - ]; -UnFence("SparseTreeMap", 3); -[Local(fn);fn:=String(SparseTreeMap2);`UnFence(@fn,3);]; - -10 # SparseTreeScan(_op,_depth,_list) <-- SparseTreeScan2(list,depth,{}); -10 # SparseTreeScan2(_list,0,_coefs) <-- ApplyPure(op,{coefs,list}); -20 # SparseTreeScan2(_list,_depth,_coefs) - <-- - ForEach(item,list) - [ - SparseTreeScan2(item[2],AddN(depth,-1),Concat(coefs,{item[1]})); - ]; -UnFence("SparseTreeScan", 3); -[Local(fn);fn:=String(SparseTreeScan2);`UnFence(@fn,3);]; - - - -5 # AddSparseTrees(0,_x,_y) <-- x+y; -10 # AddSparseTrees(_depth,_x,_y) <-- -[ - Local(i,t1,t2,inspt); - Set(t1,x); - Set(i,1); - Set(t2,y); - Set(inspt,{}); - While(t1 != {} And t2 != {}) - [ - Muaddterm(Head(t1),Head(t2)); - ]; - While(t2 != {}) - [ - Set(x,DestructiveAppend(x,Head(t2))); - Set(t2,Tail(t2)); - ]; - While(inspt != {}) - [ - Set(i,Head(inspt)); - Set(x,DestructiveInsert(x,i[2],i[1])); - Set(inspt,Tail(inspt)); - ]; - x; -]; - -10 # Muaddterm({_pow,_list1},{_pow,_list2}) <-- -[ - if(depth=1) - [ t1[1][2] := list1+list2; ] - else - [ t1[1][2] := AddSparseTrees(AddN(depth,-1),list1,list2);]; - Set(t2,Tail(t2)); -]; -20 # Muaddterm(_h1,_h2)_(h1[1]0) - [ - DestructiveAppend(result,Div(10*n,d)); - n:=Mod(10*n,d); - count--; - ]; -]; - -DecimalFindPeriod(_list) <-- -[ - Local(period,nr,reversed,first,i); - reversed:=Tail(DestructiveReverse(FlatCopy(Tail(list)))); - nr:=Length(reversed)>>1; - period:=1; - first:=reversed[1]; - - For(i:=1,i1 And list[first] = list[first+period]) first--; - first++; - - {first,period}; -]; - -DecimalMatches(_reversed,_period) <-- -[ - Local(nr,matches,first); - nr:=0; - matches:=True; - first:=1; - While((nr<100) And matches) - [ - matches := (matches And - (reversed[first .. (first+period-1)] = reversed[(first+period) .. (first+2*period-1)])); - first:=first+period; - nr:=nr+period; - ]; - matches; -]; - - - - - - -LagrangeInt(_var,_list) <-- -[ - Local(nr); - nr:=Length(list); - Factorize(FillList(var,nr)-list); -]; - -LagrangeInterpolant(list_IsList,_values,_var) <-- -[ - Local(i,nr,sublist); - nr:=Length(list); - result:=0; - For(i:=1,i<=nr,i++) - [ - sublist:=FlatCopy(list); - DestructiveDelete(sublist,i); - result:=result + values[i]*LagrangeInt(var,sublist)/LagrangeInt(list[i],sublist); - ]; - result; -]; - - -/* Lagrangian power series reversion. Copied - from Knuth seminumerical algorithms */ - -ReversePoly(_f,_g,_var,_newvar,_degree) <-- -[ - Local(orig,origg,G,V,W,U,n,initval,firstder,j,k,newsum); - orig:=MakeUni(f,var); - origg:=MakeUni(g,var); - initval:=Coef(orig,0); - firstder:=Coef(orig,1); - V:=Coef(orig,1 .. Degree(orig)); - V:=Concat(V,FillList(0,degree)); - G:=Coef(origg,1 .. Degree(origg)); - G:=Concat(G,FillList(0,degree)); - W:=FillList(0,Length(V)+2); - W[1]:=G[1]/firstder; - U:=FillList(0,Length(V)+2); - U[1]:=1/firstder; - n:=1; - While(nLength(x1), - // "x1" ended but matched, so use "x2" as "x1" - x1:=x2, - If( - i>Length(x2), - // "x2" ended but matched, so use "x1" - True, - // neither "x1" nor "x2" ended and there is a mismatch at "i" - // apply recipe: select the smalest of the differing terms - x1[i]:=Min(x1[i],x2[i]) - ) - ); - // recipe: x1dd 1 to the lx1st term unless it's the lx1st in the originx1l sequence - //Ayal added this line, i could become bigger than Length(x1)! - If(InVerboseMode(), Echo({"NearRational: using ", i, "terms of the continued fraction"})); - If(i>Length(x1),i:=Length(x1)); - x1[i] := x1[i] + If(i=Length(x1), 0, 1); - BuiltinPrecisionSet(old'prec); - ContFracEval(Take(x1, i)); -]; - -/// guess the rational number behind an imprecise number -/// prec parameter is the max number of digits you can have in the denominator -GuessRational(_x) <-- GuessRational(x, Floor(1/2*BuiltinPrecisionGet())); -GuessRational(x_IsRationalOrNumber, prec_IsInteger) <-- [ - Local(denom'estimate, cf, i); - denom'estimate := 1; - cf := ContFracList(x); - For(i:=2, i<=Length(cf) And denom'estimate < 10^prec, i++) - [ // estimate the denominator - denom'estimate := denom'estimate * If( - cf[i] = 1, - If( - i+2<=Length(cf), // have at least two more terms, do a full estimate - RoundTo(N(Eval(cf[i]+1/(cf[i+1]+1/cf[i+2]))), 3), - // have only one more term - RoundTo(N(Eval(cf[i]+1/cf[i+1])), 3) - ), - // term is not 1, use the simple estimate - cf[i] - ); - ]; - If (denom'estimate < 10^prec, - If(InVerboseMode(), Echo({"GuessRational: all ", i, "terms are within limits"})), - i-- // do not use the last term - ); - i--; // loop returns one more number - If(InVerboseMode(), Echo({"GuessRational: using ", i, "terms of the continued fraction"})); - ContFracEval(Take(cf, i)); -]; - -////////////////////////////////////////////////// -/// BracketRational: find two rational approximations -////////////////////////////////////////////////// - -/// Return a list of two rational numbers r1, r2 such that r1 Abs(N(Eval(eps*r)) ) ) ) - [ - r2 := r1; - n++; - r1 := ContFracEval(Take(cflist,n)); - ]; - // now r1 and r2 are some rational numbers. - // decide whether the search was successful. - If( - n=Length(cflist), - {}, // return empty list if not enough precision - If(N(Eval(r-r1))>0, - {r1, r2}, // successive approximations are always bracketing, we only need to decide their order - {r2, r1} - ) - ); -]; - -/** MatchLinear(variable,expression) - */ -LocalSymbols(a,b)[ - -10 # MatchLinear(var_IsAtom,expr_CanBeUni(var)) <-- -[ - Set(expr,MakeUni(expr,var)); - MatchLinear(expr); -]; -20 # MatchLinear(_var,_expr) <-- False; - -10 # MatchLinear(_expr)_(Degree(expr,var)<2) <-- -[ - Check(IsUniVar(expr),ToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"})); - -//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way? -// Check(a = Hold(a), ToString()(Echo({"Found bound variable a which should have been unbound, in MatchLinear: ", a, "=", Eval(a)}))); -// Check(b = Hold(b), ToString()(Echo({"Found bound variable b which should have been unbound, in MatchLinear: ", b, "=", Eval(b)}))); - - a := Coef(expr,1); - b := Coef(expr,0); - True; -]; -20 # MatchLinear(_expr) <-- False; -UnFence("MatchLinear",1); -UnFence("MatchLinear",2); - -/** MatchPureSquared(variable,expression) - matches expressions - * of the form a*x^2+b. - */ -10 # MatchPureSquared(var_IsAtom,_sign2,_sign0,expr_CanBeUni(var)) <-- -[ - Set(expr,MakeUni(expr,var)); - MatchPureSquared(expr,sign2,sign0); -]; -20 # MatchPureSquared(_var,_sign2,_sign0,_expr) <-- False; - -10 # MatchPureSquared(_expr,_sign2,_sign0)_(Degree(expr,var)=2 And - Coef(expr,1) = 0 And - IsNumber(Coef(expr,0)) And - IsNumber(Coef(expr,2)) And - Coef(expr,0)*sign0 > 0 And - Coef(expr,2)*sign2 > 0 - ) <-- -[ - Check(IsUniVar(expr),ToString()Echo({"Incorrect argument ",expr," passed to MatchLinear"})); -//TODO if I enable these checks, then integration fails (only users of this function any way). Can this be removed? Where are these variables cleared any way? -// Check(a = Hold(a), "Found bound variable which should have been unbound, in MatchLinear"); -// Check(b = Hold(b), "Found bound variable which should have been unbound, in MatchLinear"); - a := Coef(expr,2); - b := Coef(expr,0); - True; -]; -20 # MatchPureSquared(_expr,_sign2,_sign0) <-- False; -UnFence("MatchPureSquared",3); -UnFence("MatchPureSquared",4); - -Matched'a() := a; -Matched'b() := b; - - - -]; // LocalSymbols a,b - diff -Nru mathpiper-0.0.svn2556/storage/scripts/newly.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/newly.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/newly.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/newly.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Nl -NewLine -Space -UniqueConstant -IsFreeOf -IsZeroVector -WithValue -CharacteristicEquation -EigenValues -EigenVectors -Rationalize -ContFrac -ContFracList -ContFracEval -NearRational -GuessRational -BracketRational -Decimal -LagrangeInterpolant -ReversePoly -InverseTaylor -Series -MatchLinear -MatchPureSquared -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/numbers.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/numbers.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,666 +0,0 @@ - -/// Return integer part of the logarithm of x in given base. Use only integer arithmetic. -10 # IntLog(_x, _base) _ (base<=1) <-- Undefined; -/// Use variable steps to speed up operation for large numbers x -20 # IntLog(_x, _base) <-- -[ - Local(result, step, old'step, factor, old'factor); - result := 0; - old'step := step := 1; - old'factor := factor := base; - // first loop: increase step - While (x >= factor) - [ - old'factor := factor; - factor := factor*factor; - old'step := step; - step := step*2; - ]; - If(x >= base, - [ - step := old'step; - result := step; - x := Div(x, old'factor); - ], - step := 0 - ); - // second loop: decrease step - While (step > 0 And x != 1) - [ - step := Div(step,2); // for each step size down to 1, divide by factor if x is up to it - factor := base^step; - If( - x >= factor, - [ - x:=Div(x, factor); - result := result + step; - ] - ); - ]; - result; -]; - -/// obtain next number that has good chances of being prime (not divisible by 2,3) -1# NextPseudoPrime(i_IsInteger)_(i<=1) <-- 2; -2# NextPseudoPrime(2) <-- 3; -//2# NextPseudoPrime(3) <-- 5; -3# NextPseudoPrime(i_IsOdd) <-- -[ - // this sequence generates numbers not divisible by 2 or 3 - i := i+2; - If(Mod(i,3)=0, i:=i+2, i); -/* commented out because it slows things down without a real advantage -// this works only for odd i>=5 - i := If( - Mod(-i,3)=0, - i + 2, - i + 2*Mod(-i, 3) - ); - // now check if divisible by 5 - If( - Mod(i,5)=0, - NextPseudoPrime(i), - i - ); -*/ -]; -// this works only for even i>=4 -4# NextPseudoPrime(i_IsEven) <-- NextPseudoPrime(i-1); - -/// obtain the real next prime number -- use primality testing -1# NextPrime(_i) <-- -[ - Until(IsPrime(i)) i := NextPseudoPrime(i); - i; -]; - -/* Returns whether n is a small by a lookup table, very fast. -The largest prime number in the table is returned by FastIsPrime(0). */ - -2 # IsSmallPrime(0) <-- False; -3 # IsSmallPrime(n_IsInteger) <-- (FastIsPrime(n)>0); - -2 # IsPrime(_n)_(Not IsInteger(n) Or n<=1) <-- False; -3 # IsPrime(n_IsInteger)_(n<=FastIsPrime(0)) <-- IsSmallPrime(n); - -/* Fast pseudoprime testing: if n is a prime, then 24 divides (n^2-1) */ -5 # IsPrime(n_IsPositiveInteger)_(n > 4 And Mod(n^2-1,24)!=0) <-- False; - -/* Determine if a number is prime, using Rabin-Miller primality - testing. Code submitted by Christian Obrecht - */ -10 # IsPrime(n_IsPositiveInteger) <-- RabinMiller(n); - -5 # IsComposite(1) <-- False; -10 # IsComposite(n_IsPositiveInteger) <-- (Not IsPrime(n)); - -/* Returns whether n is a prime^m. */ -10 # IsPrimePower(n_IsPrime) <-- True; -10 # IsPrimePower(0) <-- False; -10 # IsPrimePower(1) <-- False; -20 # IsPrimePower(n_IsPositiveInteger) <-- (GetPrimePower(n)[2] > 1); - -/// Check whether n is a power of some prime integer and return that integer and the power. -/// This routine uses only integer arithmetic. -/// Returns {p, s} where p is a prime and n=p^s. -/// If no powers found, returns {n, 1}. Primality testing of n is not done. -20 # GetPrimePower(n_IsPositiveInteger) <-- -[ - Local(s, factors, new'factors); - // first, separate any small prime factors - factors := TrialFactorize(n, 257); // "factors" = {n1, {p1,s1},{p2,s2},...} or just {n} if no factors found - If( - Length(factors) > 1, // factorized into something - // now we return {n, 1} either if we haven't completely factorized, or if we factorized into more than one prime factor; otherwise we return the information about prime factors - If( - factors[1] = 1 And Length(factors) = 2, // factors = {1, {p, s}}, so we have a prime power n=p^s - factors[2], - {n, 1} - ), - // not factorizable into small prime factors -- use main algorithm - [ - factors := CheckIntPower(n, 257); // now factors = {p, s} with n=p^s - If( - factors[2] > 1, // factorized into something - // now need to check whether p is a prime or a prime power and recalculate "s" - If( - IsPrime(factors[1]), - factors, // ok, prime power, return information - [ // not prime, need to check if it's a prime power - new'factors := GetPrimePower(factors[1]); // recursive call; now new'factors = {p1, s1} where n = (p1^s1)^s; we need to check that s1>1 - If( - new'factors[2] > 1, - {new'factors[1], new'factors[2]*factors[2]}, // recalculate and return prime power information - {n, 1} // not a prime power - ); - ] - ), - // not factorizable -- return {n, 1} - {n, 1} - ); - ] - ); -]; - -/// Check whether n is a power of some integer, assuming that it has no prime factors <= limit. -/// This routine uses only integer arithmetic. -/// Returns {p, s} where s is the smallest prime integer such that n=p^s. (p is not necessarily a prime!) -/// If no powers found, returns {n, 1}. Primality testing of n is not done. -CheckIntPower(n, limit) := -[ - Local(s0, s, root); - If(limit<=1, limit:=2); // guard against too low value of limit - // compute the bound on power s - s0 := IntLog(n, limit); - // loop: check whether n^(1/s) is integer for all prime s up to s0 - root := 0; - s := 0; - While(root = 0 And NextPseudoPrime(s)<=s0) // root=0 while no root is found - [ - s := NextPseudoPrime(s); - root := IntNthRoot(n, s); - If( - root^s = n, // found root - True, - root := 0 - ); - ]; - // return result - If( - root=0, - {n, 1}, - {root, s} - ); -]; - -/// Compute integer part of s-th root of (positive) integer n. -// algorithm using floating-point math -10 # IntNthRoot(_n, 2) <-- Floor(SqrtN(n)); -20 # IntNthRoot(_n, s_IsInteger) <-- -[ - Local(result, k); - GlobalPush(BuiltinPrecisionGet()); - // find integer k such that 2^k <= n^(1/s) < 2^(k+1) - k := Div(IntLog(n, 2), s); - // therefore we need k*Ln(2)/Ln(10) digits for the floating-point calculation - BuiltinPrecisionSet(2+Div(k*3361, 11165)); // 643/2136 < Ln(2)/Ln(10) < 3361/11165 - result := Round(ExpN(DivideN(Internal'LnNum(DivideN(n, 2^(k*s))), s))*2^k); - BuiltinPrecisionSet(GlobalPop()); - // result is rounded and so it may overshoot (we do not use Floor above because numerical calculations may undershoot) - If(result^s>n, result-1, result); -]; - -/* algorithm using only integer arithmetic. -(this is slower than the floating-point algorithm for large numbers because all calculations are with long integers) -IntNthRoot1(_n, s_IsInteger) <-- -[ - Local(x1, x2, x'new, y1); - // initial guess should always undershoot - // x1:= 2 ^ Div(IntLog(n, 2), s); // this is worse than we can make it - x1 := IntLog(n,2); - // select initial interval using (the number of bits in n) mod s - // note that if the answer is 1, the initial guess must also be 1 (not 0) - x2 := Div(x1, s); // save these values for the next If() - x1 := Mod(x1, s)/s; // this is kept as a fraction - // now assign the initial interval, x1 <= root <= x2 - {x1, x2} := If( - x1 >= 263/290, // > Ln(15/8)/Ln(2) - Div({15,16}*2^x2, 8), - If( - x1 >= 373/462, // > Ln(7/4)/Ln(2) - Div({7,8}*2^x2, 4), - If( - x1 >= 179/306, // > Ln(3/2)/Ln(2) - Div({6,7}*2^x2, 4), - If( - x1 >= 113/351, // > Ln(5/4)/Ln(2) - Div({5,6}*2^x2, 4), - Div({4,5}*2^x2, 4) // between x1 and (5/4)*x1 - )))); - // check whether x2 is the root - y1 := x2^s; - If( - y1=n, - x1 := x2, - // x2 is not a root, so continue as before with x1 - y1 := x1^s // henceforth, y1 is always x1^s - ); - // Newton iteration combined with bisection - While(y1 < n) - [ -// Echo({x1, x2}); - x'new := Div(x1*((s-1)*y1+(s+1)*n), (s+1)*y1+(s-1)*n) + 1; // add 1 because the floating-point value undershoots - If( - x'new < Div(x1+x2, 2), - // x'new did not reach the midpoint, need to check progress - If( - Div(x1+x2, 2)^s <= n, - // Newton's iteration is not making good progress, so leave x2 in place and update x1 by bisection - x'new := Div(x1+x2, 2), - // Newton's iteration knows what it is doing. Update x2 by bisection - x2 := Div(x1+x2, 2) - ) - // else, x'new reached the midpoint, good progress, continue - ); - x1 := x'new; - y1 := x1^s; - ]; - If(y1=n, x1, x1-1); // subtract 1 if we overshot -]; -*/ - -CatalanNumber(_n) <-- -[ - Check( IsPositiveInteger(n), "CatalanNumber: Error: argument must be positive" ); - Bin(2*n,n)/(n+1); -]; - -/// Product of small primes <= 257. Computed only once. -LocalSymbols(p, q) -[ - // p:= 1; - ProductPrimesTo257() := 2*3*[ - If( - IsInteger(p), - p, - p := Factorize(Select({{q}, Mod(q^2,24)=1 And IsSmallPrime(q)}, 5 .. 257)) - ); -// p; - ]; -]; - -10 # Repunit(0) <-- 0; -// Number consisting of n 1's -Repunit(n_IsPositiveInteger) <-- -[ - (10^n-1)/9; -]; - -10 # HarmonicNumber(n_IsInteger) <-- HarmonicNumber(n,1); -HarmonicNumber(n_IsInteger,r_IsPositiveInteger) <-- -[ - // small speed up - if( r=1 )[ - Sum(k,1,n,1/k); - ] else [ - Sum(k,1,n,1/k^r); - ]; -]; -Function("FermatNumber",{n})[ - Check(IsPositiveInteger(n), - "FermatNumber: argument must be a positive integer"); - 2^(2^n)+1; -]; - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 6.2 p112 -5 # Divisors(0) <-- 0; -5 # Divisors(1) <-- 1; -// Unsure about if there should also be a function that returns -// n's divisors, may have to change name in future -10 # Divisors(_n) <-- -[ - Check(IsPositiveInteger(n), - "Divisors: argument must be positive integer"); - Local(len,sum,factors,i); - sum:=1; - factors:=Factors(n); - len:=Length(factors); - For(i:=1,i<=len,i++)[ - sum:=sum*(factors[i][2]+1); - ]; - sum; -]; -10 # ProperDivisors(_n) <-- -[ - Check(IsPositiveInteger(n), - "ProperDivisors: argument must be positive integer"); - Divisors(n)-1; -]; -10 # ProperDivisorsSum(_n) <-- -[ - Check(IsPositiveInteger(n), - "ProperDivisorsSum: argument must be positive integer"); - DivisorsSum(n)-n; -]; - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 6.2 p112 -5 # DivisorsSum(0) <-- 0; -5 # DivisorsSum(1) <-- 1; -10 # DivisorsSum(_n) <-- -[ - Check(IsPositiveInteger(n), - "DivisorsSum: argument must be positive integer"); - Local(factors,i,sum,len,p,k); - p:=0;k:=0; - factors:={}; - factors:=Factors(n); - len:=Length(factors); - sum:=1; - For(i:=1,i<=len,i++)[ - p:=factors[i][1]; - k:=factors[i][2]; - sum:=sum*(p^(k+1)-1)/(p-1); - ]; - sum; -]; - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Definition 6.3 p120 - -5 # Moebius(1) <-- 1; -10 # Moebius(_n) <-- -[ - Check(IsPositiveInteger(n), - "Moebius: argument must be positive integer"); - Local(factors,i,repeat); - repeat:=0; - factors:=Factors(n); - len:=Length(factors); - For(i:=1,i<=len,i++)[ - If(factors[i][2]>1,repeat:=1); - ]; - If(repeat=0,(-1)^len,0); - -]; - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 7.3 p139 - -10 # Totient(_n) <-- -[ - Check(IsPositiveInteger(n), - "Totient: argument must be positive integer"); - Local(i,sum,factors,len); - sum:=n; - factors:=Factors(n); - len:=Length(factors); - For(i:=1,i<=len,i++)[ - sum:=sum*(1-1/factors[i][1]); - ]; - sum; -]; -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Definition 9.2 p191 - -10 # LegendreSymbol(_a,_p) <-- -[ - Check( IsInteger(a) And IsInteger(p) And p>2 And IsCoprime(a,p) And IsPrime(p), - "LegendreSymbol: Invalid arguments"); - If(IsQuadraticResidue(a,p), 1, -1 ); -]; - - -IsPerfect(n_IsPositiveInteger) <-- ProperDivisorsSum(n)=n; - -5 # IsCoprime(list_IsList) <-- (Lcm(list) = Product(list)); -10 # IsCoprime(n_IsInteger,m_IsInteger) <-- (Gcd(n,m) = 1); - -// Algorithm adapted from: -// Elementary Number Theory, David M. Burton -// Theorem 9.1 p187 -10 # IsQuadraticResidue(_a,_p) <-- -[ - Check( IsInteger(a) And IsInteger(p) And p>2 And IsCoprime(a,p) And IsPrime(p), - "IsQuadraticResidue: Invalid arguments"); - If(a^((p-1)/2) % p = 1, True, False); -]; - -// Digital root of n (repeatedly add digits until reach a single digit). -10 # DigitalRoot(n_IsPositiveInteger) <-- If(n%9=0,9,n%9); - -IsTwinPrime(n_IsPositiveInteger) <-- (IsPrime(n) And IsPrime(n+2)); - -IsAmicablePair(m_IsPositiveInteger,n_IsPositiveInteger) <-- ( ProperDivisorsSum(m)=n And ProperDivisorsSum(n)=m ); - -5 # IsIrregularPrime(p_IsComposite) <-- False; -// First irregular prime is 37 -5 # IsIrregularPrime(_p)_(p<37) <-- False; - -// an odd prime p is irregular iff p divides the numerator of a Bernoulli number B(2*n) with -// 2*n+1

    n) <-- 0; -10 # PartitionsP(n_IsInteger,k_IsInteger) <-- PartitionsP(n-1,k-1)+PartitionsP(n-k,k); - -/// the number of additive partitions of an integer -5 # PartitionsP(0) <-- 1; -5 # PartitionsP(1) <-- 1; -// decide which algorithm to use -10 # PartitionsP(n_IsInteger)_(n<250) <-- PartitionsP'recur(n); -20 # PartitionsP(n_IsInteger) <-- PartitionsP'HR(n); - -/// Calculation using the Hardy-Ramanujan series. -10 # PartitionsP'HR(n_IsPositiveInteger) <-- -[ - Local(P0, A, lambda, mu, mu'k, result, term, j, k, l, prec, epsilon); - result:=0; - term:=1; // initial value must be nonzero - GlobalPush(BuiltinPrecisionGet()); - // precision must be at least Pi/Ln(10)*Sqrt(2*n/3)-Ln(4*n*Sqrt(3))/Ln(10) - // here Pi/Ln(10) < 161/118, and Ln(4*Sqrt(3))/Ln(10) <1 so it is disregarded. Add 2 guard digits and compensate for round-off errors by not subtracting Ln(n)/Ln(10) now - prec := 2+Div(IntNthRoot(Div(2*n+2,3),2)*161+117,118); - BuiltinPrecisionSet(prec); // compensate for round-off errors - epsilon := PowerN(10,-prec)*n*10; // stop when term < epsilon - - // get the leading term approximation P0 - compute once at high precision - lambda := N(Sqrt(n - 1/24)); - mu := N(Pi*lambda*Sqrt(2/3)); - // the hoops with DivideN are needed to avoid roundoff error at large n due to fixed precision: - // Exp(mu)/(n) must be computed by dividing by n, not by multiplying by 1/n - P0 := N(1-1/mu)*DivideN(ExpN(mu),(n-DivideN(1,24))*4*SqrtN(3)); - /* - the series is now equal to - P0*Sum(k,1,Infinity, - ( - Exp(mu*(1/k-1))*(1/k-1/mu) + Exp(-mu*(1/k+1))*(1/k+1/mu) - ) * A(k,n) * Sqrt(k) - ) - */ - - A := 0; // this is also used as a flag - // this is a heuristic, because the next term error is expensive - // to calculate and the theoretic bounds have arbitrary constants - // use at most 5+Sqrt(n)/2 terms, stop when the term is nonzero and result stops to change at precision prec - For(k:=1, k<=5+Div(IntNthRoot(n,2),2) And (A=0 Or Abs(term)>epsilon), k++) - [ - // compute A(k,n) - A:=0; - For(l:=1,l<=k,l++) - [ - If( - Gcd(l,k)=1, - A := A + Cos(Pi* - ( // replace Exp(I*Pi*...) by Cos(Pi*...) since the imaginary part always cancels - Sum(j,1,k-1, j*(Mod(l*j,k)/k-1/2)) - 2*l*n - // replace (x/y - Floor(x/y)) by Mod(x,y)/y for integer x,y - )/k) - ); - A:=N(A); // avoid accumulating symbolic Cos() expressions - ]; - - term := If( - A=0, // avoid long calculations if the term is 0 - 0, - N( A*Sqrt(k)*( - [ - mu'k := mu/k; // save time, compute mu/k once - Exp(mu'k-mu)*(mu'k-1) + Exp(-mu'k-mu)*(mu'k+1); - ] - )/(mu-1) ) - ); -// Echo("k=", k, "term=", term); - result := result + term; -// Echo("result", new'result* P0); - ]; - result := result * P0; - BuiltinPrecisionSet(GlobalPop()); - Round(result); -]; - -// old code for comparison - -10 # PartitionsP1(n_IsPositiveInteger) <-- - [ - Local(C,A,lambda,m,pa,k,h,term); - GlobalPush(BuiltinPrecisionGet()); - // this is an overshoot, but seems to work up to at least n=4096 - BuiltinPrecisionSet(10 + Floor(N(Sqrt(n))) ); - pa:=0; - C:=Pi*Sqrt(2/3)/k; - lambda:=Sqrt(m - 1/24); - term:=1; - // this is a heuristic, because the next term error is expensive - // to calculate and the theoretic bounds have arbitrary constants - For(k:=1,k<=5+Floor(SqrtN(n)*0.5) And ( term=0 Or Abs(term)>0.1) ,k++)[ - A:=0; - For(h:=1,h<=k,h++)[ - if( Gcd(h,k)=1 )[ - A:=A+Exp(I*Pi*Sum(j,1,k-1,(j/k)*((h*j)/k - Floor((h*j)/k) -1/2)) -- 2*Pi*I*h*n/k ); - ]; - ]; - If(A!=0, term:= N(A*Sqrt(k)*(Deriv(m) Sinh(C*lambda)/lambda) Where m==n ),term:=0 ); -// Echo("Term ",k,"is ",N(term/(Pi*Sqrt(2)))); - pa:=pa+term; -// Echo("result", N(pa/(Pi*Sqrt(2)))); - ]; - pa:=N(pa/(Pi*Sqrt(2))); - BuiltinPrecisionSet(GlobalPop()); - Round(pa); - ]; - -/// integer partitions by recurrence relation P(n) = Sum(k,1,n, (-1)^(k+1)*( P(n-k*(3*k-1)/2)+P(n-k*(3*k+1)/2) ) ) = P(n-1)+P(n-2)-P(n-5)-P(n-7)+... -/// where 1, 2, 5, 7, ... is the "generalized pentagonal sequence" -/// this method is faster with internal math for number<300 or so. -PartitionsP'recur(number_IsPositiveInteger) <-- -[ - // need storage of n values PartitionsP(k) for k=1,...,n - Local(sign, cache, n, k, pentagonal, P); - cache:=ArrayCreate(number+1,1); // cache[n] = PartitionsP(n-1) - n := 1; - While(n 1 )[ - a := re * i + im * j; - b := im * i - re * j; - While( (Mod(a,d) = 0) And (Mod(b,d) = 0) ) [ - FactorGaussianInteger(Complex(i,j)); - re:= a/d; - im:= b/d; - a := re * i + im * j; - b := im * i - re * j; - norm := re^2 + im^2; - ]; - ]; - ]; - ]; - ]; - If( re != 1 Or im != 0, Echo(Complex(re,im)) ); - ] else [ - Echo(Complex(re,im)); - ]; -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/numbers.rep/GaussianIntegers.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/GaussianIntegers.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/numbers.rep/GaussianIntegers.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/GaussianIntegers.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -IsGaussianUnit -IsGaussianInteger -IsGaussianPrime -GaussianFactorPrime -GaussianNorm -GaussianMod -GaussianFactors -AddGaussianFactor -FactorGaussianInteger -GaussianGcd -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/numbers.rep/nthroot.mpi mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/nthroot.mpi --- mathpiper-0.0.svn2556/storage/scripts/numbers.rep/nthroot.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/nthroot.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,124 +0,0 @@ -////// -// $Id: nthroot.mpi,v 1.5 2007/05/17 11:56:45 ayalpinkus Exp $ -// calculation/simplifaction of nth roots of nonnegative integers -// NthRoot - interface function -// NthRoot'Calc - actually calculate/simplifies -// NthRoot'List - list table entries for a given n -// NthRoot'Restore - get a root from lookup table -// NthRoot'Save - save a root in lookup table -// NthRoot'Clear - clear lookup table -////// - -// LocalSymbols(m,n,r, -// NthRoot'Table, -// NthRoot'Calc, -// NthRoot'List, -// NthRoot'Restore, -// NthRoot'Save, -// NthRoot'Clear) -LocalSymbols(m,n,r, - NthRoot'Table) -[ - -// interface function for nth root of m -// m>=0, n>1, integers -// m^(1/n) --> f*(r^(1/n)) -NthRoot(m_IsNonNegativeInteger,n_IsInteger)_(n>1) <-- -[ - Local(r); - r:=NthRoot'Restore(m,n); - If(Length(r)=0, - [ - r:=NthRoot'Calc(m,n); - NthRoot'Save(m,n,r); - ]); - r; -]; - -// internal functions -Function("NthRoot'Calc",{m,n}) -[ - Local(i,j,f,r,in); - Set(i,2); - Set(j,Ceil(FastPower(m,N(1.0/n))+1)); - Set(f,1); - Set(r,m); - // for large j (approx >4000) - // using Factors instead of the - // following. would this be - // faster in general? -//Echo("i j ",i," ",j); - While(LessThan(i,j)) - [ - Set(in,PowerN(i,n)); -//Echo("r in mod ",r, " ",in," ",ModN(r,in)); - While(Equals(ModN(r,in),0)) - [ - Set(f,MultiplyN(f,i)); - Set(r,DivN(r,in)); - ]; - While(Equals(ModN(r,i),0)) // - Set(r,DivN(r,i)); // - //Set(i,NextPrime(i)); - Set(i,NextPseudoPrime(i)); - Set(j,Ceil(FastPower(r,N(1.0/n))+1)); - ]; - //List(f,r); - List(f,DivN(m,PowerN(f,n))); // -]; - -// lookup table utilities -Function("NthRoot'List",{n}) -[ - If(Length(NthRoot'Table)>0, - [ - Local(p,xx); - p:=Select({{xx},Head(xx)=n},NthRoot'Table); - If(Length(p)=1,Tail(p[1]),List()); - ], - List()); -]; - -Function("NthRoot'Restore",{m,n}) -[ - Local(p); - p:=NthRoot'List(n); - If(Length(p)>0, - [ - Local(r,xx); - r:=Select({{xx},Head(xx)=m},p); - If(Length(r)=1,Head(Tail(r[1])),List()); - ], - List()); -]; - -Function("NthRoot'Save",{m,n,r}) -[ - Local(p); - p:=NthRoot'List(n); - If(Length(p)=0, - // create power list and save root - DestructiveInsert(NthRoot'Table,1,List(n,List(m,r))), - [ - Local(rr,xx); - rr:=Select({{xx},Head(xx)=m},p); - If(Length(rr)=0, - [ - // save root only - DestructiveAppend(p,List(m,r)); - ], - // already saved - False); - ]); -]; - -//TODO why is NthRoot'Table both lazy global and protected with LocalSymbols? -Function("NthRoot'Clear",{}) SetGlobalLazyVariable(NthRoot'Table,List()); - -// create empty table -NthRoot'Clear(); - -]; // LocalSymbols(m,n,r,NthRoot'Table); - -////// -////// diff -Nru mathpiper-0.0.svn2556/storage/scripts/numbers.rep/nthroot.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/nthroot.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/numbers.rep/nthroot.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/nthroot.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -NthRoot -NthRoot'Calc -NthRoot'List -NthRoot'Save -NthRoot'Restore -NthRoot'Clear -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/numbers.rep/NumberTheory.mpi mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/NumberTheory.mpi --- mathpiper-0.0.svn2556/storage/scripts/numbers.rep/NumberTheory.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/NumberTheory.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,120 +0,0 @@ -/* Implementation of some number theoretical functions for MathPiper */ -/* (C) 2002 Pablo De Napoli under GNU GPL */ - -/* DivisorsList(n) = the list of divisors of n */ - -DivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {1}; - ForEach (f,nFactors) - [ - oldresult := result; - For (k:=1,k<=f[2],k++) - ForEach (x,oldresult) - result:=Append(result,x*f[1]^k); - ]; - result; -]; - -/* This function performs a sum where sumvar runs through - the divisors of n - For example SumForDivisors(d,10,d^2) - sums d^2 with d walking through the divisors of 10 - LocalSymbols is needed since we use Eval() inside - Look at Programming in MathPiper: Evaluating Variables in the Wrong - Scope */ - -Function ("SumForDivisors",{sumvar,n,sumbody}) LocalSymbols(s,d) -[ - Local(s,d); - s:=0; - ForEach (d,DivisorsList(n)) - [ - MacroLocal(sumvar); - MacroSet(sumvar,d); - s:=s+Eval(sumbody); - ]; - s; -]; -UnFence("SumForDivisors",3); -HoldArg("SumForDivisors",sumvar); -HoldArg("SumForDivisors",sumbody); - -/* Returns a list of the square-free divisors of n */ -SquareFreeDivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {1}; - ForEach (f,nFactors) - [ - oldresult := result; - ForEach (x,oldresult) - result:=Append(result,x*f[1]); - ]; - result; -]; - -/* Returns a list of pairs {d,m} - where d runs through the square free divisors of n - and m=Moebius(m) - This is much more efficient than making a list of all - square-free divisors of n, and then compute Moebius on each of them. - It is useful for computing the Cyclotomic polinomials. - It can be useful in other computations based on - Moebius inversion formula. */ - -MoebiusDivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {{1,1}}; - ForEach (f,nFactors) - [ - oldresult := result; - ForEach (x,oldresult) - result:=Append(result,{x[1]*f[1],-x[2]}); - ]; - result; -]; - -/* RamanujanSum(k,n) = the sum of the n-th powers of the -k-th primitive roots of the identity */ - -10 # RamanujanSum(k_IsPositiveInteger,0) <-- Totient(k); - -20 # RamanujanSum(k_IsPositiveInteger,n_IsPositiveInteger) <-- -[ - Local(s,gcd,d); - s:= 0; - gcd := Gcd(n,k); - ForEach (d,DivisorsList(gcd)) - s:=s+d*Moebius(k/d); - s; -]; - - -/** Compute the Jacobi symbol JS(m/n) - n must be odd, both positive. -See the Algo book for documentation. - -*/ - -10 # JacobiSymbol(_a, 1) <-- 1; -15 # JacobiSymbol(0, _b) <-- 0; -18 # JacobiSymbol(_a, _b) _ (Gcd(a,b)>1) <-- 0; - -20 # JacobiSymbol(_a, b_IsOdd)_(a>=Abs(b) Or a<0) <-- JacobiSymbol(Mod(a,Abs(b)),Abs(b)); - -30 # JacobiSymbol(a_IsEven, b_IsOdd) <-- -[ - Local(c, s); - // compute c,s where a=c*2^s and c is odd - {c,s}:=FindPrimeFactorSimple(a, 2); // use the "Simple" function because we don't expect a worst case here - If(Mod(s,2)=1 And Abs(Mod(b,8)-4)=1, -1, 1) * JacobiSymbol(c,b); -]; - -40 # JacobiSymbol(a_IsOdd, b_IsOdd) <-- If(Mod(a,4)=3 And Mod(b,4)=3, -1, 1) * JacobiSymbol(b,a); - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/numbers.rep/NumberTheory.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/NumberTheory.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/numbers.rep/NumberTheory.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/NumberTheory.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -DivisorsList -SquareFreeDivisorsList -MoebiusDivisorsList -SumForDivisors -RamanujanSum -JacobiSymbol -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/numbers.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/numbers.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/numbers.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -// From code.mpi.def: -OMDef( "BellNumber", "piper","BellNumber" ); -OMDef( "CatalanNumber", "piper","CatalanNumber" ); -OMDef( "DigitalRoot", "piper","DigitalRoot" ); -OMDef( "Divisors", "piper","Divisors" ); -OMDef( "DivisorsSum", "piper","DivisorsSum" ); -OMDef( "Euler", "piper","Euler" ); -OMDef( "EulerArray", "piper","EulerArray" ); -OMDef( "Eulerian", "piper","Eulerian" ); -OMDef( "FermatNumber", "piper","FermatNumber" ); -OMDef( "GetPrimePower", "piper","GetPrimePower" ); -OMDef( "HarmonicNumber", "piper","HarmonicNumber" ); -OMDef( "IntLog", "piper","IntLog" ); -OMDef( "IntNthRoot", "piper","IntNthRoot" ); -OMDef( "IsAmicablePair", "piper","IsAmicablePair" ); -OMDef( "IsCarmichaelNumber", "piper","IsCarmichaelNumber" ); -OMDef( "IsComposite", "piper","IsComposite" ); -OMDef( "IsCoprime", "piper","IsCoprime" ); -OMDef( "IsIrregularPrime", "piper","IsIrregularPrime" ); -OMDef( "IsPerfect", "piper","IsPerfect" ); -OMDef( "IsPrime", "piper","IsPrime" ); -OMDef( "IsPrimePower", "piper","IsPrimePower" ); -OMDef( "IsQuadraticResidue", "piper","IsQuadraticResidue" ); -OMDef( "IsSmallPrime", "piper","IsSmallPrime" ); -OMDef( "IsSquareFree", "piper","IsSquareFree" ); -OMDef( "IsTwinPrime", "piper","IsTwinPrime" ); -OMDef( "LegendreSymbol", "piper","LegendreSymbol" ); -OMDef( "Moebius", "piper","Moebius" ); -OMDef( "NextPrime", "piper","NextPrime" ); -OMDef( "NextPseudoPrime", "piper","NextPseudoPrime" ); -OMDef( "PartitionsP", "piper","PartitionsP" ); -OMDef( "ProductPrimesTo257", "piper","ProductPrimesTo257" ); -OMDef( "ProperDivisors", "piper","ProperDivisors" ); -OMDef( "ProperDivisorsSum", "piper","ProperDivisorsSum" ); -OMDef( "Repunit", "piper","Repunit" ); -OMDef( "StirlingNumber1", "piper","StirlingNumber1" ); -OMDef( "StirlingNumber2", "piper","StirlingNumber2" ); -OMDef( "Totient", "piper","Totient" ); - -// From GaussianIntegers.mpi.def -OMDef( "IsGaussianUnit", "piper","IsGaussianUnit" ); -OMDef( "IsGaussianInteger", "piper","IsGaussianInteger" ); -OMDef( "IsGaussianPrime", "piper","IsGaussianPrime" ); -OMDef( "GaussianFactorPrime", "piper","GaussianFactorPrime" ); -OMDef( "GaussianNorm", "piper","GaussianNorm" ); -OMDef( "GaussianMod", "piper","GaussianMod" ); -OMDef( "GaussianFactors", "piper","GaussianFactors" ); -OMDef( "AddGaussianFactor", "piper","AddGaussianFactor" ); -OMDef( "FactorGaussianInteger", "piper","FactorGaussianInteger" ); -OMDef( "GaussianGcd", "piper","GaussianGcd" ); - -// From nthroot.mpi.def -OMDef( "NthRoot", "piper","NthRoot" ); -OMDef( "NthRoot'Calc", "piper","NthRoot'Calc" ); -OMDef( "NthRoot'List", "piper","NthRoot'List" ); -OMDef( "NthRoot'Save", "piper","NthRoot'Save" ); -OMDef( "NthRoot'Restore", "piper","NthRoot'Restore" ); -OMDef( "NthRoot'Clear", "piper","NthRoot'Clear" ); - -// From NumberTheory.mpi.def -OMDef( "DivisorsList", "piper","DivisorsList" ); -OMDef( "SquareFreeDivisorsList", "piper","SquareFreeDivisorsList" ); -OMDef( "MoebiusDivisorsList", "piper","MoebiusDivisorsList" ); -OMDef( "SumForDivisors", "piper","SumForDivisors" ); -OMDef( "RamanujanSum", "piper","RamanujanSum" ); -OMDef( "JacobiSymbol", "piper","JacobiSymbol" ); diff -Nru mathpiper-0.0.svn2556/storage/scripts/odesolver.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/odesolver.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/odesolver.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/odesolver.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,281 +0,0 @@ -/* - 1) implement more sub-solvers - 2) test code - 3) Done: documentation for OdeSolve and OdeTest - */ - -10 # OdeLeftHandSideEq(_l == _r) <-- (l-r); -20 # OdeLeftHandSideEq(_e) <-- e; - -10 # OdeNormChange(y(n_IsInteger)) <-- UnList({yyy,n}); -20 # OdeNormChange(y) <-- yyy(0); -25 # OdeNormChange(y') <-- yyy(1); -25 # OdeNormChange(y'') <-- yyy(2); -30 # OdeNormChange(_e) <-- e; -OdeNormPred(_e) <-- (e != OdeNormChange(e)); - - -OdeNormalForm(_e) <-- -[ - e := Substitute(OdeLeftHandSideEq(e),"OdeNormPred","OdeNormChange"); -]; - -/*TODO better OdeNormalForm? -OdeNormalForm(_e) <-- -[ - OdeLeftHandSideEq(e) /: - { - y <- yyy(0), - y' <- yyy(1), - y'' <- yyy(2), - y(_n) <- yyy(n) - }; -]; -*/ - -10 # OdeChange(yyy(n_IsInteger)) <-- Apply(yn,{n}); -30 # OdeChange(_e) <-- e; -OdePred(_e) <-- (e != OdeChange(e)); -UnFence("OdeChange",1); -UnFence("OdePred",1); -OdeSubstitute(_e,_yn) <-- -[ - Substitute(e,"OdePred","OdeChange"); -]; -UnFence("OdeSubstitute",2); - -OdeConstantList(n_IsInteger) <-- -[ - Local(result,i); - result:=ZeroVector(n); - For (i:=1,i<=n,i++) result[i]:=UniqueConstant(); - result; -]; - - -RuleBase("OdeTerm",{px,list}); - -/*5 # OdeFlatTerm(_x)_[Echo({x});False;] <-- True; */ - -10# OdeFlatTerm(OdeTerm(_a0,_b0)+OdeTerm(_a1,_b1)) <-- OdeTerm(a0+a1,b0+b1); -10# OdeFlatTerm(OdeTerm(_a0,_b0)-OdeTerm(_a1,_b1)) <-- OdeTerm(a0-a1,b0-b1); -10# OdeFlatTerm(-OdeTerm(_a1,_b1)) <-- OdeTerm(-a1,-b1); -10# OdeFlatTerm(OdeTerm(_a0,_b0)*OdeTerm(_a1,_b1))_ - (IsZeroVector(b0) Or IsZeroVector(b1)) <-- -[ - OdeTerm(a0*a1,a1*b0+a0*b1); -]; - -10# OdeFlatTerm(OdeTerm(_a0,_b0)/OdeTerm(_a1,_b1))_ - (IsZeroVector(b1)) <-- - OdeTerm(a0/a1,b0/a1); - -10# OdeFlatTerm(OdeTerm(_a0,b0_IsZeroVector)^OdeTerm(_a1,b1_IsZeroVector)) <-- - OdeTerm(a0^a1,b0); -15 # OdeFlatTerm(OdeTerm(_a,_b)) <-- OdeTerm(a,b); - -15# OdeFlatTerm(OdeTerm(_a0,_b0)*OdeTerm(_a1,_b1)) <-- OdeTermFail(); -15# OdeFlatTerm(OdeTerm(_a0,b0)^OdeTerm(_a1,b1)) <-- OdeTermFail(); -15# OdeFlatTerm(OdeTerm(_a0,b0)/OdeTerm(_a1,b1)) <-- OdeTermFail(); -20 # OdeFlatTerm(a_IsAtom) <-- OdeTermFail(); - -20 # OdeFlatTerm(_a+_b) <-- OdeFlatTerm(OdeFlatTerm(a) + OdeFlatTerm(b)); -20 # OdeFlatTerm(_a-_b) <-- OdeFlatTerm(OdeFlatTerm(a) - OdeFlatTerm(b)); -20 # OdeFlatTerm(_a*_b) <-- OdeFlatTerm(OdeFlatTerm(a) * OdeFlatTerm(b)); -20 # OdeFlatTerm(_a^_b) <-- OdeFlatTerm(OdeFlatTerm(a) ^ OdeFlatTerm(b)); -20 # OdeFlatTerm(_a/_b) <-- OdeFlatTerm(OdeFlatTerm(a) / OdeFlatTerm(b)); - -OdeMakeTerm(xx_IsAtom) <-- OdeTerm(xx,FillList(0,10)); -OdeMakeTerm(yyy(_n)) <-- OdeTerm(0,BaseVector(n+1,10)); - - -20 # OdeMakeTerm(_xx) <-- OdeTerm(xx,FillList(0,10)); -10 # OdeMakeTermPred(_x+_y) <-- False; -10 # OdeMakeTermPred(_x-_y) <-- False; -10 # OdeMakeTermPred( -_y) <-- False; -10 # OdeMakeTermPred(_x*_y) <-- False; -10 # OdeMakeTermPred(_x/_y) <-- False; -10 # OdeMakeTermPred(_x^_y) <-- False; -20 # OdeMakeTermPred(_rest) <-- True; - - -OdeCoefList(_e) <-- -[ - Substitute(e,"OdeMakeTermPred","OdeMakeTerm"); -]; -OdeTermFail() <-- OdeTerm(Error,FillList(Error,10)); - -// should check if it is linear... -OdeAuxiliaryEquation(_e) <-- -[ - // extra conversion that should be optimized away later - e:=OdeNormalForm(e); - e:=OdeSubstitute(e,{{n},aaa^n*Exp(aaa*x)}); - e:=Subst(Exp(aaa*x),1)e; - Simplify(Subst(aaa,x)e); -]; - -/* Solving a Homogeneous linear differential equation - with real constant coefficients */ -OdeSolveLinearHomogeneousConstantCoefficients(_e) <-- -[ - Local(roots,consts,auxeqn); - - /* Try solution Exp(aaa*x), and divide by Exp(aaa*x), which - * should yield a polynomial in aaa. - e:=OdeSubstitute(e,{{n},aaa^n*Exp(aaa*x)}); - e:=Subst(Exp(aaa*x),1)e; - auxeqn:=Simplify(Subst(aaa,x)e); - e:=auxeqn; - */ - e:=OdeAuxiliaryEquation(e); - auxeqn:=e; - - If(InVerboseMode(), Echo("OdeSolve: Auxiliary Eqn ",auxeqn) ); - - - /* Solve the resulting polynomial */ - e := Apply("RootsWithMultiples",{e}); - e := RemoveDuplicates(e); - - /* Generate dummy constants */ - if( Length(e) > 0 )[ - roots:=Transpose(e); - consts:= MapSingle(Hold({{nn},Add(OdeConstantList(nn)*(x^(0 .. (nn-1))))}),roots[2]); - roots:=roots[1]; - - /* Return results */ - //Sum(consts * Exp(roots*x)); - Add( consts * Exp(roots*x) ); - ] else if ( Degree(auxeqn,x) = 2 ) [ - // we can solve second order equations without RootsWithMultiples - Local(a,b,c,roots); - roots:=ZeroVector(2); - - // this should probably be incorporated into RootsWithMultiples - {c,b,a} := Coef(auxeqn,x,0 .. 2); - - - roots := PSolve(a*x^2+b*x+c,x); - If(InVerboseMode(),Echo("OdeSolve: Roots of quadratic:",roots) ); - - // assuming real coefficients, the roots must come in a complex - // conjugate pair, so we don't have to check both - // also, we don't need to check to repeated root case, because - // RootsWithMultiples (hopefully) catches those, except for - // the case b,c=0 - - if( b=0 And c=0 )[ - Add(OdeConstantList(2)*{1,x}); - ] else if( IsNumber(N(roots[1])) )[ - If(InVerboseMode(),Echo("OdeSolve: Real roots")); - Add(OdeConstantList(2)*{Exp(roots[1]*x),Exp(roots[2]*x)}); - ] else [ - If(InVerboseMode(),Echo("OdeSolve: Complex conjugate pair roots")); - Local(alpha,beta); - alpha:=Re(roots[1]); - beta:=Im(roots[1]); - Exp(alpha*x)*Add( OdeConstantList(2)*{Sin(beta*x),Cos(beta*x)} ); - ]; - - ] else [ - Echo("OdeSolve: Could not find roots of auxilliary equation"); - ]; -]; - -// this croaks on Sin(x)*y'' because OdeMakeTerm does -10 # OdeOrder(_e) <-- [ - Local(h,i,coefs); - - coefs:=ZeroVector(10); //ugly - e:=OdeNormalForm(e); - - If(InVerboseMode(),Echo("OdeSolve: Normal form is",e)); - h:=OdeFlatTerm(OdeCoefList(e)); - If(InVerboseMode(),Echo("OdeSolve: Flatterm is",h)); - - // get the list of coefficients of the derivatives - // in decreasing order - coefs:=Reverse(Listify(h)[3]); - While( Head(coefs) = 0 )[ - coefs:=Tail(coefs); - ]; - Length(coefs)-1; -]; - - -10 # OdeSolve(_expr)_(OdeOrder(expr)=0) <-- Echo("OdeSolve: Not a differential equation"); - -// Solve the ever lovable seperable equation - -10 # OdeSolve(y'+_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr-a); -10 # OdeSolve(y'-_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr+a); -10 # OdeSolve(y'/_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr*a); -10 # OdeSolve(_a*y'==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr/a); -10 # OdeSolve(y'*_a==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==expr/a); -10 # OdeSolve(_a/y'==_expr)_(IsFreeOf(y,a)) <-- OdeSolve(y'==a/expr); - -// only works for low order equations -10 # OdeSolve(y'==_expr)_(IsFreeOf({y,y',y''},expr)) <-- -[ - If(InVerboseMode(),Echo("OdeSolve: Integral in disguise!")); - If(InVerboseMode(),Echo("OdeSolve: Attempting to integrate ",expr)); - - (Integrate(x) expr)+UniqueConstant(); -]; - -50 # OdeSolve(_e) <-- -[ - Local(h); - e:=OdeNormalForm(e); - If(InVerboseMode(),Echo("OdeSolve: Normal form is",e)); - h:=OdeFlatTerm(OdeCoefList(e)); - If(InVerboseMode(),Echo("OdeSolve: Flatterm is",h)); - if (IsFreeOf(Error,h)) - [ - OdeSolveLinear(e,h); - ] - else - OdeUnsolved(e); -]; - -10 # OdeSolveLinear(_e,OdeTerm(0,_list))_(Length(VarList(list)) = 0) <-- -[ - OdeSolveLinearHomogeneousConstantCoefficients(OdeNormalForm(e)); -]; - -100 # OdeSolveLinear(_e,_ode) <-- OdeUnsolved(e); - -OdeUnsolved(_e) <-- Subst(yyy,y)e; - - - -/* -FT3(_e) <-- -[ - e:=OdeNormalForm(e); -Echo({e}); - e:=OdeCoefList(e); -Echo({e}); - e:=OdeFlatTerm(e); -Echo({e}); - e; -]; -OdeBoundaries(_solution,bounds_IsList) <-- -[ -]; -*/ - -OdeTest(_e,_solution) <-- -[ - Local(s); - s:= `Lambda({n},if (n>0)(D(x,n)(@solution)) else (@solution)); - e:=OdeNormalForm(e); - e:=Apply("OdeSubstitute",{e,s}); - e:=Simplify(e); - e; -]; - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/odesolver.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/odesolver.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/odesolver.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/odesolver.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -OdeSolve -OdeTest -OdeOrder -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/openmath.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/openmath.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/openmath.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/openmath.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,690 +0,0 @@ -//////////////////////// -// Written by Alberto González Palomo and Ayal Pinkus. -//////////////////////// - -/* The read-eval-print loop */ -/* It can take one parameter, that is the evaluation count. If it is greater - than zero, only that number of iterations will be performed before - exiting. This is particularly useful when connecting to MathPiper via pipes. -*/ -RuleBase("OMREP",{}); -Rule("OMREP",0,1,True) -[ - OMREP(0);// 0 means keep repeating, as usual. -]; -RuleBase("OMREP",{count}); -LocalSymbols(input,stringOut,result) -Rule("OMREP",1,1,True) -[ - Local(input,stringOut,result); - While(Not(IsExitRequested())) - [ - Set(errorObject, ""); - TrapError(Set(input, FromString(ConcatStrings(ReadCmdLineString("")," "))OMRead()),Set(errorObject,OMGetCoreError())); - If(Not(errorObject = ""), errorObject); - If (Not(IsExitRequested()) And errorObject="", - [ - Set(stringOut,""); - Set(result,False); - TrapError(Set(stringOut,ToString()[Secure(Set(result,Eval(input)));]),Set(errorObject,OMGetCoreError())); - If(Not(errorObject = ""), errorObject); - If(Not(stringOut = ""), WriteString(stringOut)); - SetGlobalLazyVariable(%,result); - If(PrettyPrinter'Get()="", - [ - Apply("OMForm",{result}); - ], - Apply(PrettyPrinter'Get(),{result})); - If(count > 0 And (count:=count-1) = 0, Exit()); - ]); - ]; -]; - - -LocalSymbols(omindent) [ - // Function definitions - OMIndent() := [omindent := omindent + 2;]; - OMUndent() := [omindent := omindent - 2;]; - OMClearIndent() := [omindent := 0;]; - OMIndentSpace() := Space(omindent); - - // Initialization of indentation - OMClearIndent(); -]; // LocalSymbols(omindent) - -/////////////////////////////////////////////////////////////////////// -// Output - -10 # OMForm(_expression) - <-- - [ - OMClearIndent(); - OMEcho(""); - OMIndent(); - If(IsAtom(expression), - If(expression = Atom("%"), - Secure(expression := Eval(expression)) - ) - ); - OMFormExpression(expression); - OMUndent(); - OMEcho(""); - ]; - -10 # OMFormExpression(i_IsString) <-- OMEcho("":i:""); -11 # OMFormExpression(i_IsInteger) <-- OMEcho("":String(i):""); -12 # OMFormExpression(i_IsNumber) <-- OMEcho(""); -13 # OMFormExpression(i_IsConstant)_(OMSymbol()[ String(i) ] != Empty) - <-- OMEcho("" - ); -14 # OMFormExpression(i_IsConstant)// Should we rather evaluate it? - <-- OMEcho(""); -15 # OMFormExpression(i_IsVariable)_(OMSymbol()[ String(i) ] != Empty) - <-- OMEcho("" - ); -16 # OMFormExpression(i_IsVariable) - <-- OMEcho(""); -16 # OMFormExpression(i_IsVariable)_(i = Empty) - <-- False; // This is useful for void expressions. - -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMError") - <-- - [ - Local(cd, name); - If(IsList(function[1]), - [ cd := function[1][1]; name := function[1][2]; ], - [ cd := "error"; name := function[1]; ]); - OMEcho(""); - OMIndent(); - OMEcho(""); - ForEach(i, Tail(function)) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OME") - <-- - [ - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMS") - <-- OMEcho(""); -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMBIND") - <-- - [ - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMBVAR") - <-- - [ - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -10 # OMFormExpression(function_IsFunction)_(Type(function) = "OMA") - <-- - [ - // This is not the same as the next rule: this is OMA(a,b,c,...), - // which is used for building OMA constructs in the mapping to OM. - OMEcho(""); - OMIndent(); - ForEach(i, function) OMFormExpression(i); - OMUndent(); - OMEcho(""); - ]; -11 # OMFormExpression(function_IsFunction) - <-- - [ - OMEcho(""); - OMIndent(); - OMFormFunction(function); - OMUndent(); - OMEcho(""); - ]; - -11 # OMFormFunction(function_IsFunction) - <-- - [ - Local(arity); - arity := Length(function); - OMEcho(""); - If(arity > 0, ForEach(arg, function) OMFormExpression(arg)); - ]; -10 # OMFormFunction(function_IsFunction)_(OMSymbol()[ Type(function) ] != Empty) - <-- - [ - Local(symbolDef); - // [20051016 AGP] The "signature" feature is an old attempt at pattern - // matching, but now that we have real predicates in the mappings it's - // probably obsolete. I'll think about removing it. - symbolDef := OMSymbol()[ OMSignature(function) ]; - If(symbolDef = Empty, symbolDef := OMSymbol()[ Type(function) ] ); - If(symbolDef = Empty Or Length(symbolDef) < 3 Or symbolDef[3] = {}, - [ - OMEcho(""); - ForEach(arg, function) OMFormExpression(arg); - ], - [ - Local(result); - result := OMApplyMapping(function, symbolDef[3]); - //Check(IsList(result), ToString()Echo("Mapping result is not a list: ", result)); - If(IsList(result), - [ - result := UnList(Subst($, function[0]) result); - OMFormExpression(result[0]); - ForEach(i, result) OMFormExpression(i); - ], - If(result = Empty, - Echo("No rule matched ", function, symbolDef[3]), - Echo("Unexpected result value from OMApplyMapping(): ", result) - ) - ); - ] - ); - ]; - - -OMWrite(_expression) <-- -[ - Write(expression); -]; - -OMEcho(_expression) <-- -[ - OMIndentSpace(); - Write(expression); - NewLine(); -]; -OMEcho(expression_IsString) <-- -[ - OMIndentSpace(); - WriteString(expression); - NewLine(); -]; -OMEcho(expression_IsList) <-- -[ - ForEach(arg, expression) - [ - If (IsString(arg), WriteString(arg), Write(arg)); - ]; - NewLine(); -]; - -OMEscape(_expression) <-- -[ - ""; -]; -OMEscapeString(_expression_IsString) <-- -[ - ""; -]; -OMWriteEscape(_expression) <-- -[ - WriteString(OMEscape(expression)); -]; -OMWriteStringEscape(expression_IsString) <-- -[ - WriteString(OMEscapeString(expression)); -]; -OMEchoEscape(_expression) <-- -[ - OMWriteEscape(expression); - NewLine(); -]; -OMEchoEscape(expression_IsString) <-- -[ - OMWriteStringEscape(expression); - NewLine(); -]; -OMEchoEscape(expression_IsList) <-- -[ - WriteString(""); - NewLine(); -]; - - -HoldArgNr("OMForm",1,1); -//HoldArgNr("OMFormExpression",1,1); -//HoldArgNr("OMFormFunction",1,1); - - -OMSignature(_function) <-- ""; -OMSignature(function_IsFunction) <-- -[ - Local(makeSig); - makeSig := {ConcatStrings, Type(function), "_"}; - Local(type); - type := "";// If "function" doesn't have parameters, the signature is "f_". - ForEach(arg, function) - [ - If(Type(arg) = "List", - type := "L", - If(IsFunction(arg), - type := "F", - If(IsInteger(arg), - type := "I", - type := "V" - ) - ) - ); - DestructiveAppend(makeSig, type); - ]; - Secure(Eval(UnList(makeSig))); -]; -HoldArgNr("OMSignature", 1, 1); - - - -/////////////////////////////////////////////////////////////////////// -// Input - -// Troubleshooting guide: -// "encodingError:unexpected closing brace": this happens in the ReadOMOBJ -// rules. It means that you forgot to call OMNextToken() from your rule. - -LocalSymbols(omtoken) [ - OMNextToken() := - [ - omtoken := XmlExplodeTag(String(ReadToken())); - ]; - OMToken() := omtoken; -]; // LocalSymbols(omtoken) - -OMRead():= -[ - Local(result); - TrapError( - [ - XmlTokenizer(); - OMNextToken(); - result := MatchOMOBJ(OMToken()); - DefaultTokenizer(); - ], - [ - result := OMGetCoreError(); - DefaultTokenizer(); - ]); - result; -]; - - -OMDump(str):= -FromString(str:" EndOfFile") -[ - Local(result); - XmlTokenizer(); - OMNextToken(); - While(OMToken() != "EndOfFile") - [ - Echo("Exploded ",OMToken()); - OMNextToken(); - ]; - DefaultTokenizer(); - True; -]; - - - -10 # MatchClose(_x)_(x = OMToken()) <-- [OMNextToken();True;]; -20 # MatchClose(_x) <-- Check(False,ToString()Echo("encodingError:unexpected closing brace")); //@@@ TODO better error reporting - -10 # MatchOMOBJ(XmlTag("OMOBJ",_attributes,"Open")) <-- -[ - // Any attributes are ignored. - Local(result); - OMNextToken(); - result := ReadOMOBJ(OMToken()); - MatchClose(XmlTag("OMOBJ",{},"Close")); - result; -]; -10 # MatchOMOBJ(XmlTag("OMOBJ",_attributes,"OpenClose")) <-- -[ - OMNextToken(); - // Any attributes are ignored. - // This is a void expression, of the form "". - Empty; -]; -20 # MatchOMOBJ(_rest) <-- Check(False,ToString()Echo("encodingError:not an OMOBJ :",rest)); - -10 # ReadOMOBJ(XmlTag("OMOBJ",_attributes,"Close")) <-- -[ - // This is a void expression, of the form "". - Empty; -]; - -10 # ReadOMOBJ(XmlTag("OMI",{},"Open")) <-- -[ - Local(result); - OMNextToken(); - result := Atom(OMToken()); - OMNextToken(); - MatchClose(XmlTag("OMI",{},"Close")); - result; -]; - -10 # ReadOMOBJ(XmlTag("OMV",{{"NAME",_name}},"OpenClose")) <-- -[ - OMNextToken(); - Atom(name); -]; - -10 # ReadOMOBJ(XmlTag("OMF",{{"DEC",_dec}},"OpenClose")) <-- -[ - OMNextToken(); - Atom(dec); -]; - -10 # ReadOMOBJ(XmlTag("OMSTR",{},"Open")) <-- -[ - Local(result); - OMNextToken(); - If(IsString(OMToken()), [result := OMToken(); OMNextToken();], result := ""); - MatchClose(XmlTag("OMSTR",{},"Close")); - result; -]; -10 # ReadOMOBJ(XmlTag("OMSTR",{},"OpenClose")) <-- -[ - OMNextToken(); - ""; -]; - -10 # ReadOMOBJ(XmlTag("OMA",{},"Open")) <-- -[ - Local(result, new); - result:={}; - OMNextToken(); - While (OMToken() != XmlTag("OMA",{},"Close")) - [ - new:=ReadOMOBJ(OMToken()); - DestructiveAppend(result,new); - ]; - MatchClose(XmlTag("OMA",{},"Close")); - OMApplyReverseMapping(UnList(result)); -]; - -10 # ReadOMOBJ(XmlTag("OMBIND",{},"Open")) <-- -[ - Local(result, new); - result:={}; - OMNextToken(); - While (OMToken() != XmlTag("OMBIND",{},"Close")) - [ - new:=ReadOMOBJ(OMToken()); - DestructiveAppend(result,new); - ]; - MatchClose(XmlTag("OMBIND",{},"Close")); - result; -]; -10 # ReadOMOBJ(XmlTag("OMBVAR",{},"Open")) <-- -[ - Local(result, new); - result:={}; - OMNextToken(); - While (OMToken() != XmlTag("OMBVAR",{},"Close")) - [ - new:=ReadOMOBJ(OMToken()); - DestructiveAppend(result,new); - ]; - MatchClose(XmlTag("OMBVAR",{},"Close")); - result; -]; - -10 # OMApplyReverseMapping(piperExp_IsFunction) <-- piperExp; -10 # OMApplyReverseMapping(piperExp_IsFunction)_(OMSymbol()[ Type(piperExp) ] != Empty) - <-- - [ - Local(symbolDef, result); - symbolDef := OMSymbol()[ Type(piperExp) ]; - If(symbolDef[4] = {}, - result := piperExp, - [ - result := OMApplyMapping(piperExp, symbolDef[4]); - result := Subst($, piperExp[0]) result; - If(IsList(result), result := UnList(result)); - ] - ); - result; - ]; - -10 # OMApplyMapping(_function, _mapping) <-- -[ - Local(expandRules, result); - expandRules := { _(_path) <- OMPathSelect(path, function) }; - expandRules[1][2][2] := function;// the "function" variable is not expanded above. - - mapping := (mapping /: expandRules);// "/:" has lower precedence than ":=". - - Local(ruleMatched); - ruleMatched := False; - If(Type(mapping) = "|", - [ - mapping := Flatten(mapping, "|"); - ForEach(rule, mapping) - If(Not ruleMatched, - [ - If(Type(rule) = "_", - If( Eval(rule[2]), [ result := rule[1]; ruleMatched := True; ] ), - [ result := rule; ruleMatched := True; ] - ); - ] - ); - ], - [ - If(Type(mapping) = "_", - If(Eval(mapping[2]), - result := mapping[1], - result := Listify(function) - ), - result := mapping - ); - ruleMatched := True; - ] - ); - - If(ruleMatched, - If(Type(result) = ":", - If(Length(result) = 2, - result[1]:result[2], - result),// Perhaps we should give a warning here. - result), - Empty); -]; - -11 # OMPathSelect(path_IsNumber, _expression) <-- -[ - If(path >= 0 And path <= Length(expression), - expression[path], - Undefined); -]; -11 # OMPathSelect(path_IsList, _expression) <-- -[ - ForEach(i, path) - If(IsFunction(expression) And i >= 0 And i <= Length(expression), - expression := expression[i], - Undefined); - expression; -]; -HoldArgNr("OMPathSelect", 2, 2); - -// Previously, any unknown symbols where reported as errors. -// Now, we just store them as OMS(cd, name) since MathPiper is perfectly happy -// with such unknown symbols, and will handle them right: When -// producing an OpenMath result from them, they will be output back -// unmodified, forming a valid OpenMath expression. -// This way we don't have to bother defining bogus symbols for concepts that -// MathPiper does not handle. -100 # ReadOMOBJ(XmlTag("OMS", _attributes, "OpenClose")) <-- -[ - OMNextToken(); - Local(omcd, omname); - omcd := attributes["CD"]; - omname := attributes["NAME"]; - If(omcd = Empty Or omname = Empty, - OMCheck(False,OMError({"moreerrors", "encodingError"}, ToString()Echo("missing \"cd\" or \"name\" attribute: ",attributes))), - [ - Local(cdTable, piperform); - cdTable := OMSymbolReverse()[ omcd ]; - If(cdTable != Empty, piperform := cdTable[ omname ]); - // We can not optimize here by checking first whether the CD is "piper" - // and avoiding the table lookup then, because for some symbols the - // OM name have to be different from the MathPiper name (e.g. "/@"). - If(piperform = Empty, - If(cd = "piper", Atom(omname), OMS(omcd, omname)), - If(IsString(piperform), Atom(piperform), piperform)); - ] - ); -]; - -101 # ReadOMOBJ(_rest) <-- OMCheck(False,OMError({"moreerrors", "encodingError"}, ToString()Echo("unhandled tag: ",rest))); - - - -/////////////////////////////////////////////////////////////////////// -// Error reporting - -Macro(OMCheck,{predicate,error}) -[ - If(Not(@predicate), - [ - Assert("omErrorObject", @error) False; - Check(False,"omErrorObject"); - ] - , - True); -]; -OMGetCoreError():= -[ - Local(result); - result := GetCoreError(); - If(result != "", - If( IsError("omErrorObject"), - [result := GetError("omErrorObject"); ], - [result := OMError({"moreerrors", "unexpected"}, result); ]) - ); - result; -]; - - - -/////////////////////////////////////////////////////////////////////// -// Symbol mapping tables - -LocalSymbols(omsymbol, omsymbolreverse) [ - // Initialization of the openmath symbol dictionaries - omsymbol := {}; - omsymbolreverse := {}; - - // Access to the dictionaries - OMSymbol() := omsymbol; - OMSymbolReverse() := omsymbolreverse; - -]; // LocalSymbols(omsymbol, omsymbolreverse) - -OMDef(_piperform, omcd_IsString, omname_IsString, _directMapping, _reverseMapping) <-- -[ - Local(cdTable); - If(IsString(piperform), - OMSymbol()[ piperform ] := {omcd, omname, directMapping, reverseMapping} - ); - cdTable := OMSymbolReverse()[ omcd ]; - If(cdTable = Empty, - OMSymbolReverse()[ omcd ] := {{omname, piperform}}, - [ - Local(oldMathPiperform); - oldMathPiperform := cdTable[ omname ]; - If(oldMathPiperform = Empty, - cdTable[ omname ] := piperform, - [ - If(oldMathPiperform != piperform, - [ - cdTable[ omname ] := piperform; - Echo("Warning: the mapping for ", omcd, ":", omname, - " was already defined as ", oldMathPiperform, - ", but is redefined now as ", piperform - ); - ] - ); - ] - ); - ] - ); - True; -]; - -OMDef(_piperform, omcd_IsString, omname_IsString) -<-- OMDef(piperform, omcd, omname, {}, {}); - -OMDef(piperalias_IsString, pipername_IsString) <-- -[ - OMSymbol()[ piperalias ] := OMSymbol()[ pipername ]; -]; -HoldArgNr("OMDef", 5, 4); -HoldArgNr("OMDef", 5, 5); - -// Many objects, such as matrices and sets, do not have a specific -// encoding in MathPiper, but are represented as lists. -OMDef( {}, "set1","emptyset" ); -OMDef( "List", "set1","set" ); -OMDef( "List", "linalg2","matrix" ); -OMDef( "List", "linalg2","matrixrow" ); -OMDef( "List", "linalg2","vector" ); -OMDef( "List", "list1","list" ); - -// [20010916 AGP] I couldn't find these symbols in the def files: -// "E" , "nums1", "e" -// "Gamma" , "nums1", "gamma" -OMDef( "Infinity" , "nums1", "infinity" ); -OMDef( "Undefined", "nums1", "NaN" ); -// [20010916 AGP] From org/mathpiper/scripts/initialization.rep/stdopers.mpi: -OMDef( "And" , "logic1", "and" ); -OMDef( "==" , "logic1", "equivalent" ); -OMDef( "!==" , "logic1", "not", - { "", - 1, - 2, - "" - } - ); -OMDef( "False", "logic1", "false" ); -OMDef( "Or" , "logic1", "or" ); -OMDef( "True" , "logic1", "true" ); -//[20010916 AGP ] Xor is not available in MathPiper. -// "Xor" , "logic1", "xor" ); -OMDef( "&" , "piper", "bitwise_and" ); -OMDef( "|" , "piper", "bitwise_or" ); -OMDef( "%" , "piper", "bitwise_xor" ); -OMDef( "/" , "arith1", "divide");// This definition is for OM arith1:divide to MathPiper. In all other cases, the next one will be used. -OMDef( "/" , "nums1", "rational", {$, _1, _2}_(IsRational(_1/_2)) | {OMS("arith1", "divide"), _1, _2}, {/, _1, _2}); -OMDef( "-" , "arith1", "unary_minus"); -OMDef( "-" , "arith1", "minus" );// We need a way of testing the arity. -OMDef( "+" , "arith1", "plus" ); -OMDef( "^" , "arith1", "power" ); -OMDef( "*" , "arith1", "times" ); - - -Use("org/mathpiper/scripts/constants.rep/om.mpi"); -Use("org/mathpiper/scripts/stdfuncs.rep/om.mpi"); -Use("org/mathpiper/scripts/stubs.rep/om.mpi"); -Use("org/mathpiper/scripts/logic.rep/om.mpi"); -Use("org/mathpiper/scripts/complex.rep/om.mpi"); -Use("org/mathpiper/scripts/integrate.rep/om.mpi"); -Use("org/mathpiper/scripts/sums.rep/om.mpi"); -Use("org/mathpiper/scripts/limit.rep/om.mpi"); -//Use("org/mathpiper/scripts/numbers.rep/om.mpi");// Sqrt is loaded before (stubs.rep) than IntNthRoot. -Use("org/mathpiper/scripts/functional.rep/om.mpi"); diff -Nru mathpiper-0.0.svn2556/storage/scripts/openmath.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/openmath.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/openmath.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/openmath.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -OMREP -OMDef -OMForm -OMRead -OMParse -OMEcho -OMEchoEscape -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/orthopoly.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/orthopoly.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/orthopoly.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/orthopoly.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,464 +0,0 @@ -/* -Orthogonal polynomials -version 1.2 -(Serge Winitzki) - -Polynomials are found from direct recurrence relations. Sums of series of polynomials are found using the Clenshaw-Smith recurrence scheme. - -Reference: Yudell L. Luke. Mathematical functions and their approximations. Academic Press, N. Y., 1975. - -Usage: - The polynomials are evaluated by functions named Ortho*, where * is one of P, G, H, L, T, U. The first argument of these functions is an integer. The series of polynomials are evaluated by functions named Ortho*Sum. The first argument of these functions is a list of coefficients. The last argument is the value x at which the polynomials are to be computed; if x is numerical, a faster routine is used. - - If n is an integer, n>=0, then: - OrthoP(n, x) gives the n-th Legendre polynomial, evaluated on x - OrthoP(n, a, b, x) gives the n-th Jacobi polynomial with parameters a, b, evaluated on x - OrthoG(n, a, x) gives the n-th Gegenbauer polynomial - OrthoH(n, x) gives the n-th Hermite polynomial - OrthoL(n, a, x) gives the n-th Laguerre polynomial - OrthoT(n, x) gives the n-th Tschebyscheff polynomial of the 1st kind - OrthoU(n, x) gives the n-th Tschebyscheff polynomial of the 2nd kind - - If c is a list of coefficients c[1], c[2], ..., c[N], then Ortho*Sum(c, ...) where * is one of P, G, H, L, T, U, computes the sum of a series c[1]*P_0+c[2]*P_1+...+c[N]*P_N, where P_k is the relevant polynomial of k-th order. (For polynomials taking parameters: the parameters must remain constant throughout the summation.) Note that the intermediate polynomials are not evaluated and the recurrence relations are different for this computation, so there may be a numerical difference between Ortho*(c, ...) and computing the sum of the series directly. - - Internal functions that may be useful: - OrthoPolyCoeffs(name_IsString, n_IsInteger, parameters_IsList) returns a list of coefficients of the polynomial. Here "name" must be one of the predefined names: "Jacobi", "Gegenbauer", "Hermite", "Laguerre", "Tscheb1", "Tscheb2"; and "parameters" is a list of extra parameters for the given family of polynomials, e.g. {a,b} for the Jacobi, {a} for Laguerre and {} for Hermite polynomials. - OrthoPolySumCoeffs(name_IsString, c_IsList, parameters_IsList) returns a list of coefficients of the polynomial which is a sum of series with coefficients c. - EvaluateHornerScheme(coefficients, x) returns the Horner-evaluated polynomial on x. The "coefficients" is a list that starts at the lowest power. For example, EvaluateHornerScheme({a,b,c}, x) should return (a+x*(b+x*c)) -*/ - -10 # EvaluateHornerScheme({}, _x) <-- 0; -/* Strictly speaking, the following rule is not needed, but it doesn't hurt */ -10 # EvaluateHornerScheme({_coeffs}, _x) <-- coeffs; -20 # EvaluateHornerScheme(coeffs_IsList, _x) <-- Head(coeffs)+x*EvaluateHornerScheme(Tail(coeffs), x); - -/* Plain polynomials */ -// some are computed by general routines, and some are replaced by more efficient routines below -OrthoP(n_IsInteger, _x)_(n>=0) <-- OrthoP(n, 0, 0, x); -OrthoP(n_IsInteger, a_IsRationalOrNumber, b_IsRationalOrNumber, _x)_(n>=0 And a> -1 And b> -1) <-- OrthoPoly("Jacobi", n, {a, b}, x); - -OrthoG(n_IsInteger, a_IsRationalOrNumber, _x)_(n>=0 And a> -1/2) <-- OrthoPoly("Gegenbauer", n, {a}, x); - -OrthoH(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Hermite", n, {}, x); - -OrthoL(n_IsInteger, a_IsRationalOrNumber, _x)_(n>=0 And a> -1) <-- OrthoPoly("Laguerre", n, {a}, x); - -OrthoT(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Tscheb1", n, {}, x); -OrthoU(n_IsInteger, _x)_(n>=0) <-- OrthoPoly("Tscheb2", n, {}, x); - -/* Sums of series of orthogonal polynomials */ - -OrthoPSum(c_IsList, _x) <-- OrthoP(c, 0, 0, x); -OrthoPSum(c_IsList, a_IsRationalOrNumber, b_IsRationalOrNumber, _x)_(a> -1 And b> -1) <-- OrthoPolySum("Jacobi", c, {a, b}, x); - -OrthoGSum(c_IsList, a_IsRationalOrNumber, _x)_(a> -1/2) <-- OrthoPolySum("Gegenbauer", c, {a}, x); - -OrthoHSum(c_IsList, _x) <-- OrthoPolySum("Hermite", c, {}, x); - -OrthoLSum(c_IsList, a_IsRationalOrNumber, _x)_(a> -1) <-- OrthoPolySum("Laguerre", c, {a}, x); - -OrthoTSum(c_IsList, _x) <-- OrthoPolySum("Tscheb1", c, {}, x); -OrthoUSum(c_IsList, _x) <-- OrthoPolySum("Tscheb2", c, {}, x); - -/* -Orthogonal polynomials are evaluated using a general routine OrthoPolyCoeffs that generates their coefficients recursively. - -The recurrence relations start with n=0 and n=1 (the n=0 polynomial is always identically 1) and continue for n>=2. Note that the n=1 polynomial is not always given by the n=1 recurrence formula if we assume P_{-1}=0, so the recurrence should be considered undefined at n=1. - - For Legendre/Jacobi polynomials: (a>-1, b>-1) -P(0,a,b,x):=1 -P(1,a,b,x):=(a-b)/2+x*(1+(a+b)/2) -P(n,a,b,x):=(2*n+a+b-1)*(a^2-b^2+x*(2*n+a+b-2)*(2*n+a+b))/(2*n*(n+a+b)*(2*n+a+b-2))*P(n-1,a,b,x)-(n+a-1)*(n+b-1)*(2*n+a+b)/(n*(n+a+b)*(2*n+a+b-2))*P(n-2,a,b,x) - - For Hermite polynomials: -H(0,x):=1 -H(1,x):=2*x -H(n,x):=2*x*H(n-1,x)-2*(n-1)*H(n-2,x) - - For Gegenbauer polynomials: (a>-1/2) -G(0,a,x):=1 -G(1,a,x):=2*a*x -G(n,a,x):=2*(1+(a-1)/n)*x*G(n-1,a,x)-(1+2*(a-2)/n)*G(n-2,a,x) - - For Laguerre polynomials: (a>-1) -L(0,a,x):=1 -L(1,a,x):=a+1-x -L(n,a,x):=(2+(a-1-x)/n)*L(n-1,a,x)-(1+(a-1)/n)*L(n-2,a,x) - - For Tschebycheff polynomials of the first kind: -T(0,x):=1 -T(1,x):=x -T(n,x):=2*x*T(n-1,x)-T(n-2,x) - - For Tschebycheff polynomials of the second kind: -U(0,x):=1 -U(1,x):=2*x -U(n,x):=2*x*U(n-1,x)-U(n-2,x) - -The database "KnownOrthoPoly" contains closures that return coefficients for the recurrence relations of each family of polynomials. KnownOrthoPoly["name"] is a closure that takes two arguments: the order (n) and the extra parameters (p), and returns a list of two lists: the first list contains the coefficients {A,B} of the n=1 polynomial, i.e. "A+B*x"; the second list contains the coefficients {A,B,C} in the recurrence relation, i.e. "P_n = (A+B*x)*P_{n-1}+C*P_{n-2}". (So far there are only 3 coefficients in the second list, i.e. no "C+D*x", but we don't want to be limited.) - -*/ - -LocalSymbols(knownOrthoPoly) [ - knownOrthoPoly := Hold({ - {"Jacobi", {{n, p}, {{(p[1]-p[2])/2, 1+(p[1]+p[2])/2}, {(2*n+p[1]+p[2]-1)*((p[1])^2-(p[2])^2)/(2*n*(n+p[1]+p[2])*(2*n+p[1]+p[2]-2)), (2*n+p[1]+p[2]-1)*(2*n+p[1]+p[2])/(2*n*(n+p[1]+p[2])), -(n+p[1]-1)*(n+p[2]-1)*(2*n+p[1]+p[2])/(n*(n+p[1]+p[2])*(2*n+p[1]+p[2]-2))}}}}, - {"Gegenbauer", {{n, p}, {{0, 2*p[1]}, {0, 2+2*(p[1]-1)/n, -1-2*(p[1]-1)/n}}}}, - {"Laguerre", {{n, p}, {{p[1]+1, -1}, {2+(p[1]-1)/n, -1/n, -1-(p[1]-1)/n}}}}, - {"Hermite", {{n, p}, {{0,2}, {0, 2, -2*(n-1)}}}}, - {"Tscheb1", {{n, p}, {{0,1}, {0,2,-1}}}}, - {"Tscheb2", {{n, p}, {{0,2}, {0,2,-1}}}} - }); - KnownOrthoPoly() := knownOrthoPoly; - -]; // LocalSymbols(knownOrthoPoly) - -/* -For efficiency, polynomials are represented by lists of coefficients rather than by MathPiper expressions. Polynomials are evaluated using the explicit Horner scheme. On numerical arguments, the polynomial coefficients are not computed, only the resulting value. -*/ - -/* -Sums of series of orthogonal polynomials are found using the Clenshaw-Smith recurrence scheme: - If $P_n$ satisfy $P_n = A_n p_{n-1} + B_n p_{n-2}$, $n>=2$, and if $A_1$ is defined so that $P_1 = A_1 P_0$, then $\sum _{n=0}^N c_n P_n = X_0 P_0$, where $X_n$ are found from the following backward recurrence: $X_{N+1} = X_{N+2} = 0$, $X_n = c_n + A_{n+1} X_{n+1} + B_{n+2} X_{n+2}$, $n=N, N-1, ..., 0$. -*/ - -/* Numeric arguments are processed by a faster routine */ - -10 # OrthoPoly(name_IsString, _n, p_IsList, x_IsRationalOrNumber) _ (KnownOrthoPoly()[name] != Empty) <-- OrthoPolyNumeric(name, n, p, x); -20 # OrthoPoly(name_IsString, _n, p_IsList, _x) _ (KnownOrthoPoly()[name] != Empty) <-- EvaluateHornerScheme(OrthoPolyCoeffs(name, n, p), x); - -10 # OrthoPolySum(name_IsString, c_IsList, p_IsList, x_IsRationalOrNumber) _ (KnownOrthoPoly()[name] != Empty) <-- OrthoPolySumNumeric(name, c, p, x); -20 # OrthoPolySum(name_IsString, c_IsList, p_IsList, _x) _ (KnownOrthoPoly()[name] != Empty) <-- EvaluateHornerScheme(OrthoPolySumCoeffs(name, c, p), x); - -/* -OrthoPolyNumeric computes the value of the polynomial from recurrence relations directly. Do not use with non-numeric arguments, except for testing! -*/ -OrthoPolyNumeric(name_IsString, n_IsInteger, p_IsList, _x) <-- [ - Local(value1, value2, value3, ruleCoeffs, index); - value1 := 1; - ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[1]; - value2 := ruleCoeffs[1] + x*ruleCoeffs[2]; - index := 1; - /* value1, value2, value3 is the same as P_{n-2}, P_{n-1}, P_n where n = index */ - While(index=1) [ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[2]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; - value3 := (ruleCoeffs[1] + x*ruleCoeffs[2])*value2 + ruleCoeffs1[3]*value1 + c[index+1]; - value1 := value2; - value2 := value3; - index := index - 1; - ]; - /* Last iteration by hand: works correctly also if c has only 1 element */ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {1, p})[1]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {2, p})[2]; - value2 := (ruleCoeffs[1] + x*ruleCoeffs[2])*value2 + ruleCoeffs1[3]*value1 + c[1]; - value2; -]; - -/* -OrthoPolyCoeffs(name, n, p) returns the list of coefficients for orthogonal polynomials, starting with the lowest powers. -*/ - -10 # OrthoPolyCoeffs(name_IsString, 0, p_IsList) <-- {1}; -10 # OrthoPolyCoeffs(name_IsString, 1, p_IsList) <-- Apply(KnownOrthoPoly()[name], {1, p})[1]; - -/* Simple implementation, very slow, for testing only: recursive rule matches, no loops -20 # OrthoPolyCoeffs(name_IsString, n_IsInteger, p_IsList)_(n>1) <-- [ - Local(ruleCoeffs, newCoeffs); - ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[2]; - newCoeffs := OrthoPolyCoeffs(name, n-1, p); - Concat(newCoeffs,{0})*ruleCoeffs[1] + Concat(OrthoPolyCoeffs(name, n-2, p),{0,0})*ruleCoeffs[3] + Concat({0}, newCoeffs)*ruleCoeffs[2]; -]; -*/ - -/* A fast implementation that works directly with lists and saves memory. Same recurrence as in OrthoPolyNumeric() */ -/* note: here we pass "name" instead of "KnownOrthoPoly()[name]" for efficiency, but strictly speaking we don't need to use this global constant */ - -20 # OrthoPolyCoeffs(name_IsString, n_IsInteger, p_IsList)_(n>1) <-- [ - Local(ruleCoeffs, tmpCoeffs, newCoeffs, prevCoeffs, index, jndex, tmptmpCoeffs, prevCoeffsA, newCoeffsA, tmpCoeffsA); - /* For speed, allocate all lists now. Length is n+1 */ - prevCoeffsA := ZeroVector(n+1); - newCoeffsA := ZeroVector(n+1); - tmpCoeffsA := ZeroVector(n+1); - /* pointers to arrays */ - prevCoeffs := prevCoeffsA; - newCoeffs := newCoeffsA; - tmpCoeffs := tmpCoeffsA; - /* Initialize: n=0 and n=1 */ - prevCoeffs[1] := 1; - ruleCoeffs := Apply(KnownOrthoPoly()[name], {n, p})[1]; - newCoeffs[1] := ruleCoeffs[1]; - newCoeffs[2] := ruleCoeffs[2]; - /* Invariant: answer ready in "newCoeffs" at value of index */ - index := 1; - /* main loop */ - While(index < n) [ - index := index + 1; - /* Echo({"index ", index}); */ /* in case this is slow */ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index, p})[2]; - tmpCoeffs[1] := ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs[3]*prevCoeffs[1]; - /* The polynomial tmpCoeffs must have (index+1) coefficients now */ - For(jndex:=2, jndex <= index, jndex:=jndex+1) [ - tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; - ]; - tmpCoeffs[index+1] := ruleCoeffs[2]*newCoeffs[index]; -/* - prevCoeffs := FlatCopy(newCoeffs); - newCoeffs := FlatCopy(tmpCoeffs); -*/ -/* juggle pointers instead of copying lists */ - tmptmpCoeffs := prevCoeffs; - prevCoeffs := newCoeffs; - newCoeffs := tmpCoeffs; - tmpCoeffs := tmptmpCoeffs; - ]; - newCoeffs; -]; - -/* -OrthoPolySumCoeffs(name, c, p) returns the list of coefficients for the sum of a series of orthogonal polynomials. Same recurrence as in OrthoPolySumNumeric() -*/ - -OrthoPolySumCoeffs(name_IsString, c_IsList, p_IsList) <-- [ - Local(n, ruleCoeffs, ruleCoeffs1, tmpCoeffs, newCoeffs, prevCoeffs, index, jndex, tmptmpCoeffs, prevCoeffsA, newCoeffsA, tmpCoeffsA); - /* n is the max polynomial order we need */ - n := Length(c) - 1; - /* For speed, allocate all lists now. Length is n+1 */ - prevCoeffsA := ZeroVector(n+1); - newCoeffsA := ZeroVector(n+1); - tmpCoeffsA := ZeroVector(n+1); - /* pointers to arrays */ - prevCoeffs := prevCoeffsA; - newCoeffs := newCoeffsA; - tmpCoeffs := tmpCoeffsA; - /* Invariant: answer ready in "newCoeffs" at value of index */ - /* main loop */ - For(index:=n, index >= 1, index:=index-1) [ - /* Echo({"index ", index}); */ /* in case this is slow */ - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[2]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; - tmpCoeffs[1] := c[index+1] + ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs1[3]*prevCoeffs[1]; - /* The polynomial tmpCoeffs must have (n-index+1) coefficients now */ - For(jndex:=2, jndex <= n-index, jndex:=jndex+1) [ - tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs1[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; - ]; - If(n-index>0, tmpCoeffs[n-index+1] := ruleCoeffs[2]*newCoeffs[n-index]); -/* - prevCoeffs := FlatCopy(newCoeffs); - newCoeffs := FlatCopy(tmpCoeffs); -*/ -/* juggle pointers instead of copying lists */ - tmptmpCoeffs := prevCoeffs; - prevCoeffs := newCoeffs; - newCoeffs := tmpCoeffs; - tmpCoeffs := tmptmpCoeffs; - ]; - /* Last iteration by hand: works correctly also if c has only 1 element */ - index:=0; - ruleCoeffs := Apply(KnownOrthoPoly()[name], {index+1, p})[1]; - ruleCoeffs1 := Apply(KnownOrthoPoly()[name], {index+2, p})[2]; - tmpCoeffs[1] := c[index+1] + ruleCoeffs[1]*newCoeffs[1] + ruleCoeffs1[3]*prevCoeffs[1]; - /* The polynomial tmpCoeffs must have (n-index+1) coefficients now */ - For(jndex:=2, jndex <= n-index, jndex:=jndex+1) [ - tmpCoeffs[jndex] := ruleCoeffs[1]*newCoeffs[jndex] + ruleCoeffs1[3]*prevCoeffs[jndex] + ruleCoeffs[2]*newCoeffs[jndex-1]; - ]; - tmpCoeffs[n-index+1] := ruleCoeffs[2]*newCoeffs[n-index]; - tmpCoeffs; -]; - -////////////////////////////////////////////////// -/// Very fast computation of Chebyshev polynomials -////////////////////////////////////////////////// -/// (This is not used now because of numerical instability, until I figure out how much to increase the working precision to get P correct digits.) -/// See: W. Koepf. Efficient computation of Chebyshev polynomials in computer algebra (unpublished preprint). Contrary to Koepf's claim (unsupported by any calculation in his paper) that the method is numerically stable, I found unsatisfactory numerical behavior for very large orders. -/// Koepf suggests to use M. Bronstein's algorithm for finding rational solutions of linear ODEs for all other orthogonal polynomials (may be faster than recursion if we want to find the analytic form of the polynomial, but still slower if an explicit formula is available). -////////////////////////////////////////////////// -/// Main formulae: T(2*n,x) = 2*T(n,x)^2-1; T(2*n+1,x) = 2*T(n+1,x)*T(n,x)-x; -/// U(2*n,x) = 2*T(n,x)*U(n,x)-1; T(2*n+1,x) = 2*T(n+1,x)*U(n,x); -/// We avoid recursive calls and build the sequence of bits of n to determine the minimal sequence of n[i] for which T(n[i], x) and U(n[i], x) need to be computed -////////////////////////////////////////////////// -/* -/// This function will return the list of binary bits, e.g. BitList(10) returns {1,0,1,0}. -BitList(n) := BitList(n, {}); -/// This will not be called on very large numbers so it's okay to use recursion -1# BitList(0, _bits) <-- bits; -2# BitList(_n, _bits) <-- BitList(Div(n,2), Push(bits, Mod(n,2))); - -// Tchebyshev polynomials of 1st kind -1 # FastOrthoT(0, _x) <-- 1; -1 # FastOrthoT(1, _x) <-- x; -// Tchebyshev polynomials of 2nd kind -1 # FastOrthoU(0, _x) <-- 1; -1 # FastOrthoU(1, _x) <-- 2*x; - -// guard against user errors -2 # FastOrthoT(_n, _x) _ (IsInteger(n) And n<0) <-- Undefined; -2 # FastOrthoU(_n, _x) _ (IsInteger(n) And n<0) <-- Undefined; - -// make T(), U() of even order more efficient: delegate gruntwork to odd order -2 # FastOrthoT(n_IsEven, _x) <-- 2*FastOrthoT(Div(n,2), x)^2-1; -2 # FastOrthoU(n_IsEven, _x) <-- 2*FastOrthoT(Div(n,2), x)*FastOrthoU(Div(n,2), x)-1; - -// FastOrthoT() of odd order -3 # FastOrthoT(n_IsOdd, _x) <-- -[ - Local(T1, T2, i); - // first bit in the list is always 1, so initialize the pair - T1 := FastOrthoT(1, x); - T2 := FastOrthoT(2, x); - ForEach(i, Tail(BitList(n))) // skip first bit - [ - // if the current bit is 1, we need to double the second index, else double the first index. - // Invariant: n[i+1] = 2*n[i] + BitList[i] and we need to have FastOrthoT(n[i]), FastOrthoT(1+n[i]) as T1, T2. Initially n[1]=1 and after the cycle n[i]=n. - {T1, T2} := If - ( - i=1, - {2*T1*T2-x, 2*T2^2-1}, - {2*T1^2-1, 2*T1*T2-x} - ); - ]; - T1; -]; - -// FastOrthoU() of any order -3 # FastOrthoU(_n, _x) <-- -[ - Local(U1, T1, T2, i); - // first bit in the list is always 1, so initialize the pair - U1 := FastOrthoU(1, x); - T1 := FastOrthoT(1, x); - T2 := FastOrthoT(2, x); - ForEach(i, Tail(BitList(n))) // skip first bit - [ - // if the current bit is 1, we need to double the second index, else double the first index - // Invariant: n[i+1] = 2*n[i] + BitList[i] and we need to have U(n[i]), T(n[i]), T(1+n[i]) as U1, T1, T2. Initially n[1]=1 and after the cycle n[i]=n. - {U1, T1, T2} := If - ( - i=1, - {2*U1*T2, 2*T1*T2-x, 2*T2^2-1}, - {2*U1*T1-1, 2*T1^2-1, 2*T1*T2-x} - ); - ]; - U1; -]; -*/ -////////////////////////////////////////////////// -/// Fast symbolic computation of some polynomials -////////////////////////////////////////////////// - - -////////////////////////////////////////////////// -/// Fast symbolic computation of Legendre polynomials -////////////////////////////////////////////////// - -8# OrthoPolyCoeffs("Jacobi", n_IsInteger, {0,0}) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := (2*n-1)!! /n!; // coefficient at x^n - i := 1; - While(2*i<=n) - [ // prepare coefficient at x^(n-2*i) now - result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+1)*(n-2*i+2)) / ((2*n-2*i+1)*2*i); - i++; - ]; - result; -]; - -////////////////////////////////////////////////// -/// Fast symbolic computation of Hermite polynomials -////////////////////////////////////////////////// - -OrthoPolyCoeffs("Hermite", n_IsInteger, {}) <-- HermiteCoeffs(n); - -/// Return the list of coefficiets of Hermite polynomials. -HermiteCoeffs(n_IsEven)_(n>0) <-- -[ - Local(i, k, result); - k := Div(n,2); - result := ZeroVector(n+1); - result[1] := (-2)^k*(n-1)!!; // coefficient at x^0 - For(i:=1,i<=k,i++) // prepare coefficient at x^(2*i) now - result[2*i+1] := Div(-2*result[2*i-1] * (k-i+1), (2*i-1)*i); // this division is always integer but faster with Div() - result; -]; -HermiteCoeffs(n_IsOdd)_(n>0) <-- -[ - Local(i, k, result); - k := Div(n,2); - result := ZeroVector(n+1); - result[2] := 2*(-2)^k*(n!!); // coefficient at x^1 - For(i:=1,i<=k,i++) // prepare coefficient at x^(2*i+1) now - result[2*i+2] := Div(-2*result[2*i] * (k-i+1), i*(2*i+1)); // this division is always integer but faster with Div() - result; -]; - -////////////////////////////////////////////////// -/// Fast symbolic computation of Laguerre polynomials -////////////////////////////////////////////////// - -/// Return the list of coefficients of Laguerre polynomials. -OrthoPolyCoeffs("Laguerre", n_IsInteger, {_k}) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := (-1)^n/n!; // coefficient at x^n - For(i:=n,i>=1,i--) // prepare coefficient at x^(i-1) now - result[i] := -(result[i+1]*i*(k+i))/(n-i+1); - result; -]; - - -////////////////////////////////////////////////// -/// Fast symbolic computation of Chebyshev polynomials -////////////////////////////////////////////////// - -OrthoPolyCoeffs("Tscheb1", n_IsInteger, {}) <-- ChebTCoeffs(n); -OrthoPolyCoeffs("Tscheb2", n_IsInteger, {}) <-- ChebUCoeffs(n); - -1 # ChebTCoeffs(0) <-- {1}; -2 # ChebTCoeffs(n_IsInteger) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := 2^(n-1); // coefficient at x^n - i := 1; - While(2*i<=n) - [ // prepare coefficient at x^(n-2*i) now - result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+2)*(n-2*i+1)) / ((n-i)*4*i); - i++; - ]; - result; -]; - -1 # ChebUCoeffs(0) <-- {1}; -2 # ChebUCoeffs(n_IsInteger) <-- -[ - Local(i, result); - result := ZeroVector(n+1); - result[n+1] := 2^n; // coefficient at x^n - i := 1; - While(2*i<=n) - [ // prepare coefficient at x^(n-2*i) now - result[n+1-2*i] := -(result[n+3-2*i]*(n-2*i+2)*(n-2*i+1)) / ((n-i+1)*4*i); - i++; - ]; - result; -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/orthopoly.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/orthopoly.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/orthopoly.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/orthopoly.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -OrthoP -OrthoG -OrthoH -OrthoL -OrthoT -OrthoU -OrthoPSum -OrthoGSum -OrthoHSum -OrthoLSum -OrthoTSum -OrthoUSum -EvaluateHornerScheme -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/padic.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/padic.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/padic.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/padic.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,327 +0,0 @@ - -/* - TODO: - - - - - - example: - 20 # f(_x) <-- Sin(x); - 10 # f(Eval(_x)) <-- Sin(Eval(x)); - HoldArgNr("f",1,1); - - Out( 0 ) = True; - In( 1 ) = f(2+3) - Out( 1 ) = Sin(2+3); - In( 2 ) = f(Eval(2+3)) - Out( 2 ) = Sin(5); - - Alternative: - f(x):= - [ - UnHoldable(x); - Sin(x); - ]; - - this is if you don't want to use patterns. - - - Mini-module padic. This module creates a p-adic expansion of - an expression: - - expression = a0 + a1*p + a2 * p^2 + ... etc. - - PAdicExpand and PAdicExpandInternal can be called with integer - or univariate polynomial arguments. - */ - - -Expand(x); /* TODO no idea why this is needed! Mod/Div/UniVariate thing :-( */ - -10 # PAdicExpand(_x,_y) <-- -[ - Local(coefs); - coefs:=PAdicExpandInternal(x,y); - Subst(p,y)Add(coefs*(p^(0 .. Length(coefs)))); -]; - -10 # PAdicExpandInternal(0,_y) <-- {}; -20 # PAdicExpandInternal(_x,_y) <-- -[ - Mod(x,y) : PAdicExpandInternal(Div(x,y),y); -]; - - - - -/* Extended Euclidean algorithm. Algorithm taken from - * "Modern Computer Algebra". It does a Gcd calculation, but - * returns the intermediate results also. - * - * Returns {l,r,s,t} - * where - * - l the number of steps required - * - r[i] the i-th remainder - * - s[i] and t[i] the i-th bezout coefficients of f and g: - s[i]*f + t[i]*g = r[i] . - * The gcd is r[l]. - * - * This is a slightly modified version from the one described in - * "Modern Computer Algebra", where the elements in list r are not - * monic. If needed this can be done afterwards. As a consequence - * this version works on integers as well as on polynomials. - */ - -ExtendedEuclidean(_f,_g) <-- -[ - Local(r,s,t,i); - - /* Initialize the loop */ - r:={f,g}; - s:={1,0}; - t:={0,1}; - i:=1; - - Local(q,newr,news,newt); - newr:=1; - While(newr != 0) - [ - newr:=Rem(r[i],r[i+1]); - q :=Div(r[i],r[i+1]); - news :=(s[i]-q*s[i+1]); - newt :=(t[i]-q*t[i+1]); - DestructiveAppend(r ,newr); - DestructiveAppend(s,news); - DestructiveAppend(t,newt); - i++; - ]; - {r[i],s[i],t[i]}; -]; - -ExtendedEuclideanMonic(_f,_g) <-- -[ - Local(rho,r,s,t,i); - -/* -Echo({f,g}); -Echo({}); -*/ - - /* Initialize the loop */ - rho:={LeadingCoef(f),LeadingCoef(g)}; - r:={Monic(f),Monic(g)}; - s:={1/(rho[1]),0}; - t:={0,1/(rho[2])}; - i:=1; - - Local(q,newr,news,newt,newrho); - newr:=r[2]; - While(newr != 0) - [ - q :=Div(r[i],r[i+1]); - newr:=Mod(r[i],r[i+1]); - newrho:=LeadingCoef(newr); - - - If (newr != 0, newr:=Monic(newr)); - news :=(s[i]-q*s[i+1]); - newt :=(t[i]-q*t[i+1]); - If(newrho != 0, - [ - news:=news/newrho; - newt:=newt/newrho; - ]); - DestructiveAppend(rho,newrho); - DestructiveAppend(r ,newr); - DestructiveAppend(s,news); - DestructiveAppend(t,newt); - i++; - ]; - -/* -TableForm({i,r,s,t}); -Echo({}); -*/ - - {r[i],s[i],t[i]}; -]; - - - - - - - - -/* Chinese Remaindering algorithm, as described in "Modern Computer Algebra". - */ -ChineseRemainderInteger(mlist_IsList,vlist_IsList) <-- -[ - Local(m,i,nr,result,msub,euclid,clist); - clist:={}; - m:=Factorize(mlist); - result:=0; - - nr:=Length(mlist); - For(i:=1,i<=nr,i++) - [ - msub:=Div(m,mlist[i]); - euclid := ExtendedEuclidean(msub,mlist[i]); - Local(c); - c:=vlist[i] * euclid[2]; - c:=Rem(c, mlist[i]); - DestructiveAppend(clist,c); - result:=result + msub * c; - ]; - {result,clist}; -]; -ChineseRemainderPoly(mlist_IsList,vlist_IsList) <-- -[ - Local(m,i,nr,result,msub,euclid,clist); - clist:={}; - m:=Factorize(mlist); - result:=0; - -/* Echo({mlist,m}); */ - - - nr:=Length(mlist); - For(i:=1,i<=nr,i++) - [ - msub:=Div(m,mlist[i]); - -/* Echo({Factor(msub)}); */ - - euclid := ExtendedEuclideanMonic(msub,mlist[i]); - Local(c); - - c:=vlist[i] * euclid[2]; - - c:=Mod(c, mlist[i]); - - DestructiveAppend(clist,c); - result:=result + msub * c; - ]; - {Expand(result),clist}; -]; - -/* Partial fraction expansion of g/f with Degree(g)(values, options'hash) - options'hash is a hash that contains all plotting options: - ["xrange"] - a list of {x1, x2}, ["xname"] - name of the variable to plot, ["yname"] - array of string representations of the function(s), and perhaps other options relevant to the particular backend. - {values} is a list of lists of pairs of the form {{{x1, y1}, {x2, y2}, ...}, {{x1, z1}, {x2, z2}, ...}, ...} corresponding to the functions y(x), z(x), ... to be plotted. The abscissa points x[i] are not the same for all functions. - The backend should prepare the graph of the function(s). The "datafile" backend Plot2D'datafile(values, options'hash) may be used to output all data to file(s), in which case the file name should be given by the value options'hash["filename"]. Multiple files are created with names obtained by appending numbers to the filename. - Note that the "data" backend does not do anything and simply returns the data. - The backend Plot2D'datafile takes care not to write "Infinity" or "Undefined" data points (it just ignores them). Custom backends should either use Plot2D'datafile or take care of this themselves. -*/ - -/// trivial backend: return data list (do not confuse with Plot2D'get'data() defined in the main code which is the middle-level plotting routine) -Plot2D'data(values_IsList, _options'hash) <-- values; - -/// The Java back-end generates a call-list that the Java graph plotter can handle -Plot2D'java(values_IsList, _options'hash) <-- -[ - Local(result,count); - count := 0; - result:="$plot2d:"; - - result := result:" pensize 2.0 "; - ForEach(function,values) - [ - result := result:ColorForGraphNr(count); - count++; - result:=result:" lines2d ":String(Length(function)); - - function:=Select(Lambda({item},item[2] != Undefined),function); - - ForEach(item,function) - [ - result := result:" ":String(item[1]):" ":String(item[2]):" "; - ]; - ]; - WriteString(result:"$"); - True; -]; - -10 # ColorForGraphNr(0) <-- " pencolor 64 64 128 "; -10 # ColorForGraphNr(1) <-- " pencolor 128 64 64 "; -10 # ColorForGraphNr(2) <-- " pencolor 64 128 64 "; -20 # ColorForGraphNr(_count) <-- ColorForGraphNr(Mod(count,3)); - - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/plots.rep/backends_3d.mpi mathpiper-0.81f+dfsg1/storage/scripts/plots.rep/backends_3d.mpi --- mathpiper-0.0.svn2556/storage/scripts/plots.rep/backends_3d.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/plots.rep/backends_3d.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -////////////////////////////////////////////////// -/// Backends for 3D plotting -////////////////////////////////////////////////// - -/// List of all defined backends and their symbolic labels. -/// Add any new backends here -Plot3DS'outputs() := { - {"default", "data"}, - {"data", "Plot3DS'data"}, -}; - -/* - How backends work: - Plot3DS'(values, options'hash) - options'hash is a hash that contains all plotting options: - ["xrange"] - a list of {x1, x2}, ["xname"] - name of the variable to plot, same for "yrange"; - ["zname"] - array of string representations of the function(s), and perhaps other options relevant to the particular backend. - {values} is a list of lists of triples of the form {{{x1, y1, z1}, {x2, y2, z2}, ...}, {{x1, y1, t1}, {x2, y2, t2}, ...}, ...} corresponding to the functions z(x,y), t(x,y), ... to be plotted. The points x[i], y[i] are not necessarily the same for all functions. - The backend should prepare the graph of the function(s). The "datafile" backend Plot3DS'datafile(values, options'hash) may be used to output all data to file(s), in which case the file name should be given by the value options'hash["filename"]. Multiple files are created with names obtained by appending numbers to the filename. - Note that the "data" backend does not do anything and simply returns the data. - The backend Plot3DS'datafile takes care not to write "Infinity" or "Undefined" data points (it just ignores them). Custom backends should either use Plot3DS'datafile to prepare a file, or take care of this themselves. -*/ - -/// trivial backend: return data list (do not confuse with Plot3DS'get'data() defined in the main code which is the middle-level plotting routine) -Plot3DS'data(values_IsList, _options'hash) <-- values; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/plots.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/plots.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/plots.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/plots.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -/// Common functions used by all plotting packages - -/// utility function: convert options lists of the form -/// "{key=value, key=value}" into a hash of the same form. -/// The argument list is kept unevaluated using "HoldArgNr()". -/// Note that symbolic values of type atom are automatically converted to strings, e.g. ListToHash(a=b) returns {{"a", "b"}} -ListToHash(list) := -[ - Local(item, result); - result := {}; - ForEach(item, list) - If( - IsFunction(item) And (Type(item) = "=" Or Type(item) = "==") And IsAtom(item[1]), - result[String(item[1])] := If( - IsAtom(item[2]) And Not IsNumber(item[2]) And Not IsString(item[2]), - String(item[2]), - item[2] - ), - Echo({"ListToHash: Error: item ", item, " is not of the format a=b or a==b"}) - ); - result; -]; - -HoldArgNr("ListToHash", 1, 1); - - -/// utility function: check whether the derivative changes sign in given 3 numbers, return 0 or 1. Also return 1 when one of the arguments is not a number. -sign'change(x,y,z) := -If( - IsNumber(x) And IsNumber(y) And IsNumber(z) - And Not ( - x>y And yz - ) -, 0, 1); - - - -/// service function. WriteDataItem({1,2,3}, {}) will output "1 2 3" on a separate line. -/// Writes data points to the current output stream, omits non-numeric values. -WriteDataItem(tuple_IsList, _options'hash) <-- -[ - Local(item); - If( // do not write anything if one of the items is not a number - IsNumericList(tuple), - ForEach(item,tuple) - [ - Write(item); - Space(); - ] - ); - NewLine(); -]; - - -10 # RemoveRepeated({}) <-- {}; -10 # RemoveRepeated({_x}) <-- {x}; -20 # RemoveRepeated(list_IsList) <-- [ - Local(i, done); - done := False; - For(i:=0, Not done, i++) - [ - While(i on that data. - - Algorithm for Plot2D'get'data: - 1) Split the given interval into Div(points+3, 4) subintervals, and split each subinterval into 4 parts. - 2) For each of the parts: evaluate function values and call Plot2D'adaptive - 3) concatenate resulting lists and return -*/ - - LocalSymbols(var, func, range, option, options'list, delta, options'hash, c, fc, all'values, dummy) -[ - -// declaration of Plot2D with variable number of arguments -Function() Plot2D(func); -Function() Plot2D(func, range); -Function() Plot2D(func, range, options, ...); - -/// interface routines -1 # Plot2D(_func) <-- ("Plot2D" @ {func, -5:5}); -2 # Plot2D(_func, _range) <-- ("Plot2D" @ {func, range, {}}); -3 # Plot2D(_func, _range, option_IsFunction) _ (Type(option) = "=" Or Type(option) = "==") <-- ("Plot2D" @ {func, range, {option}}); - -/// Plot a single function -5 # Plot2D(_func, _range, options'list_IsList)_(Not IsList(func)) <-- ("Plot2D" @ {{func}, range, options'list}); - -/// Top-level 2D plotting routine: -/// plot several functions sharing the same xrange and other options -4 # Plot2D(func'list_IsList, _range, options'list_IsList) <-- -[ - Local(var, func, delta, options'hash, c, fc, all'values, dummy); - all'values := {}; - options'hash := "ListToHash" @ {options'list}; - // this will be a string - name of independent variable - options'hash["xname"] := ""; - // this will be a list of strings - printed forms of functions being plotted - options'hash["yname"] := {}; - // parse range - If ( - Type(range) = "=" Or Type(range) = "==", // variable also specified -- ignore for now, store in options - [ - // store alternative variable name - options'hash["xname"] := String(range[1]); - range := range[2]; - ] - ); - If( - Type(range) = ":", // simple range - range := N(Eval({range[1], range[2]})) - ); - // set default option values - If( - options'hash["points"] = Empty, - options'hash["points"] := 23 - ); - If( - options'hash["depth"] = Empty, - options'hash["depth"] := 5 - ); - If( - options'hash["precision"] = Empty, - options'hash["precision"] := 0.0001 - ); - If( - options'hash["output"] = Empty Or IsString(options'hash["output"]) And Plot2D'outputs()[options'hash["output"]] = Empty, - options'hash["output"] := Plot2D'outputs()["default"] - ); - // a "filename" parameter is required when using data file - If( - options'hash["output"] = "datafile" And options'hash["filename"] = Empty, - options'hash["filename"] := "output.data" - ); - // we will divide each subinterval in 4 parts, so divide number of points by 4 now - options'hash["points"] := N(Eval(Div(options'hash["points"]+3, 4))); - // in case it is not a simple number but an unevaluated expression - options'hash["precision"] := N(Eval(options'hash["precision"])); - // store range in options - options'hash["xrange"] := {range[1], range[2]}; - // compute the separation between grid points - delta := N(Eval( (range[2] - range[1]) / (options'hash["points"]) )); - // check that the input parameters are valid (all numbers) - Check(IsNumber(range[1]) And IsNumber(range[2]) And IsNumber(options'hash["points"]) And IsNumber(options'hash["precision"]), - "Plot2D: Error: plotting range '" - :(ToString()Write(range)) - :"' and/or the number of points '" - :(ToString()Write(options'hash["points"])) - :"' and/or precision '" - :(ToString()Write(options'hash["precision"])) - :"' is not numeric" - ); - // loop over functions in the list - ForEach(func, func'list) - [ - // obtain name of variable - var := VarList(func); // variable name in a one-element list - Check(Length(var)<=1, - "Plot2D: Error: expression is not a function of one variable: " - :(ToString()Write(func)) - ); - // Allow plotting of constant functions - If(Length(var)=0, var:={dummy}); - // store variable name if not already done so - If( - options'hash["xname"] = "", - options'hash["xname"] := String(VarList(var)[1]) - ); - // store function name in options - DestructiveAppend(options'hash["yname"], ToString()Write(func)); - // compute the first point to see if it's okay - c := range[1]; - fc := N(Eval(Apply({var, func}, {c}))); - Check(IsNumber(fc) Or fc=Infinity Or fc= -Infinity Or fc=Undefined, - "Plot2D: Error: cannot evaluate function '" - :(ToString()Write(func)) - :"' at point '" - :(ToString()Write(c)) - :"' to a number, instead got '" - :(ToString()Write(fc)) - :"'" - ); - // compute all other data points - DestructiveAppend(all'values, Plot2D'get'data(func, var, c, fc, delta, options'hash)); - If(InVerboseMode(), Echo({"Plot2D: using ", Length(all'values[Length(all'values)]), " points for function ", func}), True); - ]; - // call the specified output backend - Plot2D'outputs()[options'hash["output"]] @ {all'values, options'hash}; -]; - -//HoldArg("Plot2D", range); -//HoldArg("Plot2D", options); -HoldArgNr("Plot2D", 2, 2); -HoldArgNr("Plot2D", 3, 2); -HoldArgNr("Plot2D", 3, 3); - -/// this is the middle-level plotting routine; it generates the initial -/// grid, calls the adaptive routine, and gathers data points. -/// func must be just one function (not a list) -Plot2D'get'data(_func, _var, _x'init, _y'init, _delta'x, _options'hash) <-- -[ - Local(i, a, fa, b, fb, c, fc, result); - // initialize list by first points (later will always use Tail() to exclude first points of subintervals) - result := { {c,fc} := {x'init, y'init} }; - For(i:=0, i on that data. - - Algorithm for Plot3DS'get'data: - 1) Split the given square into Div(Sqrt(points)+1, 2) subsquares, and split each subsquare into 4 parts. - 2) For each of the parts: evaluate function values and call Plot3DS'adaptive - 3) concatenate resulting lists and return -*/ - - LocalSymbols(var, func, xrange, yrange, option, options'list, xdelta, ydelta, options'hash, cx, cy, fc, all'values, dummy) -[ - -// declaration of Plot3DS with variable number of arguments -Function() Plot3DS(func); -Function() Plot3DS(func, xrange, yrange); -Function() Plot3DS(func, xrange, yrange, options, ...); - - -/// interface routines -1 # Plot3DS(_func) <-- ("Plot3DS" @ {func, -5:5, -5:5}); -2 # Plot3DS(_func, _xrange, _yrange) <-- ("Plot3DS" @ {func, xrange, yrange, {}}); -3 # Plot3DS(_func, _xrange, _yrange, option_IsFunction) _ (Type(option) = "=" Or Type(option) = "==") <-- ("Plot3DS" @ {func, xrange, yrange, {option}}); - -/// Plot a single function -5 # Plot3DS(_func, _xrange, _yrange, options'list_IsList)_(Not IsList(func)) <-- ("Plot3DS" @ {{func}, xrange, yrange, options'list}); - -/// Top-level 3D plotting routine: -/// plot several functions sharing the same ranges and other options -4 # Plot3DS(func'list_IsList, _xrange, _yrange, options'list_IsList) <-- -[ - Local(var, func, xdelta, ydelta, options'hash, cx, cy, fc, all'values, dummy); - // this will be a list of all computed values - all'values := {}; - options'hash := "ListToHash" @ {options'list}; - // this will be a string - name of independent variable - options'hash["xname"] := ""; - options'hash["yname"] := ""; - // this will be a list of strings - printed forms of functions being plotted - options'hash["zname"] := {}; - // parse range - If ( - Type(xrange) = "=" Or Type(xrange) = "==", // variable also specified -- ignore for now, store in options - [ - // store alternative variable name - options'hash["xname"] := String(xrange[1]); - xrange := xrange[2]; - ] - ); - If ( - Type(yrange) = "=" Or Type(yrange) = "==", // variable also specified -- ignore for now, store in options - [ - // store alternative variable name - options'hash["yname"] := String(yrange[1]); - yrange := yrange[2]; - ] - ); - If( - Type(xrange) = ":", // simple range - xrange := N(Eval({xrange[1], xrange[2]})) - ); - If( - Type(yrange) = ":", // simple range - yrange := N(Eval({yrange[1], yrange[2]})) - ); - // set default option values - If( - options'hash["points"] = Empty, - options'hash["points"] := 10 // default # of points along each axis - ); - If( - options'hash["xpoints"] = Empty, - options'hash["xpoints"] := options'hash["points"] - ); - If( - options'hash["ypoints"] = Empty, - options'hash["ypoints"] := options'hash["points"] - ); - - If( - options'hash["depth"] = Empty, - options'hash["depth"] := 2 - ); - If( - options'hash["precision"] = Empty, - options'hash["precision"] := 0.0001 - ); - If( - options'hash["hidden"] = Empty Or Not IsBoolean(options'hash["hidden"]), - options'hash["hidden"] := True - ); - If( - options'hash["output"] = Empty Or IsString(options'hash["output"]) And Plot3DS'outputs()[options'hash["output"]] = Empty, - options'hash["output"] := Plot3DS'outputs()["default"] - ); - // a "filename" parameter is required when using data file - If( - options'hash["output"] = "datafile" And options'hash["filename"] = Empty, - options'hash["filename"] := "output.data" - ); - options'hash["used depth"] := options'hash["depth"]; - // we will divide each subsquare in 4 parts, so divide number of points by 2 now - options'hash["xpoints"] := N(Eval(Div(options'hash["xpoints"]+1, 2))); - options'hash["ypoints"] := N(Eval(Div(options'hash["ypoints"]+1, 2))); - // in case it is not a simple number but an unevaluated expression - options'hash["precision"] := N(Eval(options'hash["precision"])); - // store range in options - options'hash["xrange"] := {xrange[1], xrange[2]}; - options'hash["yrange"] := {yrange[1], yrange[2]}; - // compute the separation between grid points - xdelta := N(Eval( (xrange[2] - xrange[1]) / (options'hash["xpoints"]) ) ); - ydelta := N(Eval( (yrange[2] - yrange[1]) / (options'hash["ypoints"]) ) ); - // check that the input parameters are valid (all numbers) - Check(IsNumericList({xrange[1], xrange[2], options'hash["xpoints"], options'hash["ypoints"], options'hash["precision"]}), - "Plot3DS: Error: plotting ranges '" - :(ToString()Write(xrange, yrange)) - :"' and/or the number of points '" - :(ToString()Write(options'hash["xpoints"], options'hash["ypoints"])) - :"' and/or precision '" - :(ToString()Write(options'hash["precision"])) - :"' is not numeric" - ); - // loop over functions in the list - ForEach(func, func'list) - [ - // obtain name of variable - var := VarList(func); // variable names in a list - Check(Length(var)<=2, - "Plot3DS: Error: expression is not a function of at most two variables: " - :(ToString()Write(func)) - ); - // Allow plotting of constant functions - If(Length(var)=0, var:={dummy, dummy}); - If(Length(var)=1, var:={var[1], dummy}); - // store variable name if not already done so - If( - options'hash["xname"] = "", - options'hash["xname"] := String(var[1]) - ); - If( - options'hash["yname"] = "", - options'hash["yname"] := String(var[2]) - ); - // store function name in options - DestructiveAppend(options'hash["zname"], ToString()Write(func)); - // compute the first point to see if it's okay - cx := xrange[1]; cy := yrange[1]; - fc := N(Eval(Apply({var, func}, {cx, cy}))); - Check(IsNumber(fc) Or fc=Infinity Or fc= -Infinity Or fc=Undefined, - "Plot3DS: Error: cannot evaluate function '" - :(ToString()Write(func)) - :"' at point '" - :(ToString()Write(cx, cy)) - :"' to a number, instead got '" - :(ToString()Write(fc)) - :"'" - ); - // compute all other data points - DestructiveAppend(all'values, RemoveRepeated(HeapSort( Plot3DS'get'data(func, var, {cx, cy, fc}, {xdelta, ydelta}, options'hash), Hold({{x,y},x[1]0, -[ - Local(n); - n:=Length(x); - If(Length(Select(IsVector,x))=n, - MapSingle(Length,x)=Length(x[1])+ZeroVector(n), - False); -], -False); - -// test for a matrix w/ element test p (dr) -Function("IsMatrix",{p,x}) -If(IsMatrix(x), -[ - Local(i,j,m,n,result); - m:=Length(x); - n:=Length(x[1]); - i:=1; - result:=True; - While(i<=m And result) - [ - j:=1; - While(j<=n And result) - [ - result:=Apply(p,{x[i][j]}); - j++; - ]; - i++; - ]; - result; -], -False); - -/* remove? (dr) -IsSquareMatrix(_x) <-- -[ - Local(d); - d:=Dimensions(x); - Length(d)=2 And d[1]=d[2]; -]; -*/ - -// test for a square matrix (dr) -Function("IsSquareMatrix",{x}) IsMatrix(x) And Length(x)=Length(x[1]); -// test for a square matrix w/ element test p (dr) -Function("IsSquareMatrix",{p,x}) IsMatrix(p,x) And Length(x)=Length(x[1]); - -]; // LocalSymbols(p,x) - -/* changed definition of IsRational, Nobbi 030529 -Function("IsRational",{aLeft}) Type(aLeft) = "/"; - -Function("IsRationalNumeric",{aLeft}) - Type(aLeft) = "/" And - IsNumber(aLeft[1]) And - IsNumber(aLeft[2]); - -IsRationalOrNumber(_x) <-- (IsNumber(x) Or IsRationalNumeric(x)); - -10 # IsRationalOrInteger(x_IsInteger) <-- True; -10 # IsRationalOrInteger(x_IsInteger / y_IsInteger) <-- True; -20 # IsRationalOrInteger(_x) <-- False; - -*/ - -10 # IsRational(x_IsInteger) <-- True; -10 # IsRational(x_IsInteger / y_IsInteger) <-- True; -10 # IsRational(-(x_IsInteger / y_IsInteger)) <-- True; -60000 # IsRational(_x) <-- False; - -10 # IsRationalOrNumber(x_IsNumber) <-- True; -10 # IsRationalOrNumber(x_IsNumber / y_IsNumber) <-- True; -10 # IsRationalOrNumber(-(x_IsNumber / y_IsNumber)) <-- True; -60000 # IsRationalOrNumber(_x) <-- False; - - -IsNegativeNumber(x):= IsNumber(x) And x < 0; -IsNonNegativeNumber(x):= IsNumber(x) And x >= 0; -IsPositiveNumber(x):= IsNumber(x) And x > 0; - -IsNegativeInteger(x):= IsInteger(x) And x < 0; -IsNonNegativeInteger(x):= IsInteger(x) And x >= 0; -IsPositiveInteger(x):= IsInteger(x) And x > 0; - - -/* -10 # IsZero(x_IsNumber) <-- (DivideN( Round( MultiplyN(x, 10^BuiltinPrecisionGet()) ), 10^BuiltinPrecisionGet() ) = 0); -10 # IsNotZero(x_IsNumber) <-- ( RoundTo(x,BuiltinPrecisionGet()) != 0); -*/ -// these should be calls to MathSign() and the math library should do this. Or it should be just MathEquals(x,0). -// for now, avoid underflow and avoid IsZero(10^(-BuiltinPrecisionGet())) returning True. -10 # IsZero(x_IsNumber) <-- ( MathSign(x) = 0 Or AbsN(x) < PowerN(10, -BuiltinPrecisionGet())); -60000 # IsZero(_x) <-- False; - -10 # IsNotZero(x_IsNumber) <-- ( AbsN(x) >= PowerN(10, -BuiltinPrecisionGet())); -10 # IsNotZero(x_IsInfinity) <-- True; -60000 # IsNotZero(_x) <-- False; - -IsNonZeroInteger(x) := (IsInteger(x) And x != 0); - -// why do we need this? Why doesn't x=1 not work? -10 # IsOne(x_IsNumber) <-- IsZero(SubtractN(x,1)); -60000 # IsOne(_x) <-- False; - -IsEven(n) := IsInteger(n) And ( BitAnd(n,1) = 0 ); -IsOdd(n) := IsInteger(n) And ( BitAnd(n,1) = 1 ); - -IsEvenFunction(f,x):= (f = Eval(Subst(x,-x)f)); -IsOddFunction(f,x):= (f = Eval(-Subst(x,-x)f)); - - -10 # IsInfinity(Infinity) <-- True; -10 # IsInfinity(-(_x)) <-- IsInfinity(x); - -// This is just one example, we probably need to extend this further to include all -// cases for f*Infinity where f can be guaranteed to not be zero -11 # IsInfinity(Sign(_x)*y_IsInfinity) <-- True; - -60000 # IsInfinity(_x) <-- False; - -IsConstant(_n) <-- (VarList(n) = {}); - -Function ("IsBoolean", {x}) - (x=True) Or (x=False) Or IsFunction(x) And Contains({"=", ">", "<", ">=", "<=", "!=", "And", "Not", "Or"}, Type(x)); - -0 # IsBoolType(True) <-- True; -0 # IsBoolType(False) <-- True; -1 # IsBoolType(_anythingelse) <-- False; - -/* See if a number, when evaluated, would be a positive/negative real value */ -IsPositiveReal(_r) <-- -[ - r:=N(Eval(r)); - (IsNumber(r) And r >= 0); -]; -IsNegativeReal(_r) <-- -[ - r:=N(Eval(r)); - (IsNumber(r) And r <= 0); -]; - - -/* Predicates on matrices */ -IsDiagonal(A_IsMatrix) <-- -[ - Local(i,j,m,n,result); - m:=Length(A); - n:=Length(A[1]); - i:=2; - result:=(m=n); - While(i<=m And result) - [ - j:=1; - While(j<=n And result) - [ - result:= (i=j Or A[i][j] = 0); - j++; - ]; - i++; - ]; - result; -]; -IsUpperTriangular(A_IsMatrix) <-- -[ - Local(i,j,m,n,result); - m:=Length(A); - n:=Length(A[1]); - i:=2; - result:=(m=n); - While(i<=m And result) - [ - j:=1; - While(j<=n And result) - [ - result:= (i<=j Or A[i][j] = 0); - j++; - ]; - i++; - ]; - result; -]; -IsLowerTriangular(A_IsMatrix) <-- (IsUpperTriangular(Transpose(A))); -IsSkewSymmetric(A_IsMatrix) <-- (Transpose(A)=(-1*A)); -IsHermitian(A_IsMatrix) <-- (Conjugate(Transpose(A))=A); -IsSymmetric(A_IsMatrix) <-- (Transpose(A)=A); -IsOrthogonal(A_IsMatrix) <-- (Transpose(A)*A=Identity(Length(A))); -IsIdempotent(A_IsMatrix) <-- (A^2 = A); -IsUnitary(A_IsMatrix) <-- (Transpose(Conjugate(A))*A = Identity(Length(A))); - -IsVariable(_expr) <-- (IsAtom(expr) And Not(expr=Infinity) And Not(expr= -Infinity) And Not(expr=Undefined) And Not(IsNumber(N(Eval(expr))))); - -// check that all items in the list are numbers -IsNumericList(_arg'list) <-- IsList(arg'list) And - ("And" @ (MapSingle(Hold({{x},IsNumber(N(Eval(x)))}), arg'list))); - -////////////////////////////////////////////////// -/// Predicates HasExpr*, HasFunc*, ListHasFunc -////////////////////////////////////////////////// - -/// HasExpr --- test for an expression containing a subexpression -/// for checking dependence on variables, this may be faster than using VarList or IsFreeOf and this also can be used on non-variables, e.g. strings or numbers or other atoms or even on non-atoms -// an expression contains itself -- check early -10 # HasExpr(_expr, _atom) _ Equals(expr, atom) <-- True; -// an atom contains itself -15 # HasExpr(expr_IsAtom, _atom) <-- Equals(expr, atom); -// a list contains an atom if one element contains it -// we test for lists now because lists are also functions -// first take care of the empty list: -19 # HasExpr({}, _atom) <-- False; -20 # HasExpr(expr_IsList, _atom) <-- HasExpr(Head(expr), atom) Or HasExpr(Tail(expr), atom); -// a function contains an atom if one of its arguments contains it -30 # HasExpr(expr_IsFunction, _atom) <-- HasExpr(Tail(Listify(expr)), atom); - -/// Same except only look at function arguments for functions in a given list -HasExprSome(_expr, _atom, _look'list) _ Equals(expr, atom) <-- True; -// an atom contains itself -15 # HasExprSome(expr_IsAtom, _atom, _look'list) <-- Equals(expr, atom); -// a list contains an atom if one element contains it -// we test for lists now because lists are also functions -// first take care of the empty list: -19 # HasExprSome({}, _atom, _look'list) <-- False; -20 # HasExprSome(expr_IsList, _atom, _look'list) <-- HasExprSome(Head(expr), atom, look'list) Or HasExprSome(Tail(expr), atom, look'list); -// a function contains an atom if one of its arguments contains it -// first deal with functions that do not belong to the list: return False since we have already checked it at #15 -25 # HasExprSome(expr_IsFunction, _atom, _look'list)_(Not Contains(look'list, Atom(Type(expr)))) <-- False; -// a function contains an atom if one of its arguments contains it -30 # HasExprSome(expr_IsFunction, _atom, _look'list) <-- HasExprSome(Tail(Listify(expr)), atom, look'list); - -/// HasFunc --- test for an expression containing a function -/// function name given as string. -10 # HasFunc(_expr, string_IsString) <-- HasFunc(expr, Atom(string)); -/// function given as atom. -// atom contains no functions -10 # HasFunc(expr_IsAtom, atom_IsAtom) <-- False; -// a list contains the function List so we test it together with functions -// a function contains itself, or maybe an argument contains it -20 # HasFunc(expr_IsFunction, atom_IsAtom) <-- Equals(Head(Listify(expr)), atom) Or ListHasFunc(Tail(Listify(expr)), atom); - -/// function name given as string. -10 # HasFuncSome(_expr, string_IsString, _look'list) <-- HasFuncSome(expr, Atom(string), look'list); -/// function given as atom. -// atom contains no functions -10 # HasFuncSome(expr_IsAtom, atom_IsAtom, _look'list) <-- False; -// a list contains the function List so we test it together with functions -// a function contains itself, or maybe an argument contains it - -// first deal with functions that do not belong to the list: return top level function -15 # HasFuncSome(expr_IsFunction, atom_IsAtom, _look'list)_(Not Contains(look'list, Atom(Type(expr)))) <-- Equals(Head(Listify(expr)), atom); -// function belongs to the list - check its arguments -20 # HasFuncSome(expr_IsFunction, atom_IsAtom, _look'list) <-- Equals(Head(Listify(expr)), atom) Or ListHasFuncSome(Tail(Listify(expr)), atom, look'list); - -/// ListHasFunc --- test for one of the elements of a list to contain a function -/// this is mainly useful to test whether a list has nested lists, i.e. ListHasFunc({1,2,3}, List)=False and ListHasFunc({1,2,{3}}, List)=True. -// need to exclude the List atom itself, so don't use Listify -19 # ListHasFunc({}, _atom) <-- False; -20 # ListHasFunc(expr_IsList, atom_IsAtom) <-- HasFunc(Head(expr), atom) Or ListHasFunc(Tail(expr), atom); - -19 # ListHasFuncSome({}, _atom, _look'list) <-- False; -20 # ListHasFuncSome(expr_IsList, atom_IsAtom, _look'list) <-- HasFuncSome(Head(expr), atom, look'list) Or ListHasFuncSome(Tail(expr), atom, look'list); - -/// Analyse arithmetic expressions - -HasExprArith(expr, atom) := HasExprSome(expr, atom, {Atom("+"), Atom("-"), *, /}); -HasFuncArith(expr, atom) := HasFuncSome(expr, atom, {Atom("+"), Atom("-"), *, /}); - - -/// TODO FIXME document this: FloatIsInt returns True if the argument is integer after removing potential trailing -/// zeroes after the decimal point -// but in fact this should be a call to BigNumber::IsIntValue() -FloatIsInt(_x) <-- - [ - x:=N(Eval(x)); - Local(prec,result,n); - Set(prec,BuiltinPrecisionGet()); - If(IsZero(x),Set(n,2), - If(x>0, - Set(n,2+FloorN(N(FastLog(x)/FastLog(10)))), - Set(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) - )); - BuiltinPrecisionSet(n+prec); - Set(result,IsZero(RoundTo(x-Floor(x),prec)) Or IsZero(RoundTo(x-Ceil(x),prec))); - BuiltinPrecisionSet(prec); - result; - ]; -// diff -Nru mathpiper-0.0.svn2556/storage/scripts/predicates.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/predicates.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/predicates.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/predicates.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -IsScalar -IsMatrix -IsVector -IsSquareMatrix -IsRational -IsRationalOrNumber -IsPositiveNumber -IsNegativeNumber -IsNonNegativeNumber -IsZero -IsNotZero -IsNonZeroInteger -IsPositiveInteger -IsNegativeInteger -IsNonNegativeInteger -IsEven -IsOdd -IsEvenFunction -IsOddFunction -IsInfinity -IsConstant -IsBoolean -IsBoolType -IsPositiveReal -IsNegativeReal -IsHermitian -IsSymmetric -IsSkewSymmetric -IsIdempotent -IsOrthogonal -IsUnitary -IsVariable -IsDiagonal -IsUpperTriangular -IsLowerTriangular -IsNumericList -HasExpr -HasFunc -HasExprSome -HasFuncSome -ListHasFunc -HasExprArith -HasFuncArith -FloatIsInt -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/probability.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/probability.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/probability.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/probability.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -/* Evaluates distribution dst at point x - known distributions are: - 1. Discrete distributions - -- BernoulliDistribution(p) - -- BinomialDistribution(p,n) - -- DiscreteUniformDistribution(a,b) - -- PoissonDistribution(l) - 2. Continuous distributions - -- ExponentialDistribution(l) - -- NormalDistrobution(a,s) - -- ContinuousUniformDistribution(a,b) - -- tDistribution(m) - -- GammaDistribution(m) - -- ChiSquareDistribution(m) - - DiscreteDistribution(domain,probabilities) represent arbitrary - distribution with finite number of possible values; domain list - contains possible values such that - Pr(X=domain[i])=probabilities[i]. - TODO: Should domain contain numbers only? -*/ - - -10 # PDF(BernoulliDistribution(_p),0) <-- p; -10 # PDF(BernoulliDistribution(_p),1) <-- 1-p; -10 # PDF(BernoulliDistribution(_p),x_IsNumber)_(x != 0 And x != 1) <-- 0; -10 # PDF(BernoulliDistribution(_p),_x) <-- Hold(If(x=0,p,If(x=1,1-p,0))); - -10 # PDF(BinomialDistribution(_p,_n),_k) <-- Bin(n,k)*p^k*(1-p)^(n-k); - -10 # PDF(DiscreteUniformDistribution(_a,_b), x_IsNumber) <-- If(xb, 0 ,1/(b-a+1)); -11 # PDF(DiscreteUniformDistribution(_a,_b), _x) <-- Hold(If(xb, 0 ,1/(b-a+1))); - -10 # PDF( PoissonDistribution(_l), n_IsNumber) <-- If(n<0,0,Exp(-l)*l^n/n!); -11 # PDF(PoissonDistribution(_l),_n) <-- Exp(-l)*l^n/n!; - -10 # PDF(GeometricDistribution(_p),_n) <--If(n<0,0,p*(1-p)^n); - -10 # PDF(ExponentialDistribution(_l), _x) <-- If(x<0,0,l*Exp(-l*x)); - -10 # PDF(NormalDistribution(_a,_s),_x) <-- Exp(-(x-a)^2/(2*s))/Sqrt(2*Pi*s); - -10 # PDF(ContinuousUniformDistribution(_a,_b),x)_(ab,0,1/(b-a)); - -10 # PDF( DiscreteDistribution( dom_IsList, prob_IsList), _x)_( Length(dom)=Length(prob) And Simplify(Add(prob))=1) <-- - [ - Local(i); - i:=Find(dom,x); - If(i = -1,0,prob[i]); - ]; -10 # PDF( ChiSquareDistribution( _m),x_IsRationalOrNumber)_(x<=0) <-- 0; -20 # PDF( ChiSquareDistribution( _m),_x) <-- x^(m/2-1)*Exp(-x/2)/2^(m/2)/Gamma(m/2); - -10 # PDF(tDistribution(_m),x) <-- Gamma((m+1)/2)*(1+x^2/m)^(-(m+1)/2)/Gamma(m/2)/Sqrt(Pi*m); - -/* Evaluates Cumulative probability function CDF(x)=Pr(X0 And x<=1, p,1)); -11 # CDF(BernoulliDistribution(_p), _x) <-- Hold(If(x<=0,0,If(x>0 And x<=1, p,1))); - -10 # CDF(BinomialDistribution(_p,_n),m_IsNumber)_(m<=0) <-- 0; -10 # CDF(BinomialDistribution(_p,n_IsInteger),m_IsNumber)_(m>n) <-- 1; -10 # CDF(BinomialDistribution(_p,_n),_m) <-- Sum @ { i, 0, m-1, PDF(BinomialDistribution(p,n),i)}; - -10 # CDF(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(x<=a) <-- 0; -10 # CDF(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(x>b) <-- 1; -10 # CDF(DiscreteUniformDistribution( a_IsNumber, b_IsNumber), x_IsNumber)_(a Pslq({2*Pi-4*Exp(1),Pi,Exp(1)},20) - Out> {1,-2,4}; - -*/ - -Pslq(x, precision) := -[ - Local (ndigits, gam, A, B, H, n, i, j, k, s, y, tmp, t, m, maxi, gami, - t0, t1, t2, t3, t4, mini, Confidence, norme,result); - n:=Length(x); - ndigits:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(precision+10); // 10 is chosen arbitrarily, but should always be enough. Perhaps we can optimize by lowering this number - Confidence:=10^(-FloorN(N(Eval(precision/3)))); -//Echo("Confidence is ",Confidence); - - gam:=N(Sqrt(4/3)); - For (i:=1, i<=n,i++) x[i]:=N(Eval(x[i])); - -//Echo("1..."); - - A:=Identity(n); /*A and B are of Integer type*/ - B:=Identity(n); /*but this doesn't speed up*/ - s:=ZeroVector(n); - y:=ZeroVector(n); - -//Echo("2..."); - - For(k:=1,k<=n,k++) - [ - tmp:=0; - For (j:=k,j<=n,j++) tmp:=tmp + N(x[j]^2); -//tmp:=DivideN(tmp,1.0); -//Echo("tmp is ",tmp); -//MathDebugInfo(tmp); -/*If(Not IsPositiveNumber(tmp), - Echo("******** not a positive number: ",tmp) -); -If(Not IsNumber(tmp), - Echo("******** not a number: ",tmp) -); -If(LessThan(tmp,0), -[ - Echo("******** not positive: ",tmp); -] -);*/ - - s[k]:=SqrtN(tmp); - - -/*If(Not IsNumber(tmp), -[ -Echo("************** tmp = ",tmp); -]); -If(Not IsNumber(s[k]), -[ -Echo("************** s[k] = ",s[k]); -]);*/ - - ]; - -//Echo("3..."); - - tmp:=N(Eval(s[1])); -/*If(Not IsNumber(tmp), -[ -Echo("************** tmp = ",tmp); -]);*/ - - For (k:= 1,k<= n,k++) - [ - y[k]:=N(Eval(x[k]/tmp)); - s[k]:=N(Eval(s[k]/tmp)); - -//Echo("1..."," ",y[k]," ",s[k]); -/*If(Not IsNumber(y[k]), -[ -Echo("************** y[k] = ",y[k]); -]); -If(Not IsNumber(s[k]), -[ -Echo("************** s[k] = ",s[k]); -]);*/ - - ]; - H:=ZeroMatrix(n, n-1); - -//Echo("4...",n); - For (i:=1,i<= n,i++) - [ - - if (i <= n-1) [ H[i][i]:=N(s[i + 1]/s[i]); ]; - -//Echo("4.1..."); - For (j:= 1,j<=i-1,j++) - [ -//Echo("4.2..."); - H[i][j]:= N(-(y[i]*y[j])/(s[j]*s[j + 1])); -//Echo("4.3..."); - -/*If(Not IsNumber(H[i][j]), -[ -Echo("************** H[i][j] = ",H[i][j]); -] -);*/ - - ]; - ]; - -//Echo("5..."); - - For (i:=2,i<=n,i++) - [ - For (j:=i-1,j>= 1,j--) - [ -//Echo("5.1..."); - t:=Round(H[i][j]/H[j][j]); -//Echo("5.2..."); - y[j]:=y[j] + t*y[i]; -//Echo("2..."," ",y[j]); - For (k:=1,k<=j,k++) [ H[i][k]:=H[i][k]-t*H[j][k]; ]; - For (k:=1,k<=n,k++) - [ - A[i][k]:=A[i][k]-t*A[j][k]; - B[k][j]:=B[k][j] + t*B[k][i]; - ]; - ]; - ]; - Local(found); - found:=False; - -//Echo("Enter loop"); - - While (Not(found)) - [ - m:=1; -//Echo("maxi 1...",maxi); - maxi:=N(gam*Abs(H[1][1])); -//Echo("maxi 2...",maxi); - gami:=gam; -//Echo("3..."); - For (i:= 2,i<= n-1,i++) - [ - gami:=gami*gam; - tmp:=N(gami*Abs(H[i][i])); - if (maxi < tmp) - [ - maxi:=tmp; -//Echo("maxi 3...",maxi); - m:=i; - ]; - ]; -//Echo("4...",maxi); - tmp:=y[m + 1]; - y[m + 1]:=y[m]; - y[m]:=tmp; -//Echo("3..."," ",y[m]); -//Echo("5..."); - For (i:= 1,i<=n,i++) - [ - tmp:=A[m + 1][ i]; - A[m + 1][ i]:=A[m][ i]; - A[m][ i]:=tmp; - tmp:=B[i][ m + 1]; - B[i][ m + 1]:=B[i][ m]; - B[i][ m]:=tmp; - ]; - For (i:=1,i<=n-1,i++) - [ - tmp:=H[m + 1][ i]; - - H[m + 1][ i]:=H[m][ i]; - H[m][ i]:=tmp; - ]; -//Echo("7..."); - if (m < n-1) - [ - t0:=N(Eval(Sqrt(H[m][ m]^2 + H[m][ m + 1]^2))); - - t1:=H[m][ m]/t0; - t2:=H[m][ m + 1]/t0; - -// If(IsZero(t0),t0:=N(Confidence)); -//Echo(""); -//Echo("H[m][ m] = ",N(H[m][ m])); -//Echo("H[m][ m+1] = ",N(H[m][ m+1])); - -//If(IsZero(t0),[t1:=Infinity;t2:=Infinity;]); -//Echo("t0=",N(t0)); -//Echo("t1=",N(t1)); -//Echo("t2=",N(t2)); - - For (i:=m,i<=n,i++) - [ - t3:=H[i][ m]; - t4:=H[i][ m + 1]; -//Echo(" t1 = ",t1); -//Echo(" t2 = ",t2); -//Echo(" t3 = ",t3); -//Echo(" t4 = ",t4); - H[i][ m]:=t1*t3 + t2*t4; -//Echo("7.1... ",H[i][ m]); - H[i][ m + 1]:= -t2*t3 + t1*t4; -//Echo("7.2... ",H[i][ m+1]); - ]; - ]; -//Echo("8..."); - For (i:= 1,i<= n,i++) - [ - For (j := Min(i-1, m + 1),j>= 1,j--) - [ - t:=Round(H[i][ j]/H[j][ j]); -//Echo("MATRIX",H[i][ j]," ",H[j][ j]); -//Echo("5... before"," ",y[j]," ",t," ",y[i]); - y[j]:=y[j] + t*y[i]; -//Echo("5... after"," ",y[j]); - For (k:=1,k<=j,k++) H[i][ k]:=H[i][ k]-t*H[j][ k]; - For (k:= 1,k<=n,k++) - [ - A[i][ k]:=A[i][ k]-t*A[j][ k]; - B[k][ j]:=B[k][ j] + t*B[k][ i]; - ]; - ]; - ]; -//Echo("9...",N(H[1],10)); - - /* BuiltinPrecisionSet(10);*/ /*low precision*/ -// maxi := N(H[1] . H[1],10); - maxi := N(H[1] . H[1]); -//Echo("H[1] = ",H[1]); -//Echo("N(H[1]) = ",N(H[1])); -//Echo("N(H[1] . H[1]) = ",N(H[1] . H[1])); -//Echo("maxi 4...",maxi); - -//Echo("9... maxi = ",maxi); - - For (j:=2,j<=n,j++) - [ -//Echo("9.1..."); - tmp:=N(H[j] . H[j],10); -//Echo("9.2..."); - if (maxi < tmp) [ maxi:=tmp; ]; -//Echo("maxi 5...",maxi); -//Echo("9.3..."); - ]; -//Echo("10..."); - norme:=N(Eval(1/Sqrt(maxi))); - m:=1; - mini:=N(Eval(Abs(y[1]))); -//Echo("y[1] = ",y[1]," mini = ",mini); - maxi:=mini; - -//Echo("maxi 6...",maxi); -//Echo("11..."); - For (j:=2,j<=n,j++) - [ - tmp:=N(Eval(Abs(y[j]))); - if (tmp < mini) - [ - mini:=tmp; - m:=j; - ]; - if (tmp > maxi) [ maxi:=tmp; ]; -//Echo("maxi 7...",maxi); - ]; - /* following line may be commented */ -//Echo({"Norm bound:",norme," Min=",mini," Conf=",mini/maxi," required ",Confidence}); - if ((mini/maxi) < Confidence) /*prefered to : if mini < 10^(- precision) then*/ - [ - /* following line may be commented */ -/* Echo({"Found with Confidence ",mini/maxi}); */ - BuiltinPrecisionSet(ndigits); - result:=Transpose(B)[m]; - found:=True; - ] - else - [ - maxi:=Abs(A[1][ 1]); - For (i:=1,i<=n,i++) - [ -//Echo("i = ",i," n = ",n); - For (j:=1,j<=n,j++) - [ -//Echo("j = ",j," n = ",n); - tmp:=Abs(A[i][ j]); - if (maxi < tmp) [ maxi:=tmp;]; - ]; - ]; -//Echo("maxi = ",maxi); - if (maxi > 10^(precision)) - [ - BuiltinPrecisionSet(ndigits); - result:=Fail; - found:=True; - ]; - BuiltinPrecisionSet(precision+2); -//Echo("CLOSE"); - ]; - ]; - result; -]; - -/* end of file */ - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/pslq.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/pslq.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/pslq.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/pslq.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -Pslq -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/rabinmiller.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/rabinmiller.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/rabinmiller.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/rabinmiller.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,175 +0,0 @@ -/* - * File `rabinmiller.mpi' is an implementation of the - * Rabin-Miller primality test. - */ - - -/* - * FastModularPower(a, b, n) computes a^b (mod n) efficiently. - * This function is called by IsStronglyProbablyPrime. - */ - -FastModularPower(a_IsPositiveInteger, b_IsPositiveInteger, n_IsPositiveInteger) <-- -[ - Local(p, j, r); - p := a; - j := b; - r := 1; - - While (j > 0) - [ - If (IsOdd(j), r := ModN(r*p, n)); - p := ModN(p*p, n); - j := ShiftRight(j, 1); - ]; - r; -]; - - -/* - * An integer n is `strongly-probably-prime' for base b if - * - * b^q = 1 (mod n) or - * b^(q*2^i) = -1 (mod n) for some i such that 0 <= i < r - * - * where q and r are such that n-1 = q*2^r and q is odd. - * - * If an integer is not strongly-probably-prime for a given - * base b, then it is composed. The reciprocal is false. - * Composed strongly-probably-prime numbers for base b - * are called `strong pseudoprimes' for base b. - */ -// this will return a pair {root, True/False} -IsStronglyProbablyPrime(b_IsPositiveInteger, n_IsPositiveInteger) <-- -[ - Local(m, q, r, a, flag, i, root); - m := n-1; - q := m; - r := 0; - root := 0; // will be the default return value of the "root" - While (IsEven(q)) - [ - q := ShiftRight(q, 1); - r++; - ]; - - a := FastModularPower(b, q, n); - flag := (a = 1 Or a = m); - i := 1; - - While (Not(flag) And (i < r)) - [ - root := a; // this is the value of the root if flag becomes true now - a := ModN(a*a, n); - flag := (a = m); - i++; - ]; - - {root, flag}; // return a root of -1 (or 0 if not found) -]; - - -/* - * For numbers less than 3.4e14, exhaustive computations have - * shown that there is no strong pseudoprime simultaneously for - * bases 2, 3, 5, 7, 11, 13 and 17. - * Function RabinMillerSmall is based on the results of these - * computations. - */ - -10 # RabinMillerSmall(1) <-- False; - -10 # RabinMillerSmall(2) <-- True; - -20 # RabinMillerSmall(n_IsEven) <-- False; - -20 # RabinMillerSmall(3) <-- True; - -30 # RabinMillerSmall(n_IsPositiveInteger) <-- -[ - Local(continue, prime, i, primetable, pseudotable, root); - continue := True; - prime := True; - i := 1; - primetable := {2, 3, 5, 7, 11, 13, 17}; - pseudotable := {2047, 1373653, 25326001, 3215031751, 2152302898747, - 3474749660383, 34155071728321}; - // if n is strongly probably prime for all bases up to and including primetable[i], then n is actually prime unless it is >= pseudotable[i]. - While (continue And prime And (i < 8)) - [ // we do not really need to collect the information about roots of -1 here, so we do not do anything with root - {root, prime} := IsStronglyProbablyPrime(primetable[i], n); - If(InVerboseMode() And prime, Echo("RabinMiller: Info: ", n, "is spp base", primetable[i])); - continue := (n >= pseudotable[i]); - i++; - ]; - // the function returns "Overflow" when we failed to check (i.e. the number n was too large) - If (continue And (i = 8), Overflow, prime); -]; - - -/* - * RabinMillerProbabilistic(n, p) tells whether n is prime. - * If n is actually prime, the result will always be `True'. - * If n is composed the probability to obtain the wrong - * result is less than 4^(-p). - */ -// these 4 rules are not really used now because RabinMillerProbabilistic is only called for large enough n -10 # RabinMillerProbabilistic(1, _p) <-- False; - -10 # RabinMillerProbabilistic(2, _p) <-- True; - -20 # RabinMillerProbabilistic(n_IsEven, _p) <-- False; - -20 # RabinMillerProbabilistic(3, _p) <-- True; - -30 # RabinMillerProbabilistic(n_IsPositiveInteger, p_IsPositiveInteger) <-- -[ - Local(k, prime, b, roots'of'minus1, root); - k := 1+IntLog(IntLog(n,2),4)+p; // find k such that Ln(n)*4^(-k) < 4^(-p) - b := 1; - prime := True; - roots'of'minus1 := {0}; // accumulate the set of roots of -1 modulo n - While (prime And k>0) - [ - b := NextPseudoPrime(b); // use only prime bases, as suggested by Davenport; weak pseudo-primes are good enough - {root, prime} := IsStronglyProbablyPrime(b, n); - If(prime, roots'of'minus1 := Union(roots'of'minus1, {root})); - If(Length(roots'of'minus1)>3, prime := False); - If(InVerboseMode() And prime, Echo("RabinMiller: Info: ", n, "is spp base", b)); - If( // this whole If() clause is only working when InVerboseMode() is in effect and the test is terminated in the unusual way - InVerboseMode() And Length(roots'of'minus1)>3, - [ // we can actually find a factor of n now - Local(factor); - roots'of'minus1 := Difference(roots'of'minus1,{0}); - Echo("RabinMiller: Info: ", n, "is composite via roots of -1 ; ", roots'of'minus1); - factor := Gcd(n, If( - roots'of'minus1[1]+roots'of'minus1[2]=n, - roots'of'minus1[1]+roots'of'minus1[3], - roots'of'minus1[1]+roots'of'minus1[2] - )); - Echo(n, " = ", factor, " * ", n/factor); - ] - ); - k--; - ]; - prime; -]; - - -/* - * This is the frontend function, which uses RabinMillerSmall for - * ``small'' numbers and RabinMillerProbabilistic for bigger ones. - * - * The probability to err is set to 1e-25, hopping this is less - * than the one to step on a rattlesnake in northern Groenland. :-) - */ - -RabinMiller(n_IsPositiveInteger) <-- -[ - If(InVerboseMode(), Echo("RabinMiller: Info: Testing ", n)); - If( - n < 34155071728321, - RabinMillerSmall(n), - RabinMillerProbabilistic(n, 40) // 4^(-40) - ); -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/rabinmiller.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/rabinmiller.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/rabinmiller.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/rabinmiller.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -RabinMiller -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/radsimp.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/radsimp.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/radsimp.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/radsimp.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ - -/* Simplification of nested radicals. -*/ - -RadSimp(_n) <-- -[ - Local(max, result); - Set(max, CeilN(N(Eval(n^2)))); - Set(result,0); - Set(result,RadSimpTry(n,0,1,max)); - -//Echo("result is ",result); - if (CheckRadicals(n,result)) - result - else - n; -]; - -/*Echo({"Try ",test}); */ - -CheckRadicals(_n,_test) <-- Abs(N(Eval(n-test),20)) < 0.000001; - -10 # ClampRadicals(_r)_(N(Eval(Abs(r)), 20)<0.000001) <-- 0; -20 # ClampRadicals(_r) <-- r; - - - -RadSimpTry(_n,_result,_current,_max)<-- -[ -//Echo(result," ",n," ",current); - if (LessThan(N(Eval(result-n)), 0)) - [ - Local(i); - - // First, look for perfect match - i:=BSearch(max,Hold({{try},ClampRadicals(N(Eval((result+Sqrt(try))-n),20))})); - If(i>0, - [ - Set(result,result+Sqrt(i)); - Set(i,AddN(max,1)); - Set(current,AddN(max,1)); - ]); - - // Otherwise, search for another solution - if (LessThan(N(Eval(result-n)), 0)) - [ - For (Set(i,current),i<=max,Set(i,AddN(i,1))) - [ - Local(new, test); - Set(test,result+Sqrt(i)); - -/* Echo({"Full-try ",test}); */ - - Set(new,RadSimpTry(n,test,i,max)); - if (CheckRadicals(n,new)) - [ - Set(result,new); - Set(i,AddN(max,1)); - ]; - ]; - ]; - ]; - result; -]; - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/radsimp.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/radsimp.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/radsimp.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/radsimp.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -RadSimp -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/random.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/random.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/random.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/random.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,292 +0,0 @@ -/* -Random number generators implemented in an object-oriented manner. - -Old interface (still works): - - RandomSeed(123); - Random(); Random(); - -It provides only one global RNG with a globally assigned seed. - -New interface allows creating many RNG objects: - - r1:=RngCreate(); // create a default RNG object, assign structure to r1 - r2:=RngCreate(12345); // create RNG object with given seed - r3:=RngCreate(seed==0, engine==advanced, dist==gauss); // extended options: specify seed, type of RNG engine and the type of statistical distribution - Rng(r1); Rng(r1); Rng(r2); // generate some floating-point numbers - RngSeed(r1, 12345); // r1 is re-initialized with given seed, r2 is unaffected - -More "RNG engines" and "RNG distribution adaptors" can be defined later (at run time). - -RngCreate() will return an object of the following structure: - {SomeDist, SomeEngine, state } - -here SomeEngine is a function atom that describes the RNG engine, -SomeDist is a function atom that specifies the distribution adaptor, -and state is a "RNG state object", e.g. a list of all numbers that specify the current RNG state (seeds, temporaries, etc.). - -RngSeed(r1, seed) expects an integer seed. -It will re-initialize the RNG object r1 with the given seed. - -The "RNG engine API": calling RngCreate with engine==SomeEngine expects that: - SomeEngine(seed_IsInteger) will create and initialize a state object with given seed and return the new state object (a list). SomeEngine can assume that "seed" is a positive integer. - SomeEngine(state1_IsList) will update the RNG state object state1 and return the pair {new state object, new number}. - -The "RNG distribution adaptor API": calling RngCreate with distribution==SomeDist expects that: - SomeDist(r1) will update the RNG object r1 and return the pair {new state object, new number}. r1 is a full RNG object, not just a state object. - - -*/ - -////////////////////////////////////////////////// -/// lists of defined RNG entities -////////////////////////////////////////////////// - -/// The idea is that options must be easy to type, but procedure names could be long. - -LocalSymbols(knownRNGEngines, knownRNGDists) [ - knownRNGEngines := - { - { "default", "RNGEngine'LCG'2"}, - { "advanced", "RNGEngine'L'Ecuyer"}, - }; - - knownRNGDists := - { - {"default", "FlatRNGDist"}, - {"flat", "FlatRNGDist"}, - // {"uniform", "FlatRNGDist"}, // we probably don't need this alias... - {"gauss", "GaussianRNGDist"}, - }; - - KnownRNGDists() := knownRNGDists; - KnownRNGEngines() := knownRNGEngines; -]; - - -////////////////////////////////////////////////// -/// RNG object API -////////////////////////////////////////////////// - -Function() RngCreate(); -Function() RngCreate(seed, ...); -HoldArg("RngCreate", seed); // this is needed to prevent evaluation of = and also to prevent substitution of variables, e.g. if "seed" is defined -//UnFence("RngCreate", 0); -//UnFence("RngCreate", 1); -Function() RngSeed(r, seed); -//UnFence("RngSeed", 2); -/// accessor for RNG objects -Function() Rng(r); -//UnFence("Rng", 1); - - -RngCreate() <-- RngCreate(0); - -10 # RngCreate(a'seed_IsInteger) <-- (RngCreate @ {Atom("seed") == a'seed}); - -// a single option given: convert explicitly to a list -20 # RngCreate(_key == _value) <-- (RngCreate @ {{key == value}}); -20 # RngCreate(_key = _value) <-- (RngCreate @ {{key == value}}); - -// expect a list of options -30 # RngCreate(options_IsList) <-- -[ - options := ListToHash @ {options}; - // check options and assign defaults - If( - options["seed"] = Empty Or options["seed"] <= 0, - options["seed"] := 76544321 // some default seed out of the blue sky - ); - If( - options["engine"] = Empty Or Not (Assert("warning", {"RngCreate: invalid engine", options["engine"]}) KnownRNGEngines()[options["engine"] ] != Empty), - options["engine"] := "default" - ); - If( - options["dist"] = Empty Or Not (Assert("warning", {"RngCreate: invalid distribution", options["dist"]}) KnownRNGDists()[options["dist"] ] != Empty), - options["dist"] := "default" - ); - - // construct a new RNG object - // a RNG object has the form {"SomeDist", "SomeEngine", {state}} - { - KnownRNGDists()[options["dist"] ], KnownRNGEngines()[options["engine"] ], - // initialize object with given seed using "SomeEngine"(seed) - KnownRNGEngines()[options["engine"] ] @ { options["seed"] } - }; -]; - -/// accessor function: will call SomeDist(r) and update r -Rng(_r) <-- -[ - Local(state, result); - {state, result} := (r[1] @ {r}); // this calls SomeDist(r) - DestructiveReplace(r, 3, state); // update RNG object - result; // return floating-point number -]; - -/// set seed: will call SomeEngine(r, seed) and update r -RngSeed(_r, seed_IsInteger) <-- -[ - Local(state); - (Assert("warning", {"RngSeed: seed must be positive", seed}) seed > 0 - ) Or (seed:=76544321); - state := (r[2] @ {seed}); // this calls SomeEngine(r) - DestructiveReplace(r, 3, state); // update object - True; -]; - -////////////////////////////////////////////////// -/// RNG distribution adaptors -////////////////////////////////////////////////// - -/// trivial distribution adaptor: flat distribution, simply calls SomeEngine(r) -/* we have to return whole objects; we can't use references b/c the core -function ApplyPure will not work properly on references, i.e. if r = {"", "", {1}} so that -r[3] = {1}, then LCG'2(r[3]) modifies r[3], but LCG'2 @ r[3] or -ApplyPure("LCG'2", {r[3]}) do not actually modify r[3]. -*/ - -// return pair {state, number} -FlatRNGDist(_r) <-- (r[2] @ {r[3]}); // this calls SomeEngine(state) - -/// Gaussian distribution adaptor, returns a complex number with normal distribution with unit variance, i.e. Re and Im are independent and both have unit variance -/* Gaussian random number, Using the Box-Muller transform, from Knuth, - "The Art of Computer Programming", - Volume 2 (Seminumerical algorithms, third edition), section 3.4.1 - */ -GaussianRNGDist(_rng) <-- -[ - // a Gaussian distributed complex number p + I*q is made up of two uniformly distributed numbers x,y according to the formula: - // a:=2*x-1, b:=2*y-1, m:=a^2+b^2; p = a*Sqrt(-2*Ln(m)/m); q:=b*Sqrt(-2*Ln(m)/m); - // here we need to make sure that m is nonzero and strictly less than 1. - Local(a,b,m, new'state, rnumber); - new'state := rng[3]; // this will be updated at the end - m:=0; - While(m=0 Or m>=1) // repeat generating new x,y - should not take more than one iteration really - [ - {new'state, rnumber} := (rng[2] @ {new'state}); - a:=2*rnumber-1; - {new'state, rnumber} := (rng[2] @ {new'state}); - b:=2*rnumber-1; - m:=a*a+b*b; - ]; - {new'state, (a+I*b)*SqrtN(-2*DivideN(Internal'LnNum(m),m))}; -]; - - -////////////////////////////////////////////////// -/// RNG engines -////////////////////////////////////////////////// - -/// default RNG engine: the LCG generator - -// first method: initialize a state object with given seed -RNGEngine'LCG'1(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'1(state_IsList) <-- LCG'1(state); - -// first method: initialize a state object with given seed -RNGEngine'LCG'2(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'2(state_IsList) <-- LCG'2(state); - -// first method: initialize a state object with given seed -RNGEngine'LCG'3(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'3(state_IsList) <-- LCG'3(state); - -// first method: initialize a state object with given seed -RNGEngine'LCG'4(seed_IsInteger) <-- {seed}; -// second method: update state object and return new number -RNGEngine'LCG'4(state_IsList) <-- LCG'4(state); - -/// parameters from P. Hellekalek, 1994; see G. S. Fishman, Math. Comp. vol. 54, 331 (1990) -LCG'1(state) := RandomLCG(state, 2147483647,950706376,0); -LCG'2(state) := RandomLCG(state, 4294967296,1099087573,0); -LCG'3(state) := RandomLCG(state, 281474976710656,68909602460261,0); -LCG'4(state) := RandomLCG(state, 18014398509481984,2783377640906189,0); - -/// Linear congruential generator engine: backend -// state is a list with one element -RandomLCG(_state, _im, _ia, _ic) <-- -{ - DestructiveReplace(state,1, ModN(state[1]*ia+ic,im)), - DivideN(state[1], im) // division should never give 1 -}; - -/// Advanced RNG engine due to L'Ecuyer et al. -/// RNG from P. L'ecuyer et al (2000). Period approximately 2^191 -// state information: 6 32-bit integers, corresponding to {x3,x2,x1,y3,y2,y1} - -// first method: initialize a state object with given seed -RNGEngine'L'Ecuyer(a'seed_IsInteger) <-- -[ - // use LCG'2 as auxiliary RNG to fill the seeds - Local(rng'aux, result); - rng'aux := (RngCreate @ {a'seed}); - // this will be the state vector - result:=ZeroVector(6); - // fill the state object with random numbers - Local(i); - For(i:=1, i<=6, i++) - [ - Rng(rng'aux); - result[i] := rng'aux[3][1]; // hack to get the integer part - ]; - // return the state object - result; -]; - -// second method: update state object and return a new random number (floating-point) -RNGEngine'L'Ecuyer(state_IsList) <-- -[ - Local(new'state, result); - new'state := { - Mod(1403580*state[2]-810728*state[3], 4294967087), state[1], state[2], - Mod(527612*state[4]-1370589*state[6], 4294944433), state[4], state[5] - }; - result:=Mod(state[1]-state[4], 4294967087); - { - new'state, - DivideN(If(result=0, 4294967087, result), 4294967088) - }; -]; - -////////////////////////////////////////////////// -/// old interface: using one global RNG object -////////////////////////////////////////////////// -/* this is a little slower but entirely equivalent to the code below -GlobalRNG := RngCreate(76544321); -Random() := Rng(GlobalRNG); -RandomSeed(seed) := RngSeed(GlobalRNG, seed); -*/ - -LocalSymbols(RandSeed) [ - // initial seed should be nonzero - RandSeed:=76544321; - - /// assign random seed - Function("RandomSeed", {seed}) Set(RandSeed, seed); - - /// Linear congruential generator - RandomLCG(_im, _ia, _ic) <-- - [ - RandSeed:=ModN(RandSeed*ia+ic,im); - DivideN(RandSeed,im); // should never give 1 - ]; -]; // LocalSymbols(RandSeed) - - -Function("Random1",{}) RandomLCG(4294967296,1103515245,12345); -Function("Random6",{}) RandomLCG(1771875,2416,374441); -/// parameters from P. Hellekalek, 1994; see G. S. Fishman, Math. Comp. vol. 54, 331 (1990) -Function("Random2",{}) RandomLCG(2147483647,950706376,0); -Function("Random3",{}) RandomLCG(4294967296,1099087573,0); -Function("Random4",{}) RandomLCG(281474976710656,68909602460261,0); -Function("Random5",{}) RandomLCG(18014398509481984,2783377640906189,0); - -// select one of them -Function("Random",{}) Random3(); - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/random.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/random.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/random.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/random.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -RandomSeed -Random -Rng -RngSeed -RngCreate -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/simplify.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/simplify.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ - - -10 # Simplify(expr_IsList) <-- MapSingle("Simplify",expr); - -15 # Simplify(Complex(_r,_i)) <-- Complex(Simplify(r),Simplify(i)); - -20 # Simplify((_xex) == (_yex)) <-- (Simplify(xex-yex) == 0); - -20 # Simplify((_xex) > (_yex)) <-- (Simplify(xex-yex) > 0); -20 # Simplify((_xex) < (_yex)) <-- (Simplify(xex-yex) < 0); -20 # Simplify((_xex) >= (_yex)) <-- (Simplify(xex-yex) >= 0); -20 # Simplify((_xex) <= (_yex)) <-- (Simplify(xex-yex) <= 0); -20 # Simplify((_xex) !== (_yex)) <-- (Simplify(xex-yex) !== 0); - -// conditionals -25 # Simplify(if (_a) _b) <-- "if" @ {Simplify(a), Simplify(b)}; -25 # Simplify(_a else _b) <-- "else" @ {Simplify(a), Simplify(b)}; - -50 # Simplify(_expr) <-- MultiSimp(Eval(expr)); - - -Eliminate(_var,_replace,_function) <-- Simplify(Subst(var,replace)function); -//ExpandBrackets(_xx) <-- SimpExpand(SimpImplode(SimpFlatten(xx))); -ExpandBrackets(x) := NormalForm(MM(x)); - -Function("Flatten",{body,flattenoper}) -[ - DoFlatten(body); -]; - -RuleBase("DoFlatten",{doflattenx}); -UnFence("DoFlatten",1); - -10 # DoFlatten(_doflattenx)_(Type(doflattenx)=flattenoper) <-- - Apply("Concat",MapSingle("DoFlatten",Tail(Listify(doflattenx)))); -20 # DoFlatten(_doflattenx) <-- { doflattenx }; - - -10 # UnFlatten({},_op,_identity) <-- identity; -20 # UnFlatten(list_IsList,_op,_identity) <-- - Apply(op,{Head(list),UnFlatten(Tail(list),op,identity)}); - - -RuleBase("SimpAdd",{x,y}); -RuleBase("SimpMul",{x,y}); -RuleBase("SimpDiv",{x,y}); - - -10 # SimpFlatten((_x)+(_y)) <-- SimpAdd(SimpFlatten(x),SimpFlatten(y)); -10 # SimpFlatten((_x)-(_y)) <-- SimpAdd(SimpFlatten(x),SimpMul(-1,SimpFlatten(y))); -10 # SimpFlatten( -(_y)) <-- SimpMul(-1,SimpFlatten(y)); - -10 # SimpFlatten((_x)*(_y)) <-- SimpMul(SimpFlatten(x),SimpFlatten(y)); -10 # SimpFlatten((_x)/(_y)) <-- SimpDiv(SimpFlatten(x),SimpFlatten(y)); -10 # SimpFlatten((_x)^(n_IsPositiveInteger)) <-- - SimpMul(SimpFlatten(x),SimpFlatten(x^(n-1))); - -100 # SimpFlatten(_x) <-- -[ - x; -]; - -10 # SimpExpand(SimpAdd(_x,_y)) <-- SimpExpand(x) + SimpExpand(y); -10 # SimpExpand(SimpMul(_x,_y)) <-- SimpExpand(x) * SimpExpand(y); -10 # SimpExpand(SimpDiv(_x,_y)) <-- SimpExpand(x) / SimpExpand(y); -20 # SimpExpand(_x) <-- x; - -/* Distributed multiplication rule */ -10 # SimpImplode(SimpMul(SimpAdd(_x,_y),_z)) <-- - SimpImplode(SimpAdd(SimpImplode(SimpMul(x,z)), - SimpImplode(SimpMul(y,z)))); -10 # SimpImplode(SimpMul(_z,SimpAdd(_x,_y))) <-- - SimpImplode(SimpAdd(SimpImplode(SimpMul(z,x)), - SimpImplode(SimpMul(z,y)))); -/* Distributed division rule */ -10 # SimpImplode(SimpDiv(SimpAdd(_x,_y),_z)) <-- - SimpImplode(SimpAdd(SimpImplode(SimpDiv(x,z)), - SimpImplode(SimpDiv(y,z)))); - - - -20 # SimpImplode(SimpAdd(_x,_y)) <-- - SimpAdd(SimpImplode(x),SimpImplode(y)); -20 # SimpImplode(SimpMul(_x,_y)) <-- - SimpMul(SimpImplode(x),SimpImplode(y)); -20 # SimpImplode(SimpDiv(_x,_y)) <-- - SimpDiv(SimpImplode(x),SimpImplode(y)); -30 # SimpImplode(_x) <-- x; - - -////////////////////////////////////////////////// -/// ExpandFrac --- normalize rational functions (no simplification) -////////////////////////////////////////////////// - -5 # ExpandFrac(expr_IsList) <-- MapSingle("ExpandFrac", expr); - -// expression does not contain fractions -10 # ExpandFrac(_expr)_Not(HasFuncSome(expr, "/", {Atom("+"), Atom("-"), *, /, ^})) <-- expr; -15 # ExpandFrac(a_IsRationalOrNumber) <-- a; -20 # ExpandFrac(_expr) <-- ExpandFrac'combine(GetNumerDenom(expr)); - -ExpandFrac'combine({_a, _b}) <-- a/b; - -/// GetNumerDenom(x) returns a pair of expressions representing normalized numerator and denominator; GetNumerDenom(x, a) multiplies the numerator by the number a -GetNumerDenom(_expr, _a) <-- GetNumerDenom(expr)*{a,1}; - -// on expressions that are not fractions, we return unit denominator -10 # GetNumerDenom(_expr)_Not(HasFuncSome(expr, "/", {Atom("+"), Atom("-"), *, /, ^})) <-- {expr, 1}; -// rational numbers are not simplified -15 # GetNumerDenom(a_IsRationalOrNumber) <-- {a, 1}; -// arithmetic -20 # GetNumerDenom(_a + _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b)); -20 # GetNumerDenom(_a - _b) <-- ExpandFrac'add(GetNumerDenom(a), GetNumerDenom(b, -1)); -20 # GetNumerDenom(- _a) <-- GetNumerDenom(a, -1); -20 # GetNumerDenom(+ _a) <-- GetNumerDenom(a); -20 # GetNumerDenom(_a * _b) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(b)); -20 # GetNumerDenom(_a / _b) <-- ExpandFrac'divide(GetNumerDenom(a), GetNumerDenom(b)); -// integer powers -20 # GetNumerDenom(_a ^ b_IsInteger)_(b > 1) <-- ExpandFrac'multiply(GetNumerDenom(a), GetNumerDenom(a^(b-1))); -20 # GetNumerDenom(_a ^ b_IsInteger)_(b < -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a^(-b))); -20 # GetNumerDenom(_a ^ b_IsInteger)_(b = -1) <-- ExpandFrac'divide(GetNumerDenom(1), GetNumerDenom(a)); -// non-integer powers are not considered to be rational functions -25 # GetNumerDenom(_a ^ _b) <-- {a^b, 1}; - -// arithmetic on fractions; not doing any simplification here, whereas we might want to -ExpandFrac'add({_a, _b}, {_c, _d}) <-- {a*d+b*c, b*d}; -ExpandFrac'multiply({_a, _b}, {_c, _d}) <-- {a*c, b*d}; -ExpandFrac'divide({_a, _b}, {_c, _d}) <-- {a*d, b*c}; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/simplify.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/simplify.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -Eliminate -ExpandBrackets -Simplify -Flatten -UnFlatten -ExpandFrac -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/simplify.rep/factorial.mpi mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/factorial.mpi --- mathpiper-0.0.svn2556/storage/scripts/simplify.rep/factorial.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/factorial.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,252 +0,0 @@ - -/* FactorialSimplify algorithm: - 1) expand binomials into factors - 2) expand brackets as much as possible - 3) for the remaining rational expressions x/y, - take all the factors of x and y, and match them - up one by one to determine if they can be - factored out. The algorithm will look at expressions like x^n/x^m - where (n-m) is an integer, or at expressions x!/y! where (x-y) - is an integer. The routine CommonDivisors does these steps, and - returns the new numerator and denominator factor. - FactorialSimplifyWorker does the actual O(n^2) algorithm of - matching all terms up. -*/ - -FactorialNormalForm(x):= -[ - // Substitute binomials - x:=(x/:{Bin(_n,_m)<- (n!)/((m!)*(n-m)!)}); - // Expand expression as much as possible so that the terms become - // simple rationals. - - x:=( - x/::Hold({ - (_a/_b)/_c <- (a)/(b*c), - (-(_a/_b))/_c <- (-a)/(b*c), - (_a/_b)*_c <- (a*c)/b, - (_a*_b)^_m <- a^m*b^m, - (_a/_b)^_m*_c <- (a^m*c)/b^m, - _a*(_b+_c) <- a*b+a*c, - (_b+_c)*_a <- a*b+a*c, - (_b+_c)/_a <- b/a+c/a, - _a*(_b-_c) <- a*b-a*c, - (_b-_c)*_a <- a*b-a*c, - (_b-_c)/_a <- b/a-c/a - })); - x; -]; - -FactorialSimplify(x):= -[ - x := FactorialNormalForm(x); - FactorialSimplifyWorker(x); -]; - - -/* CommonDivisors takes two parameters x and y as input, determines a common divisor g - and then returns {x/g,y/g,g}. - */ -10 # CommonDivisors(_x^(_n),_x^(_m)) <-- {x^Simplify(n-m),1,x^m}; -10 # CommonDivisors(_x^(_n),_x) <-- {x^Simplify(n-1),1,x}; -10 # CommonDivisors(_x,_x^(_m)) <-- {x^Simplify(1-m),1,x^m}; -10 # CommonDivisors((_x) !,_x) <-- {(x-1)!,1,x}; -10 # CommonDivisors(_x,_x) <-- {1,1,x}; -10 # CommonDivisors(- _x,_x) <-- {-1,1,x}; -10 # CommonDivisors(_x,- _x) <-- {1,-1,x}; -10 # CommonDivisors((_x),(_x)!) <-- {1,(x-1)!,x}; -10 # CommonDivisors((_x)!, (_y)!)_IsInteger(Simplify(x-y)) <-- CommonFact(Simplify(x-y),y); - - -10 # CommonDivisors((_x)! ^ _m, (_y)! ^ _m)_IsInteger(Simplify(x-y)) <-- CommonFact(Simplify(x-y),y)^m; - -10 # CommonFact(dist_IsNegativeInteger,_y) - <-- {1,Factorize(i,1,-dist,Simplify(y+i+dist)),Simplify(y+dist)!}; -11 # CommonFact(_dist,_y) - <-- {Factorize(i,1,dist,Simplify(y+i)),1,Simplify(y)!}; -60000 # CommonDivisors(_x,_y) <-- {x,y,1}; - -10 # CommonFactors((_x)!,_y)_(Simplify(y-x) = 1) <-- {y!,1}; -10 # CommonFactors((_x)!,_y)_(Simplify((-y)-x) = 1) <-- {(-y)!,-1}; - -10 # CommonFactors(_x^_n,_x^_m) <-- {x^Simplify(n+m),1}; -10 # CommonFactors(_x^_n,_x) <-- {x^Simplify(n+1),1}; - -60000 # CommonFactors(_x,_y) <-- {x,y}; - -10 # FactorialSimplifyWorker(_x+_y) <-- FactorialSimplifyWorker(x)+FactorialSimplifyWorker(y); -10 # FactorialSimplifyWorker(_x-_y) <-- FactorialSimplifyWorker(x)-FactorialSimplifyWorker(y); -10 # FactorialSimplifyWorker( -_y) <-- -FactorialSimplifyWorker(y); - -LocalSymbols(x,y,i,j,n,d)[ - -20 # FactorialSimplifyWorker(_x/_y) <-- -[ - // first separate out factors of the denominator - Local(numerCommon,numerTerms); - {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); - Local(denomCommon,denomTerms); - {denomCommon,denomTerms}:=FactorialGroupCommonDivisors(y); - Local(n,d,c); - {n,d,c} := FactorialDivideTerms(numerCommon,denomCommon); - (n/d)*Simplify((numerTerms)/(denomTerms)); -]; - - - -20 # FactorialGcd(_x,_y) <-- -[ - // first separate out factors of the denominator - Local(numerCommon,numerTerms); - {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); - Local(denomCommon,denomTerms); - {denomCommon,denomTerms}:=FactorialGroupCommonDivisors(y); - Local(n,d,c); - {n,d,c} := FactorialDivideTerms(numerCommon,denomCommon); - c; -]; - - - - - -10 # FactorialDivideTerms(- _x,- _y) <-- FactorialDivideTermsAux(x,y); -LocalSymbols(n,d,c) -[ - 20 # FactorialDivideTerms(- _x, _y) - <-- - [ - Local(n,d,c); - {n,d,c} := FactorialDivideTermsAux(x,y); - {-n,d,c}; - ]; - 30 # FactorialDivideTerms( _x,- _y) - <-- - [ - Local(n,d,c); - {n,d,c} := FactorialDivideTermsAux(x,y); - {n,-d,c}; - ]; -]; -40 # FactorialDivideTerms( _x, _y) - <-- - [ -// Echo("GOTHERE 40"); - FactorialDivideTermsAux(x,y); - ]; - -LocalSymbols(n,d,c) -[ - 10 # FactorialDivideTermsAux(_x,_y) <-- - [ - x:=Flatten(x,"*"); - y:=Flatten(y,"*"); - - Local(i,j,common); - common:=1; - For(i:=1,i<=Length(x),i++) - For(j:=1,j<=Length(y),j++) - [ - Local(n,d,c); -//Echo("inp is ",x[i]," ",y[j]); - {n,d,c} := CommonDivisors(x[i],y[j]); - -//Echo("aux is ",{n,d,c}); - x[i] := n; - y[j] := d; - common:=common*c; - ]; -//Echo("final ",{x,y,common}); -//Echo("finalor ",{Factorize(x),Factorize(y),common}); - {Factorize(x),Factorize(y),common}; - ]; -]; - -]; - -60000 # FactorialSimplifyWorker(_x) - <-- - [ - // first separate out factors of the denominator - Local(numerCommon,numerTerms); - {numerCommon,numerTerms}:=FactorialGroupCommonDivisors(x); - numerCommon*numerTerms; - ]; - -/* FactorialFlattenAddition accepts an expression of form a+b+c-d+e-f+ ... +z with arbitrary additions - and subtractions, and converts it to a list of terms. Terms that need to be subtracted start with a - negation sign (useful for pattern matching). - */ -10 # FactorialFlattenAddition(_x+_y) <-- Concat(FactorialFlattenAddition(x), FactorialFlattenAddition(y)); -10 # FactorialFlattenAddition(_x-_y) <-- Concat(FactorialFlattenAddition(x),-FactorialFlattenAddition(y)); -10 # FactorialFlattenAddition( -_y) <-- -FactorialFlattenAddition(y); -20 # FactorialFlattenAddition(_x ) <-- {x}; - -LocalSymbols(n,d,c) -[ - 10 # FactorialGroupCommonDivisors(_x) <-- - [ - Local(terms,common,tail); - terms:=FactorialFlattenAddition(x); -//Echo("terms is ",terms); - common := Head(terms); - tail:=Tail(terms); - While (tail != {}) - [ - Local(n,d,c); - {n,d,c} := FactorialDivideTerms(common,Head(tail)); - -//Echo(common, " ",Head(tail)," ",c); - common := c; - tail:=Tail(tail); - ]; - Local(i,j); - -// Echo("common is ",common); - - For(j:=1,j<=Length(terms),j++) - [ - Local(n,d,c); -// Echo("IN = ",terms[j]," ",common); -// Echo("n = ",n); - {n,d,c} := FactorialDivideTerms(terms[j],common); -// Echo("n = ",n); -// Echo("{n,d,c} = ",{n,d,c}); - Check(d = 1, - ToString()[ - Echo("FactorialGroupCommonDivisors failure 1 : ",d); - ]); -/* - Check(Simplify(c-common) = 0, - ToString() - [ - Echo("FactorialGroupCommonDivisors failure 2 : "); - Echo(c," ",common); - Echo(Simplify(c-common)); - ]); -*/ - terms[j] := n; - ]; - terms:=Add(terms); - - common:=Flatten(common,"*"); - For(j:=1,j<=Length(common),j++) - [ - Local(f1,f2); - {f1,f2}:=CommonFactors(common[j],terms); - common[j]:=f1; - terms:=f2; - - For(i:=1,i<=Length(common),i++) - If(i != j, - [ - {f1,f2}:=CommonFactors(common[j],common[i]); - common[j]:=f1; - common[i]:=f2; - ]); - ]; - common := Factorize(common); - {common,terms}; - ]; -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/simplify.rep/factorial.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/factorial.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/simplify.rep/factorial.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/simplify.rep/factorial.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -FactorialSimplify -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/solve.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/solve.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/solve.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/solve.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,543 +0,0 @@ -/* - * Strategy for Solve(expr, x): - * - * 10. Call Solve'System for systems of equations. - * 20. Check arguments. - * 30. Get rid of "==" in 'expr'. - * 40. Special cases. - * 50. If 'expr' is a polynomial in 'x', try to use PSolve. - * 60. If 'expr' is a product, solve for either factor. - * 70. If 'expr' is a quotient, solve for the denominator. - * 80. If 'expr' is a sum and one of the terms is free of 'x', - * try to use Solve'Simple. - * 90. If every occurance of 'x' is in the same context, use this to reduce - * the equation. For example, in 'Cos(x) + Cos(x)^2 == 1', the variable - * 'x' always occurs in the context 'Cos(x)', and hence we can attack - * the equation by first solving 'y + y^2 == 1', and then 'Cos(x) == y'. - * This does not work for 'Exp(x) + Cos(x) == 2'. - * 100. Apply Simplify to 'expr', and try again. - * 110. Give up. - */ - -LocalSymbols(res) -[ - 10 # Solve(expr_IsList, var_IsList) <-- Solve'System(expr, var); - 20 # Solve(_expr, _var)_(Not IsAtom(var) Or IsNumber(var) Or IsString(var)) <-- - [ Assert("Solve'TypeError", "Second argument, ":(ToString() Write(var)):", is not the name of a variable") False; {}; ]; - 30 # Solve(_lhs == _rhs, _var) <-- Solve(lhs - rhs, var); - 40 # Solve(0, _var) <-- {var == var}; - 41 # Solve(a_IsConstant, _var) <-- {}; - 42 # Solve(_expr, _var)_(Not HasExpr(expr,var)) <-- - [ Assert("Solve", "expression ":(ToString() Write(expr)):" does not depend on ":ToString() Write(var)) False; {}; ]; - 50 # Solve(_expr, _var)_((res := Solve'Poly(expr, var)) != Failed) <-- res; - 60 # Solve(_e1 * _e2, _var) <-- Union(Solve(e1,var), Solve(e2,var)); - 70 # Solve(_e1 / _e2, _var) <-- Solve(e1, var); - 80 # Solve(_e1 + _e2, _var)_(Not HasExpr(e2,var) And (res := Solve'Simple(e1,-e2,var)) != Failed) <-- res; - 80 # Solve(_e1 + _e2, _var)_(Not HasExpr(e1,var) And (res := Solve'Simple(e2,-e1,var)) != Failed) <-- res; - 80 # Solve(_e1 - _e2, _var)_(Not HasExpr(e2,var) And (res := Solve'Simple(e1,e2,var)) != Failed) <-- res; - 80 # Solve(_e1 - _e2, _var)_(Not HasExpr(e1,var) And (res := Solve'Simple(e2,e1,var)) != Failed) <-- res; - 85 # Solve(_expr, _var)_((res := Solve'Simple(expr, 0, var)) != Failed) <-- res; - 90 # Solve(_expr, _var)_((res := Solve'Reduce(expr, var)) != Failed) <-- res; - 95 # Solve(_expr, _var)_((res := Solve'Divide(expr, var)) != Failed) <-- res; - 100 # Solve(_expr, _var)_((res := Simplify(expr)) != expr) <-- Solve(res, var); - 110 # Solve(_expr, _var) <-- - [ Assert("Solve'Fails", "cannot solve equation ":(ToString() Write(expr)):" for ":ToString() Write(var)) False; {}; ]; -]; - -/********** Solve'Poly **********/ - -/* Tries to solve by calling PSolve */ -/* Returns Failed if this doesn't work, and the solution otherwise */ - -/* CanBeUni is not documented, but defined in org/mathpiper/scripts/univar.rep/code.mpi */ -/* It returns True iff 'expr' is a polynomial in 'var' */ - -10 # Solve'Poly(_expr, _var)_(Not CanBeUni(var, expr)) <-- Failed; - -/* The call to PSolve can have three kind of results - * 1) PSolve returns a single root - * 2) PSolve returns a list of roots - * 3) PSolve remains unevaluated - */ - -20 # Solve'Poly(_expr, _var) <-- -LocalSymbols(x) -[ - Local(roots); - roots := PSolve(expr, var); - If(Type(roots) = "PSolve", - Failed, /* Case 3 */ - If(Type(roots) = "List", - MapSingle({{x},var==x}, roots), /* Case 2 */ - {var == roots})); /* Case 1 */ -]; - -/********** Solve'Reduce **********/ - -/* Tries to solve by reduction strategy */ -/* Returns Failed if this doesn't work, and the solution otherwise */ - -10 # Solve'Reduce(_expr, _var) <-- -[ - Local(context, expr2, var2, res, sol, sol2, i); - context := Solve'Context(expr, var); - If(context = False, - res := Failed, - [ - expr2 := Eval(Subst(context, var2) expr); - If(CanBeUni(var2, expr2) And (Degree(expr2, var2) = 0 Or (Degree(expr2, var2) = 1 And Coef(expr2, var2, 1) = 1)), - res := Failed, /* to prevent infinite recursion */ - [ - sol2 := Solve(expr2, var2); - If(IsError("Solve'Fails"), - [ - ClearError("Solve'Fails"); - res := Failed; - ], - [ - res := {}; - i := 1; - While(i <= Length(sol2) And res != Failed) [ - sol := Solve(context == (var2 Where sol2[i]), var); - If(IsError("Solve'Fails"), - [ - ClearError("Solve'Fails"); - res := Failed; - ], - res := Union(res, sol)); - i++; - ]; - ]); - ]); - ]); - res; -]; - -/********** Solve'Context **********/ - -/* Returns the unique context of 'var' in 'expr', */ -/* or {} if 'var' does not occur in 'expr', */ -/* or False if the context is not unique. */ - -10 # Solve'Context(expr_IsAtom, _var) <-- If(expr=var, var, {}); - -20 # Solve'Context(_expr, _var) <-- -[ - Local(lst, foundVarP, context, i, res); - lst := Listify(expr); - foundVarP := False; - i := 2; - While(i <= Length(lst) And Not foundVarP) [ - foundVarP := (lst[i] = var); - i++; - ]; - If(foundVarP, - context := expr, - [ - context := {}; - i := 2; - While(i <= Length(lst) And context != False) [ - res := Solve'Context(lst[i], var); - If(res != {} And context != {} And res != context, context := False); - If(res != {} And context = {}, context := res); - i++; - ]; - ]); - context; -]; - -/********** Solve'Simple **********/ - -/* Simple solver of equations - * - * Returns (possibly empty) list of solutions, - * or Failed if it cannot handle the equation - * - * Calling format: Solve'Simple(lhs, rhs, var) - * to solve 'lhs == rhs'. - * - * Note: 'rhs' should not contain 'var'. - */ - -20 # Solve'Simple(_e1 + _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs-e2 }; -20 # Solve'Simple(_e1 + _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == rhs-e1 }; - -20 # Solve'Simple(_e1 - _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs+e2 }; -20 # Solve'Simple(_e1 - _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == e1-rhs }; -20 # Solve'Simple(-(_e1), _rhs, _var)_(e1 = var) <-- { var == -rhs }; - -20 # Solve'Simple(_e1 * _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs/e2 }; -20 # Solve'Simple(_e1 * _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == rhs/e1 }; - -20 # Solve'Simple(_e1 / _e2, _rhs, _var)_(e1 = var And Not HasExpr(e2,var)) <-- { var == rhs*e2 }; -10 # Solve'Simple(_e1 / _e2, 0, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { }; -20 # Solve'Simple(_e1 / _e2, _rhs, _var)_(e2 = var And Not HasExpr(e1,var)) <-- { var == e1/rhs }; - -LocalSymbols(x) -[ - 20 # Solve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsPositiveInteger(n)) - <-- MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. n)/n)); - 20 # Solve'Simple(_e1 ^ _n, _rhs, _var)_(e1 = var And IsNegativeInteger(n)) - <-- MapSingle({{x}, var == rhs^(1/n)*x}, Exp(2*Pi*I*(1 .. (-n))/(-n))); -]; - -20 # Solve'Simple(_e1 ^ _e2, _rhs, _var) - _ (IsPositiveReal(e1) And e1 != 0 And e2 = var And IsPositiveReal(rhs) And rhs != 0) - <-- { var == Ln(rhs)/Ln(e1) }; - -/* Note: These rules do not take the periodicity of the trig. functions into account */ -10 # Solve'Simple(Sin(_e1), 1, _var)_(e1 = var) <-- { var == 1/2*Pi }; -10 # Solve'Simple(Sin(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- { var == 3/2*Pi }; -20 # Solve'Simple(Sin(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcSin(rhs), var == Pi-ArcSin(rhs) }; -10 # Solve'Simple(Cos(_e1), 1, _var)_(e1 = var) <-- { var == 0 }; -10 # Solve'Simple(Cos(_e1), _rhs, _var)_(e1 = var And rhs = -1) <-- { var == Pi }; -20 # Solve'Simple(Cos(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcCos(rhs), var == -ArcCos(rhs) }; -20 # Solve'Simple(Tan(_e1), _rhs, _var)_(e1 = var) <-- { var == ArcTan(rhs) }; - -20 # Solve'Simple(ArcSin(_e1), _rhs, _var)_(e1 = var) <-- { var == Sin(rhs) }; -20 # Solve'Simple(ArcCos(_e1), _rhs, _var)_(e1 = var) <-- { var == Cos(rhs) }; -20 # Solve'Simple(ArcTan(_e1), _rhs, _var)_(e1 = var) <-- { var == Tan(rhs) }; - -/* Note: Second rule neglects (2*I*Pi)-periodicity of Exp() */ -10 # Solve'Simple(Exp(_e1), 0, _var)_(e1 = var) <-- { }; -20 # Solve'Simple(Exp(_e1), _rhs, _var)_(e1 = var) <-- { var == Ln(rhs) }; -20 # Solve'Simple(Ln(_e1), _rhs, _var)_(e1 = var) <-- { var == Exp(rhs) }; - -/* The range of Sqrt is the set of (complex) numbers with either - * positive real part, together with the pure imaginary numbers with - * nonnegative real part. */ -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsPositiveReal(Re(rhs)) And Re(rhs) != 0) <-- { var == rhs^2 }; -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsPositiveReal(Im(rhs))) <-- { var == rhs^2 }; -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And Re(rhs)=0 And IsNegativeReal(Im(rhs)) And Im(rhs) != 0) <-- { }; -20 # Solve'Simple(Sqrt(_e1), _rhs, _var)_(e1 = var And IsNegativeReal(Re(rhs)) And Re(rhs) != 0) <-- { }; - -30 # Solve'Simple(_lhs, _rhs, _var) <-- Failed; - - -/********** Solve'Divide **********/ -/* For some classes of equations, it may be easier to solve them if we - * divide through by their first term. A simple example of this is the - * equation Sin(x)+Cos(x)==0 - * One problem with this is that we may lose roots if the thing we - * are dividing by shares roots with the whole equation. - * The final HasExprs are an attempt to prevent infinite recursion caused by - * the final Simplify step in Solve undoing what we do here. It's conceivable - * though that this won't always work if the recurring loop is more than two - * steps long. I can't think of any ways this can happen though :) - */ - -10 # Solve'Divide(_e1 + _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) - And Not (HasExpr(Simplify(1 + (e2/e1)), e1) - Or HasExpr(Simplify(1 + (e2/e1)), e2))) - <-- Solve(1 + (e2/e1), var); -10 # Solve'Divide(_e1 - _e2, _var)_(HasExpr(e1, var) And HasExpr(e2, var) - And Not (HasExpr(Simplify(1 - (e2/e1)), e1) - Or HasExpr(Simplify(1 - (e2/e1)), e2))) - <-- Solve(1 - (e2/e1), var); - -20 # Solve'Divide(_e, _v) <-- Failed; - - -/********** Solve'System **********/ - -// for now, just use a very simple backsubstitution scheme -Solve'System(_eqns, _vars) <-- Solve'SimpleBackSubstitution(eqns,vars); - -// Check(False, "Solve'System: not implemented"); - -10 # Solve'SimpleBackSubstitution'FindAlternativeForms((_lx) == (_rx)) <-- -[ - Local(newEq); - newEq := (Simplify(lx) == Simplify(rx)); - If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq)); - newEq := (Simplify(lx - rx) == 0); - If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq)); -]; -20 # Solve'SimpleBackSubstitution'FindAlternativeForms(_equation) <-- -[ -]; -UnFence("Solve'SimpleBackSubstitution'FindAlternativeForms",1); - -/* Solving sets of equations using simple backsubstitution. - * Solve'SimpleBackSubstitution takes all combinations of equations and - * variables to solve for, and it then uses SuchThat to find an expression - * for this variable, and then if found backsubstitutes it in the other - * equations in the hope that they become simpler, resulting in a final - * set of solutions. - */ -10 # Solve'SimpleBackSubstitution(eq_IsList,var_IsList) <-- -[ - If(InVerboseMode(), Echo({"Entering Solve'SimpleBackSubstitution"})); - - Local(result,i,j,nrvar,nreq,sub,nrSet,origEq); - eq:=FlatCopy(eq); - origEq:=FlatCopy(eq); - nrvar:=Length(var); - result:={FlatCopy(var)}; - nrSet := 0; - -//Echo("Before: ",eq); - ForEach(equation,origEq) - [ -//Echo("equation ",equation); - Solve'SimpleBackSubstitution'FindAlternativeForms(equation); - ]; -// eq:=Simplify(eq); -//Echo("After: ",eq); - - nreq:=Length(eq); - - /* Loop over each variable, solving for it */ - -/* Echo({eq}); */ - - For(j:=1,j<=nreq And nrSet < nrvar,j++) - [ - Local(vlist); - vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt))); - For(i:=1,i<=nrvar And nrSet < nrvar,i++) - [ - -//Echo("eq[",j,"] = ",eq[j]); -//Echo("var[",i,"] = ",var[i]); -//Echo("varlist = ",vlist); -//Echo(); - - If(Count(vlist,var[i]) = 1, - [ - sub := Listify(eq[j]); - sub := sub[2]-sub[3]; -//Echo("using ",sub); - sub:=SuchThat(sub,var[i]); - If(InVerboseMode(), Echo({"From ",eq[j]," it follows that ",var[i]," = ",sub})); - If(SolveFullSimplify=True, - result:=Simplify(Subst(var[i],sub)result), - result[1][i]:=sub - ); -//Echo("result = ",result," i = ",i); - nrSet++; - -//Echo("current result is ",result); - Local(k,reset); - reset:=False; - For(k:=1,k<=nreq And nrSet < nrvar,k++) - If(Contains(VarListAll(eq[k],`Lambda({pt},Contains(@var,pt))),var[i]), - [ - Local(original); - original:=eq[k]; - eq[k]:=Subst(var[i],sub)eq[k]; - If(Simplify(Simplify(eq[k])) = (0 == 0), - eq[k] := (0 == 0), - Solve'SimpleBackSubstitution'FindAlternativeForms(eq[k]) - ); -// eq[k]:=Simplify(eq[k]); -// eq[k]:=Simplify(eq[k]); //@@@??? TODO I found one example where simplifying twice gives a different result from simplifying once! - If(original!=(0==0) And eq[k] = (0 == 0),reset:=True); - If(InVerboseMode(), Echo({" ",original," simplifies to ",eq[k]})); - ]); - nreq:=Length(eq); - vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt))); - i:=nrvar+1; - // restart at the beginning of the variables. - If(reset,j:=1); - ]); - ]; - ]; - - -//Echo("Finished finding results ",var," = ",result); -// eq:=origEq; -// nreq := Length(eq); - Local(zeroeq,tested); - tested:={}; -// zeroeq:=FillList(0==0,nreq); - - ForEach(item,result) - [ -/* - Local(eqSimplified); - eqSimplified := eq; - ForEach(map,Transpose({var,item})) - [ - eqSimplified := Subst(map[1],map[2])eqSimplified; - ]; - eqSimplified := Simplify(Simplify(eqSimplified)); - - Echo(eqSimplified); - - If(eqSimplified = zeroeq, - [ - DestructiveAppend(tested,Map("==",{var,item})); - ]); -*/ - DestructiveAppend(tested,Map("==",{var,item})); - ]; - - - -/* Echo({"tested is ",tested}); */ - If(InVerboseMode(), Echo({"Leaving Solve'SimpleBackSubstitution"})); - tested; -]; - - - - -/********** OldSolve **********/ -10 # OldSolve(eq_IsList,var_IsList) <-- Solve'SimpleBackSubstitution(eq,var); - - -90 # OldSolve((left_IsList) == right_IsList,_var) <-- - OldSolve(Map("==",{left,right}),var); - - -100 # OldSolve(_left == _right,_var) <-- - SuchThat(left - right , 0 , var); - -/* HoldArg("OldSolve",arg1); */ -/* HoldArg("OldSolve",arg2); */ - - -10 # ContainsExpression(_body,_body) <-- True; -15 # ContainsExpression(body_IsAtom,_expr) <-- False; -20 # ContainsExpression(body_IsFunction,_expr) <-- -[ - Local(result,args); - result:=False; - args:=Tail(Listify(body)); - While(args != {}) - [ - result:=ContainsExpression(Head(args),expr); - args:=Tail(args); - if (result = True) (args:={}); - ]; - result; -]; - - -SuchThat(_function,_var) <-- SuchThat(function,0,var); - -10 # SuchThat(_left,_right,_var)_(left = var) <-- right; - -/*This interferes a little with the multi-equation solver... -15 # SuchThat(_left,_right,_var)_CanBeUni(var,left-right) <-- - PSolve(MakeUni(left-right,var)); -*/ - -20 # SuchThat(left_IsAtom,_right,_var) <-- var; - -30 # SuchThat((_x) + (_y),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right-y , var); -30 # SuchThat((_y) + (_x),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right-y , var); - -30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(r,var) <-- - SuchThat(r , right-I*i , var); -30 # SuchThat(Complex(_r,_i),_right,_var)_ContainsExpression(i,var) <-- - SuchThat(i , right+I*r , var); - -30 # SuchThat(_x * _y,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right/y , var); -30 # SuchThat(_y * _x,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right/y , var); - -30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right^(1/y) , var); -30 # SuchThat(_x ^ _y,_right,_var)_ContainsExpression(y,var) <-- - SuchThat(y , Ln(right)/Ln(x) , var); - -30 # SuchThat(Sin(_x),_right,_var) <-- - SuchThat(x , ArcSin(right) , var); -30 # SuchThat(ArcSin(_x),_right,_var) <-- - SuchThat(x , Sin(right) , var); - -30 # SuchThat(Cos(_x),_right,_var) <-- - SuchThat(x , ArcCos(right) , var); -30 # SuchThat(ArcCos(_x),_right,_var) <-- - SuchThat(x , Cos(right) , var); - -30 # SuchThat(Tan(_x),_right,_var) <-- - SuchThat(x , ArcTan(right) , var); -30 # SuchThat(ArcTan(_x),_right,_var) <-- - SuchThat(x , Tan(right) , var); - -30 # SuchThat(Exp(_x),_right,_var) <-- - SuchThat(x , Ln(right) , var); -30 # SuchThat(Ln(_x),_right,_var) <-- - SuchThat(x , Exp(right) , var); - -30 # SuchThat(_x / _y,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right*y , var); -30 # SuchThat(_y / _x,_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , y/right , var); - -30 # SuchThat(- (_x),_right,_var) <-- - SuchThat(x , -right , var); - -30 # SuchThat((_x) - (_y),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , right+y , var); -30 # SuchThat((_y) - (_x),_right,_var)_ContainsExpression(x,var) <-- - SuchThat(x , y-right , var); - -30 # SuchThat(Sqrt(_x),_right,_var) <-- - SuchThat(x , right^2 , var); - - -Function("SolveMatrix",{matrix,vector}) -[ - Local(perms,indices,inv,det,n); - n:=Length(matrix); - indices:=Table(i,i,1,n,1); - perms:=Permutations(indices); - inv:=ZeroVector(n); - det:=0; - ForEach(item,perms) - [ - Local(i,lc); - lc := LeviCivita(item); - det:=det+Factorize(i,1,n,matrix[i][item[i] ])* lc; - For(i:=1,i<=n,i++) - [ - inv[i] := inv[i]+ - Factorize(j,1,n, - If(item[j] =i,vector[j ],matrix[j][item[j] ]))*lc; - ]; - ]; - Check(det != 0, "Zero determinant"); - (1/det)*inv; -]; - - - -Function("Newton",{function,variable,initial,accuracy}) -[ // since we call a function with HoldArg(), we need to evaluate some variables by hand - `Newton(@function,@variable,initial,accuracy,-Infinity,Infinity); -]; - -Function("Newton",{function,variable,initial,accuracy,min,max}) -[ - Local(result,adjust,delta,requiredPrec); - MacroLocal(variable); - requiredPrec := BuiltinPrecisionGet(); - accuracy:=N((accuracy/10)*10); // Making sure accuracy is rounded correctly - BuiltinPrecisionSet(requiredPrec+2); - function:=N(function); - adjust:= -function/Apply("D",{variable,function}); - delta:=10000; - result:=initial; - While (result > min And result < max - // avoid numerical underflow due to fixed point math, FIXME when have real floating math - And N(Eval( Max(Re(delta), -Re(delta), Im(delta), -Im(delta)) ) ) > accuracy) - [ - MacroSet(variable,result); - delta:=N(Eval(adjust)); - result:=result+delta; - ]; - - BuiltinPrecisionSet(requiredPrec); - result:=N(Eval((result/10)*10)); // making sure result is rounded to correct precision - if (result <= min Or result >= max) [result := Fail;]; - result; -]; - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/solve.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/solve.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/solve.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/solve.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -Solve -OldSolve -SuchThat -Newton -SolveMatrix -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bernou.mpi mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bernou.mpi --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bernou.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bernou.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,121 +0,0 @@ -/// Simple implementation of the recurrence relation: create an array of Bernoulli numbers -// special cases: n=0 or n=1 -10 # Internal'BernoulliArray(n_IsInteger)_(n=0 Or n=1) <-- [ - Local(B); - B:=ArrayCreate(n+1,0); - B[1] := 1; - If(n=1, B[2] := -1/2); - B; -]; -/// Assume n>=2 -20 # Internal'BernoulliArray(n_IsInteger) <-- [ - Local(B, i, k, k2, bin); - If (InVerboseMode(), Echo({"Internal'BernoulliArray: using direct recursion, n = ", n})); - B:=ArrayCreate(n+1, 0); // array of B[k], k=1,2,... where B[1] is the 0th Bernoulli number - // it would be better not to store the odd elements but let's optimize this later - // we could also maintain a global cache of Bernoulli numbers computed so far, but it won't really speed up things at large n - // all odd elements after B[2] are zero - B[1] := 1; - B[2] := -1/2; - B[3] := 1/6; - For(i:=4, i<=n, i := i+2) // compute and store B[i] - [ // maintain binomial coefficient - bin := 1; // Bin(i+1,0) - // do not sum over odd elements that are zero anyway - cuts time in half - B[i+1] := 1/2-1/(i+1)*(1 + Sum(k, 1, i/2-1, - [ - bin := bin * (i+3-2*k) * (i+2-2*k)/ (2*k-1) / (2*k); - B[2*k+1]*bin; // *Bin(i+1, 2*k) - ] - ) ); - ]; - B; -]; - -/// Find the fractional part of Bernoulli number with even index >=2 -/// return negative if the sign of the Bernoulli number is negative -BernoulliFracPart(n_IsEven)_(n>=2) <-- [ - Local(p, sum); - // always 2 and 3 - sum := 1/2+1/3; - // check whether n+1 and n/2+1 are prime - If(IsPrime(n+1), sum := sum+1/(n+1)); - If(IsPrime(n/2+1), sum := sum+1/(n/2+1)); - // sum over all primes p such that n / p-1 is integer - // enough to check up to n/3 now - For(p:=5, p<=n/3+1, p:=NextPrime(p)) - If(Mod(n, p-1)=0, sum := sum + 1/p); - // for negative Bernoulli numbers, let's change sign - // Mod(n/2, 2) is 0 for negative Bernoulli numbers and 1 for positive ones - Div(Numer(sum), Denom(sum)) - sum - + Mod(n/2,2); // we'll return a negative number if the Bernoulli itself is negative -- slightly against our definitions in the manual - //+ 1; // this would be exactly like the manual says -]; - -/// Find one Bernoulli number for large index -/// compute Riemann's zeta function and combine with the fractional part -Bernoulli1(n_IsEven)_(n>=2) <-- [ - Local(B, prec); - prec := BuiltinPrecisionGet(); - // estimate the size of B[n] using Stirling formula - // and compute Ln(B[n])/Ln(10) to find the number of digits - BuiltinPrecisionSet(10); - BuiltinPrecisionSet( - Ceil(N((1/2*Ln(8*Pi*n)-n+n*Ln(n/2/Pi))/Ln(10)))+3 // 3 guard digits - ); - If (InVerboseMode(), Echo({"Bernoulli: using zeta funcion, precision ", BuiltinPrecisionSet(), ", n = ", n})); - B := Floor(N( // compute integer part of B - If( // use different methods to compute Zeta function - n>250, // threshold is roughly right for internal math - Internal'ZetaNum2(n, n/17+1), // with this method, a single Bernoulli number n is computed in O(n*M(P)) operations where P = O(n*Ln(n)) is the required precision - // Brent's method requires n^2*P+n*M(P) - // simple array method requires - Internal'ZetaNum1(n, n/17+1) // this gives O(n*Ln(n)*M(P)) - ) - *N(2*n! /(2*Pi)^n))) - // 2*Pi*e is approx. 17, add 1 to guard precision - * (2*Mod(n/2,2)-1) // sign of B - + BernoulliFracPart(n); // this already has the right sign - BuiltinPrecisionSet(prec); // restore old precision - B; -]; - -/// Bernoulli numbers; algorithm from: R. P. Brent, "A FORTRAN multiple-precision arithmetic package", ACM TOMS vol. 4, no. 1, p. 57 (1978). -/// this may be good for floating-point (not exact) evaluation of B[n] at large n -/// but is not good at all for exact evaluation! (too slow) -/// Brent claims that the usual recurrence is numerically unstable -/// but we can't check this because MathPiper internal math is fixed-point and Brent's algorithm needs real floating point (C[k] are very small and then multiplied by (2*k)! ) -Internal'BernoulliArray1(n_IsEven) _ (n>=2) <-- -[ - Local(C, f, k, j, denom, sum); - C := ArrayCreate(n+1, 0); - f := ArrayCreate(n/2, 0); - C[1] := 1; - C[2] := -1/2; - C[3] := 1/12; // C[2*k+1] = B[2*k]/(2*k)! - f[1] := 2; // f[k] = (2k)! - For(k:=2, k<=n/2, k++) // we could start with k=1 but it would be awkward to compute f[] recursively - [ - // compute f[k] - f[k] := f[k-1] * (2*k)*(2*k-1); - // compute C[k] - C[2*k+1] := 1/(1-4^(-k))/2*( - [ - denom := 4; // = 4^1 - sum := 0; - For(j:=1, j<=k-1, j++) - [ - sum := sum + C[2*(k-j)+1]/denom/f[j]; // + C[k-j]/(2*j)! /4^j - denom := denom * 4; - ]; - (2*k-1)/denom/f[k] - sum; - ] - ); -// Echo({n, k, denom, C[k]}); - ]; - // multiply C's with factorials to get B's - For(k:=1, k<=n/2, k++) - C[2*k+1] := C[2*k+1] * f[k]; - // return array object - C; -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bernou.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bernou.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bernou.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bernou.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -BernoulliFracPart -Bernoulli1 -Internal'BernoulliArray -Internal'BernoulliArray1 -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bessel.mpi mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bessel.mpi --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bessel.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bessel.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -/// coded by Jonathan Leto - -// When x is <= 1, the series is monotonely decreasing from the -// start, so we don't have to worry about loss of precision from the -// series definition. -// When {n} is an integer, this is fast. -// When {n} is not, it is pretty slow due to Gamma() - -Function("BesselNsmall",{n,x,modified}) -[ - Local(term,result,k); - Local(prec,eps,tmp); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(Ceil(1.2*prec)); // this is a guess - eps:=5*10^(-prec); - - term:=1; - k:=0; - result:=0; - While( Abs(term) >= eps )[ - term:=x^(2*k+n); - // The only difference between BesselJ and BesselI - // is an alternating term - If( k%2=1 And modified=0 , term:=term*-1 ); - term:=N(term/(2^(2*k+n)* k! * Gamma(k+n+1) )); - //Echo({"term is ",term}); - result:=result+term; - k:=k+1; - ]; - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - RoundTo(result,prec); - -]; - -// Seems to get about 8 digits precision for most real numbers -// Only about 2 digits precision for complex -// This is just a temporary implementation, I would not want to -// expose users to it until it is much more robust -// I am still looking for a good arbitrary precision algorithm. -Function("BesselJN0",{x}) -[ - Local(ax,z,xx,y,result,res1,res2); - Local(c1,c2,c3,c4); - - // Coefficients of the rational polynomials to - // approx J_0 for x < 8 - c1:={57568490574.0,-13362590354.0,651619640.7, - -11214424.18,77392.33017,-184.9052456}; - c2:={57568490411.0,1029532985.0,9494680.718, - 59272.64853,267.8532712}; - // Coefficients of the rational polynomials to - // approx J_0 for x >= 8 - c3:={-0.001098628627,0.00002734510407,-0.000002073370639, - 0.0000002093887211}; - c4:={-0.01562499995,0.0001430488765,-0.000006911147651, - 0.0000007621095161,0.0000000934935152}; - ax:=Abs(x); - - If( ax < 8.0,[ - y:=x^2; - res1:=c1[1]+y*(c1[2]+y*c1[3]+y*(c1[4]+y*(c1[5]+y*(c1[6])))); - res2:=c1[1]+y*(c2[2]+y*c2[3]+y*(c2[4]+y*(c2[5]+y*1.0))); - result:=res1/res2; - ],[ - z:=8/ax; - y:=z^2; - xx:=ax-0.785398164; - res1:=1.0+y*(c3[1]+y*(c3[2]+y*(c3[3]+y*c4[4]))); - res2:=c4[1]+y*(c4[2]+y*(c4[3]+y*(c4[4]-y*c4[5]))); - result:=Sqrt(2/(Pi*x))*(Cos(xx)*res1-z*Sin(xx)*res2); - ] ); -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bessel.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bessel.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/bessel.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/bessel.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -BesselNsmall -BesselJN -BesselJN0 -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,524 +0,0 @@ -/// special functions coded for MathPiper by Serge Winitzki: Gamma, Zeta, Bernoulli, LambertW - -/// coded by Jonathan Leto: PolyLog, Dirichlet*, Digamma, Bessel*, Erf*, Fresnel*, Beta, -/// CatalanConstNum, Sinc, Beta, DawsonIntegral - -///////////////////////////////////////////////// -/// Euler's Gamma function -///////////////////////////////////////////////// - -/// User visible functions: Gamma(x), LnGamma(x) - -5 # Gamma(Infinity) <-- Infinity; - -10 # Gamma(_n)_(IsInteger(n) And n<=0) <-- Infinity; -10 # LnGamma(_n)_(IsInteger(n) And n<=0) <-- Infinity; - -20 # Gamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- (Round(2*n)/2-1)!; -20 # LnGamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- Ln((Round(2*n)/2-1)!); - -30 # Gamma(x_IsConstant)_(InNumericMode()) <-- Internal'GammaNum(N(Eval(x))); -30 # LnGamma(x_IsConstant)_(InNumericMode()) <-- Internal'LnGammaNum(N(Eval(x))); - -///////////////////////////////////////////////// -/// Riemann's Zeta function -///////////////////////////////////////////////// - -/// identities for exact values of Zeta - -10 # Zeta(1) <-- Infinity; -10 # Zeta(0) <-- -1/2; // let's save time -10 # Zeta(3)_InNumericMode() <-- Zeta3(); // special case -10 # Zeta(n_IsEven)_(n>0) <-- Pi^n*(2^(n-1)/n! *Abs(Bernoulli(n))); -10 # Zeta(n_IsInteger)_(n<0) <-- -Bernoulli(-n+1)/(-n+1); -11 # Zeta(n_IsInfinity) <-- 1; - -/// compute numeric value -20 # Zeta(s_IsConstant)_(InNumericMode()) <-- Internal'ZetaNum(N(Eval(s))); - -///////////////////////////////////////////////// -/// Bernoulli numbers and polynomials -///////////////////////////////////////////////// - -/// Bernoulli(n): interface to Bernoulli numbers -10 # Bernoulli(0) <-- 1; -10 # Bernoulli(1) <-- -1/2; -15 # Bernoulli(n_IsInteger)_(n<0) <-- Undefined; -30 # Bernoulli(n_IsOdd) <-- 0; - -/// numerical computations of Bernulli numbers use two different methods, one good for small numbers and one good only for very large numbers (using Zeta function) -20 # Bernoulli(n_IsEven)_(n<=Bernoulli1Threshold()) <-- Internal'BernoulliArray(n)[n+1]; -20 # Bernoulli(n_IsEven)_(n>Bernoulli1Threshold()) <-- Bernoulli1(n); - -LocalSymbols(bernoulli1Threshold) [ - /// Bernoulli1Threshold could in principle be set by the user - If(Not IsBound(bernoulli1Threshold), bernoulli1Threshold := 20); - - Bernoulli1Threshold() := bernoulli1Threshold; - SetBernoulli1Threshold(threshold) := [ bernoulli1Threshold := threshold;]; - -] ; // LocalSymbols(bernoulli1Threshold) - -/// Bernoulli polynomials of degree n in variable x -Bernoulli(n_IsInteger, _x) <-- [ - Local(B, i, result); - B := Internal'BernoulliArray(n); - result := B[1]; - For(i:=n-1, i>=0, i--) [ - result := result * x + B[n-i+1]*Bin(n,i); - ]; - result; -]; - -///////////////////////////////////////////////// -/// Bessel and related functions -///////////////////////////////////////////////// - -10 # BesselJ(0,0) <-- 1; -10 # BesselI(0,0) <-- 1; -10 # BesselJ(_n,0)_(n>0) <-- 0; -10 # BesselI(_n,0)_(n>0) <-- 0; -10 # BesselJ(_n,0)_(n<0 And IsInteger(n)) <-- 0; -10 # BesselI(_n,0)_(n<0 And IsInteger(n)) <-- 0; -10 # BesselJ(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity; - -// The following should be ComplexInfinity, if/when that is implemented -10 # BesselI(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity; - -10 # BesselJ(0,Infinity)<-- 0; -20 # BesselJ(1/2,_x) <-- Sqrt(2/(x*Pi))*Sin(x); -20 # BesselI(1/2,_x) <-- Sqrt(2/(x*Pi))*Sinh(x); -20 # BesselJ(-1/2,_x) <-- Sqrt(2/(x*Pi))*Cos(x); -20 # BesselJ(3/2,_x) <-- Sqrt(2/(x*Pi))*(Sin(x)/x - Cos(x)); - -20 # BesselI(3/2,_x) <-- Sqrt(2/(x*Pi))*(Cosh(x) - Sinh(x)/x); - -20 # BesselJ(-3/2,_x) <-- Sqrt(2/(x*Pi))*(Cos(x)/x + Sin(x)); - -20 # BesselJ(5/2,_x) <-- Sqrt(2/(x*Pi))*((3/x^2 - 1)*Sin(x) - 3*Cos(x)/x ); -20 # BesselI(5/2,_x) <-- Sqrt(2/(x*Pi))*((3/x^2 + 1)*Sinh(x) - 3*Cosh(x)/x ); - -20 # BesselJ(-5/2,_x) <-- Sqrt(2/(x*Pi))*( (3/x^2 -1)*Cos(x) + 3*Sin(x)/x ); - - -// Forward recursion, works great, but really slow when n << x -30 # BesselJ(_n,_x)_(IsConstant(x) And IsInteger(n) And N(Abs(x) > 2*Gamma(n))) <-- N((2*(n+1)/x)*BesselJ(n+1,x) - BesselJ(n+2,x)); - -30 # BesselJ(_n,_z)_(n<0 And IsInteger(n) ) <-- (-1)^n*BesselJ(-n,z); -30 # BesselI(_n,_z)_(n<0 And IsInteger(n) ) <-- BesselI(-n,z); - - -// When I put "And InNumericMode()" on the next rule, I lose precision. Why ? -// Also, if I move the the "_IsComplex" to the end with "IsComplex(x)" -// I lose precision. - -//40 # BesselJ(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N(BesselNsmall(n,x,0)); -//40 # BesselI(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N(BesselNsmall(n,x,1)); -40 # BesselJ(_n,x_IsComplex)_(N(Abs(x)<= 2*Gamma(n)) ) <-- -[ -ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} ); -]; - -40 # BesselI(_n,x_IsComplex)_(IsConstant(x) And Abs(x)<= 2*Gamma(n) ) <-- -[ -ApproxInfSum((x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} ); -]; - - -// This is buggy -40 # BesselY(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) ) <-- N((Cos(n*Pi)*BesselJ(n,x) - BesselJ(-n,x))/Sin(Pi*n)); - -50 # BesselJ(0,x_IsComplex)_(InNumericMode()) <-- N(BesselJN0(x)); - -//50 # BesselJ(_n_IsPositiveNumber,_z_IsComplex) <-- BesselJN(n,z); - - -// Ex: -// Bessel of order n: -// ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),1,x,{n} ); - -Function("ApproxInfSum",{expr,start,x})[ - ApproxInfSum(expr,start,x,{0}); -]; - -/// FIXME this has a roundoff problem when InNumericMode()=True -// Summation must be on k -Function("ApproxInfSum",{expr,start,x,c}) -[ - Local(term,result,k); - Local(prec,eps,tmp); - prec:=BuiltinPrecisionGet(); -// BuiltinPrecisionSet(Ceil(1.2*prec)); // this is a guess - BuiltinPrecisionSet(prec+2); // this is a guess -// eps:=5*10^(-prec); - eps:=10^(-prec); -//Echo(expr); -//Echo(" eps = ",N(Eval(eps))); - - term:=1; - k:=start; - result:=0; - While( N(Abs(term) >= eps) )[ - term:=N(Eval(expr)); - //Echo({"term is ",term}); - k:=k+1; - result:=result+term; - - ]; - If(InVerboseMode(), Echo("ApproxInfSum: Info: using ", k, " terms of the series")); - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - -//Echo("lastterm = ",N(Eval(term))); - -//Echo("r1",result); -//Echo("r2",RoundTo(result,prec)); -//Echo("r3",N((result/10)*10)); - - result; -]; - -///////////////////////////////////////////////// -/// Error and complementary error functions -///////////////////////////////////////////////// - -10 # Erf(0) <-- 0; -//10 # Erfc(0) <-- 1; -10 # Erf(Infinity) <-- 1; -10 # Erf(Undefined) <-- Undefined; -//10 # Erfc(Infinity) <-- 0; -10 # Erf(x_IsNumber)_(x<0) <-- -Erf(-x); -//40 # Erf(x_IsNumber)_(Abs(x) <= 1 ) <-- N(2/Sqrt(Pi)*ApproxInfSum((-1)^k*x^(2*k+1)/((2*k+1)*k!),0,x)); - -LocalSymbols(k) -[ - 40 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x)) And Abs(x) <= 1) <-- -[ - Local(prec); - prec := BuiltinPrecisionGet(); // N(...) modifies the precision - 2 / SqrtN(Internal'Pi()) * x - * SumTaylorNum(x^2, 1, {{k}, -(2*k-1)/(2*k+1)/k}, - // the number of terms n must satisfy n*Ln(n/Exp(1))>10^prec -// Hold({{k}, [Echo(k); k;]}) @ - N(1+87/32*Exp(LambertW(prec*421/497)), 20) - ); - -]; - -]; // LocalSymbols(k) - -// asymptotic expansion, can be used only for low enough precision or large enough |x| (see predicates). Also works for complex x. -LocalSymbols(n'max, k) -[ - - 50 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x)) - And ( - [ // strongest condition: the exp(-x^2) asymptotic is already good - n'max := 0; - Re(x^2) > BuiltinPrecisionGet()*3295/1431+0.121; - ] - Or - [ // next condition: the exp(-x^2) helps but we need a few terms of the series too - n'max := N(Min((BuiltinPrecisionGet()*3295/1431+0.121)/Internal'LnNum(Abs(x)), 2*Internal'LnNum(Abs(x))), 10); - 2*Abs(x)+Re(x^2) > BuiltinPrecisionGet()*3295/1431+0.121; - ] - Or - [ // worst case: exp(-x^2) does not help and we need the full series - // hack: save a value computed in the predicate to use in the body of rule - n'max := N(({{k}, k+Internal'LnNum(k)} @ BuiltinPrecisionGet()*3295/1431)/2 - 3/2, 10); - Abs(x) > n'max+3/2; - ] - ) - ) <-- If(Re(x)!=0, Sign(Re(x)), 0) - Exp(-x^2)/x/SqrtN(Internal'Pi()) - // the series is 1 - 1/2/x^2 + 1*3/2^2/x^4 - 1*3*5/2^3/x^6 + ... - * SumTaylorNum(1/x^2, 1, {{k}, -(2*k-1)/2 }, Max(0, Floor(n'max))); - -]; // LocalSymbols(n'max, k) - -10 # Erfc(_x) <-- 1 - Erf(x); -10 # Erfi(_x) <-- -I*Erf(x*I); - -///////////////////////////////////////////////// -/// Fresnel integrals -///////////////////////////////////////////////// - -10 # FresnelSin(0) <-- 0; -10 # FresnelSin(Infinity) <-- 1/2; -10 # FresnelSin(x_IsNumber)_(x<0) <-- -FresnelSin(x); -10 # FresnelCos(0) <-- 0; -10 # FresnelCos(Infinity) <-- 1/2; -10 # FresnelCos(x_IsNumber)_(x<0) <-- -FresnelCos(x); - -40 # FresnelSin(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(2*k+1)/(k! * (2*k+1)),1,x)); -40 # FresnelCos(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(4*k-3)/((4*k-3) * (2*k-2)! ),1,x)); - -///////////////////////////////////////////////// -/// Lambert's $W$ function. -///////////////////////////////////////////////// - -10 # LambertW(0) <-- 0; -10 # LambertW(Infinity) <-- Infinity; -10 # LambertW(Undefined) <-- Undefined; -10 # LambertW(-Infinity) <-- Infinity + I*Pi; -10 # LambertW(-Exp(-1)) <-- -1; -20 # LambertW(_x * Ln(_x)) <-- Ln(x); -20 # LambertW(Ln(_x) * _x) <-- Ln(x); - -30 # LambertW(x_IsConstant) _ InNumericMode() <-- Internal'LambertWNum(Eval(x)); - -/* {Internal'LambertWNum} computes a numeric approximation of Lambert's $W$ function -to the current precision. It uses a Halley iteration -$$ W'=W-(W-x*Exp(-W))/(W+1-(W+2)/(W+1)*(W-x*Exp(-W))/2) $$. -The function has real values for real $x >= -Exp(-1)$. (This point is a logarithmic branching point.) -*/ -10 # Internal'LambertWNum(x_IsNumber)_(x < -ExpN(-1)) <-- Undefined; -20 # Internal'LambertWNum(x_IsNumber) <-- -[ - Local(W); - NewtonNum( - `Hold( - { - {W}, - [ - Local(a); - a:=W- @x*ExpN(-W); - W-a/(W+1-(W+2)/(W+1)*a/2.); - ]}), - // initial approximation is the two-point global Pade: - If( - x<0, - x*ExpN(1) / (1+1 / (1 / SqrtN(2*(x*ExpN(1)+1)) - 1 / SqrtN(2) + 1/(ExpN(1)-1))), - Internal'LnNum(1+x)*(1-Internal'LnNum(1+Internal'LnNum(1+x))/(2+Internal'LnNum(1+x))) - ), - 10, // initial approximation is good to about 3 digits - 3 // 3rd order scheme - ); -]; - -10 # Beta(_n,_m) <-- Gamma(m)*Gamma(n)/Gamma(m+n); -10 # DirichletEta(_z) <-- (1-2/2^z)*Zeta(z); -10 # DirichletLambda(_z)<-- (1-1/2^z)*Zeta(z); -10 # Sinc(_x) <-- If(x=0,1,Sin(x)/x); - - -////// Polylogarithm Function -// Note: currently, the numerics are only working for x \in [-1,1] - -10 # PolyLog(_n,0) <-- 0; -// this is nicer than -Ln(1/2) -10 # PolyLog(1,1/2) <-- Ln(2); -10 # PolyLog(_n,1) <-- Zeta(n); -10 # PolyLog(_n,_m)_(m= -1) <-- DirichletEta(n); -10 # PolyLog(_n,_x)_(n< 0) <-- (1/((1-x)^(-n+1)))*Sum(i,0,-n,Eulerian(-n,i)*x^(-n-i) ); -//10 # PolyLog(_n,_x)_(n= -3) <-- x*(x^2 + 4*x + 1)/(x-1)^4; -//10 # PolyLog(_n,_x)_(n= -2) <-- x*(x+1)/(1-x)^3; -//10 # PolyLog(_n,_x)_(n= -1) <-- x/(1-x)^2; -10 # PolyLog(0,_x) <-- x/(1-x); -10 # PolyLog(1,_x) <-- -Ln(1-x); -// special values -10 # PolyLog(2,1/2) <-- (Pi^2 - 6*Ln(2)^2)/12; -10 # PolyLog(3,1/2) <-- (4*Ln(2)^3 - 2*Pi^2*Ln(2)+21*Zeta(3))/24; -10 # PolyLog(2,2) <-- Pi^2/4 - Pi*I*Ln(2); - -20 # PolyLog(_n,_x)_(InNumericMode() And x < -1 ) <-- [ - Local(prec,result); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - Echo("Warning: PolyLog is only currently accurate for x in [-1,1]"); - result:= (-1)^(n-1)*PolyLog(n,1/x) - ((Ln(-x))^n)/n! - - Sum(r,1,Round(n/2), - 2^(2*r-2)*Pi^(2*r)*Abs(Bernoulli(2*r))*Ln(-x)^(n-2*r)/( (2*r)! * (n - 2*r)! ) ); - BuiltinPrecisionSet(prec); - RoundTo(N(result),prec); -]; -20 # PolyLog(_n,_x)_(InNumericMode() And x>= -1 And x < 0 ) <-- [ - // this makes the domain [-1,0) into [0,1], - // so if the summation representation is used, it is monotone - Local(prec,result); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - - result:=PolyLog(n,x^2)/2^(n-1) - PolyLog(n,-x) ; - BuiltinPrecisionSet(prec); - RoundTo(N(result),prec); - -]; -/* this is very slow at high precision -20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x <= 1) <-- [ - Local(result,prec,term,k,eps); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - eps:=10^(-prec); - result:=0; - // Sorry Serge, I was only getting 2 digits of precision with this - // so why didn't you ask me? :) -- Serge - //terms:=Floor(10 + N(prec*Ln(10)/Ln(prec) - 1)); - //BuiltinPrecisionSet( prec + Floor(N(Ln(6*terms)/Ln(10))) ); - //result:=SumTaylorNum(x, {{k}, x^(k+1)/(k+1)^n }, terms ); - term:=1; - For(k:=1,Abs(term)>eps,k++)[ - term:=N(x^k/k^n); - result:=result+term; - ]; - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; -*/ - -20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x < 1) <-- -[ // use Taylor series x^(k+1)/(k+1)^n, converges for -1=1 ) <-- [ - Local(prec,eps,term,result,k); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+3); - eps:=10^(-prec); - result:=0; - term:=1; - For(k:=0, Abs(term) > eps, k++ )[ - term:=(-1)^k/(2*k+1)^x; - Echo("term is ",term); - result:=result+term; - ]; - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; - -///////////////////////////////////////////////// -/// Catalan's constant, various algorithms for comparison. (SW) -///////////////////////////////////////////////// - -/* Brent-Fee's method based on Ramanujan's identity and Brent's trick. - * Geometric convergence as 2^(-n). */ -CatalanConstNum1() := -[ - Local(prec,Aterm,Bterm,nterms,result,n); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(10); - // estimate the number of terms from above - nterms := 1+Floor(N((prec*Ln(10)+Ln(prec*Ln(10)/Ln(2)))/Ln(2))); - BuiltinPrecisionSet(prec+5); - Aterm:=N(1/2); - result:= Aterm; - Bterm:=Aterm; - For(n:=1, n<=nterms, n++ ) - [ -/* - Bterm := MultiplyNum(Bterm, n/(2*n+1)); - Aterm:= DivideN(MultiplyNum(Aterm,n)+Bterm, 2*n+1); -/* this is faster: */ - Bterm:=DivideN(MultiplyN(Bterm,n), 2*n+1); // Bterm = (k!)^2*2^(k-1)/(2*k+1)! - Aterm:=DivideN(MultiplyN(Aterm,n)+Bterm, 2*n+1); // Aterm = Bterm * Sum(k,0,n,1/(2*k+1)) -/**/ - result := result + Aterm; - ]; - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; - -/* Bailey 1997's method. - * Geometric convergence as 4^(-n). */ - -CatalanConstNum() := -[ - Local(prec, n, result); - prec:=BuiltinPrecisionGet(); - - // number of terms - n := 1+Div(prec*1068+642,643); // prec*Ln(10)/Ln(4) - BuiltinPrecisionSet(prec+2); // 2 guard digits - - result := N(1/(2*n+1)); - While(n>0) - [ -/* - result := MultiplyNum(result, n/(4*n+2))+N(1/(2*n-1)); -/* this is faster: */ - result := DivideN(MultiplyN(result, n), 4*n+2)+DivideN(1,2*n-1); -/**/ - n := n-1; - ]; - result := MultiplyNum(result, 3/8) + N(Pi/8*Ln(2+Sqrt(3))); - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; - -/* Broadhurst's series. - * Geometric convergence as 16^(-n). */ - -CatalanConstNum2() := -[ - Local(prec, n, result1, result2); - prec:=BuiltinPrecisionGet(); - - // first series - // number of terms - n := 1+Div(prec*534+642,643); // prec*Ln(10)/Ln(16) - BuiltinPrecisionSet(prec+2); // 2 guard digits - - result1 := 0; - While(n>=0) - [ - result1 := DivideN(result1, 16)+N( - +1/(8*n+1)^2 -1/(8*n+2)^2 +1/2/(8*n+3)^2 -1/4/(8*n+5)^2 +1/4/(8*n+6)^2 -1/8/(8*n+7)^2 - ); - n := n-1; - ]; - - // second series - // number of terms - n := 1+Div(prec*178+642,643); // prec*Ln(10)/Ln(4096) - BuiltinPrecisionSet(prec+2); // 2 guard digits - - result2 := 0; - While(n>=0) - [ - result2 := DivideN(result2, 4096)+N( - +1/(8*n+1)^2 +1/2/(8*n+2)^2 +1/8/(8*n+3)^2 -1/64/(8*n+5)^2 -1/128/(8*n+6)^2 -1/512/(8*n+7)^2 - ); - n := n-1; - ]; - result1 := MultiplyNum(result1, 3/2) - MultiplyNum(result2, 1/4); - BuiltinPrecisionSet(prec); - RoundTo(result1,prec); -]; - - - -10 # Digamma(_n)_(IsPositiveInteger(n)) <-- Sum(m,1,n-1,1/m) - gamma; -// needs Erf() that takes complex argument -/* -10 # DawsonIntegral(_x) <-- [ - Local(result,prec); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec+5); - result:=N(I*Sqrt(Pi)*Exp(-x^2)*Erf(-I*x)/2); - BuiltinPrecisionSet(prec); - RoundTo(result,prec); -]; -*/ - diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -Gamma -LnGamma -Zeta -Bernoulli -ApproxInfSum -BesselJ -BesselI -BesselY -Erf -Erfc -Erfi -FresnelSin -FresnelCos -LambertW -Beta -DirichletEta -DirichletLambda -DirichletBeta -Sinc -PolyLog -CatalanConstNum -Digamma -DawsonIntegral -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gammaconst.mpi mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gammaconst.mpi --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gammaconst.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gammaconst.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - -GammaConstNum() := -[ - Local(k, n, A, B, U'old, U, V'old, V, prec, result); - prec:=BuiltinPrecisionGet(); - NonN([ - BuiltinPrecisionSet(prec+IntLog(prec,10)+3); // 2 guard digits and 1 to compensate IntLog - n:= 1+Ceil(prec*0.5757+0.2862); // n>(P*Ln(10)+Ln(Pi))/4 - A:= -Internal'LnNum(n); - B:=1; - U:=A; - V:=1; - k:=0; - U'old := 0; // these variables are for precision control - V'old := 0; - While(U'old-U != 0 Or V'old-V != 0) - [ - k++; - U'old:=U; - V'old:=V; - // B:=N( B*n^2/k^2 ); - B:=MultiplyNum(B,n^2/k^2); // slightly faster - // A:=N( (A*n^2/k+B)/k ); - A:=MultiplyNum(MultiplyNum(A,n^2/k)+B, 1/k); // slightly faster - U:=U+A; - V:=V+B; - ]; - If(InVerboseMode(), Echo("GammaConstNum: Info: used", k, "iterations at working precision", BuiltinPrecisionGet())); - result:=DivideN(U,V); // N(U/V) - ]); - BuiltinPrecisionSet(prec); // restore precision - RoundTo(result, prec); // return correctly rounded result -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gammaconst.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gammaconst.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gammaconst.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gammaconst.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -GammaConstNum -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gamma.mpi mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gamma.mpi --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gamma.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gamma.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -/// special functions coded for MathPiper by Serge Winitzki - -///////////////////////////////////////////////// -/// Euler's Gamma function -///////////////////////////////////////////////// - -/// This procedure computes the uniform approximation for the Gamma function -/// due to Lanczos and Spouge (the so-called "less precise coefficients") -/// evaluated at arbitrary precision by using a large number of terms -/// See J. L. Spouge, SIAM J. of Num. Anal. 31, 931 (1994) -/// See also Paul Godfrey 2001 (unpublished): http://winnie.fit.edu/~gabdo/gamma.txt for a discussion - -/// Calculate the uniform approximation to the logarithm of the Gamma function -/// in the Re z > 0 half-plane; argument z may be symbolic or complex -/// but current value of precision is used -/// Note that we return LnGamma(z), not of z+1 -/// This function should not be used directly by applications -10 # Internal'LnGammaNum(_z, _a)_(N(Re(z))<0) <-- [ - If (InVerboseMode(), Echo({"Internal'LnGammaNum: using 1-z identity"})); - N(Ln(Pi/Sin(Pi*z)) - Internal'LnGammaNum(1-z, a)); -]; -20 # Internal'LnGammaNum(_z, _a) <-- [ - Local(e, k, tmpcoeff, coeff, result); - a := Max(a, 4); // guard against low values - If (InVerboseMode(), Echo({"Internal'LnGammaNum: precision parameter = ", a})); - e := N(Exp(1)); - k:=Ceil(a); // prepare k=N+1; the k=N term is probably never significant but we don't win much by excluding it - result := 0; // prepare for last term - // use Horner scheme to prevent loss of precision - While(k>1) [ // 'result' will accumulate just the sum for now - k:=k-1; - result := N( PowerN(a-k,k)/((z+k)*Sqrt(a-k))-result/(e*k) ); - ]; - N(Ln(1+Exp(a-1)/Sqrt(2*Pi)*result) + Ln(2*Pi)/2 -a-z+(z+1/2)*Ln(z+a) - Ln(z)); -]; - -Internal'LnGammaNum(z) := [ - Local(a, prec, result); - prec := BuiltinPrecisionGet(); - a:= Div((prec-IntLog(prec,10))*659, 526) + 0.4; // see algorithm docs - /// same as parameter "g" in Godfrey 2001. - /// Chosen to satisfy Spouge's error bound: - /// error < Sqrt(a)/Real(a+z)/(2*Pi)^(a+1/2) -// Echo({"parameter a = ", a, " setting precision to ", Ceil(prec*1.4)}); - BuiltinPrecisionSet(Ceil(prec*1.4)); // need more precision b/c of roundoff errors but don't know exactly how many digits - result := Internal'LnGammaNum(z,a); - BuiltinPrecisionSet(prec); - result; -]; - -Internal'GammaNum(z) := N(Exp(Internal'LnGammaNum(z))); - -/// this should not be used by applications -Internal'GammaNum(z,a) := N(Exp(Internal'LnGammaNum(z,a))); - diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gamma.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gamma.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/gamma.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/gamma.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -Internal'GammaNum -Internal'LnGammaNum -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -// From code.mpi.def: -OMDef( "Gamma", "nums1", "gamma" ); -OMDef( "LnGamma" , "piper", "LnGamma" ); -OMDef( "Zeta" , "piper", "Zeta" ); -OMDef( "Bernoulli" , "piper", "Bernoulli" ); -OMDef( "ApproxInfSum" , "piper", "ApproxInfSum" ); -OMDef( "BesselJ" , "piper", "BesselJ" ); -OMDef( "BesselI" , "piper", "BesselI" ); -OMDef( "BesselY" , "piper", "BesselY" ); -OMDef( "Erf" , "piper", "Erf" ); -OMDef( "Erfc" , "piper", "Erfc" ); -OMDef( "Erfi" , "piper", "Erfi" ); -OMDef( "FresnelSin" , "piper", "FresnelSin" ); -OMDef( "FresnelCos" , "piper", "FresnelCos" ); -OMDef( "LambertW" , "piper", "LambertW" ); -OMDef( "Beta" , "piper", "Beta" ); -OMDef( "DirichletEta" , "piper", "DirichletEta" ); -OMDef( "DirichletLambda", "piper", "DirichletLambda" ); -OMDef( "DirichletBeta" , "piper", "DirichletBeta" ); -OMDef( "Sinc" , "piper", "Sinc" ); -OMDef( "PolyLog" , "piper", "PolyLog" ); -OMDef( "CatalanConstNum", "piper", "CatalanConstNum" ); -OMDef( "Digamma" , "piper", "Digamma" ); -OMDef( "DawsonIntegral" , "piper", "DawsonIntegral" ); diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/zeta.mpi mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/zeta.mpi --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/zeta.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/zeta.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -/// special functions coded for MathPiper by Serge Winitzki - -///////////////////////////////////////////////// -/// Riemann's Zeta function -///////////////////////////////////////////////// - -/// See: Bateman, Erdelyi: Higher Transcendental Functions, vol. 1; -/// P. Borwein, An efficient algorithm for Riemann Zeta function (1995). - -/// Numerical computation of Zeta function using Borwein's "third" algorithm -/// The value of $n$ must be large enough to ensure required precision -/// Also $s$ must satisfy $Re(s)+n+1 > 0$ -Internal'ZetaNum(_s, n_IsInteger) <-- [ - Local(result, j, sign); - If (InVerboseMode(), Echo({"Internal'ZetaNum: Borwein's method, precision ", BuiltinPrecisionGet(), ", n = ", n})); - result := 0; - sign := 1; // flipping sign - For(j:=0, j<=2*n-1, j++) - [ // this is suboptimal b/c we can compute the coefficients a lot faster in this same loop, but ok for now - result := N(result + sign*Internal'ZetaNumCoeffEj(j,n)/(1+j)^s ); - sign := -sign; - ]; - N(result/(2^n)/(1-2^(1-s))); -]; - -/// direct method -- only good for large s -Internal'ZetaNum1(s, limit) := [ - Local(i, sum); - If (InVerboseMode(), Echo({"Internal'ZetaNum: direct method (sum), precision ", BuiltinPrecisionGet(), ", N = ", limit})); - sum := 0; - limit := Ceil(N(limit)); - For(i:=2, i<=limit, i++) sum := sum+N(1/PowerN(i, s)); -// sum := sum + ( N( 1/PowerN(limit, s-1)) + N(1/PowerN(limit+1, s-1)) )/2/(s-1); // these extra terms don't seem to help much - sum+1; // add small terms together and then add 1 -]; -/// direct method -- using infinite product. For internal math, Internal'ZetaNum2 is faster for Bernoulli numbers > 250 or so. -Internal'ZetaNum2(s, limit) := -[ - Local(i, prod); - If (InVerboseMode(), Echo({"Internal'ZetaNum: direct method (product), precision ", BuiltinPrecisionGet(), ", N = ", limit})); - prod := N( (1-1/PowerN(2, s))*(1-1/PowerN(3,s)) ); - limit := Ceil(N(limit)); - For(i:=5, i<=limit, i:= NextPrime(i)) - prod := prod*N(1-1/PowerN(i, s)); - 1/prod; -]; - -/// Compute coefficients e[j] (see Borwein -- excluding (-1)^j ) -Internal'ZetaNumCoeffEj(j,n) := [ - Local(k); - 2^n-If(j1-s identity, s=", s, ", precision ", prec})); - result := 2*Exp(Internal'LnGammaNum(1-s)-(1-s)*Ln(2*Internal'Pi()))*Sin(Internal'Pi()*s/2) * Internal'ZetaNum(1-s); - ], - // choose between methods - If (N(Re(s)) > N(1+(prec*Ln(10))/(Ln(prec)+0.1), 6), - [ // use direct summation - n:= N(10^(prec/(s-1)), 6)+2; // 2 guard terms - BuiltinPrecisionSet(prec+2); // 2 guard digits - result := Internal'ZetaNum1(s, n); - ], - [ // use Internal'ZetaNum(s, n) - n := Ceil( N( prec*Ln(10)/Ln(8) + 2, 6 ) ); // add 2 digits just in case - BuiltinPrecisionSet(prec+2); // 2 guard digits - result := Internal'ZetaNum(s, n); - ] - ) - ); - BuiltinPrecisionSet(prec); - result; -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/zeta.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/zeta.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/specfunc.rep/zeta.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/specfunc.rep/zeta.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -Internal'ZetaNum -Internal'ZetaNum1 -Internal'ZetaNum2 -Zeta3 -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/distributions.mpi mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/distributions.mpi --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/distributions.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/distributions.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* Guard against distribution objects with senseless parameters - Anti-nominalism */ -BernoulliDistribution(p_IsRationalOrNumber)_(p<0 Or p>1) <-- Undefined; -BinomialDistribution(_p, _n)_ - (If(IsRationalOrNumber(p),p<0 Or p>1, False) - Or (IsConstant(n) And Not IsPositiveInteger(n)) ) - <-- Undefined; -DiscreteUniformDistribution(a_IsRationalOrNumber, b_IsRationalOrNumber)_(a>=b) - <-- Undefined; -PoissonDistribution(l_IsRationalOrNumber)_(l<=0) <-- Undefined; -GeometricDistribution(p_IsRationalOrNumber)_(p<0 Or p>1) <-- Undefined; - -ExponentialDistribution(l_IsRationalOrNumber)_(l<0) <-- Undefined; -NormalDistribution( _m , s2_IsRationalOrNumber)_(s2<=0) <-- Undefined; -ChiSquareDistribution(m_IsRationalOrNumber)_(m<=0) <-- Undefined; -tDistribution(m_IsRationalOrNumber)_(Not IsPositiveInteger(m)) <-- Undefined; diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/distributions.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/distributions.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/distributions.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/distributions.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -BernoulliDistribution -BinomialDistribution -DiscreteUniformDistribution -PoissonDistribution -GeometricDistribution - -ExponentialDistribution -NormalDistribution -ChiSquareDistribution -tDistribution -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/hypothesystest.mpi mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/hypothesystest.mpi --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/hypothesystest.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/hypothesystest.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - Hypothesys testing routines - Andrei Zorine,2002 -*/ - -/* Stub: ChiSquare's CDF is computed as IncompleteGamma(x,dof/2)/Gamma(dof/2); */ - -100 # ChiSquareTest( observed'freqs_IsList, expected'freqs_IsList, estimated'params_IsInteger) - <-- - [ - Local( nominator, chi2, p'value, k, dof); - k:=Length(observed'freqs); - nominator:=(observed'freqs-expected'freqs)^2; //threading - chi2:=Sum(i,1,k,nominator[i]/(expected'freqs[i])); - dof := k-estimated'params-1; // degrees of freedom - p'value:=1-N(IncompleteGamma(chi2/2,dof/2)/Gamma(dof/2)); - { TestStatistics <- chi2 , P'value <- p'value,Atom("dof") <- dof}; - - ]; - - -100 # ChiSquareTest( observed'freqs_IsList, - expected'freqs_IsList) <-- ChiSquareTest( observed'freqs, expected'freqs, 0); - diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/hypothesystest.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/hypothesystest.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/hypothesystest.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/hypothesystest.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -ChiSquareTest -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/incompletegamma.mpi mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/incompletegamma.mpi --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/incompletegamma.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/incompletegamma.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* IncompleteGamma function \int\limits_{0}^xt^{a-1}e^{-t}dt - - Calculation is based on series - IncompleteGamma(x,a)=x^a*Sum(k,0,infinity,(-1)^k*x^k/k!/(a+k) - (see D.S.Kouznetsov. Special functions. Vysshaia Shkola, Moscow, 1965) - for small x, and on asymptotic expansion - IncompleteGamma(x,a)=Gamma(x)-x^(a-1)*Exp(-x)*(1+(a-1)/z+(a-1)(a-2)/z^2+...) - (see O.E.Barndorf-Nielsen & D.R.Cox. Asymptotic techniques for Use - in Statistics.. Russian translation is also available) - for large x. -*/ - -IncompleteGamma(_x, _a)_(x<=a+1) <-- -[ - Local(prec,eps); - prec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(Ceil(prec+1)); // this is a guess - eps:=5*10^(-prec); - - Local(term,result,k); - - term:=1/a; - k:=0; - result:=0; - While( Abs(term) >= eps )[ - k:=k+1; - result:=result+term; - term:= -x*(a+k-1)*term/k/(a+k); - ]; - result:= N(x^a*result); - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - RoundTo(result,prec); -]; - - -100 # IncompleteGamma(_x, _a)_(x>a+1) <-- -[ // Asymptotic expansion - Local(prec,eps); - prec:=BuiltinPrecisionGet(); - Builtin'Precision''Set(Ceil(prec+1)); // this is a guess - eps:=5*10^(-prec); - - Local(term,result,k,expr); - - term:=1; - k:=0; - result:=0; - While( Abs(term) >= eps )[ - k:=k+1; - result:=result+term; - term:=term*(a-k)/x; - //Echo({"term is ",term}); - ]; - result:=N(Gamma(a)-x^(a-1)*Exp(-x)*result); - BuiltinPrecisionSet(prec); - // This should not round, only truncate - // some outputs will be off by one in the last digit - RoundTo(result,prec); -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/incompletegamma.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/incompletegamma.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/incompletegamma.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/incompletegamma.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -IncompleteGamma -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/randomtest.mpi mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/randomtest.mpi --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/randomtest.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/randomtest.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* - Tests MathPiper's Randomnumber generator - Author Andrei Zorine, zoav1@uic.nnov.ru -*/ - -DefaultDerivtory("c:/src/ys/prob"); -Load("incompletegamma.mpi"); -Load("hypothesystest.mpi"); - - -Function("DoTest",{size}) -[ - Local(arr,o'f,e'f,i,j,m); -// size:=200; // sample size - arr := Table(Random(),i,1,size,1); - arr := HeapSort(arr,"<"); - o'f := {}; - e'f :={}; - m:=1; - For(i:=1, i<=10 And m<=size, i++) - [ - j:=0; - While(arr[m]>1); - If(Mod(n,2) = 1, sx[n2+1], (sx[n2]+sx[n2+1])/2); -]; - -Variance(x) := Add((x-Mean(x))^2)/Length(x); -UnbiasedVariance(x) := Add((x-Mean(x))^2)/(Length(x)-1); - -// stdev in Wester benchmark -StandardDeviation(x) := Sqrt(UnbiasedVariance(x)); -// Why Sqrt(1.01) --> Sqrt(1.01) ? - diff -Nru mathpiper-0.0.svn2556/storage/scripts/statistics.rep/statistics.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/statistics.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/statistics.rep/statistics.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/statistics.rep/statistics.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -Mean -GeometricMean -Median -Variance -UnbiasedVariance -StandardDeviation -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/stats.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/stats.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/stats.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stats.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -10 # ExpressionDepth(expression_IsFunction) <-- -[ - Local(result); - result:=0; - ForEach(item,Tail(Listify(expression))) - [ - Local(newresult); - newresult:=ExpressionDepth(item); - result:=Max(result,newresult); - ]; - result+1; -]; -20 # ExpressionDepth(_expression) <-- 1; -UnFence("ExpressionDepth",1); - diff -Nru mathpiper-0.0.svn2556/storage/scripts/stats.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/stats.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/stats.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stats.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -ExpressionDepth -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,299 +0,0 @@ -/* Standard analytic functions */ -2 # Sin(x_IsNumber)_InNumericMode() <-- SinNum(x); -4 # Sin(ArcSin(_x)) <-- x; -4 # Sin(ArcCos(_x)) <-- Sqrt(1-x^2); -4 # Sin(ArcTan(_x)) <-- x/Sqrt(1+x^2); -5 # Sin(- _x)_(Not IsConstant(x)) <-- -Sin(x); -6 # (Sin(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -Sin(-x); - -// must prevent it from looping -6 # Sin(x_IsInfinity) <-- Undefined; -6 # Sin(Undefined) <-- Undefined; - -110 # Sin(Complex(_r,_i)) <-- - (Exp(I*Complex(r,i)) - Exp(- I*Complex(r,i))) / (I*2) ; - -1 # SinMap( _n )_(Not(IsRationalOrNumber(n))) <-- UnList({Atom("Sin"),n*Pi}); -2 # SinMap( _n )_(n<0) <-- -SinMap(-n); -2 # SinMap( _n )_(n>2) <-- SinMap(Mod(n,2)); -3 # SinMap( _n )_(n>1) <-- SinMap(n-2); -4 # SinMap( _n )_(n>1/2) <-- SinMap(1-n); - -5 # SinMap( n_IsInteger ) <-- 0; -5 # SinMap( 1/6 ) <-- 1/2; -5 # SinMap( 1/4 ) <-- Sqrt(2)/2; -5 # SinMap( 1/3 ) <-- Sqrt(3)/2; -5 # SinMap( 1/2 ) <-- 1; -5 # SinMap( 1/10) <-- (Sqrt(5)-1)/4; - -10 # SinMap(_n) <-- UnList({Atom("Sin"),n*Pi}); - -200 # Sin(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- -[ - SinMap(Coef(v,Pi,1)); -]; - -2 # Cos(x_IsNumber)_InNumericMode() <-- CosNum(x); -4 # Cos(ArcCos(_x)) <-- x; -4 # Cos(ArcSin(_x)) <-- Sqrt(1-x^2); -4 # Cos(ArcTan(_x)) <-- 1/Sqrt(1+x^2); -5 # Cos(- _x)_(Not IsConstant(x)) <-- Cos(x); -6 # (Cos(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- Cos(-x); -// must prevent it from looping - -110 # Cos(Complex(_r,_i)) <-- - (Exp(I*Complex(r,i)) + Exp(- I*Complex(r,i))) / (2) ; - -1 # CosMap( _n )_(Not(IsRationalOrNumber(n))) <-- UnList({Atom("Cos"),n*Pi}); -2 # CosMap( _n )_(n<0) <-- CosMap(-n); -2 # CosMap( _n )_(n>2) <-- CosMap(Mod(n,2)); -3 # CosMap( _n )_(n>1) <-- CosMap(2-n); -4 # CosMap( _n )_(n>1/2) <-- -CosMap(1-n); - -5 # CosMap( 0 ) <-- 1; -5 # CosMap( 1/6 ) <-- Sqrt(3)/2; -5 # CosMap( 1/4 ) <-- Sqrt(2)/2; -5 # CosMap( 1/3 ) <-- 1/2; -5 # CosMap( 1/2 ) <-- 0; -5 # CosMap( 2/5 ) <-- (Sqrt(5)-1)/4; - -6 # Cos(x_IsInfinity) <-- Undefined; -6 # Cos(Undefined) <-- Undefined; -10 # CosMap(_n) <-- UnList({Atom("Cos"),n*Pi}); - -200 # Cos(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- - CosMap(Coef(v,Pi,1)); - -400 # Cos(x_IsRationalOrNumber) <-- - [ - Local(ll); - ll:= FloorN(N(Eval(x/Pi))); - If(IsEven(ll),x:=(x - Pi*ll),x:=(-x + Pi*(ll+1))); - UnList({Cos,x}); - ]; - -400 # Cos(x_IsRationalOrNumber) <-- - [ - Local(ll); - ll:= FloorN(N(Eval(Abs(x)/Pi))); - If(IsEven(ll),x:=(Abs(x) - Pi*ll),x:=(-Abs(x) + Pi*(ll+1))); - UnList({Cos,x}); - ]; - - -2 # Tan(x_IsNumber)_InNumericMode() <-- TanNum(x); -4 # Tan(ArcTan(_x)) <-- x; -4 # Tan(ArcSin(_x)) <-- x/Sqrt(1-x^2); -4 # Tan(ArcCos(_x)) <-- Sqrt(1-x^2)/x; -5 # Tan(- _x)_(Not IsConstant(x)) <-- -Tan(x); -6 # (Tan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -Tan(-x); - -// must prevent it from looping -6 # Tan(Infinity) <-- Undefined; -6 # Tan(Undefined) <-- Undefined; - -110 # Tan(Complex(_r,_i)) <-- Sin(Complex(r,i))/Cos(Complex(r,i)); - -1 # TanMap( _n )_(Not(IsRationalOrNumber(n))) <-- UnList({Atom("Tan"),n*Pi}); -2 # TanMap( _n )_(n<0) <-- -TanMap(-n); -2 # TanMap( _n )_(n>1) <-- TanMap(Mod(n,1)); -4 # TanMap( _n )_(n>1/2) <-- -TanMap(1-n); - -5 # TanMap( 0 ) <-- 0; -5 # TanMap( 1/6 ) <-- 1/3*Sqrt(3); -5 # TanMap( 1/4 ) <-- 1; -5 # TanMap( 1/3 ) <-- Sqrt(3); -5 # TanMap( 1/2 ) <-- Infinity; - -10 # TanMap(_n) <-- UnList({Atom("Tan"),n*Pi}); - -200 # Tan(v_CanBeUni(Pi))_(Not(InNumericMode()) And Degree(v,Pi) < 2 And Coef(v,Pi,0) = 0) <-- - TanMap(Coef(v,Pi,1)); - - -100 # Sin(_x)/Tan(_x) <-- Cos(x); -100 # Sin(_x)/Cos(_x) <-- Tan(x); -100 # Cos(_x)*Tan(_x) <-- Sin(x); -100 # Cos(_x)/Sin(_x) <-- (1/Tan(x)); -100 # Tan(_x)/Sin(_x) <-- (1/Cos(x)); -100 # Tan(_x)*Cos(_x) <-- Sin(x); -100 # 1/Cot(_x) <-- Tan(x); -100 # 1/Sec(_x) <-- Cos(x); -100 # 1/Csc(_x) <-- Sin(x); -100 # Sec(_x) <-- 1/Cos(x); -100 # Csc(_x) <-- 1/Sin(x); -100 # Cot(_x) <-- 1/Tan(x); - - -2 # Exp(x_IsNumber)_InNumericMode() <-- ExpNum(x); -4 # Exp(Ln(_x)) <-- x; -110 # Exp(Complex(_r,_i)) <-- Exp(r)*(Cos(i) + I*Sin(i)); -200 # Exp(0) <-- 1; -200 # Exp(-Infinity) <-- 0; -200 # Exp(Infinity) <-- Infinity; -200 # Exp(Undefined) <-- Undefined; - -2 # Ln(0) <-- -Infinity; -2 # Ln(1) <-- 0; -2 # Ln(Infinity) <-- Infinity; -2 # Ln(Undefined) <-- Undefined; - -/* 2 # Ln(-Infinity) <-- 0; */ -2 # Ln(x_IsNegativeNumber)_InNumericMode() <-- Complex(Ln(-x), Pi); -3 # Ln(x_IsNumber)_(InNumericMode() And x>=1) <-- Internal'LnNum(x); -4 # Ln(Exp(_x)) <-- x; - -3 # Ln(Complex(_r,_i)) <-- Complex(Ln(Abs(Complex(r,i))), Arg(Complex(r,i))); -4 # Ln(x_IsNegativeNumber) <-- Complex(Ln(-x), Pi); -5 # Ln(x_IsNumber)_(InNumericMode() And x<1) <-- - Internal'LnNum(DivideN(1, x)); - - -2 # ArcSin(x_IsNumber)_(InNumericMode() And Abs(x)<=1) <-- ArcSinNum(x); -/// complex ArcSin -3 # ArcSin(x_IsNumber)_InNumericMode() <-- Sign(x)*(Pi/2+I*ArcCosh(x)); -4 # ArcSin(Sin(_x)) <-- x; -110 # ArcSin(Complex(_r,_i)) <-- - (- I) * Ln((I*Complex(r,i)) + ((1-(Complex(r,i)^2))^(1/2))); - -150 # ArcSin(- _x)_(Not IsConstant(x)) <-- -ArcSin(x); -160 # (ArcSin(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcSin(-x); - -200 # ArcSin(0) <-- 0; -200 # ArcSin(1/2) <-- Pi/6; -200 # ArcSin(Sqrt(1/2)) <-- Pi/4; -200 # ArcSin(Sqrt(3/4)) <-- Pi/3; -200 # ArcSin(1) <-- Pi/2; -200 # ArcSin(_n)_(n = -1) <-- -Pi/2; -200 # ArcSin(_n)_(-n = Sqrt(3/4)) <-- -Pi/3; -200 # ArcSin(_n)_(-n = Sqrt(1/2)) <-- -Pi/4; -200 # ArcSin(_n)_(-n = 1/2) <-- -Pi/6; - -2 # ArcCos(x_IsNumber)_InNumericMode() <-- Internal'Pi()/2-ArcSin(x); -4 # ArcCos(Cos(_x)) <-- x; -5 # (ArcTan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcTan(-x); -110 # ArcCos(Complex(_r,_i)) <-- - (- I)*Ln(Complex(r,i) + (Complex(r,i)^2 - 1)^(1/2)); - /* TODO check! */ - -200 # ArcCos(0) <-- Pi/2; -200 # ArcCos(1/2) <-- Pi/3; -200 # ArcCos(Sqrt(1/2)) <-- Pi/4; -200 # ArcCos(Sqrt(3/4)) <-- Pi/6; -200 # ArcCos(1) <-- 0; -200 # ArcCos(_n)_(n = -1) <-- Pi; -200 # ArcCos(_n)_(-n = Sqrt(3/4)) <-- 5/6*Pi; -200 # ArcCos(_n)_(-n = Sqrt(1/2)) <-- 3/4*Pi; -200 # ArcCos(_n)_(-n = 1/2) <-- 2/3*Pi; - -//TODO fix! 4 # ArcTan(Tan(_x)) <-- x; -4 # ArcTan(-Tan(_x)) <-- -ArcTan(Tan(x)); -110 # ArcTan(Complex(_r,_i)) <-- - (- I*0.5)*Ln(Complex(1,Complex(r,i))/ Complex(1, - Complex(r,i))); - -150 # ArcTan(- _x)_(Not IsConstant(x)) <-- -ArcTan(x); -160 # (ArcTan(x_IsConstant))_(IsNegativeNumber(N(Eval(x)))) <-- -ArcTan(-x); - -200 # ArcTan(Sqrt(3)) <-- Pi/3; -200 # ArcTan(-Sqrt(3)) <-- -Pi/3; -200 # ArcTan(1) <-- Pi/4; -200 # ArcTan(0) <-- 0; -200 # ArcTan(_n)_(n = -1) <-- -Pi/4; - -200 # ArcTan(Infinity) <-- Pi/2; -200 # ArcTan(-Infinity) <-- -Pi/2; -200 # ArcTan(Undefined) <-- Undefined; -200 # ArcSin(Undefined) <-- Undefined; -200 # ArcCos(Undefined) <-- Undefined; - -2 # Sinh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( (Exp(x)-Exp(-x))/2 )); -2 # Cosh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( (Exp(x)+Exp(-x))/2 )); -2 # Tanh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Sinh(x)/Cosh(x) )); - - -10 # ArcSinh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln(x+Sqrt(x^2+1)) )); -10 # ArcCosh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln(x+Sqrt(x^2-1)) )); -10 # ArcTanh(_x)_(InNumericMode() And (IsNumber(x) Or Type(x) = "Complex")) <-- N(Eval( Ln((1+x)/(1-x))/2 )); - -200 # ArcSinh(Infinity) <-- Infinity; -200 # ArcSinh(-Infinity) <-- -Infinity; -200 # ArcSinh(Undefined) <-- Undefined; -200 # ArcCosh(Infinity) <-- Infinity; -200 # ArcCosh(-Infinity) <-- Infinity+I*Pi/2; -200 # ArcCosh(Undefined) <-- Undefined; -200 # ArcTanh(Infinity) <-- Infinity+I*Pi/2; -200 # ArcTanh(-Infinity) <-- -Infinity-I*Pi/2; // this is a little silly b/c we don't support correct branch cuts yet -200 # ArcTanh(Undefined) <-- Undefined; - -/* hyperbolic stuff */ -100 # 1/Coth(_x) <-- Tanh(x); -100 # 1/Sech(_x) <-- Cosh(x); -100 # 1/Csch(_x) <-- Sinh(x); -100 # Sech(_x) <-- 1/Cosh(x); -100 # Csch(_x) <-- 1/Sinh(x); -100 # Coth(_x) <-- 1/Tanh(x); - -5 # Cosh(- _x) <-- Cosh(x); -5 # Sinh(- _x) <-- -Sinh(x); - -100 # Sinh(_x)^2-Cosh(_x)^2 <-- 1; -100 # Sinh(_x)+Cosh(_x) <-- Exp(x); -100 # Sinh(_x)-Cosh(_x) <-- Exp(-x); - -// this is never activated -//100 # Sinh(I*_x) <-- I*Sin(x); -//100 # Cosh(I*_x) <-- Cos(x); - -100 # Sinh(_x)/Cosh(_x) <-- Tanh(x); -100 # Sinh(_x)*Csch(_x) <-- 1; -100 # Cosh(_x)*Sech(_x) <-- 1; -100 # Tanh(_x)*Cosh(_x) <-- Sinh(x); -100 # Coth(_x)*Sinh(_x) <-- Cosh(x); - -200 # Sinh(0) <-- 0; -200 # Sinh(Infinity) <-- Infinity; -200 # Sinh(-Infinity) <-- -Infinity; -200 # Sinh(ArcSinh(_x)) <-- x; -200 # Sinh(ArcCosh(_x)) <-- Sqrt((x-1)/(x+1))*(x+1); -200 # Sinh(ArcTanh(_x)) <-- x/Sqrt(1-x^2); - -200 # Cosh(0) <-- 1; -200 # Cosh(Infinity) <-- Infinity; -200 # Cosh(-Infinity) <-- Infinity; -200 # Cosh(ArcCosh(_x)) <-- x; -200 # Cosh(ArcSinh(_x)) <-- Sqrt(1+x^2); -200 # Cosh(ArcTanh(_x)) <-- 1/Sqrt(1-x^2); - -200 # Tanh(0) <-- 0; -200 # Tanh(Infinity) <-- 1; -200 # Tanh(-Infinity) <-- -1; -200 # Tanh(ArcTanh(_x)) <-- x; -200 # Tanh(ArcSinh(_x)) <-- x/Sqrt(1+x^2); -200 # Tanh(ArcCosh(_x)) <-- Sqrt((x-1)/(x+1))*(x+1)/x; - -200 # Sinh(Undefined) <-- Undefined; -200 # Cosh(Undefined) <-- Undefined; -200 # Tanh(Undefined) <-- Undefined; - -10 # Abs(Infinity) <-- Infinity; - -/* Threading of standard analytic functions */ -Sin(xlist_IsList) <-- MapSingle("Sin",xlist); -Cos(xlist_IsList) <-- MapSingle("Cos",xlist); -Tan(xlist_IsList) <-- MapSingle("Tan",xlist); -Sinh(xlist_IsList) <-- MapSingle("Sinh",xlist); -Cosh(xlist_IsList) <-- MapSingle("Cosh",xlist); -Tanh(xlist_IsList) <-- MapSingle("Tanh",xlist); - - -ArcSin(xlist_IsList) <-- MapSingle("ArcSin",xlist); -ArcCos(xlist_IsList) <-- MapSingle("ArcCos",xlist); -ArcTan(xlist_IsList) <-- MapSingle("ArcTan",xlist); -ArcSinh(xlist_IsList) <-- MapSingle("ArcSinh",xlist); -ArcCosh(xlist_IsList) <-- MapSingle("ArcCosh",xlist); -ArcTanh(xlist_IsList) <-- MapSingle("ArcTanh",xlist); - - -Exp(xlist_IsList) <-- MapSingle("Exp",xlist); -Ln(xlist_IsList) <-- MapSingle("Ln",xlist); - -2 # ArcTan(x_IsNumber)_InNumericMode() <-- ArcTanNum(x); diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -ArcSin -ArcCos -ArcTan -ArcSec -ArcCsc -ArcCot -ArcSinh -ArcCosh -ArcTanh -ArcSech -ArcCsch -ArcCoth -Sin -Cos -Tan -Sec -Csc -Cot -Sinh -Cosh -Tanh -Sech -Csch -Coth -Exp -Ln -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/elemfuncs.mpi mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/elemfuncs.mpi --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/elemfuncs.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/elemfuncs.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,385 +0,0 @@ -/** This file contains routines for numerical evaluation of elementary functions: - * PowerN, ExpN, SinN etc. - * It is assumed that the arguments are real (not complex) floating-point or integer numbers. (The {InNumericMode()} flag does not have to be set.) - * The result is an exact integer or a floating-point number correct to BuiltinPrecisionGet() digits. - * - * If a better optimized version of these functions is available through the kernel, - * then the kernel version will automatically shadow these functions. - * These implementations are not necessarily the best optimized versions. - */ - -/// BitsToDigits(n,base) and DigitsToBits(n,base). Enough to compute at low precision. -// this is now a call to the kernel functions, so leave as a reference implementation -BitsToDigits(n, base) := FloorN(0.51+n*N(Ln(2)/Ln(base),10)); -DigitsToBits(n, base) := FloorN(0.51+n*N(Ln(base)/Ln(2),10)); - - - -/// MathBitCount: count number of bits in an integer or a float number. -/* MathBitCount is now implemented through BigNumber::BitCount() */ -/* so this stays here as a reference implementation */ -10 # MathBitCount(0) <-- 1; -20 # MathBitCount(_x) _ (x<0) <-- MathBitCount(-x); - -30 # MathBitCount(_value) <-- -[ - Local(nbits); - nbits:=0; - If(value<1, - [ // float value < 1, need to multiply by 2 - nbits := 1; - While(value<1) - [ - nbits--; - value := MathMul2Exp(value,1); - ]; - ], - [ // need to divide by 2 - While(value>=1) - [ - nbits++; - value := MathMul2Exp(value, -1); - ]; - ]); - nbits; -]; -/**/ - -/// SqrtN(x). -SqrtN(x) := MathSqrt1(x); // to have another function is easier for debugging - -/// Compute square root(x) with nonnegative x. FIXME: No precision tracking yet. -10 # MathSqrt1(0) <-- 0; -/// negative or non-numeric arguments give error message -100 # MathSqrt1(_x) <-- [ Echo("SqrtN: invalid argument: ", x); False;]; - -// this is too slow at the moment -30 # MathSqrt1(x_IsPositiveNumber) <-- x*NewtonNum({{r}, r+r*(1-x*r^2)/2}, FastPower(x,-0.5), 4, 2); - -30 # MathSqrt1(x_IsPositiveNumber) <-- MathSqrtFloat(x); - -// for integers, we need to compute Sqrt(x) to (the number of bits in x) + 1 bits to figure out whether Sqrt(x) is itself an integer. If Sqrt(x) for integer x is exactly equal to an integer, we should return the integer answer rather than the float answer. For this answer, the current precision might be insufficient, therefore we compute with potentially more digits. This is slower but we assume this is what the user wants when calling SqrtN() on an integer. -20 # MathSqrt1(x_IsInteger) _ (GreaterThan(x,0)) <-- -[ - Local(result); - If(ModN(x,4)<2 And ModN(x,3)<2 And ModN(x+1,5)<3, - // now the number x has a nonzero chance of being an exact square - [ - // check whether increased precision would be at all necessary -// Echo("checking integer case"); - GlobalPush(BuiltinPrecisionGet()); - If(MathBitCount(x)+3>DigitsToBits(BuiltinPrecisionGet(), 10), - BuiltinPrecisionSet(BitsToDigits(MathBitCount(x), 10)+1)); - // need one more digit to decide whether Sqrt(x) is integer - // otherwise the current precision is sufficient - - // convert x to float and use the float routine - result := MathSqrtFloat(x+0.); - // decide whether result is integer: decrease precision and compare - If(FloatIsInt(SetExactBitsN(result, GetExactBitsN(result)-3)), result:= Floor(result+0.5)); - BuiltinPrecisionSet(GlobalPop()); - ], - // now the number x cannot be an exact square; current precision is sufficient - result := MathSqrtFloat(x+0.) - ); - // need to set the correct precision on the result - will have no effect on integer answers - SetExactBitsN(result, DigitsToBits(BuiltinPrecisionGet(),10)); -]; - -// This function is *only* for float and positive A! -// The answer is only obtained at the current precision. -MathSqrtFloat(_A) <-- -[ - Local(bitshift, a0, x0, x0sq, targetbits, subtargetbits, gotbits, targetprec); - bitshift := ShiftRight(MathBitCount(A)-1,1); - // this is how many bits of precision we need - targetprec := BuiltinPrecisionGet(); - // argument reduction: a0 is between 1 and 4 and has the full target precision - a0 := MathMul2Exp(A, -bitshift*2); // this bit shift would be wrong for integer A - BuiltinPrecisionSet(10); // enough to compute at this point - // cannot get more target bits than 1 + (the bits in A) - // if this is less than the requested precision, the result will be silently less precise, but c'est la vie - targetbits := Min(DigitsToBits(targetprec, 10), 1+GetExactBitsN(A)); - // initial approximation - x0 := DivideN(14+22*a0, 31+5*a0); - // this approximation gives at least 7 bits (relative error < 0.005) of Sqrt(a0) for 1 <= a0 <= 4 - gotbits := 7; - // find the conditions for the last 2 iterations to be done in almost optimal precision - subtargetbits := DivN(targetbits+8, 9); - If(gotbits >= subtargetbits, subtargetbits := DivN(targetbits+2, 3)); - If(gotbits >= subtargetbits, subtargetbits := targetbits*4); -// Echo("debug: subtargetbits=", subtargetbits, "a0=", a0, "targetbits=", targetbits, "bitshift=", bitshift, "targetprec=", targetprec); - // now perform Halley iterations until we get at least subtargetbits, then start with subtargetbits and perform further Halley iterations - While(gotbits < targetbits) - [ - gotbits := 3*gotbits+1; // Halley iteration; get 3n+2 bits, allow 1 bit for roundoff - // check for suboptimal last iterations - If(gotbits >= subtargetbits, - [ // it could be very suboptimal to continue with our value of gotbits, so we curb precision for the last 2 iterations which dominate the calculation time at high precision - gotbits := subtargetbits; - subtargetbits := targetbits*4; // make sure that the above condition never becomes true again - ]); - BuiltinPrecisionSet(BitsToDigits(gotbits, 10)+2); // guard digits - x0 := SetExactBitsN(x0, gotbits+6); // avoid roundoff - x0sq := MultiplyN(x0, x0); -// this gives too much roundoff error x0 := MultiplyN(x0, DivideN(3*a0+x0sq, a0+3*x0sq)); -// rather use this equivalent formula: - x0 := AddN(x0, MultiplyN(x0*2, DivideN(a0-x0sq, a0+3*x0sq))); -// Echo("debug: ", gotbits, x0, GetExactBitsN(x0), BuiltinPrecisionGet()); - ]; - // avoid truncating a precise result in x0 by calling BuiltinPrecisionSet() too soon - x0 := SetExactBitsN(MathMul2Exp(x0, bitshift), gotbits); - BuiltinPrecisionSet(targetprec); -// Echo("debug: answer=", x0); - x0; -]; - -//{BisectSqrt(N)} computes the integer part of $ Sqrt(N) $ for integer $N$. -// BisectSqrt() works only on integers - //sqrt(1) = 1, sqrt(0) = 0 -10 # BisectSqrt(0) <-- 0; -10 # BisectSqrt(1) <-- 1; - -20 # BisectSqrt(N_IsPositiveInteger) <-- -[ - Local(l2,u,v,u2,v2,uv2,n); - - // Find highest set bit, l2 - u := N; - l2 := MathBitCount(u)-1; - - // 1<<(l2/2) now would be a good under estimate - // for the square root. 1<<(l2/2) is definitely - // set in the result. Also it is the highest - // set bit. - l2 := l2>>1; - - // initialize u and u2 (u2==u^2). - u := 1 << l2; - u2 := u << l2; - - // Now for each lower bit: - While( l2 != 0 ) - [ - l2--; - // Get that bit in v, and v2 == v^2. - v := 1<0) // lose 'shift' bits of precision here - [ - result := MathMul2Exp(result, 1) + MultiplyN(result, result); - shift--; - ]; - result; -]; - -/// Identity transformation, compute Exp(x) from value=Exp(x/2^n) -/* -ExpN'Doubling(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ - result := MultiplyN(result, result); - shift--; - ]; - result; -]; -*/ - -/// Compute Exp(x)-1 from the Taylor series for (Exp(x)-1)/x. -ExpN'Taylor1(x) := -[ - Local(num'terms, prec, Bx); - prec := DivN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) - Bx := -DivN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 - num'terms := DivN( prec-1, DivN( MathBitCount( prec-1)*1588, 2291)+Bx)+1; - // (P*Ln(10)-1)/(Ln(P*Ln(10)-1)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) - x*SumTaylorNum(x, 1, {{k}, 1/(k+1)}, num'terms); -]; - -/// Compute Sin(x), Taylor series for Sin(x)/x -SinN'Taylor(x) := -[ - Local(num'terms, prec, Bx); - prec := DivN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) - Bx := -DivN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 - num'terms := DivN( DivN( prec+Bx, DivN( MathBitCount( prec+Bx)*1588, 2291)+Bx)+1, 2)+1; - // (P*Ln(10)-Ln(x)-2)/(Ln(P*Ln(10)-Ln(x)-2)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) - x*SumTaylorNum(MultiplyN(x,x), 1, {{k}, -1/(2*k*(2*k+1))}, num'terms); -]; - -/// Identity transformation, compute Sin(x) from value=Sin(x/3^n) - -SinN'Tripling(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ // Sin(x)*(3-4*Sin(x)^2) - result := MultiplyN(result, 3 - MathMul2Exp(MultiplyN(result,result), 2) ); - shift--; - ]; - result; -]; - - -/// Cos(x), Taylor series -CosN'Taylor(x) := -[ - Local(num'terms, prec, Bx); - prec := DivN(BuiltinPrecisionGet()*3919, 1702); // P*Ln(10) - Bx := -DivN(MathBitCount(x)*1143, 1649)-2; // -Ln(x)-2 - num'terms := DivN( DivN( prec-1, DivN( MathBitCount( prec-1)*1588, 2291)+Bx), 2)+1; - // (P*Ln(10)-1)/(Ln(P*Ln(10)-1)-Ln(x)-2); use Ln(x)<=B(x)*Ln(2) - SumTaylorNum(MultiplyN(x,x), 1, {{k}, -1/(2*k*(2*k-1))}, num'terms); -]; - -/// Identity transformation, compute 1-Cos(x) from value=1-Cos(x/2^n) - -CosN'Doubling1(value, n) := -[ - Local(shift, result); - shift := n; - result := value; - While (shift>0) // lose 'shift' bits of precision here - [ - result := MultiplyN(MathMul2Exp(result, 1), 2 - result); - shift--; - ]; - result; -]; - - -/// Ln(x), Taylor series for Ln(1+y)/y, use only with 1/20) // lose 'shift' bits of precision here - [ - result := MultiplyN(result, result); - shift--; - ]; - result; -]; - -/// ArcTan(x), Taylor series for ArcTan(x)/x, use only with -1/2=curprec, k:=Div(k,order)+2) True; - If(k<5, curprec:=5, curprec:=k); - // Echo("initial precision", curprec); - // now k is the iteration counter - For(k:=0, curprec < prec, k := k+1) [ - // at this iteration we know the result to curprec digits - curprec := Min(prec, curprec * order-2); // 2 guard digits - BuiltinPrecisionSet(curprec+2); - // Echo("Iteration ", k, " setting precision to ", BuiltinPrecisionGet()); - // Echo("old result=", CosN(result)); - /*Time*/([ - delta := CosN(result); - ]); - /*Time*/([ - deltasq := MultiplyN(delta,delta); - ]); - result := /*Time*/(result + delta*(1 + deltasq*(1/6 + deltasq*(3/40 + deltasq*(5/112 + deltasq*(35/1152 + (deltasq*63)/2816)))))); - ]; - // Echo({"Method 3, using Pi/2 and order", order, ":", k, "iterations"}); - ]); - result*2; -]; - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/elemfuncs.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/elemfuncs.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/elemfuncs.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/elemfuncs.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -BitsToDigits -DigitsToBits -ArcCosN -ArcTanN -GcdN -SqrtN -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/numerical.mpi mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/numerical.mpi --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/numerical.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/numerical.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,240 +0,0 @@ -/// low-level numerical calculations of elementary functions. -/// These are only called if InNumericMode() returns True - -////////////////////////////////////////////////// -/// Trigonometric functions: Sin, Cos, Tan, ... -////////////////////////////////////////////////// - -/* TruncRadian truncates the radian r so it is between 0 and 2*Pi. - * It calculates r mod 2*Pi using the required precision. - */ -TruncRadian(_r) <-- -[ - Local(twopi); - // increase precision by the number of digits of r before decimal point; enough to evaluate Abs(r) with 1 digit of precision - N([ - r:=Eval(r); - twopi:=2*Internal'Pi(); - r:=r-FloorN(r/twopi)*twopi; - ], BuiltinPrecisionGet() + IntLog(Ceil(Abs(N(Eval(r), 1))), 10)); - r; -]; -HoldArg("TruncRadian",r); - -SinNum(x) := -[ - If(x<0 Or 113*x>710, x:=TruncRadian(x)); // 710/113 is close to 2*Pi - SinN(x); -]; -CosNum(x) := -[ - If(x<0 Or 113*x>710, x:=TruncRadian(x)); - CosN(x); -]; -TanNum(x) := -[ - If(x<0 Or 113*x>710, x:=TruncRadian(x)); - TanN(x); -]; - -ArcSinNum(x) := -[ - // need to be careful when |x| close to 1 - If( - 239*Abs(x) >= 169, // 169/239 is a good enough approximation of 1/Sqrt(2) - // use trigonometric identity to avoid |x| close to 1 - Sign(x)*(Internal'Pi()/2-ArcSinN(Sqrt(1-x^2))), - ArcSinN(x) - ); -]; - -////////////////////////////////////////////////// -/// Exponent -////////////////////////////////////////////////// - -LocalSymbols(mathExpThreshold) [ - // improve convergence of Exp(x) for large x - mathExpThreshold := If(Not IsBound(mathExpThreshold), 500); - - MathExpThreshold() := mathExpThreshold; - SetMathExpThreshold(threshold) := [mathExpThreshold:= threshold; ]; -]; - -// large positive x -10 # ExpNum(x_IsNumber) _ (x > MathExpThreshold()) <-- [ - Local(i, y); - i:=0; - For(i:=0, x > MathExpThreshold(), i++) - x := DivideN(x, 2.); - For(y:= ExpN(x), i>0, i--) - y := MultiplyN(y, y); - y; - -]; -// large negative x -20 # ExpNum(x_IsNumber) _ (2*x < -MathExpThreshold()) <-- DivideN(1, ExpNum(-x)); -// other values of x -30 # ExpNum(x_IsNumber) <-- ExpN(x); - -////////////////////////////////////////////////// -/// Natural logarithm -////////////////////////////////////////////////// - -// LogN in the original C++ code hangs! Scripted implementation is much better -LogN(x) := Internal'LnNum(x); - -// natural logarithm: this should be called only for real x>1 -//Internal'LnNum(x) := LogN(x); -// right now the fastest algorithm is Halley's method for Exp(x)=a -// when internal math is fixed, we may want to use Brent's method (below) -// this method is using a cubically convergent Newton iteration for Exp(x/2)-a*Exp(-x/2)=0: -// x' := x - 2 * (Exp(x)-a) / (Exp(x)+a) = x-2+4*a/(Exp(x)+a) -Internal'LnNum(x_IsNumber)_(x>=1) <-- NewtonLn(x); - -Internal'LnNum(x_IsNumber)_(0 40 digits -10 # BrentLn(x_IsInteger)_(BuiltinPrecisionGet()>40) <-- -[ - Local(y, n, k, eps); - n := BuiltinPrecisionGet(); // decimal digits - // initial power of x - k := 1 + Div(IntLog(4*10^n, x), 2); // now x^(2*k)>4*10^n - BuiltinPrecisionSet(n+5); // guard digits - eps := DivideN(1, 10^n); // precision - y := PowerN(x, k); // not yet divided by 4 - // this is Brent's AGM times y. This way we work around the MathPiper limitation of fixed precision, at cost of slightly slower initial iterations - y := DivideN(Internal'Pi()*y, (2*k)*AG'Mean(4, y, eps)); - BuiltinPrecisionSet(n); - RoundTo(y, n); // do not return a more precise number than we really have -]; - -15 # BrentLn(x_IsInteger) <-- LogN(x); - -/// calculation of Ln(x) using Brent's AGM sequence - use precomputed Pi and Ln2. -20 # BrentLn(_x)_(x<1) <-- -BrentLn(1/x); - -// this is currently faster than LogN() for precision > 85 digits and numbers >2 -30 # BrentLn(_x)_(BuiltinPrecisionGet()>85) <-- -[ - Local(y, n, n1, k, eps); - N([ - n := BuiltinPrecisionGet(); // decimal digits - // effective precision is n+Ln(n)/Ln(10) - n1 := n + IntLog(n,10); // Ln(2) < 7050/10171 - // initial power of 2 - k := 2 + Div(n1*28738, 2*8651) // Ln(10)/Ln(2) < 28738/8651; now 2^(2*k)>4*10^n1 - // find how many binary digits we already have in x, and multiply by a sufficiently large power of 2 so that y=x*2^k is larger than 2*10^(n1/2) - - IntLog(Floor(x), 2); - // now we need k*Ln(2)/Ln(10) additional digits to compensate for cancellation at the final subtraction - BuiltinPrecisionSet(n1+2+Div(k*3361, 11165)); // Ln(2)/Ln(10) < 3361/11165 - eps := DivideN(1, 10^(n1+1)); // precision - y := x*2^(k-2); // divided already by 4 - // initial values for AGM - // this is Brent's AGM times y. This way we work around the MathPiper limitation of fixed precision, at cost of slightly slower initial iterations - y:=Internal'Pi()*y/(2*AG'Mean(1,y,eps)) - k*Ln2(); - BuiltinPrecisionSet(n); - ]); - y; // do not return a more precise number than we really have -]; - -40 # BrentLn(x_IsNumber) <-- LogN(x); - -CachedConstant(Ln2, Internal'LnNum(2)); // this is only useful for BrentLn -/**/ -//CachedConstant(Exp1, ExpN(1)); // Exp1 is useless so far - -////////////////////////////////////////////////// -/// ArcTan(x) -////////////////////////////////////////////////// - -ArcTanNum(x) := -[ - // using trigonometric identities is faster for now - If( - Abs(x)>1, - Sign(x)*(Internal'Pi()/2-ArcSin(1/Sqrt(x^2+1))), - ArcSin(x/Sqrt(x^2+1)) - ); -]; - -/* old methods -- slower for now -/// numerical evaluation of ArcTan using continued fractions: top level -2 # ArcTan(x_IsNumber)_InNumericMode() <-- -Sign(x) * -// now we need to compute ArcTan of a nonnegative number Abs(x) -[ - Local(nterms, y); - y := Abs(x); - // use identities to improve convergence -- see essays book - If( - y>1, - y:=1/y // now y <= 1 - // we shall know that the first identity was used because Abs(x) > 1 still - ); - // use the second identity - y := y/(1+Sqrt(1+y^2)); // now y <= Sqrt(2)-1 - // find the required number of terms in the continued fraction - nterms := 1/y; // this needs to be calculated at full precision - // see essays book on the choice of the number of terms (added 2 "guard terms"). - // we need Hold() because otherwise, if InNumericMode() returns True, N(..., 5) will not avoid the full precision calculation of Ln(). - // the value of x should not be greater than 1 here! - nterms := 2 + Ceil( N(Hold(Ln(10)/(Ln(4)+2*Ln(nterms))), 5) * BuiltinPrecisionGet() ); - If( // call the actual routine - Abs(x)>1, - Pi/2-2*MyArcTan(y, nterms), // this is for |x|>1 - 2*MyArcTan(y, nterms) - // MyArcTan(x, nterms) - ); -]; -*/ -/// numerical evaluation of ArcTan using continued fractions: low level - -// evaluation using recursion -- slightly faster but lose some digits to roundoff errors and needs large recursion depth -/* -10 # ContArcTan(_x,_n,_n) <-- (2*n-1); -20 # ContArcTan(_x,_n,_m) <-- -[ - (2*n-1) + (n*x)^2/ContArcTan(x,n+1,m); -]; - -MyArcTan(x,n) := -[ - x/ContArcTan(x,1,n); -]; -*/ -/* -/// evaluate n terms of the continued fraction for ArcTan(x) without recursion. -/// better control of roundoff errors -MyArcTan(x, n) := -[ - Local(i, p, q, t); - // initial numerator and denominator - p:=1; - q:=1; - // start evaluating from the last term upwards - For(i:=n, i>=1, i--) - [ - //{p,q} := {p + q*(i*x)^2/(4*i^2-1), p}; - // t := p*(2*i-1) + q*(i*x)^2; then have to start with p:=2*n+1 - t := p + q*(i*x)^2/(4*i^2-1); - q := p; - p := t; - ]; - // answer is x/(p/q) - x*q/p; -]; -*/ diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/numerical.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/numerical.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/numerical.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/numerical.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -TruncRadian -SinNum -CosNum -TanNum -ArcSinNum -ArcTanNum -ExpNum -MathExpThreshold -SetMathExpThreshold -LogN -Internal'LnNum -BrentLn -Ln2 -NewtonLn -Exp1 -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/nummethods.mpi mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/nummethods.mpi --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/nummethods.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/nummethods.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,379 +0,0 @@ -/// coded by Serge Winitzki. See essays documentation for algorithms. - -////////////////////////////////////////////////// -/// Numerical method: AGM sequence -////////////////////////////////////////////////// - -/// compute the AGM sequence up to a given precision -AG'Mean(a, b, eps) := -[ - Local(a1, b1); - If(InVerboseMode(), Echo("AG'Mean: Info: at prec. ", BuiltinPrecisionGet())); - // AGM main loop - While(Abs(a-b)>=eps) - [ - a1 := DivideN(a+b, 2); - b1 := SqrtN(MultiplyN(a, b)); // avoid Sqrt() which uses N() inside it - a := a1; - b := b1; - ]; - DivideN(a+b, 2); -]; -//UnFence(AG'Mean, 3); - -////////////////////////////////////////////////// -/// Numerical method: Taylor series, rectangular summation -////////////////////////////////////////////////// - -/// Fast summation of Taylor series using a rectangular scheme. -/// SumTaylorNum(x, nth'term'func, n'terms) = Sum(k, 0, n'terms, nth'term'func(k)*x^k) -/// Note that sufficient precision must be preset to avoid roundoff errors (these methods do not modify precision). -/// The only reason to try making these functions HoldArg is to make sure that the closures nth'term'func and next'term'factor are passed intact. But it's probably not desired in most cases because a closure might contain parameters that should be evaluated. - -/// The short form is used when only the nth term is known but no simple relation between a term and the next term. -/// The long form is used when there is a simple relation between consecutive terms. In that case, the n'th term function is not needed, only the 0th term value. - -/// SumTaylorNum0 is summing the terms with direct methods (Horner's scheme or simple summation). SumTaylorNum1 is for the rectangular method. - -/// nth'term'func and next'term'func must be functions applicable to one argument. - -/// interface -SumTaylorNum0(_x, _nth'term'func, _n'terms) <-- SumTaylorNum0(x, nth'term'func, {}, n'terms); - -SumTaylorNum1(_x, _nth'term'func, _n'terms) <-- SumTaylorNum1(x, nth'term'func, {}, n'terms); - -/// interface -SumTaylorNum(_x, _nth'term'func, _n'terms) <-- -If( - n'terms >= 30, // threshold for calculation with next'term'factor - // use the rectangular algorithm for large enough number of terms - SumTaylorNum1(x, nth'term'func, n'terms), - SumTaylorNum0(x, nth'term'func, n'terms) -); - -SumTaylorNum(_x, _nth'term'func, _next'term'factor, _n'terms) <-- -If( - n'terms >= 5, // threshold for calculation with next'term'factor - SumTaylorNum1(x, nth'term'func, next'term'factor, n'terms), - SumTaylorNum0(x, nth'term'func, next'term'factor, n'terms) -); -//HoldArgNr(SumTaylorNum, 3, 2); - -/// straightforward algorithms for a small number of terms -1# SumTaylorNum0(_x, _nth'term'func, {}, _n'terms) <-- -[ - Local(sum, k); - N([ - // use Horner scheme starting from the last term - x:=Eval(x); - sum := 0; - For(k:=n'terms, k>=0, k--) - sum := AddN(sum*x, nth'term'func @ k); - ]); - sum; -]; - -//HoldArgNr(SumTaylorNum0, 3, 2); - -2# SumTaylorNum0(_x, _nth'term'func, _next'term'factor, _n'terms) <-- -[ - Local(sum, k, term, delta); - N([ - x:=Eval(x); // x must be floating-point - If (IsConstant(nth'term'func), - term := nth'term'func, - term := (nth'term'func @ {0}), - ); - sum := term; // sum must be floating-point - ]); - NonN([ - delta := 1; - For(k:=1, k<=n'terms And delta != 0, k++) - [ - term := MultiplyNum(term, next'term'factor @ {k}, x); // want to keep exact fractions here, but the result is floating-point - delta := sum; - sum := sum + term; // term must be floating-point - delta := Abs(sum-delta); // check for underflow - ]; - ]); - sum; -]; - -/// interface -SumTaylorNum0(_x, _nth'term'func, _n'terms) <-- SumTaylorNum0(x, nth'term'func, {}, n'terms); - -//HoldArgNr(SumTaylorNum0, 4, 2); -//HoldArgNr(SumTaylorNum0, 4, 3); - -/// this is to be used when a simple relation between a term and the next term is known. -/// next'term'factor must be a function applicable to one argument, so that if term = nth'term'func(k-1), then nth'term'func(k) = term / next'term'factor(k). (This is optimized for Taylor series of elementary functions.) In this case, nth'term'func is either a number, value of the 0th term, or a function. -/// A special case: when next'term'factor is an empty list; then we act as if there is no next'term'factor available. -/// In this case, nth'term'func must be a function applicable to one argument. -/// Need IntLog(n'terms, 10) + 1 guard digits due to accumulated roundoff error. -SumTaylorNum1(x, nth'term'func, next'term'factor, n'terms) := -[ - // need Sqrt(n'terms/2) units of storage (rows) and Sqrt(n'terms*2) columns. Let's underestimate the storage. - Local(sum, rows, cols, rows'tmp, last'power, i, j, x'power, term'tmp); - N([ // want to keep exact fractions - x:=Eval(x); // x must be floating-point - rows := IntNthRoot(n'terms+1, 2); - cols := Div(n'terms+rows, rows); // now: rows*cols >= n'terms+1 - Check(rows>1 And cols>1, "SumTaylorNum1: Internal error: number of Taylor sum terms must be at least 4"); - rows'tmp := ArrayCreate(rows, 0); - x'power := x ^ rows; // do not use PowerN b/c x might be complex - // initialize partial sums (array rows'tmp) - the 0th column (i:=0) - // prepare term'tmp for the first element - // if we are using next'term'factor, then term'tmp is x^(rows*i)*a[rows*i] - // if we are not using it, then term'tmp is x^(rows*i) - If( - next'term'factor = {}, - term'tmp := 1, - // term'tmp := (nth'term'func @ 0) // floating-point - If (IsConstant(nth'term'func), - term'tmp := nth'term'func, - term'tmp := (nth'term'func @ {0}), - ) - ); - ]); - NonN([ // want to keep exact fractions below - // do horizontal summation using term'tmp to get the first element - For(i:=0, i0, j--) - sum := sum*x + rows'tmp[j]; - ]); - sum; -]; - -//HoldArgNr(SumTaylorNum, 4, 2); -//HoldArgNr(SumTaylorNum, 4, 3); - -/* -Examples: -In> SumTaylorNum(1,{{k}, 1/k!},{{k}, 1/k}, 10 ) -Out> 2.7182818006; -In> SumTaylorNum(1,{{k},1/k!}, 10 ) -Out> 2.7182818007; -*/ - -////////////////////////////////////////////////// -/// Numerical method: multiply floats by rationals -////////////////////////////////////////////////// - -/// aux function: optimized numerical multiplication. Use MultiplyN() and DivideN(). -/// optimization consists of multiplying or dividing by integers if one of the arguments is a rational number. This is presumably always better than floating-point calculations, except if we use Rationalize() on everything. -/// note that currently this is not a big optimization b/c of slow arithmetic but it already helps for rational numbers under InNumericMode() returns True and it will help even more when faster math is done - -Function() MultiplyNum(x, y, ...); -Function() MultiplyNum(x); - -10 # MultiplyNum(x_IsList)_(Length(x)>1) <-- MultiplyNum(Head(x), Tail(x)); - -10 # MultiplyNum(x_IsRational, y_IsRationalOrNumber) <-- -[ - If( - Type(y) = "/", // IsRational(y), changed by Nobbi before redefinition of IsRational - DivideN(Numer(x)*Numer(y), Denom(x)*Denom(y)), - // y is floating-point - // avoid multiplication or division by 1 - If( - Numer(x)=1, - DivideN(y, Denom(x)), - If( - Denom(x)=1, - MultiplyN(y, Numer(x)), - DivideN(MultiplyN(y, Numer(x)), Denom(x)) - ) - ) - ); -]; - -20 # MultiplyNum(x_IsNumber, y_IsRational) <-- MultiplyNum(y, x); - -25 # MultiplyNum(x_IsNumber, y_IsNumber) <-- MultiplyN(x,y); - -30 # MultiplyNum(Complex(r_IsNumber, i_IsNumber), y_IsRationalOrNumber) <-- Complex(MultiplyNum(r, y), MultiplyNum(i, y)); - -35 # MultiplyNum(y_IsNumber, Complex(r_IsNumber, i_IsRationalOrNumber)) <-- MultiplyNum(Complex(r, i), y); - -40 # MultiplyNum(Complex(r1_IsNumber, i1_IsNumber), Complex(r2_IsNumber, i2_IsNumber)) <-- Complex(MultiplyNum(r1,r2)-MultiplyNum(i1,i2), MultiplyNum(r1,i2)+MultiplyNum(i1,r2)); - -/// more than 2 operands -30 # MultiplyNum(x_IsRationalOrNumber, y_IsNumericList)_(Length(y)>1) <-- MultiplyNum(MultiplyNum(x, Head(y)), Tail(y)); -40 # MultiplyNum(x_IsRationalOrNumber, y_IsNumericList)_(Length(y)=1) <-- MultiplyNum(x, Head(y)); - -////////////////////////////////////////////////// -/// Numerical method: Newton-like superconvergent iteration -////////////////////////////////////////////////// - -// Newton's method, generalized, with precision control and diagnostics - -/// auxiliary utility: compute the number of common decimal digits of x and y (using relative precision) -Common'digits(x,y) := -[ - Local(diff); - diff := Abs(x-y); - If( - diff=0, - Infinity, - // use approximation Ln(2)/Ln(10) > 351/1166 - Div(IntLog(FloorN(DivideN(Max(Abs(x), Abs(y)), diff)), 2)*351, 1166) - ); // this many decimal digits in common -]; - -///interface -NewtonNum(_func, _x0) <-- NewtonNum(func, x0, 5); // default prec0 -NewtonNum(_func, _x0, _prec0) <-- NewtonNum(func, x0, prec0, 2); - -// func is the function to iterate, i.e. x' = func(x). -// prec0 is the initial precision necessary to get convergence started. -// order is the order of convergence of the given sequence (e.g. 2 or 3). -// x0 must be close enough so that x1 has a few common digits with x0 after at most 5 iterations. -NewtonNum(_func, _x'init, _prec0, _order) <-- -[ - Check(prec0>=4, "NewtonNum: Error: initial precision must be at least 4"); - Check(IsInteger(order) And order>1, "NewtonNum: Error: convergence order must be an integer and at least 2"); - Local(x0, x1, prec, exact'digits, int'part, initial'tries); - N([ - x0 := x'init; - prec := BuiltinPrecisionGet(); - int'part := IntLog(Ceil(Abs(x0)), 10); // how many extra digits for numbers like 100.2223 - // int'part must be set to 0 if we have true floating-point semantics of BuiltinPrecisionSet() - BuiltinPrecisionSet(2+prec0-int'part); // 2 guard digits - x1 := (func @ x0); // let's run one more iteration by hand - // first, we get prec0 exact digits - exact'digits := 0; - initial'tries := 5; // stop the loop the the initial value is not good - While(exact'digits*order < prec0 And initial'tries>0) - [ - initial'tries--; - x0 := x1; - x1 := (func @ x0); - exact'digits := Common'digits(x0, x1); - // If(InVerboseMode(), Echo("NewtonNum: Info: got", exact'digits, "exact digits at prec. ", BuiltinPrecisionGet())); - ]; - // need to check that the initial precision is achieved - If( - Assert("value", {"NewtonNum: Error: need a more accurate initial value than", x'init}) - exact'digits >= 1, - [ - exact'digits :=Min(exact'digits, prec0+2); - // run until get prec/order exact digits - int'part := IntLog(Ceil(Abs(x1)), 10); // how many extra digits for numbers like 100.2223 - While(exact'digits*order <= prec) - [ - exact'digits := exact'digits*order; - BuiltinPrecisionSet(2+Min(exact'digits, Div(prec,order)+1)-int'part); - x0 := x1; - x1 := (func @ x0); - // If(InVerboseMode(), Echo("NewtonNum: Info: got", Common'digits(x0, x1), "exact digits at prec. ", BuiltinPrecisionGet())); - ]; - // last iteration by hand - BuiltinPrecisionSet(2+prec); - x1 := RoundTo( (func @ x1), prec); - ], - // did not get a good initial value, so return what we were given - x1 := x'init - ); - BuiltinPrecisionSet(prec); - ]); - x1; -]; - -/* -example: logarithm function using cubically convergent Newton iteration for -Exp(x/2)-a*Exp(-x/2)=0: - -x' := x - 2 * (Exp(x)-a) / (Exp(x)+a) - -LN(x_IsNumber)_(x>1 ) <-- - LocalSymbols(y) -[ -// initial guess is obtained as Ln(x^2)/Ln(2) * (Ln(2)/2) - NewtonNum({{y},4*x/(Exp(y)+x)-2+y}, N(794/2291*IntLog(Floor(x*x),2),5), 10, 3); -]; -/**/ - -////////////////////////////////////////////////// -/// Numerical method: integer powers by binary reduction -////////////////////////////////////////////////// - -/// generalized integer Power function using the classic binary method. -5 # IntPowerNum(_x, 0, _func, _unity) <-- unity; -10 # IntPowerNum(_x, n_IsInteger, _func, _unity) <-- -[ - // use binary method - Local(result); - // unity might be of non-scalar type, avoid assignment - While(n > 0) - [ - If( - (n&1) = 1, - If( - IsBound(result), // if result is already assigned - result := Apply(func, {result,x}), - result := x, // avoid multiplication - ) - ); - x := Apply(func, {x,x}); - n := n>>1; - ]; - result; -]; - -////////////////////////////////////////////////// -/// Numerical method: binary splitting technique for simple series -////////////////////////////////////////////////// - -/// Binary splitting for series of the form -/// S(m,n) = Sum(k,m,n, a(k)/b(k)*(p(0)*...*p(k))/(q(0)*...*q(k))) - - -/// High-level interface routine -BinSplitNum(m,n,a,b,p,q) := BinSplitFinal(BinSplitData(m,n,a,b,p,q)); - -/// Low-level routine: compute the floating-point answer from P, Q, B, T data -BinSplitFinal({_P,_Q,_B,_T}) <-- DivideN(T, MultiplyN(B, Q)); - -/// Low-level routine: combine two binary-split intermediate results -BinSplitCombine({_P1, _Q1, _B1, _T1}, {_P2, _Q2, _B2, _T2}) <-- {P1*P2, Q1*Q2, B1*B2, B1*P1*T2+B2*Q2*T1}; - -/// Low-level routine: compute the list of four integers P, Q, B, T. (T=BQS) -/// Input: m, n and four functions a,b,p,q of one integer argument. - -// base of recursion -10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m>n) <-- {1,1,1,0}; - -10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m=n) <-- {p@m, q@m, b@m, (a@m)*(p@m)}; - -10 # BinSplitData(_m, _n, _a, _b, _p, _q)_(m+1=n) <-- {(p@m)*(p@n), (q@m)*(q@n), (b@m)*(b@n), (p@m)*((a@m)*(b@n)*(q@n)+(a@n)*(b@m)*(p@n))}; - -// could implement some more cases of recursion base, to improve speed - -// main recursion step -20 # BinSplitData(_m, _n, _a, _b, _p, _q) <-- -[ - BinSplitCombine(BinSplitData(m,(m+n)>>1, a,b,p,q), BinSplitData(1+((m+n)>>1),n, a,b,p,q)); -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/nummethods.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/nummethods.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/nummethods.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/nummethods.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -NewtonNum -SumTaylorNum -AG'Mean -MultiplyNum -IntPowerNum -BinSplitNum -BinSplitData -BinSplitFinal -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/stdfuncs.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stdfuncs.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -// From code.mpi.def: -OMDef( "ArcSin" , "transc1","arcsin" ); -OMDef( "ArcCos" , "transc1","arccos" ); -OMDef( "ArcTan" , "transc1","arctan" ); -OMDef( "ArcSec" , "transc1","arcsec" ); -OMDef( "ArcCsc" , "transc1","arccsc" ); -OMDef( "ArcCot" , "transc1","arccot" ); -OMDef( "ArcSinh", "transc1","arcsinh" ); -OMDef( "ArcCosh", "transc1","arccosh" ); -OMDef( "ArcTanh", "transc1","arctanh" ); -OMDef( "ArcSech", "transc1","arcsech" ); -OMDef( "ArcCsch", "transc1","arccsch" ); -OMDef( "ArcCoth", "transc1","arccoth" ); -OMDef( "Sin" , "transc1","sin" ); -OMDef( "Cos" , "transc1","cos" ); -OMDef( "Tan" , "transc1","tan" ); -OMDef( "Sec" , "transc1","sec" ); -OMDef( "Csc" , "transc1","csc" ); -OMDef( "Cot" , "transc1","cot" ); -OMDef( "Sinh" , "transc1","sinh" ); -OMDef( "Cosh" , "transc1","cosh" ); -OMDef( "Tanh" , "transc1","tanh" ); -OMDef( "Sech" , "transc1","sech" ); -OMDef( "Csch" , "transc1","csch" ); -OMDef( "Coth" , "transc1","coth" ); -OMDef( "Exp" , "transc1","exp" ); -OMDef( "Ln" , "transc1","ln" ); - -// Related OM symbols not yet defined in MathPiper: -// "log" , "transc1","log" diff -Nru mathpiper-0.0.svn2556/storage/scripts/stubs.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/stubs.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/stubs.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stubs.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,422 +0,0 @@ -/* Comparison operators. They call the internal comparison routines when - * both arguments are numbers. The value Infinity is also understood. -*/ - -// Undefined is a very special case as we return False for everything -1 # Undefined < _x <-- False; -1 # Undefined <= _x <-- False; -1 # Undefined > _x <-- False; -1 # Undefined >= _x <-- False; -1 # _x < Undefined <-- False; -1 # _x <= Undefined <-- False; -1 # _x > Undefined <-- False; -1 # _x >= Undefined <-- False; - - -// If n and m are numbers, use the standard LessThan function immediately -5 # (n_IsNumber < m_IsNumber) <-- LessThan(n-m,0); - - -// If n and m are symbolic after a single evaluation, see if they can be coerced in to a real-valued number. -LocalSymbols(nNum,mNum) -[ - 10 # (_n < _m)_[nNum:=N(Eval(n)); mNum:=N(Eval(m));IsNumber(nNum) And IsNumber(mNum);] <-- LessThan(nNum-mNum,0); -]; - -// Deal with Infinity -20 # (Infinity < _n)_(Not(IsInfinity(n))) <-- False; -20 # (-Infinity < _n)_(Not(IsInfinity(n))) <-- True; -20 # (_n < Infinity)_(Not(IsInfinity(n))) <-- True; -20 # (_n < -Infinity)_(Not(IsInfinity(n))) <-- False; - -// Lots of known identities go here -30 # (_n1/_n2) < 0 <-- (n1 < 0) != (n2 < 0); -30 # (_n1*_n2) < 0 <-- (n1 < 0) != (n2 < 0); - -// This doesn't sadly cover the case where a and b have opposite signs -30 # ((_n1+_n2) < 0)_((n1 < 0) And (n2 < 0)) <-- True; -30 # ((_n1+_n2) < 0)_((n1 > 0) And (n2 > 0)) <-- False; -30 # _x^a_IsOdd < 0 <-- x < 0; -30 # _x^a_IsEven < 0 <-- False; // This is wrong for complex x - -// Add other functions here! Everything we can compare to 0 should be here. -40 # (Sqrt(_x))_(x > 0) < 0 <-- False; - -40 # (Sin(_x) < 0)_(Not(IsEven(N(x/Pi))) And IsEven(N(Floor(x/Pi)))) <-- False; -40 # (Sin(_x) < 0)_(Not(IsOdd (N(x/Pi))) And IsOdd (N(Floor(x/Pi)))) <-- True; - -40 # Cos(_x) < 0 <-- Sin(Pi/2-x) < 0; - -40 # (Tan(_x) < 0)_(Not(IsEven(N(2*x/Pi))) And IsEven(N(Floor(2*x/Pi)))) <-- False; -40 # (Tan(_x) < 0)_(Not(IsOdd (N(2*x/Pi))) And IsOdd (N(Floor(2*x/Pi)))) <-- True; - -// Functions that need special treatment with more than one of the comparison -// operators as they always return true or false. For these we must define -// both the `<' and `>=' operators. -40 # (Complex(_a,_b) < 0)_(b!=0) <-- False; -40 # (Complex(_a,_b) >= 0)_(b!=0) <-- False; -40 # (Sqrt(_x))_(x < 0) < 0 <-- False; -40 # (Sqrt(_x))_(x < 0) >= 0 <-- False; - -// Deal with negated terms -50 # -(_x) < 0 <-- Not((x<0) Or (x=0)); - -// Define each of {>,<=,>=} in terms of < -50 # _n > _m <-- m < n; -50 # _n <= _m <-- m >= n; -50 # _n >= _m <-- Not(n0 And m>0)*/ <-- -[ - Local(n1,n2,m1,m2); - n1:=Numer(n); - n2:=Denom(n); - m1:=Numer(m); - m2:=Denom(m); - Mod(n1*m2,m1*n2)/(n2*m2); -]; - -6 # Mod(n_IsList,m_IsList) <-- Map("Mod",{n,m}); -7 # Mod(n_IsList,_m) <-- Map("Mod",{n,FillList(m,Length(n))}); - - -30 # Mod(n_CanBeUni,m_CanBeUni) <-- -[ - Local(vars); - vars:=VarList(n+m); - NormalForm(Mod(MakeUni(n,vars),MakeUni(m,vars))); -]; - -0 # Rem(n_IsNumber,m_IsNumber) <-- n-m*Div(n,m); -30 # Rem(n_CanBeUni,m_CanBeUni) <-- Mod(n,m); - - -0 # Gcd(0,0) <-- 1; -1 # Gcd(0,_m) <-- Abs(m); -1 # Gcd(_n,0) <-- Abs(n); -1 # Gcd(_m,_m) <-- Abs(m); -2 # Gcd(_n,1) <-- 1; -2 # Gcd(1,_m) <-- 1; -2 # Gcd(n_IsInteger,m_IsInteger) <-- GcdN(n,m); -3 # Gcd(_n,_m)_(IsGaussianInteger(m) And IsGaussianInteger(n) )<-- GaussianGcd(n,m); - -4 # Gcd(-(_n), (_m)) <-- Gcd(n,m); -4 # Gcd( (_n),-(_m)) <-- Gcd(n,m); -4 # Gcd(Sqrt(n_IsInteger),Sqrt(m_IsInteger)) <-- Sqrt(Gcd(n,m)); -4 # Gcd(Sqrt(n_IsInteger),m_IsInteger) <-- Sqrt(Gcd(n,m^2)); -4 # Gcd(n_IsInteger,Sqrt(m_IsInteger)) <-- Sqrt(Gcd(n^2,m)); - -5 # Gcd(n_IsRational,m_IsRational) <-- -[ - Gcd(Numer(n),Numer(m))/Lcm(Denom(n),Denom(m)); -]; - - -10 # Gcd(list_IsList)_(Length(list)>2) <-- - [ - Local(first); - first:=Gcd(list[1],list[2]); - Gcd(first:Tail(Tail(list))); - ]; -14 # Gcd({0}) <-- 1; -15 # Gcd({_head}) <-- head; - -20 # Gcd(list_IsList)_(Length(list)=2) <-- Gcd(list[1],list[2]); - -30 # Gcd(n_CanBeUni,m_CanBeUni)_(Length(VarList(n*m))=1) <-- -[ - Local(vars); - vars:=VarList(n+m); - NormalForm(Gcd(MakeUni(n,vars),MakeUni(m,vars))); -]; - -100 # Gcd(n_IsConstant,m_IsConstant) <-- 1; -110 # Gcd(_m,_n) <-- -[ - Echo("Not simplified"); -]; - - -/* Least common multiple */ -5 # Lcm(a_IsInteger,b_IsInteger) <-- Div(a*b,Gcd(a,b)); - -10 # Lcm(list_IsList)_(Length(list)>2) <-- -[ - Local(first); - first:=Lcm(list[1],list[2]); - Lcm(first:Tail(Tail(list))); -]; - -10 # Lcm(list_IsList)_(Length(list)=2) <-- Lcm(list[1],list[2]); - - -/* Expand expands polynomials. - */ -10 # Expand(expr_CanBeUni) <-- NormalForm(MakeUni(expr)); -20 # Expand(_expr) <-- expr; - -10 # Expand(expr_CanBeUni(var),_var) <-- NormalForm(MakeUni(expr,var)); -20 # Expand(_expr,_var) <-- expr; - - - -RuleBase("Object",{pred,x}); -Rule("Object",2,0,Apply(pred,{x})=True) x; - -10 # Abs(n_IsNumber) <-- AbsN(n); -10 # Abs(n_IsPositiveNumber/m_IsPositiveNumber) <-- n/m; -10 # Abs(n_IsNegativeNumber/m_IsPositiveNumber) <-- (-n)/m; -10 # Abs(n_IsPositiveNumber/m_IsNegativeNumber) <-- n/(-m); -10 # Abs( Sqrt(_x)) <-- Sqrt(x); -10 # Abs(-Sqrt(_x)) <-- Sqrt(x); -10 # Abs(Complex(_r,_i)) <-- Sqrt(r^2 + i^2); -10 # Abs(n_IsInfinity) <-- Infinity; -10 # Abs(Undefined) <-- Undefined; -20 # Abs(n_IsList) <-- MapSingle("Abs",n); - -100 # Abs(_a^_n) <-- Abs(a)^n; -100 # Abs(_a)^n_IsEven <-- a^n; -100 # Abs(_a)^n_IsOdd <-- Sign(a)*a^n; - -10 # Sign(n_IsPositiveNumber) <-- 1; -10 # Sign(n_IsZero) <-- 0; -20 # Sign(n_IsNumber) <-- -1; -15 # Sign(n_IsInfinity)_(n < 0) <-- -1; -15 # Sign(n_IsInfinity)_(n > 0) <-- 1; -15 # Sign(n_IsNumber/m_IsNumber) <-- Sign(n)*Sign(m); -20 # Sign(n_IsList) <-- MapSingle("Sign",n); - -100 # Sign(_a)^n_IsEven <-- 1; -100 # Sign(_a)^n_IsOdd <-- Sign(a); - -5 # Floor(Infinity) <-- Infinity; -5 # Floor(-Infinity) <-- -Infinity; -5 # Floor(Undefined) <-- Undefined; -5 # Ceil(Infinity) <-- Infinity; -5 # Ceil(-Infinity) <-- -Infinity; -5 # Ceil(Undefined) <-- Undefined; -5 # Round(Infinity) <-- Infinity; -5 # Round(-Infinity) <-- -Infinity; -5 # Round(Undefined) <-- Undefined; - -/* Changed by Nobbi before redefinition of Rational -10 # Floor(x_IsNumber) <-- FloorN(x); -10 # Ceil (x_IsNumber) <-- CeilN (x); -10 # Round(x_IsNumber) <-- FloorN(x+0.5); - -20 # Floor(x_IsRational) _ (IsNumber(Numer(x)) And IsNumber(Denom(x))) <-- FloorN(N(x)); -20 # Ceil (x_IsRational) _ (IsNumber(Numer(x)) And IsNumber(Denom(x))) <-- CeilN (N(x)); -20 # Round(x_IsRational) _ (IsNumber(Numer(x)) And IsNumber(Denom(x))) <-- FloorN(N(x+0.5)); -*/ - -10 # Floor(x_IsRationalOrNumber) - <-- - [ - x:=N(Eval(x)); -//Echo("x = ",x); - Local(prec,result,n); - Set(prec,BuiltinPrecisionGet()); - If(IsZero(x), - Set(n,2), - If(x>0, - Set(n,2+FloorN(N(FastLog(x)/FastLog(10)))), - Set(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) - )); - If(n>prec,BuiltinPrecisionSet(n)); -//Echo("Before"); - Set(result,FloorN(x)); -//Echo("After"); - BuiltinPrecisionSet(prec); - result; - ]; - -// FloorN(N(x)); - -10 # Ceil (x_IsRationalOrNumber) - <-- - [ - x:=N(x); - Local(prec,result,n); - Set(prec,BuiltinPrecisionGet()); - If(IsZero(x),Set(n,2), - If(x>0, - Set(n,2+FloorN(N(FastLog(x)/FastLog(10)))), - Set(n,2+FloorN(N(FastLog(-x)/FastLog(10)))) - )); - If(n>prec,BuiltinPrecisionSet(n)); - Set(result,CeilN(x)); - BuiltinPrecisionSet(prec); - result; - ]; -// CeilN (N(x)); -10 # Round(x_IsRationalOrNumber) <-- FloorN(N(x+0.5)); -10 # Round(x_IsList) <-- MapSingle("Round",x); - -20 # Round(x_IsComplex) _ (IsRationalOrNumber(Re(x)) And IsRationalOrNumber(Im(x)) ) - <-- FloorN(N(Re(x)+0.5)) + FloorN(N(Im(x)+0.5))*I; - - -// Canonicalise an expression so its terms are grouped to the right -// ie a+(b+(c+d)) -// This doesn't preserve order of terms, when doing this would cause more -// subtractions and nested parentheses than necessary. -1 # CanonicalAdd((_a+_b)+_c) <-- CanonicalAdd(CanonicalAdd(a)+ - CanonicalAdd(CanonicalAdd(b)+ - CanonicalAdd(c))); -1 # CanonicalAdd((_a-_b)+_c) <-- CanonicalAdd(CanonicalAdd(a)+ - CanonicalAdd(CanonicalAdd(c)- - CanonicalAdd(b))); -1 # CanonicalAdd((_a+_b)-_c) <-- CanonicalAdd(CanonicalAdd(a)+ - CanonicalAdd(CanonicalAdd(b)- - CanonicalAdd(c))); -1 # CanonicalAdd((_a-_b)-_c) <-- CanonicalAdd(CanonicalAdd(a)- - CanonicalAdd(CanonicalAdd(b)+ - CanonicalAdd(c))); -2 # CanonicalAdd(_a) <-- a; - -////////////////////// Log rules stuff ////////////////////// - -// LnExpand -1 # LnExpand(Ln(x_IsInteger)) - <-- Add(Map({{n,m},m*Ln(n)},Transpose(Factors(x)))); -1 # LnExpand(Ln(_a*_b)) <-- LnExpand(Ln(a))+LnExpand(Ln(b)); -1 # LnExpand(Ln(_a/_b)) <-- LnExpand(Ln(a))-LnExpand(Ln(b)); -1 # LnExpand(Ln(_a^_n)) <-- LnExpand(Ln(a))*n; -2 # LnExpand(_a) <-- a; - -// LnCombine is nice and simple now -LnCombine(_a) <-- DoLnCombine(CanonicalAdd(a)); - -// Combine single terms. This can always be done without a recursive call. -1 # DoLnCombine(Ln(_a)) <-- Ln(a); -1 # DoLnCombine(Ln(_a)*_b) <-- Ln(a^b); -1 # DoLnCombine(_b*Ln(_a)) <-- Ln(a^b); - -// Deal with the first two terms so they are both simple logs if at all -// possible. This involves converting a*Ln(b) to Ln(b^a) and moving log terms -// to the start of expressions. One of either of these operations always takes -// us to a strictly simpler form than we started in, so we can get away with -// calling DoLnCombine again with the partly simplified argument. - -// TODO: Make this deal with division everywhere it deals with multiplication - -// first term is a log multiplied by something -2 # DoLnCombine(Ln(_a)*_b+_c) <-- DoLnCombine(Ln(a^b)+c); -2 # DoLnCombine(Ln(_a)*_b-_c) <-- DoLnCombine(Ln(a^b)-c); -2 # DoLnCombine(_b*Ln(_a)+_c) <-- DoLnCombine(Ln(a^b)+c); -2 # DoLnCombine(_b*Ln(_a)-_c) <-- DoLnCombine(Ln(a^b)-c); - -// second term of a two-term expression is a log multiplied by something -2 # DoLnCombine(_a+(_c*Ln(_b))) <-- DoLnCombine(a+Ln(b^c)); -2 # DoLnCombine(_a-(_c*Ln(_b))) <-- DoLnCombine(a-Ln(b^c)); -2 # DoLnCombine(_a+(Ln(_b)*_c)) <-- DoLnCombine(a+Ln(b^c)); -2 # DoLnCombine(_a-(Ln(_b)*_c)) <-- DoLnCombine(a-Ln(b^c)); - -// second term of a three-term expression is a log multiplied by something -2 # DoLnCombine(_a+((Ln(_b)*_c)+_d)) <-- DoLnCombine(a+(Ln(b^c)+d)); -2 # DoLnCombine(_a+((Ln(_b)*_c)-_d)) <-- DoLnCombine(a+(Ln(b^c)-d)); -2 # DoLnCombine(_a-((Ln(_b)*_c)+_d)) <-- DoLnCombine(a-(Ln(b^c)+d)); -2 # DoLnCombine(_a-((Ln(_b)*_c)-_d)) <-- DoLnCombine(a-(Ln(b^c)-d)); - -2 # DoLnCombine(_a+((_c*Ln(_b))+_d)) <-- DoLnCombine(a+(Ln(b^c)+d)); -2 # DoLnCombine(_a+((_c*Ln(_b))-_d)) <-- DoLnCombine(a+(Ln(b^c)-d)); -2 # DoLnCombine(_a-((_c*Ln(_b))+_d)) <-- DoLnCombine(a-(Ln(b^c)+d)); -2 # DoLnCombine(_a-((_c*Ln(_b))-_d)) <-- DoLnCombine(a-(Ln(b^c)-d)); - -// Combine the first two terms if they are logs, otherwise move one or both to -// the front, then recurse on the remaining possibly-log-containing portion. -// (the code makes more sense than this comment) -3 # DoLnCombine(Ln(_a)+Ln(_b)) <-- Ln(a*b); -3 # DoLnCombine(Ln(_a)-Ln(_b)) <-- Ln(a/b); -3 # DoLnCombine(Ln(_a)+(Ln(_b)+_c)) <-- DoLnCombine(Ln(a*b)+c); -3 # DoLnCombine(Ln(_a)+(Ln(_b)-_c)) <-- DoLnCombine(Ln(a*b)-c); -3 # DoLnCombine(Ln(_a)-(Ln(_b)+_c)) <-- DoLnCombine(Ln(a/b)-c); -3 # DoLnCombine(Ln(_a)-(Ln(_b)-_c)) <-- DoLnCombine(Ln(a/b)+c); - -// We know that at least one of the first two terms isn't a log -4 # DoLnCombine(Ln(_a)+(_b+_c)) <-- b+DoLnCombine(Ln(a)+c); -4 # DoLnCombine(Ln(_a)+(_b-_c)) <-- b+DoLnCombine(Ln(a)-c); -4 # DoLnCombine(Ln(_a)-(_b+_c)) <-- DoLnCombine(Ln(a)-c)-b; -4 # DoLnCombine(Ln(_a)-(_b-_c)) <-- DoLnCombine(Ln(a)+c)-b; - -4 # DoLnCombine(_a+(Ln(_b)+_c)) <-- a+DoLnCombine(Ln(b)+c); -4 # DoLnCombine(_a+(Ln(_b)-_c)) <-- a+DoLnCombine(Ln(b)-c); -4 # DoLnCombine(_a-(Ln(_b)+_c)) <-- a-DoLnCombine(Ln(b)+c); -4 # DoLnCombine(_a-(Ln(_b)-_c)) <-- a-DoLnCombine(Ln(b)-c); - -// If we get here we know that neither of the first two terms is a log -5 # DoLnCombine(_a+(_b+_c)) <-- a+(b+DoLnCombine(c)); - -// Finished -6 # DoLnCombine(_a) <-- a; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/stubs.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/stubs.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/stubs.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stubs.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -= -< -> -<= ->= -!= -<< ->> -Div -Mod -Gcd -Expand -Object -Sqrt -Abs -Sign -Lcm -Floor -Ceil -Round -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/stubs.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/stubs.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/stubs.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/stubs.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -// From code.mpi.def: -OMDef( "Not", "logic1","not" ); -OMDef( "=" , "relation1","eq" ); -OMDef( ">=", "relation1","geq" ); -OMDef( ">" , "relation1","gt" ); -OMDef( "<=", "relation1","leq" ); -OMDef( "<" , "relation1","lt" ); -OMDef( "!=", "relation1","neq" ); -OMDef( "Gcd", "arith1","gcd" ); -OMDef( "Sqrt", "arith1","root", { $, _1, 2 }, $(_1)_(_2=2) | (_1^(1/_2)) ); -// Test [result: Sqrt(16)]: -// FromString("162 ")OMRead() -// Test [result: IntNthRoot(16,3))]: -// FromString("163 ")OMRead() -OMDef( "Abs", "arith1","abs" ); -OMDef( "Lcm", "arith1","lcm" ); - -OMDef( "Floor", "rounding1","floor" ); -OMDef( "Ceil" , "rounding1","ceiling" ); -OMDef( "Round", "rounding1","round" ); - -OMDef( "Div" , "piper","div" ); -OMDef( "Mod" , "piper","mod" ); -OMDef( "Expand", "piper","expand" ); -OMDef( "Object", "piper","object" ); -OMDef( "Sign" , "piper","sign" ); diff -Nru mathpiper-0.0.svn2556/storage/scripts/substitute.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/substitute.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/substitute.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/substitute.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ - - -Function("Substitute",{body,predicate,change}) -[ - Substitute(body); -]; -HoldArg("Substitute",predicate); -HoldArg("Substitute",change); -UnFence("Substitute",3); -RuleBase("Substitute",{body}); -UnFence("Substitute",1); - -Rule("Substitute",1,1,Apply(predicate,{body}) = True) -[ - Apply(change,{body}); -]; -Rule("Substitute",1,2,IsFunction(body)) -[ - Apply("MapArgs",{body,"Substitute"}); -]; -Rule("Substitute",1,3,True) body; - -/*Extremely hacky workaround, MacroSubstitute is actually the same as Substitute, - but without re-evaluating its arguments. I could not just change Substitute, as - it changed behaviour such that tests started to break. - */ -Function("MacroSubstitute",{body,predicate,change}) -[ - `MacroSubstitute((Hold(@body))); -]; -HoldArg("MacroSubstitute",predicate); -HoldArg("MacroSubstitute",change); -UnFence("MacroSubstitute",3); -RuleBase("MacroSubstitute",{body}); -UnFence("MacroSubstitute",1); - -Rule("MacroSubstitute",1,1,`ApplyPure(predicate,{Hold(Hold(@body))}) = True) -[ - `ApplyPure(change,{Hold(Hold(@body))}); -]; -Rule("MacroSubstitute",1,2,`IsFunction(Hold(@body))) -[ - `ApplyPure("MacroMapArgs",{Hold(Hold(@body)),"MacroSubstitute"}); -]; -Rule("MacroSubstitute",1,3,True) -[ - `Hold(@body); -]; - - - -LocalSymbols(predicate,list,result,item) -[ - Function("Select",{predicate,list}) - [ - Local(result); - result:={}; - ForEach(item,list) - [ - If(Apply(predicate,{item}),DestructiveAppend(result,item)); - ]; - result; - ]; - HoldArg("Select",predicate); - UnFence("Select",2); -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/substitute.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/substitute.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/substitute.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/substitute.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -Substitute -MacroSubstitute -Select -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/sums.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/sums.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,361 +0,0 @@ -/* this is disabled because some functions seem to implicitly define Min / Max with a different number of args, and then MathPiper is confused if it hasn't loaded all the Function() declarations beforehand. -FIXME -/// Min, Max with many arguments -*/ -Retract("Min", 1); -Retract("Min", 2); -Retract("Min", 3); -Retract("Max", 1); -Retract("Max", 2); -Retract("Max", 3); -//Function() Min(list); -//Function() Max(list); - -//Function() Min(l1, l2); -//Function() Max(l1, l2); -Function() Min(l1, l2, l3, ...); -Function() Max(l1, l2, l3, ...); - -10 # Min(_l1, _l2, l3_IsList) <-- Min(Concat({l1, l2}, l3)); -20 # Min(_l1, _l2, _l3) <-- Min({l1, l2, l3}); - -10 # Max(_l1, _l2, l3_IsList) <-- Max(Concat({l1, l2}, l3)); -20 # Max(_l1, _l2, _l3) <-- Max({l1, l2, l3}); -/**/ -10 # Min(l1_IsList,l2_IsList) <-- Map("Min",{l1,l2}); -10 # Max(l1_IsList,l2_IsList) <-- Map("Max",{l1,l2}); - -20 # Min(l1_IsRationalOrNumber,l2_IsRationalOrNumber) <-- If(l1l2,l1,l2); - -30 # Min(l1_IsConstant,l2_IsConstant) <-- If(N(Eval(l1-l2))<0,l1,l2); -30 # Max(l1_IsConstant,l2_IsConstant) <-- If(N(Eval(l1-l2))>0,l1,l2); - -// Min and Max on empty lists -10 # Min({}) <-- Undefined; -10 # Max({}) <-- Undefined; - -20 # Min(list_IsList) <-- -[ - Local(result); - result:= list[1]; - ForEach(item,Tail(list)) result:=Min(result,item); - result; -]; -20 # Max(list_IsList) <-- -[ - Local(result); - result:= list[1]; - ForEach(item,Tail(list)) result:=Max(result,item); - result; -]; - -30 # Min(_x) <-- x; -30 # Max(_x) <-- x; - -/* Factorials */ - -10 # 0! <-- 1; -10 # (Infinity)! <-- Infinity; -20 # ((n_IsPositiveInteger)!) <-- [ - Check(n <= 65535, "Factorial: Error: the argument " : ( ToString() Write(n) ) : " is too large, you may want to avoid exact calculation"); - MathFac(n); -]; - -25 # ((x_IsConstant)!)_(FloatIsInt(x) And x>0) <-- (Round(x)!); - -30 # ((x_IsNumber)!)_InNumericMode() <-- Internal'GammaNum(x+1); - -40 # (n_IsList)! <-- MapSingle("!",n); - -/* formulae for half-integer factorials: - -(+(2*z+1)/2)! = Sqrt(Pi)*(2*z+1)! / (2^(2*z+1)*z!) for z >= 0 -(-(2*z+1)/2)! = Sqrt(Pi)*(-1)^z*z!*2^(2*z) / (2*z)! for z >= 0 - -Double factorials are more efficient: - (2*n-1)!! := 1*3*...*(2*n-1) = (2*n)! / (2^n*n!) - (2*n)!! := 2*4*...*(2*n) = 2^n*n! - -*/ -/* // old version - not using double factorials -HalfIntegerFactorial(n_IsOdd) _ (n>0) <-- - Sqrt(Pi) * ( n! / ( 2^n*((n-1)/2)! ) ); -HalfIntegerFactorial(n_IsOdd) _ (n<0) <-- - Sqrt(Pi) * ( (-1)^((-n-1)/2)*2^(-n-1)*((-n-1)/2)! / (-n-1)! ); -*/ -// new version using double factorials -HalfIntegerFactorial(n_IsOdd) _ (n>0) <-- - Sqrt(Pi) * ( n!! / 2^((n+1)/2) ); -HalfIntegerFactorial(n_IsOdd) _ (n<0) <-- - Sqrt(Pi) * ( (-1)^((-n-1)/2)*2^((-n-1)/2) / (-n-2)!! ); -//HalfIntegerFactorial(n_IsOdd) _ (n= -1) <-- Sqrt(Pi); - -/* Want to also compute (2.5)! */ -40 # (n_IsRationalOrNumber)! _(Denom(Rationalize(n))=2) <-- HalfIntegerFactorial(Numer(Rationalize(n))); - -/// partial factorial -n1_IsRationalOrNumber *** n2_IsRationalOrNumber <-- -[ - Check(n2-n1 <= 65535, "Partial factorial: Error: the range " : ( ToString() Write(n2-n1) ) : " is too large, you may want to avoid exact calculation"); - If(n2-n1<0, - 1, - Factorial'partial(n1, n2) - ); -]; - -/// recursive routine to evaluate "partial factorial" a*(a+1)*...*b -// TODO lets document why the >>1 as used here is allowed (rounding down? What is the idea behind this algorithm?) -2# Factorial'partial(_a, _b) _ (b-a>=4) <-- Factorial'partial(a, a+((b-a)>>1)) * Factorial'partial(a+((b-a)>>1)+1, b); -3# Factorial'partial(_a, _b) _ (b-a>=3) <-- a*(a+1)*(a+2)*(a+3); -4# Factorial'partial(_a, _b) _ (b-a>=2) <-- a*(a+1)*(a+2); -5# Factorial'partial(_a, _b) _ (b-a>=1) <-- a*(a+1); -6# Factorial'partial(_a, _b) _ (b-a>=0) <-- a; - - -/* Binomials -- now using partial factorial for speed */ -// Bin(n,m) = Bin(n, n-m) -10 # Bin(0,0) <-- 1; -10 # Bin(n_IsPositiveInteger,m_IsNonNegativeInteger)_(2*m <= n) <-- ((n-m+1) *** n) / m!; -15 # Bin(n_IsPositiveInteger,m_IsNonNegativeInteger)_(2*m > n And m <= n) <-- Bin(n, n-m); -20 # Bin(n_IsInteger,m_IsInteger) <-- 0; - -/// even/odd double factorial: product of even or odd integers up to n -1# (n_IsPositiveInteger)!! _ (n<=3) <-- n; -2# (n_IsPositiveInteger)!! <-- -[ - Check(n<=65535, "Double factorial: Error: the argument " : ( ToString() Write(n) ) : " is too large, you may want to avoid exact calculation"); - Factorial'double(2+Mod(n, 2), n); -]; -// special cases -3# (_n)!! _ (n= -1 Or n=0)<-- 1; - -// the purpose of this mess "Div(a+b,2)+1+Mod(Div(a+b,2)+1-a, 2)" is to obtain the smallest integer which is >= Div(a+b,2)+1 and is also odd or even when a is odd or even; we need to add at most 1 to (Div(a+b,2)+1) -2# Factorial'double(_a, _b) _ (b-a>=6) <-- Factorial'double(a, Div(a+b,2)) * Factorial'double(Div(a+b,2)+1+Mod(Div(a+b,2)+1-a, 2), b); -3# Factorial'double(_a, _b) _ (b-a>=4) <-- a*(a+2)*(a+4); -4# Factorial'double(_a, _b) _ (b-a>=2) <-- a*(a+2); -5# Factorial'double(_a, _b) <-- a; - -/// double factorial for lists is threaded -30 # (n_IsList)!! <-- MapSingle("!!",n); - - - -/* Sums */ - -RuleBase("Sum",{sumvar'arg,sumfrom'arg,sumto'arg,sumbody'arg}); - -5 # Sum(_sumvar,sumfrom_IsNumber,sumto_IsNumber,_sumbody)_(sumfrom>sumto) <-- 0; - -10 # Sum(_sumvar,sumfrom_IsNumber,sumto_IsNumber,_sumbody)_(sumto @sumfrom) - <-- - [ - Local(sub); - (sub := Eval(UnList({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg}))); - Simplify(Eval(@sum) - sub ); - ]); -]; - -SumFunc(_sumvar,sumfrom_IsInteger,_sumto,_sumbody,_sum,_condition) <-- -[ - - `(40 # Sum(@sumvar,@sumfrom,@sumto,@sumbody)_(@condition) <-- Eval(@sum) ); - `(41 # Sum(@sumvar,p_IsInteger,@sumto,@sumbody )_(@condition And p > @sumfrom) - <-- - [ - Local(sub); - `(sub := Eval(UnList({Sum,sumvar'arg,@sumfrom,p-1,sumbody'arg}))); - Simplify(Eval(@sum) - sub ); - ]); -]; - -// Some type of canonical form is needed so that these match when -// given in a different order, like x^k/k! vs. (1/k!)*x^k -// works ! -SumFunc(_k,1,_n,_c + _d, - Eval(UnList({Sum,sumvar'arg,1,n,c})) + - Eval(UnList({Sum,sumvar'arg,1,n,d})) -); -SumFunc(_k,1,_n,_c*_expr,Eval(c*UnList({Sum,sumvar'arg,1,n,expr})), IsFreeOf(k,c) ); -SumFunc(_k,1,_n,_expr/_c,Eval(UnList({Sum,sumvar'arg,1,n,expr})/c), IsFreeOf(k,c) ); - -// this only works when the index=1 -// If the limit of the general term is not zero, then the series diverges -// We need something like IsUndefined(term), because this croaks when limit return Undefined -//SumFunc(_k,1,Infinity,_expr,Infinity,Eval(Abs(UnList({Limit,sumvar'arg,Infinity,expr})) > 0)); -SumFunc(_k,1,Infinity,1/k,Infinity); - -SumFunc(_k,1,_n,_c,c*n,IsFreeOf(k,c) ); -SumFunc(_k,1,_n,_k, n*(n+1)/2 ); -//SumFunc(_k,1,_n,_k^2, n*(n+1)*(2*n+1)/6 ); -//SumFunc(_k,1,_n,_k^3, (n*(n+1))^2 / 4 ); -SumFunc(_k,1,_n,_k^_p,(Bernoulli(p+1,n+1) - Bernoulli(p+1))/(p+1), IsInteger(p) ); -SumFunc(_k,1,_n,2*_k-1, n^2 ); -SumFunc(_k,1,_n,HarmonicNumber(_k),(n+1)*HarmonicNumber(n) - n ); - -// Geometric series! The simplest of them all ;-) -SumFunc(_k,0,_n,(r_IsFreeOf(k))^(_k), (1-r^(n+1))/(1-r) ); - -// Infinite Series -// this allows Zeta a complex argument, which is not supported yet -SumFunc(_k,1,Infinity,1/(_k^_d), Zeta(d), IsFreeOf(k,d) ); -SumFunc(_k,1,Infinity,_k^(-_d), Zeta(d), IsFreeOf(k,d) ); - -SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1)!,Sinh(x) ); -SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k+1)/(2*_k+1)!,Sin(x) ); -SumFunc(_k,0,Infinity,_x^(2*_k)/(2*_k)!,Cosh(x) ); -SumFunc(_k,0,Infinity,(-1)^k*_x^(2*_k)/(2*_k)!,Cos(x) ); -SumFunc(_k,0,Infinity,_x^(2*_k+1)/(2*_k+1),ArcTanh(x) ); -SumFunc(_k,0,Infinity,1/(_k)!,Exp(1) ); -SumFunc(_k,0,Infinity,_x^_k/(_k)!,Exp(x) ); -40 # Sum(_var,_from,Infinity,_expr)_( `(Limit(@var,Infinity)(@expr)) = Infinity) <-- Infinity; - -SumFunc(_k,1,Infinity,1/Bin(2*_k,_k), (2*Pi*Sqrt(3)+9)/27 ); -SumFunc(_k,1,Infinity,1/(_k*Bin(2*_k,_k)), (Pi*Sqrt(3))/9 ); -SumFunc(_k,1,Infinity,1/(_k^2*Bin(2*_k,_k)), Zeta(2)/3 ); -SumFunc(_k,1,Infinity,1/(_k^3*Bin(2*_k,_k)), 17*Zeta(4)/36 ); -SumFunc(_k,1,Infinity,(-1)^(_k-1)/_k, Ln(2) ); - diff -Nru mathpiper-0.0.svn2556/storage/scripts/sums.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/sums.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -Min -Max -! -Bin -!! -*** -Add -Sum -Average -Factorize -Taylor -Subfactorial -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/sums.rep/om.mpi mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/om.mpi --- mathpiper-0.0.svn2556/storage/scripts/sums.rep/om.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/om.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -// From code.mpi.def: -// [2005-12-28 matmota]: I have to implement some better solution for the -// MathPiper -> OM mapping for these symbols. -OMDef( "Min", "minmax1","min", - { "", "", - 1,2,3,4,5,6,7,8,9,10,11,12,13,14, - "", "" }, - ($):_1 ); -OMDef( "Max", "minmax1","max", - { "", "", - 1,2,3,4,5,6,7,8,9,10,11,12,13,14, - "", "" }, - ($):_1 ); -OMDef( "!", "integer1","factorial" ); -OMDef( "Bin", "combinat1","binomial" ); -OMDef( "!!", "piper","double_factorial" ); -OMDef( "***", "piper","partial_factorial" ); -OMDef( "Add", "piper","Add" ); -OMDef( "Sum", "arith1","sum", // Same argument reordering as Integrate. - { $, _2 .. _3, OMBIND(OMS("fns1", "lambda"), OMBVAR(_1), _4) }, - { $, _{2,2,1}, _{1,1}, _{1,2}, _{2,3} } - ); -OMDef( "Factorize", "piper","Factorize" ); -OMDef( "Taylor", "piper","Taylor" ); -OMDef( "Subfactorial", "piper","Subfactorial" ); diff -Nru mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor3.mpi mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor3.mpi --- mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor3.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor3.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,193 +0,0 @@ - - -/* Taylor3, implementation of Taylor series expansion by doing calculation on series directly. - */ - -Defun("Taylor3'MultiplyCoefs",{coefs1,coefs2,degree}) -[ - Local(result,i,j,jset,ilimit,jlimit); - Set(result, ArrayCreate(AddN(degree,1),0)); - Set(i,1); - Set(ilimit,AddN(degree,2)); - While (Not Equals(i,ilimit)) - [ -//Echo(coefs1,coefs2); - Set(j,1); - Set(jlimit,AddN(degree,SubtractN(3,i))); - While (Not Equals(j,jlimit)) - [ - Set(jset,AddN(i,SubtractN(j,1))); -//Echo("index = ",i+j-1); - ArraySet(result,jset,ArrayGet(result,jset) + ArrayGet(coefs1,i)*ArrayGet(coefs2,j)); - Set(j,AddN(j,1)); - ]; - Set(i,AddN(i,1)); - ]; - result; -]; - - -Bodied("Taylor3'TaylorCoefs",0); -10 # (Taylor3'TaylorCoefs(_var,_degree)(_var)) <-- -[ - Local(result); - Set(result,ArrayCreate(degree+1,0)); - ArraySet(result,2, 1); - result; -//Echo("degree = ",degree); -// BaseVector(2,degree+1); -]; -20 # (Taylor3'TaylorCoefs(_var,_degree)(_atom))_(IsFreeOf(var,atom)) - <-- - [ - Local(result); - Set(result,ArrayCreate(degree+1,0)); - ArraySet(result,1, atom); - result; -// atom*BaseVector(1,degree+1); - ]; -30 # (Taylor3'TaylorCoefs(_var,_degree)(_X + _Y)) - <-- - [ - Local(result,add,i); - Set(result,Taylor3'TaylorCoefs(var,degree)(X)); - Set(add, Taylor3'TaylorCoefs(var,degree)(Y)); - For(i:=1,i<=degree+1,i++) - [ - ArraySet(result,i,ArrayGet(result,i)+ArrayGet(add,i)); - ]; - result; - ]; - -30 # (Taylor3'TaylorCoefs(_var,_degree)(_X - _Y)) - <-- - [ - Local(result,add,i); - Set(result,Taylor3'TaylorCoefs(var,degree)(X)); - Set(add, Taylor3'TaylorCoefs(var,degree)(Y)); - For(i:=1,i<=degree+1,i++) - [ - ArraySet(result,i,ArrayGet(result,i)-ArrayGet(add,i)); - ]; - result; - ]; - -30 # (Taylor3'TaylorCoefs(_var,_degree)( - _Y)) - <-- - [ - Local(result,add,i); - Set(result,Taylor3'TaylorCoefs(var,degree)(Y)); - For(i:=1,i<=degree+1,i++) - [ - ArraySet(result,i,-ArrayGet(result,i)); - ]; - result; - ]; - -30 # (Taylor3'TaylorCoefs(_var,_degree)(_X * _Y)) - <-- Taylor3'MultiplyCoefs( - Taylor3'TaylorCoefs(var,degree)(X), - Taylor3'TaylorCoefs(var,degree)(Y), - degree); - -30 # (Taylor3'TaylorCoefs(_var,_degree)((_X) ^ N_IsPositiveInteger)) - <-- -[ - Local(result,factor); - factor:=Taylor3'TaylorCoefs(var,degree)(X); - result:=ArrayCreate(degree+1,0); - result[1] := 1; - //TODO@@@ optimize - While(N>0) - [ - result:=Taylor3'MultiplyCoefs(result,factor,degree); - N--; - ]; - result; -]; - -60 # Taylor3'UniFunction("Exp") <-- True; -60 # Taylor3'CompCoeff("Exp", _n) <-- 1/n!; - -80 # Taylor3'UniFunction("Ln") <-- False; // False because this rule is only applicable for Ln(x+1) -80 # Taylor3'CompCoeff("Ln", 0) <-- 0; -81 # Taylor3'CompCoeff("Ln", _n) <-- (-1)^(n+1)/n; - -90 # Taylor3'UniFunction("Sin") <-- True; -90 # Taylor3'CompCoeff("Sin", n_IsOdd) <-- (-1)^((n-1)/2) / n!; -90 # Taylor3'CompCoeff("Sin", n_IsEven) <-- 0; - -100 # Taylor3'UniFunction("Cos") <-- True; -100 # Taylor3'CompCoeff("Cos", n_IsOdd) <-- 0; -100 # Taylor3'CompCoeff("Cos", n_IsEven) <-- (-1)^(n/2) / n!; - - -210 # Taylor3'UniFunction(_any)_ - ( - [ - Local(result); - result:= Deriv(var)UnList({Atom(any),var}); - Type(result) != "Deriv"; - ] - ) <-- - [ - True; - ]; -210 # Taylor3'CompCoeff(_any, n_IsInteger) - <-- - [ - Limit(var,0)(Deriv(var,n)(UnList({Atom(any),var}))/n!); - ]; - - - -60000 # Taylor3'UniFunction(_any) <-- False; - - -Taylor3'FuncCoefs(_fname,_degree) <-- -[ - Local(sins,i); - Set(sins, ArrayCreate(degree+1,0)); - For (i:=0,i<=degree,Set(i,i+1)) - [ - ArraySet(sins,i+1, Taylor3'CompCoeff(fname,i)); - ]; - sins; -]; - - -100 # (Taylor3'TaylorCoefs(_var,_degree)(Ln(_f)))_(Simplify(f-1) = var) <-- Taylor3'FuncCoefs("Ln",degree); - - -110 # (Taylor3'TaylorCoefs(_var,_degree)(f_IsFunction))_(NrArgs(f) = 1 And (Taylor3'UniFunction(Type(f)))) <-- -[ - Local(sins,i,j,result,xx,expr,sinfact); - expr := f[1]; - sins:=Taylor3'FuncCoefs(Type(f),degree); -//Echo("sins = ",sins); - expr:=Taylor3'TaylorCoefs(var,degree)expr; - result:=ArrayCreate(degree+1,0); - ArraySet(result,1, ArrayGet(sins,1)); - xx:=expr; -//Echo("8...",sins,expr); - For (i:=2,i<=degree+1,i++) - [ - Set(sinfact,sins[i]); -//Echo("8.1..",i," ",j); - For (j:=1,j<=degree+1,j++) - [ - ArraySet(result,j,ArrayGet(result,j) + (ArrayGet(xx,j) * sinfact)); - ]; -//Echo("8.2.."); - Set(xx,Taylor3'MultiplyCoefs(xx,expr,degree)); -//Echo("8.3.."); - ]; - result; -]; - - -(Taylor3(_var,_degree)(_expr)) <-- Add((Taylor3'TaylorCoefs(var,degree)(expr))[1 .. degree+1]*var^(0 .. degree)); -10 # (Taylor3(_x, 0, _n) _y) <-- Taylor3(x,n) y; -20 # (Taylor3(_x, _a, _n) _y) <-- Subst(x,x-a) Taylor3(x,n) Subst(x,x+a) y; - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor3.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor3.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor3.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor3.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -Taylor3 -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor.mpi mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor.mpi --- mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,799 +0,0 @@ -/* - * Taylor(x,a,n) y --- ENTRY POINT - * ~~~~~~~~~~~~~~~ - * The n-th degree Taylor polynomial of y around x=a - * - * This function is implemented by doing calculus on power series. For - * instance, the Taylor series of Sin(x)^2 around x=0 is computed as - * follows. First, we look up the series for Sin(x) - * Sin(x) = x - 1/6 x^3 + 1/120 x^5 - 1/5040 x^7 + ... - * and then we compute the square of this series - * Sin(x)^2 = x^2 - x^4/3 + 2/45 x^6 - 1/315 x^8 + ... - * - * An alternative method is to use the formula - * Taylor(x,a,n) y = \sum_{k=0}^n 1/k! a_k x^k, - * where a_k is the k-th order derivative of y with respect to x, - * evaluated at x=a. In fact, the old implementation of "Taylor", which - * is retained in obsolete.mpi, uses this method. However, we found out - * that the expressions for the derivatives often grow very large, which - * makes the computation too slow. - * - * The power series are implemented as lazy power series, which means - * that the coefficients are computed on demand. Lazy power series are - * encapsulated in expressions of the form - * Taylor'LPS(order, coeffs, var, expr). - * This represent the power series of "expr", seen as a function of - * "var". "coeffs" is list of coefficients that have been computed thus - * far. The integer "order" is the order of the first coefficient. - * - * For instance, the expression - * Taylor'LPS(1, {1,0,-1/6,0}, x, Sin(x)) - * contains the power series of Sin(x), viewed as a function of x, where - * the four coefficients corresponding to x, x^2, x^3, and x^4 have been - * computed. One can view this expression as x - 1/6 x^3 + O(x^5). - * - * "coeffs" is the empty list in the following special cases: - * 1) order = Infinity represents the zero power series - * 2) order = Undefined represents a power series of which no - * coefficients have yet been computed. - * 3) order = n represents a power series of order at least n, - * of which no coefficients have yet been computed. - * - * "expr" may contain subexpressions of the form - * Taylor'LPS'Add(lps1, lps2) = lps1)x) + lps2(x) - * Taylor'LPS'ScalarMult(a, lps) = a*lps(x) (a is scalar) - * Taylor'LPS'Multiply(lps1, lps2) = lps1(x) * lps2(x) - * Taylor'LPS'Inverse(lps) = 1/lps(x) - * Taylor'LPS'Power(lps, n) = lps(x)^n (n is natural number) - * Taylor'LPS'Compose(lps1, lps2) = lps1(lps2(x)) - * - * A well-formed LPS is an expression of the form - * Taylor'LPS(order, coeffs, var, expr) - * satisfying the following conditions: - * 1) order is an integer, Infinity, or Undefined; - * 2) coeffs is a list; - * 3) if order is Infinity or Undefined, then coeffs is {}; - * 4) if order is an integer, then coeffs is empty - * or its first entry is nonzero; - * 5) var does not appear in coeffs; - * 6) expr is normalized with Taylor'LPS'NormalizeExpr. - * - */ - -/* For the moment, the function is called Taylor2. */ - -/* HELP: Is this the correct mechanism to signal incorrect input? */ -/*COMMENT FROM AYAL: Formally, I would do it the other way around, although this is more efficient. This - scheme says: all following rules hold if n>=0. Ideally you'd have a rule "this transformation rule holds - if n>=0". But then you would end up checking that n>=0 for each transformation rule, making things a little - bit slower (but more correct, more elegant). - */ -10 # (Taylor2(_x, _a, _n) _y) - _ (Not(IsPositiveInteger(n) Or IsZero(n))) - <-- Check(False, - "Third argument to Taylor should be a nonnegative integer"); - -20 # (Taylor2(_x, 0, _n) _y) <-- -[ - Local(res); - res := Taylor'LPS'PowerSeries(Taylor'LPS'Construct(x, y), n, x); - If (ClearError("singularity"), - Echo(y, "has a singularity at", x, "= 0.")); - If (ClearError("dunno"), - Echo("Cannot determine power series of", y)); - res; -]; - -30 # (Taylor2(_x, _a, _n) _y) - <-- Subst(x,x-a) Taylor2(x,0,n) Subst(x,x+a) y; - -/********************************************************************** - * - * Parameters - * ~~~~~~~~~~ - * The number of coefficients to be computed before concluding that a - * given power series is zero */ - - - -/*TODO COMMENT FROM AYAL: This parameter, 15, seems to be a bit arbitrary. This implies that there is an input - with more than 15 zeroes, and then a non-zero coefficient, that this would fail on. Correct? Is there not - a more accurate estimation of this parameter? - */ -Taylor'LPS'Param1() := 15; - -/********************************************************************** - * - * Taylor'LPS'Construct(var, expr) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * construct a LPS - * PRE: var is a name - * POST: returns a well-formed LPS - */ - -10 # Taylor'LPS'Construct(_var, _expr) - <-- Taylor'LPS(Undefined, {}, var, - Taylor'LPS'NormalizeExpr(var, expr)); - -/********************************************************************** - * - * Taylor'LPS'Coeffs(lps, n1, n2) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * List of coefficients of order n1 up to n2 - * PRE: lps is a well-formed LPS, n1 in Z, n2 in Z, n2 >= n1 - * POST: returns list of length n2-n1+1, - * or raises "dunno", "div-by-zero", or "maybe-div-by-zero" - * lps may be changed, but it's still a well-formed LPS - */ - -Taylor'LPS'Coeffs(_lps, _n1, _n2) <-- -[ - Local(res, finished, order, j, k, n, tmp, c1, c2); - finished := False; - - /* Case 1: Zero power series */ - - If (lps[1] = Infinity, - [ - res := FillList(0, n2-n1+1); - finished := True; - ]); - - /* Case 2: Coefficients are already computed */ - - If (Not finished And lps[1] != Undefined And n2 < lps[1]+Length(lps[2]), - [ - If (n1 >= lps[1], - res := Take(lps[2], {n1-lps[1]+1, n2-lps[1]+1}), - If (n2 >= lps[1], - res := Concat(FillList(0, lps[1]-n1), - Take(lps[2], n2-lps[1]+1)), - res := FillList(0, n2-n1+1))); - finished := True; - ]); - - /* Case 3: We need to compute the coefficients */ - - If (Not finished, - [ - /* Subcase 3a: Expression is recognized by Taylor'LPS'CompOrder */ - - order := Taylor'LPS'CompOrder(lps[3], lps[4]); - If (Not ClearError("dunno"), - [ - If (lps[1] = Undefined, - [ - lps[1] := order; - If (order <= n2, - [ - lps[2] := Table(Taylor'LPS'CompCoeff(lps[3], lps[4], n), - n, order, n2, 1); - ]); - ],[ - tmp := Table(Taylor'LPS'CompCoeff(lps[3], lps[4], n), - n, lps[1]+Length(lps[2]), n2, 1); - lps[2] := Concat(lps[2], tmp); - ]); - finished := True; - ]); - - /* Subcase 3b: Addition */ - - If (Not finished And lps[4][0] = Taylor'LPS'Add, - [ - lps[1] := Min(Taylor'LPS'GetOrder(lps[4][1])[1], - Taylor'LPS'GetOrder(lps[4][2])[1], n2); - If (IsError("dunno"), - [ - ClearError("dunno"); - ClearError("dunno"); - ],[ - If (lps[1] <= n2, - [ - c1 := Taylor'LPS'Coeffs(lps[4][1], lps[1] + Length(lps[2]), n2); - c2 := Taylor'LPS'Coeffs(lps[4][2], lps[1] + Length(lps[2]), n2); - lps[2] := Concat(lps[2], c1 + c2); - ]); - finished := True; - ]); - ]); - - /* Subcase 3c: Scalar multiplication */ - - If (Not finished And lps[4][0] = Taylor'LPS'ScalarMult, - [ - lps[1] := Min(Taylor'LPS'GetOrder(lps[4][2])[1], n2); - If (Not ClearError("dunno"), - [ - If (lps[1] <= n2, - [ - tmp := Taylor'LPS'Coeffs(lps[4][2], - lps[1] + Length(lps[2]), n2); - tmp := lps[4][1] * tmp; - lps[2] := Concat(lps[2], tmp); - ]); - finished := True; - ]); - ]); - - /* Subcase 3d: Multiplication */ - - If (Not finished And lps[4][0] = Taylor'LPS'Multiply, - [ - lps[1] := Taylor'LPS'GetOrder(lps[4][1])[1] - + Taylor'LPS'GetOrder(lps[4][2])[1]; - If (IsError("dunno"), - [ - ClearError("dunno"); - ClearError("dunno"); - ],[ - If (lps[1] <= n2, - [ - c1 := Taylor'LPS'Coeffs(lps[4][1], lps[4][1][1], - n2 - lps[4][2][1]); - c2 := Taylor'LPS'Coeffs(lps[4][2], lps[4][2][1], - n2 - lps[4][1][1]); - tmp := lps[2]; - ForEach(k, (Length(lps[2])+1) .. Length(c1)) - tmp := Append(tmp, Sum(j, 1, k, c1[j]*c2[k+1-j])); - lps[2] := tmp; - ]); - finished := True; - ]); - ]); - - /* Subcase 3e: Inversion */ - - If (Not finished And lps[4][0] = Taylor'LPS'Inverse, - [ - If (lps[4][1][1] = Infinity, - [ - Assert("div-by-zero") False; - finished := True; - ]); - If (Not finished And lps[2] = {}, - [ - order := Taylor'LPS'GetOrder(lps[4][1])[1]; - n := order; - c1 := Taylor'LPS'Coeffs(lps[4][1], n, n)[1]; - While (c1 = 0 And n < order + Taylor'LPS'Param1()) - [ - n := n + 1; - c1 := Taylor'LPS'Coeffs(lps[4][1], n, n)[1]; - ]; - If (c1 = 0, - [ - Assert("maybe-div-by-zero") False; - finished := True; - ]); - ]); - If (Not finished, - [ - lps[1] := -lps[4][1][1]; - c1 := Taylor'LPS'Coeffs(lps[4][1], lps[4][1][1], - lps[4][1][1]+n2-lps[1]); - tmp := lps[2]; - If (tmp = {}, tmp := {1/c1[1]}); - If (Length(c1)>1, - [ - ForEach(k, (Length(tmp)+1) .. Length(c1)) - [ - n := -Sum(j, 1, k-1, c1[k+1-j]*tmp[j]) / c1[1]; - tmp := Append(tmp, n); - ]; - ]); - lps[2] := tmp; - finished := True; - ]); - ]); - - /* Subcase 3f: Composition */ - - If (Not finished And lps[4][0] = Taylor'LPS'Compose, - [ - j := Taylor'LPS'GetOrder(lps[4][1])[1]; - Check(j >= 0, "Expansion of f(g(x)) where f has a" - : "singularity is not implemented"); - k := Taylor'LPS'GetOrder(lps[4][2])[1]; - c1 := {j, Taylor'LPS'Coeffs(lps[4][1], j, n2)}; - c2 := {k, Taylor'LPS'Coeffs(lps[4][2], k, n2)}; - c1 := Taylor'TPS'Compose(c1, c2); - lps[1] := c1[1]; - lps[2] := c1[2]; - finished := True; - ]); - - /* Case 3: The end */ - - If (finished, - [ - /* normalization: remove initial zeros from lps[2] */ - - While (lps[2] != {} And lps[2][1] = 0) - [ - lps[1] := lps[1] + 1; - lps[2] := Tail(lps[2]); - ]; - - /* get result */ - - If (Not IsError("dunno") And Not IsError("div-by-zero") - And Not IsError("maybe-div-by-zero"), - [ - If (lps[1] <= n1, - res := Take(lps[2], {n1-lps[1]+1, n2-lps[1]+1}), - If (lps[1] <= n2, - res := Concat(FillList(0, lps[1]-n1), lps[2]), - res := FillList(0, n2-n1+1))); - ]); - ],[ - Assert("dunno") False; - res := False; - ]); - ]); - - /* Return res */ - - res; -]; - - -/********************************************************************** - * - * Truncated power series - * ~~~~~~~~~~~~~~~~~~~~~~ - * Here is the start of an implementation of truncated power series. - * This should be cleaned up. - * - * {n, {a0,a1,a2,a3,...}} represents - * a0 x^n + a1 x^(n+1) + a2 x^(n+2) + a3 x^(n+3) + ... - * - * The function Taylor'TPS'Add(tps1, tps2) adds two of such beasts, - * and returns the sum in the same truncated power series form. - * Similar for the other functions. - */ - -10 # Taylor'TPS'GetCoeff({_n,_c}, _k) _ (k < n) <-- 0; -10 # Taylor'TPS'GetCoeff({_n,_c}, _k) _ (k >= n+Length(c)) <-- Undefined; -20 # Taylor'TPS'GetCoeff({_n,_c}, _k) <-- c[k-n+1]; - - -10 # Taylor'TPS'Add({_n1,_c1}, {_n2,_c2}) <-- -[ - Local(n, len, c1b, c2b); - n := Min(n1,n2); - len := Min(n1+Length(c1), n2+Length(c2)) - n; - c1b := Take(Concat(FillList(0, n1-n), c1), len); - c2b := Take(Concat(FillList(0, n2-n), c2), len); - {n, c1b+c2b}; -]; - -10 # Taylor'TPS'ScalarMult(_a, {_n2,_c2}) <-- {n2, a*c2}; - -10 # Taylor'TPS'Multiply({_n1,_c1}, {_n2,_c2}) <-- -[ - Local(j,k,c); - c := {}; - For (k:=1, k<=Min(Length(c1), Length(c2)), k++) - [ - c := c : Sum(j, 1, k, c1[j]*c2[k+1-j]); - ]; - {n1+n2, c}; -]; - -10 # Taylor'TPS'Compose({_n1,_c1}, {_n2,_c2}) <-- -[ - Local(res, tps, tps2, k, n); - n := Min(n1+Length(c1)-1, n2+Length(c2)-1); - tps := {0, 1 : FillList(0, n)}; // tps = {n2,c2} ^ k - res := Taylor'TPS'ScalarMult(Taylor'TPS'GetCoeff({n1,c1}, 0), tps); - For (k:=1, k<=n, k++) - [ - tps := Taylor'TPS'Multiply(tps, {n2,c2}); - tps2 := Taylor'TPS'ScalarMult(Taylor'TPS'GetCoeff({n1,c1}, k), tps); - res := Taylor'TPS'Add(res, tps2); - ]; - res; -]; - - - -/********************************************************************** - * - * Taylor'LPS'NormalizeExpr(var, expr) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Return expr, with "+" replaced by Taylor'LPS'Add, etc. - * PRE: var is a name - */ - -5 # Taylor'LPS'NormalizeExpr(_var, _e1) - _ [Taylor'LPS'CompOrder(var,e1); Not ClearError("dunno");] - <-- e1; - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 + _e2) - <-- Taylor'LPS'Add(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e2)); - -10 # Taylor'LPS'NormalizeExpr(_var, - _e1) - <-- Taylor'LPS'ScalarMult(-1, Taylor'LPS'Construct(var, e1)); - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 - _e2) - <-- (Taylor'LPS'Add(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e3)) - Where e3 == Taylor'LPS'ScalarMult(-1, Taylor'LPS'Construct(var, e2))); - -10 # Taylor'LPS'NormalizeExpr(_var, e1_IsFreeOf(var) * _e2) - <-- Taylor'LPS'ScalarMult(e1, Taylor'LPS'Construct(var, e2)); - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 * e2_IsFreeOf(var)) - <-- Taylor'LPS'ScalarMult(e2, Taylor'LPS'Construct(var, e1)); - -20 # Taylor'LPS'NormalizeExpr(_var, _e1 * _e2) - <-- Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e2)); - -10 # Taylor'LPS'NormalizeExpr(_var, _e1 / e2_IsFreeOf(var)) - <-- Taylor'LPS'ScalarMult(1/e2, Taylor'LPS'Construct(var, e1)); - -20 # Taylor'LPS'NormalizeExpr(_var, 1 / _e1) - <-- Taylor'LPS'Inverse(Taylor'LPS'Construct(var, e1)); - -30 # Taylor'LPS'NormalizeExpr(_var, _e1 / _e2) - <-- (Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e3)) - Where e3 == Taylor'LPS'Inverse(Taylor'LPS'Construct(var, e2))); - -/* Implement powers as repeated multiplication, - * which is seriously inefficient. - */ -10 # Taylor'LPS'NormalizeExpr(_var, _e1 ^ (n_IsPositiveInteger)) - _ (e1 != var) - <-- Taylor'LPS'Multiply(Taylor'LPS'Construct(var, e1), - Taylor'LPS'Construct(var, e1^(n-1))); - -10 # Taylor'LPS'NormalizeExpr(_var, Tan(_x)) - <-- (Taylor'LPS'Multiply(Taylor'LPS'Construct(var, Sin(x)), - Taylor'LPS'Construct(var, e3)) - Where e3 == Taylor'LPS'Inverse(Taylor'LPS'Construct(var, Cos(x)))); - -LocalSymbols(res) -[ -50 # Taylor'LPS'NormalizeExpr(_var, _e1) -_[ - Local(c, lps1, lps2, lps3, success); - success := True; - If (IsAtom(e1), success := False); - If (success And Length(e1) != 1, success := False); - If (success And IsAtom(e1[1]), success := False); - If (success And CanBeUni(var, e1[1]) And Degree(e1[1], var) = 1, - [ - success := False; - ]); - If (success, - [ - lps2 := Taylor'LPS'Construct(var, e1[1]); - c := Taylor'LPS'Coeffs(lps2, 0, 0)[1]; - If (IsError(), - [ - ClearErrors(); - success := False; - ]); - If (success And Taylor'LPS'GetOrder(lps2)[1] < 0, - [ - success := False; - ],[ - If (c = 0, - [ - lps1 := Taylor'LPS'Construct(var, Apply(e1[0], {var})); - res := Taylor'LPS'Compose(lps1, lps2); - ],[ - lps1 := Taylor'LPS'Construct(var, Apply(e1[0], {var+c})); - lps3 := Taylor'LPS'Construct(var, -c); - lps2 := Taylor'LPS'Construct(var, Taylor'LPS'Add(lps2, lps3)); - res := Taylor'LPS'Compose(lps1, lps2); - ]); - ]); - ]); - success; - ] <-- res; -]; - -60000 # Taylor'LPS'NormalizeExpr(_var, _e1) <-- e1; - - -/********************************************************************** - * - * Taylor'LPS'CompOrder(var, expr) --- HOOK - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Compute order of expr as a power series in var - * PRE: var is a name - * POST: returns an integer, or raises "dunno" - * - * Taylor'LPS'CompCoeff(var, expr, n) --- HOOK - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Compute n-th coefficient of expr as a power series in var - * PRE: var is a name, n is an integer, - * Taylor'LPS'CompOrder(var, expr) does not raise "dunno" - * POST: returns an expression not containing var - */ - -5 # Taylor'LPS'CompCoeff(_var, _expr, _n) - _ (n < Taylor'LPS'CompOrder(var, expr)) - <-- 0; - -/* Zero */ - -10 # Taylor'LPS'CompOrder(_x, 0) <-- Infinity; - -/* Constant */ - -20 # Taylor'LPS'CompOrder(_x, e_IsFreeOf(x)) <-- 0; -20 # Taylor'LPS'CompCoeff(_x, e_IsFreeOf(x), 0) <-- e; -21 # Taylor'LPS'CompCoeff(_x, e_IsFreeOf(x), _n) <-- 0; - -/* Identity */ - -30 # Taylor'LPS'CompOrder(_x, _x) <-- 1; -30 # Taylor'LPS'CompCoeff(_x, _x, 1) <-- 1; -31 # Taylor'LPS'CompCoeff(_x, _x, _n) <-- 0; - -/* Powers */ - -40 # Taylor'LPS'CompOrder(_x, _x^(k_IsPositiveInteger)) <-- k; -40 # Taylor'LPS'CompCoeff(_x, _x^(k_IsPositiveInteger), _k) <-- 1; -41 # Taylor'LPS'CompCoeff(_x, _x^(k_IsPositiveInteger), _n) <-- 0; - -/* Sqrt */ - -50 # Taylor'LPS'CompOrder(_x, Sqrt(_y)) - _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) - <-- 0; - -50 # Taylor'LPS'CompCoeff(_x, Sqrt(_y), 0) - _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) - <-- Sqrt(Coef(y,x,0)); - -51 # Taylor'LPS'CompCoeff(_x, Sqrt(_y), _n) - _ (CanBeUni(x,y) And Degree(y,x) = 1 And Coef(y,x,0) != 0) <-- -[ - Local(j); - Coef(y,x,0)^(1/2-n) * Factorize(j,0,n-1,1/2-j) * Coef(y,x,1)^n/n!; -]; - -/* Exp */ - -60 # Taylor'LPS'CompOrder(_x, Exp(_x)) <-- 0; -60 # Taylor'LPS'CompCoeff(_x, Exp(_x), _n) <-- 1/n!; - -70 # Taylor'LPS'CompOrder(_x, Exp(_y))_(CanBeUni(x,y) And Degree(y,x) = 1) - <-- 0; - -70 # Taylor'LPS'CompCoeff(_x, Exp(_y), _n)_(CanBeUni(x,y) And Degree(y,x) = 1) - <-- Exp(Coef(y,x,0)) * Coef(y,x,1)^n / n!; - -/* Ln */ - -80 # Taylor'LPS'CompOrder(_x, Ln(_x+1)) <-- 1; -80 # Taylor'LPS'CompCoeff(_x, Ln(_x+1), _n) <-- (-1)^(n+1)/n; - -/* Sin */ - -90 # Taylor'LPS'CompOrder(_x, Sin(_x)) <-- 1; -90 # Taylor'LPS'CompCoeff(_x, Sin(_x), n_IsOdd) <-- (-1)^((n-1)/2) / n!; -90 # Taylor'LPS'CompCoeff(_x, Sin(_x), n_IsEven) <-- 0; - -/* Cos */ - -100 # Taylor'LPS'CompOrder(_x, Cos(_x)) <-- 0; -100 # Taylor'LPS'CompCoeff(_x, Cos(_x), n_IsOdd) <-- 0; -100 # Taylor'LPS'CompCoeff(_x, Cos(_x), n_IsEven) <-- (-1)^(n/2) / n!; - -/* Inverse (not needed but speeds things up) */ - -110 # Taylor'LPS'CompOrder(_x, 1/_x) <-- -1; -110 # Taylor'LPS'CompCoeff(_x, 1/_x, -1) <-- 1; -111 # Taylor'LPS'CompCoeff(_x, 1/_x, _n) <-- 0; - - -/*COMMENT FROM AYAL: Jitse, what do you think, fall-through defaulting to calculating the coefficient - the hard way? Worst-case, if people define a taylor series in this module it is faster, otherwise it uses - the old scheme that does explicit derivatives, which is slower, but still better than not returning a result - at all? With this change the new taylor code is at least as good as the old code? - - The ugly part is obvious: instead of having a rule here that says "I work for the following input" I had to - find out empirically what the "exclude list" is, eg. the input it will not work on. This because the system - as it works currently yields "dunno", at which moment some other routine picks up. - - I think we can refactor this. - */ - - - - -Taylor'LPS'AcceptDeriv(_expr) <-- - (Contains({"ArcTan"},Type(expr))); -/* - ( Type(Deriv(x)(expr)) != "Deriv" - And Not Contains({ - "/","+","*","^","-","Sin","Cos","Sqrt","Ln","Exp","Tan" - },Type(expr))); -*/ - -200 # Taylor'LPS'CompOrder(_x, (_expr))_(Taylor'LPS'AcceptDeriv(expr)) - <-- - [ -//Echo("CompOrder for ",expr); -// 0; //generic case, assume zeroeth coefficient is non-zero. - Local(n); - n:=0; - While ((Limit(x,0)expr) = 0 And n=0 ) <-- - [ - // This routine is written out for debugging purposes - Local(result); - result:=(Limit(x,0)(Deriv(x,n)expr))/(n!); -Echo(expr," ",n," ",result); - result; - ]; - -/* Default */ - -60000 # Taylor'LPS'CompOrder(_var, _expr) - <-- Assert("dunno") False; - -60000 # Taylor'LPS'CompCoeff(_var, _expr, _n) - <-- Check(False, "Taylor'LPS'CompCoeff'FallThrough" - : ToString() Write({var,expr,n})); - -/********************************************************************** - * - * Taylor'LPS'GetOrder(lps) - * ~~~~~~~~~~~~~~~~~~~~~~~~ - * Returns a pair {n,flag}. If flag is True, then n is the order of - * the LPS. If flag is False, then n is a lower bound on the order. - * PRE: lps is a well-formed LPS - * POST: returns a pair {n,flag}, where n is an integer or Infinity, - * and flag is True or False, or raises "dunno"; - * may update lps. - */ - -20 # Taylor'LPS'GetOrder(Taylor'LPS(_order, _coeffs, _var, _expr)) - _ (order != Undefined) - <-- {order, coeffs != {}}; - -40 # Taylor'LPS'GetOrder(_lps) <-- -[ - Local(res, computed, exact, res1, res2); - computed := False; - - res := Taylor'LPS'CompOrder(lps[3], lps[4]); - If (Not ClearError("dunno"), - [ - res := {res, True}; - computed := True; - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Add, - [ - res1 := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - res2 := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), - [ - res := {Min(res1[1],res2[1]), False}; - /* flag = False, since terms may cancel */ - computed := True; - ]); - ]); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'ScalarMult, - [ - res := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), computed := True); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Multiply, - [ - res1 := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - res2 := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), - [ - res := {res1[1]+res2[1], res1[1] And res2[1]}; - computed := True; - ]); - ]); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Inverse, - [ - res := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - If (res[1] = Infinity, - [ - res[1] = Undefined; - Assert("div-by-zero") False; - computed := True; - ]); - If (Not computed And res[2] = False, - [ - Local(c, n); - n := res[1]; - c := Taylor'LPS'Coeffs(lps[4][1], res[1], res[1])[1]; - While (c = 0 And res[1] < n + Taylor'LPS'Param1()) - [ - res[1] := res[1] + 1; - c := Taylor'LPS'Coeffs(lps[4][1], res[1], res[1])[1]; - ]; - If (c = 0, - [ - res[1] := Undefined; - Assert("maybe-div-by-zero") False; - computed := True; - ]); - ]); - If (Not computed, - [ - res := {-res[1], True}; - computed := True; - ]); - ]); - ]); - - If (Not computed And lps[4][0] = Taylor'LPS'Compose, - [ - res1 := Taylor'LPS'GetOrder(lps[4][1]); - If (Not ClearError("dunno"), - [ - res2 := Taylor'LPS'GetOrder(lps[4][2]); - If (Not ClearError("dunno"), - [ - res := {res1[1]*res2[1], res1[1] And res2[1]}; - computed := True; - ]); - ]); - ]); - - If (computed, lps[1] := res[1]); - Assert("dunno") computed; - res; -]; - -/********************************************************************** - * - * Taylor'LPS'PowerSeries(lps, n, var) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Convert the LPS in a power series in var up to order n - * PRE: lps is a well-formed LPS, n is a natural number - * POST: returns an expression, or raises "singularity" or "dunno" - */ - -10 # Taylor'LPS'PowerSeries(_lps, _n, _var) <-- -[ - Local(ord, k, coeffs); - coeffs := Taylor'LPS'Coeffs(lps, 0, n); - If (IsError("dunno"), - [ - False; - ],[ - If (lps[1] < 0, - [ - Assert("singularity") False; - Undefined; - ],[ - Sum(k, 0, n, coeffs[k+1]*var^k); - ]); - ]); -]; diff -Nru mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/sums.rep/taylor.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/sums.rep/taylor.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -Taylor2 -} \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/storage/scripts/tensor.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/tensor.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/tensor.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/tensor.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,176 +0,0 @@ - -/* Tensor package. This code intends to simplify tensorial expressions. - */ - -/* functions internal to tensors */ -RuleBase("Delta",{ind1,ind2}); -RuleBase("TList",{head,tail}); -RuleBase("TSum",{indices,body}); -RuleBase("TD",{ind}); -RuleBase("X",{ind}); - -/* And the simplificaiton rules for X, addition, subtraction - and multiplication */ -10 # (TD(_i)X(_j)) <-- Delta(i,j); -10 # (TD(_i) ( (_f) + (_g) ) ) <-- (TD(i)f) + (TD(i)g); -10 # (TD(_i) ( (_f) - (_g) ) ) <-- (TD(i)f) - (TD(i)g); -10 # (TD(_i) ( - (_g) ) ) <-- - TD(i)g; -10 # (TD(_i) ( (_f) * (_g) ) ) <-- (TD(i)f)*g + f*(TD(i)g); -10 # (TD(_i) ( (_f) ^ (n_IsPositiveInteger) ) ) <-- n*(TD(i)f)*f^(n-1); -10 # (TD(_i)Delta(_j,_k)) <-- 0; -10 # (TD(_i)f_IsNumber) <-- 0; - -/* The only TSum summation simplification: summing over no indices - means no summation. */ -10 # (TSum({})(_body)) <-- body; - -/* Explicit summation when Ndim is defined. This summation will - be invoked when using TExplicitSum. */ -20 # (TSum(_indices)(_body))_(IsInteger(Ndim)) <-- - LocalSymbols(index,i,sum) - [ - Local(index,i,sum); - index:=indices[1]; - sum:=0; - MacroLocal(index); - For(i:=1,i<=Ndim,i++) - [ - MacroSet(index,i); - sum:=sum+Eval(TSum(Tail(indices))body); - ]; - sum; - ]; - -/* TExplicitSum sets the dimension of the space under consideration, - so summation can proceed */ -(TExplicitSum(Ndim_IsInteger)(_body)) <-- Eval(body); - -/* Move the delta factors to the front, so they can be simplified - away. It uses ApplyDelta to move a factor either to the front - or to the back of the list. Input is a list of factors, as - returned by Flatten(expressions,"*") - */ -MoveDeltas(_list) <-- -[ - Local(result,i,nr); - result:={}; - nr:=Length(list); - For(i:=1,i<=nr,i++) - [ - ApplyDelta(result,list[i]); - ]; - result; -]; - - -10 # ApplyDelta(_result,Delta(_i,_j)) <-- - DestructiveInsert(result,1,Delta(i,j)); -20 # ApplyDelta(_result,(_x) ^ (n_IsInteger))_(n>0) <-- - [ - Local(i); - For(i:=1,i<=n,i++) - [ - ApplyDelta(result,x); - ]; - ]; -100 # ApplyDelta(_result,_term) <-- - DestructiveAppend(result,term); - - -/* TSimplify : expand brackets, and send the expression of addition - of terms to TSimplifyAux */ -TSimplify(TSum(_indices)(_f)) <-- -[ - TSimplifyAux(TSum(indices)ExpandBrackets(f)); -]; - - -/* TSimplifyAux : simplify each term independently */ -10 # TSimplifyAux(TSum(_indices)((_f) + (_g))) <-- - TSimplifyAux(TSum(FlatCopy(indices))(f)) + - TSimplifyAux(TSum(FlatCopy(indices))(g)); -10 # TSimplifyAux(TSum(_indices)((_f) - (_g))) <-- - TSimplifyAux(TSum(FlatCopy(indices))(f)) - - TSimplifyAux(TSum(FlatCopy(indices))(g)); -10 # TSimplifyAux(TSum(_indices)( - (_g))) <-- - - TSimplifyAux(TSum(indices)(g)); - -40 # TSimplifyAux(TSum(_indices)_body) <-- -[ - Local(flat); - - /* Convert expressions of the form (a*b*c) to {a,b,c} */ - flat:=Flatten(body,"*"); - - /* Move the deltas to the front. */ - flat:=MoveDeltas(flat); - - /* Simplify the deltas away (removing the required indices) */ - flat:=TSumRest(flat); - - /* Determine if there are indices the summand still depends on */ - Local(varlist,independ,nrdims); - varlist:=VarList(flat); - independ:=Intersection(indices,varlist); - nrdims:=Length(indices)-Length(independ); - - /* Return result, still summing over the indices not removed by deltas */ - Ndim^nrdims*TSum(independ)flat; -]; - - -/* Terminating condition for the tensorial simplification */ - -10 # TSumSimplify(TList(Delta(_ind,_ind),_list))_Contains(indices,ind) <-- - -[ - /* Remove the index from the list of indices to sum over, since - it is now implicitly summed over by simplifying the delta */ - DestructiveDelete(indices,Find(indices,ind)); - -/* Return result simplified for this delta */ - Ndim*TSumRest(list); -]; - -11 # TSumSimplify(TList(Delta(_ind1,_ind2),_list))_ - Contains(indices,ind2) <-- -[ - /* Remove the index from the list of indices to sum over, since - it is now implicitly summed over by simplifying the delta */ - DestructiveDelete(indices,Find(indices,ind2)); - - /* Return result simplified for this delta */ - TSumRest( Subst(ind2,ind1)list ); -]; -11 # TSumSimplify(TList(Delta(_ind1,_ind2),_list))_ - Contains(indices,ind1) <-- -[ - /* Remove the index from the list of indices to sum over, since - it is now implicitly summed over by simplifying the delta */ - DestructiveDelete(indices,Find(indices,ind1)); - - /* Return result simplified for this delta */ - TSumRest( Subst(ind1,ind2)list ); -]; - - - -1010 # TSumSimplify(TList(_term,_list)) <-- -[ - term*TSumRest(list); -]; - - -10 # TSumRest({}) <-- 1; -20 # TSumRest(_list) <-- -[ - TSumSimplify(TList(Head(list),Tail(list))); -]; - - - -UnFence("TSumSimplify",1); -UnFence("TSumRest",1); -UnFence("TSum",2); - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/tensor.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/tensor.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/tensor.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/tensor.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -TSimplify -TExplicitSum -TSum -Delta -TD -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/testers.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/testers.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/testers.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/testers.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,326 +0,0 @@ - -/* Functions that aid in testing */ - -/* Round to specified number of digits */ -10 # RoundTo(x_IsNumber, prec_IsPositiveInteger) <-- -[ - Local(oldPrec,result); - oldPrec:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(prec); - Set(result,DivideN( Round( MultiplyN(x, 10^prec) ), 10^prec )); - BuiltinPrecisionSet(oldPrec); - result; -]; -// complex numbers too -10 # RoundTo(Complex(r_IsNumber, i_IsNumber), prec_IsPositiveInteger) <-- Complex(RoundTo(r, prec), RoundTo(i, prec)); - -// Infinities, rounding does not apply. -20 # RoundTo( Infinity,prec_IsPositiveInteger) <-- Infinity; -20 # RoundTo(-Infinity,prec_IsPositiveInteger) <-- -Infinity; - -Macro(NumericEqual,{left,right,precision}) -[ - Verify(RoundTo((@left)-(@right),@precision),0); -]; - - -// print current file and line -ShowLine() := [Echo({CurrentFile(),": ",CurrentLine()});]; - - -/* Logging functions */ -// curline:=0; - -/* -Function("StartTests",{}) -[ - curline:=0; -]; -*/ - -Function("NextTest",{aLeft}) -[ -// curline++; -WriteString(" -Test suite for ":aLeft:" : " - ); - NewLine(); -]; - - -Function("Testing",{aLeft}) -[ - WriteString("--"); - WriteString(aLeft); NewLine(); -]; - - -Function("KnownFailure",{expr}) -[ - Local(rfail); - Echo({"Known failure: ", expr}); - Set(rfail,Eval(expr)); - If(rfail,Echo({"Failure resolved!"})); -]; -HoldArg("KnownFailure",expr); - - -/* -Macro("Verify",{aLeft,aRight}) -[ - - Local(result); - result := @aLeft; // to save time - If (Not(Equals(result,@aRight)), - [ - WriteString("******************"); - NewLine(); - ShowLine(); - NewLine(); - Write(Hold(@aLeft)); - NewLine(); - WriteString(" evaluates to "); - NewLine(); - Write(result); - WriteString(" which differs from "); - NewLine(); - Write(Hold(@aRight)); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ], - True - ); -]; -*/ - - -Function("Verify",{aLeft,aRight}) -[ - - Local(result); - result := Eval(aLeft); // to save time - If (Not(Equals(result,aRight)), - [ - WriteString("******************"); - NewLine(); - ShowLine(); - NewLine(); - Write(aLeft); - NewLine(); - WriteString(" evaluates to "); - NewLine(); - Write(result); - NewLine(); - WriteString(" which differs from "); - NewLine(); - Write(aRight); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ], - True - ); -]; -HoldArg("Verify",aLeft); -UnFence("Verify",2); -/* -HoldArg("Verify",aRight); -*/ - -Macro("Verify", {a,b,message}) -[ - Echo("test ", @message); - Verify(@a, @b); -]; - - -Function("LogicVerify",{aLeft,aRight}) -[ - If(aLeft != aRight, - Verify(CanProve(aLeft => aRight),True) - ); -]; - - - -/* LogicTest compares the truth tables of two expressions. */ -LocalSymbols(TrueFalse) -[ - MacroRuleBase(TrueFalse,{var,expr}); - 10 # TrueFalse(var_IsAtom,_expr) <-- `{(@expr) Where (@var)==False,(@expr) Where (@var)==True}; - 20 # TrueFalse({},_expr) <-- `(@expr); - 30 # TrueFalse(var_IsList,_expr) <-- - `[ - Local(t,h); - Set(h,Head(@var)); - Set(t,Tail(@var)); - TrueFalse(h,TrueFalse(t,@expr)); - ]; - - Macro(LogicTest,{vars,expr1,expr2}) Verify(TrueFalse((@vars),(@expr1)), TrueFalse((@vars),(@expr2))); -]; - - -LocalSymbols(f1,f2) -[ - // f1 and f2 are used inside VerifyArithmetic - f1(x,n,m):=(x^n-1)*(x^m-1); - f2(x,n,m):=x^(n+m)-(x^n)-(x^m)+1; - - VerifyArithmetic(x,n,m):= - [ - Verify(f1(x,n,m),f2(x,n,m)); - ]; -]; - -RandVerifyArithmetic(_n)<-- -[ - While(n>0) - [ - n--; - VerifyArithmetic(FloorN(300*Random()),FloorN(80*Random()),FloorN(90*Random())); - ]; -]; - -VerifyDiv(_u,_v) <-- -[ - Local(q,r); - q:=Div(u,v); - r:=Rem(u,v); - - Verify(Expand(u),Expand(q*v+r)); -]; - -10 # EchoInternal(string_IsString) <-- -[ - WriteString(string); -]; - -20 # EchoInternal(_item) <-- -[ - Write(item);Space(); -]; - -RuleBaseListed("Echo",{args}); -10 # Echo(list_IsList)<-- -[ - ForEach(item,list) EchoInternal(item); - NewLine(); -]; -20 # Echo(_item)<-- -[ - EchoInternal(item); - NewLine(); -]; - - -Function("BenchCall",{expr}) -[ - Echo({"In> ",expr}); - WriteString(""); - Eval(expr); - WriteString(""); - True; -]; -HoldArg("BenchCall",expr); - -Function("BenchShow",{expr}) -[ - Echo({"In> ",expr}); - WriteString(" "); - Echo({"Out> ",Eval(expr),""}); - True; -]; -HoldArg("BenchShow",expr); - - - - -/* Testing MathPiper functionality by checking expressions against correct - answer. - Use with algebraic expressions only, since we need Simplify() for that to work. - */ - - - -/* -Macro ("TestMathPiper", {expr, ans}) -[ - Local(diff,exprEval, ansEval); - exprEval:= @expr; - ansEval:= @ans; - - diff := Simplify(exprEval - ansEval); - If (Simplify(diff)=0, True, - [ - WriteString("******************"); - NewLine(); - ShowLine(); - Write(Hold(@expr)); - WriteString(" evaluates to "); - NewLine(); - Write(exprEval); - NewLine(); - WriteString(" which differs from "); - NewLine(); - Write(ansEval); - NewLine(); - WriteString(" by "); - NewLine(); - Write(diff); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ] - ); -]; -*/ - - - - - - - -Function ("TestMathPiper", {expr, ans}) -[ - Local(diff); - diff := Simplify(Eval(expr)-Eval(ans)); - If (Simplify(diff)=0, True, - [ - WriteString("******************"); - NewLine(); - ShowLine(); - Write(expr); - WriteString(" evaluates to "); - NewLine(); - Write(Eval(expr)); - NewLine(); - WriteString(" which differs from "); - NewLine(); - Write(Eval(ans)); - NewLine(); - WriteString(" by "); - NewLine(); - Write(diff); - NewLine(); - WriteString("******************"); - NewLine(); - False; - ] - ); -]; - -HoldArg("TestMathPiper", expr); -HoldArg("TestMathPiper", ans); - - - - - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/testers.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/testers.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/testers.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/testers.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -Verify -KnownFailure -Echo -VerifyArithmetic -RandVerifyArithmetic -VerifyDiv -TestMathPiper -RoundTo -NumericEqual -LogicVerify -LogicTest -Testing -NextTest -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/texform.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/texform.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/texform.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/texform.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,350 +0,0 @@ -/* TeXForm: convert MathPiper objects to TeX math mode strings */ - -/* version 0.4 */ - -/* Changelog - 0.1 basic functionality - 0.2 fixed bracketing of Exp, added all infix ops and math functions - 0.3 fixed bracketing of lists, changed bracketing of math functions, modified TeX representation of user-defined functions (up to two-letter functions are in italics), added TeX Greek letters - 0.4 added nth roots, Sum, Limit, Integrate, hyperbolics, set operations, Abs, Max, Min, "==", ":=", Infinity; support indexed expressions A[i] and matrices. - 0.4.1 bugfixes for [] operator, support for multiple indices a[1][2][3] - 0.4.2 fix for variable names ending on digits "a2" represented as $a_2$ - 0.4.3 bugfixes: complex I, indeterminate integration; relaxed bracketing of Sin()-like functions; implemented $TeX$ and $LaTeX$ correctly now (using \textrm{}) - 0.4.4 use ordinary instead of partial derivative if expression has only one variable - 0.4.5 fixes for bracketing of Sum(); added <> to render as \sim and <=> to render as \approx; added Bin() - 0.4.6 moved the <> and <=> operators to org/mathpiper/scripts/initialization.rep/stdopers.mpi - 0.4.7 added Factorize() i.e. Product() - 0.4.8 added D(x,n), Deriv(x,n), =>, and fixed errors with ArcSinh, ArcCosh, ArcTanh - 0.4.9 fixed omission: (fraction)^n was not put in brackets - 0.4.10 cosmetic change: insert \cdot between numbers in cases like 2*10^n - 0.4.11 added DumpErrors() to TexForm for the benefit of TeXmacs notebooks - 0.4.12 implement the % operation as Mod - 0.4.13 added Bessel{I,J,K,Y}, Ortho{H,P,T,U}, with a general framework for usual two-argument functions of the form $A_n(x)$; fix for Max, Min - 0.4.14 added mathematical notation for Floor(), Ceil() - 0.4.15 added Prog() represented by ( ) - 0.4.16 added Zeta() -*/ - -/* To do: - 0. Find and fix bugs. - 1. The current bracketing approach has limitations: can't omit extra brackets sometimes. " sin a b" is ambiguous, so need to do either "sin a sin b" or "(sin a) b" Hold((a*b)*Sqrt(x)). The current approach is *not* to bracket functions unless the enveloping operation is more binding than multiplication. This produces "sin a b" for both Sin(a*b) and Sin(a)*b but this is the current mathematical practice. - 2. Need to figure out how to deal with variable names such as "alpha3" -*/ - -/// TeXmacs prettyprinter -TexForm(_expr) <-- [DumpErrors();WriteString(TeXForm(expr));NewLine();]; - -RuleBase("TeXForm",{expression}); -RuleBase("TeXForm",{expression, precedence}); - -/* Boolean predicate */ - - -/* this function will put TeX brackets around the string if predicate holds */ - -Function ("TeXFormBracketIf", {predicate, string}) -[ - Check(IsBoolean(predicate) And IsString(string), "TeXForm internal error: non-boolean and/or non-string argument of TeXFormBracketIf"); - If(predicate, ConcatStrings("\\left( ", string, "\\right) "), string); -]; - -/* First, we convert TeXForm(x) to TeXForm(x, precedence). The enveloping precedence will determine whether we need to bracket the results. So TeXForm(x, TeXFormMaxPrec()) will always print "x", while TeXForm(x,-TeXFormMaxPrec()) will always print "(x)". -*/ - -TeXFormMaxPrec() := 60000; /* This precedence will never be bracketed. It is equal to KMaxPrec */ - -/// main front-end -100 # TeXForm(_x) <-- ConcatStrings("$", TeXForm(x, TeXFormMaxPrec()), "$"); - -/* Replace numbers and variables -- never bracketed except explicitly */ - -110 # TeXForm(x_IsNumber, _p) <-- String(x); -/* Variables */ -200 # TeXForm(x_IsAtom, _p) <-- TeXFormTeXify(String(x)); - -/* Strings must be quoted but not bracketed */ -100 # TeXForm(x_IsString, _p) <-- ConcatStrings("\\mathrm{", x, "}"); - -/* Listify(...) can generate lists with atoms that would otherwise result in unparsable expressions. */ -100 # TeXForm(x_IsAtom, _p)_(IsInfix(String(x))) <-- ConcatStrings("\\mathrm{", String(x), "}"); - - -/* Lists: make sure to have matrices processed before them. Enveloping precedence is irrelevant because lists are always bracketed. List items are never bracketed. Note that TeXFormFinishList({a,b}) generates ",a,b" */ - -100 # TeXForm(x_IsList, _p)_(Length(x)=0) <-- TeXFormBracketIf(True, ""); -110 # TeXForm(x_IsList, _p) <-- TeXFormBracketIf(True, ConcatStrings(TeXForm(Head(x), TeXFormMaxPrec()), TeXFormFinishList(Tail(x)) ) ); -100 # TeXFormFinishList(x_IsList)_(Length(x)=0) <-- ""; -110 # TeXFormFinishList(x_IsList) <-- ConcatStrings(", ", TeXForm(Head(x), TeXFormMaxPrec()), TeXFormFinishList(Tail(x))); - -/* Replace operations */ - - - /* Template for "regular" binary infix operators: -100 # TeXForm(_x + _y, _p) <-- TeXFormBracketIf(p=","\\geq "}, - {"<"," < "}, - {">"," > "}, - {"And","\\wedge "}, - {"Or", "\\vee "}, - {"<>", "\\sim "}, - {"<=>", "\\approx "}, - {"=>", "\\Rightarrow "}, - {"%", "\\bmod "}, - }; - - TeXFormRegularPrefixOps := { {"+"," + "}, {"-"," - "}, {"Not"," \\neg "} }; - - - - /* Unknown function: precedence 200. Leave as is, never bracket the function itself and bracket the argumentPointer(s) automatically since it's a list. Other functions are precedence 100 */ - - TeXFormGreekLetters := {"Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon", "Phi", "Psi", "Omega", "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega", "varpi", "varrho", "varsigma", "varphi", "varepsilon"}; - TeXFormSpecialNames := { - {"I", "\\imath "}, // this prevents a real uppercase I, use BesselI instead - {"Pi", "\\pi "}, // this makes it impossible to have an uppercase Pi... hopefully it's not needed - {"Infinity", "\\infty "}, - {"TeX", "\\textrm{\\TeX\\/}"}, - {"LaTeX", "\\textrm{\\LaTeX\\/}"}, - {"Max", "\\max "}, // this replaces these function names - {"Min", "\\min "}, - {"Prog", " "}, - {"Zeta", "\\zeta "}, - }; - - - /* this function will take a user-defined variable or function name and output either this name unmodified if it's only 2 characters long, or the name in normal text if it's longer, or a TeX Greek letter code */ - Function ("TeXFormTeXify", {string}) - [ - Check(IsString(string), "TeXForm internal error: non-string argument of TeXFormTeXify"); - /* Check if it's a greek letter or a special name */ - If (Contains(AssocIndices(TeXFormSpecialNames), string), TeXFormSpecialNames[string], - If (Contains(TeXFormGreekLetters, string), ConcatStrings("\\", string, " "), - If (Contains(AssocIndices(TeXFormRegularOps), string), TeXFormRegularOps[string], - If (Contains(AssocIndices(TeXFormRegularPrefixOps), string), TeXFormRegularPrefixOps[string], - If (Length(string) >= 2 And IsNumber(Atom(StringMidGet(2, Length(string)-1, string))), ConcatStrings(StringMidGet(1,1,string), "_{", StringMidGet(2, Length(string)-1, string), "}"), - If (Length(string) > 2, ConcatStrings("\\mathrm{ ", string, " }"), - string - )))))); - ]; - -]; - -/* */ - -/* Unknown bodied function */ - -200 # TeXForm(x_IsFunction, _p) _ (IsBodied(Type(x))) <-- [ - Local(func, args, last'arg); - func := Type(x); - args := Tail(Listify(x)); - last'arg := PopBack(args); - TeXFormBracketIf(p1, "\\frac{\\partial}{\\partial ", "\\frac{d}{d " - ), TeXForm(x, OpPrecedence("^")), "}", TeXForm(y, OpPrecedence("/")) ) ); - -100 # TeXForm(Deriv(_x, _n)_y, _p) <-- TeXFormBracketIf(p1, - "\\frac{\\partial^" : TeXForm(n, TeXFormMaxPrec()) : "}{\\partial ", - "\\frac{d^" : TeXForm(n, TeXFormMaxPrec()) : "}{d " - ), TeXForm(x, OpPrecedence("^")), " ^", TeXForm(n, TeXFormMaxPrec()), "}", TeXForm(y, OpPrecedence("/")) ) ); -100 # TeXForm(D(_x)_y, _p) <-- TeXForm(Deriv(x) y, p); -100 # TeXForm(D(_x, _n)_y, _p) <-- TeXForm(Deriv(x, n) y, p); - -/* Indexed expressions */ - -/* This seems not to work because x[i] is replaced by Nth(x,i) */ -/* -100 # TeXForm(_x [ _i ], _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); -*/ -/* Need to introduce auxiliary function, or else have trouble with arguments of Nth being lists */ -100 # TeXForm(Nth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p); -100 # TeXForm(TeXFormNth(Nth(_x, i_IsList), _j), _p) <-- TeXForm(TeXFormNth(x, Append(i,j)), p); -110 # TeXForm(Nth(Nth(_x, _i), _j), _p) <-- TeXForm(TeXFormNth(x, List(i,j)), p); -120 # TeXForm(Nth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); -120 # TeXForm(TeXFormNth(_x, _i), _p) <-- ConcatStrings(TeXForm(x, TeXFormMaxPrec()), " _{", TeXForm(i, TeXFormMaxPrec()), "}"); - -/* Matrices are always bracketed. Precedence 80 because lists are at 100. */ - -80 # TeXForm(M_IsMatrix, _p) <-- TeXFormBracketIf(True, TeXFormPrintMatrix(M)); - -Function ("TeXFormPrintMatrix", {M}) -[ -/* - Want something like "\begin{array}{cc} a & b \\ c & d \\ e & f \end{array}" - here, "cc" is alignment and must be given for each column -*/ - Local(row, col, result, ncol); - result := "\\begin{array}{"; - ForEach(col, M[1]) result:=ConcatStrings(result, "c"); - result := ConcatStrings(result, "}"); - - ForEach(row, 1 .. Length(M)) [ - ForEach(col, 1 .. Length(M[row])) [ - result := ConcatStrings( result, " ", TeXForm(M[row][col], TeXFormMaxPrec()), If(col = Length(M[row]), If(row = Length(M), "", " \\\\"), " &")); - ]; - ]; - - ConcatStrings(result, " \\end{array} "); -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/texform.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/texform.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/texform.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/texform.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -TeXForm -TeXFormMaxPrec -TexForm -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/transforms.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/transforms.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/transforms.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/transforms.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -10 # LaplaceTransform(_var1,_var2, _expr ) <-- LapTran(var1,var2,expr); - -// Linearity properties -10 # LapTran(_var1,_var2,_x + _y) <-- LapTran(var1,var2,x) + LapTran(var1,var2,y); -10 # LapTran(_var1,_var2,_x - _y) <-- LapTran(var1,var2,x) - LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, - _y) <-- LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, c_IsConstant*_y) <-- c*LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, _y*c_IsConstant) <-- c*LapTran(var1,var2,y); -10 # LapTran(_var1,_var2, _y/c_IsConstant) <-- LapTran(var1,var2,y)/c; - -// Shift properties -10 # LapTran(_var1,_var2, Exp(c_IsConstant*_var1)*_expr ) <-- LapTran(var1,var2-c,expr); -10 # LapTran(_var1,_var2, Exp(-c_IsConstant*_var1)*_expr ) <-- LapTran(var1,var2+c,expr); -10 # LapTran(_var1,_var2, _expr*Exp(c_IsConstant*_var1) ) <-- LapTran(var1,var2-c,expr); -10 # LapTran(_var1,_var2, _expr*Exp(-c_IsConstant*_var1) ) <-- LapTran(var1,var2+c,expr); - -// Other operational properties -10 # LapTran(_var1,_var2, _expr/_var1 ) <-- Integrate(var2,var2,Infinity) LapTran(var1,var2,expr) ; -10 # LapTran(_var1,_var2, _var1*_expr ) <-- - Deriv(var2) LapTran(var1,var2,expr); -10 # LapTran(_var1,_var2, _var1^(n_IsInteger)*_expr ) <-- (-1)^n * Deriv(var2,n) LapTran(var1,var2,expr); -10 # LapTran(_var1,_var2, _expr*_var1 ) <-- - Deriv(var2) LapTran(var1,var2,expr); -10 # LapTran(_var1,_var2, _expr*_var1^(n_IsInteger) ) <-- (-1)^n * Deriv(var2,n) LapTran(var1,var2,expr); - -// didn't match, return unevaled -100 # LapTran(_var1,_var2, _expr ) <-- `Hold(LaplaceTransform(@var1,@var2,@expr)); - -LapTranDef(_in,_out) <-- -[ - Local(i,o); - - //Echo("50 # LapTran(_t,_s,",in,") <-- ",out,";"); - `(50 # LapTran(_t,_s,@in) <-- @out ); - - i:=Subst(_t,c_IsPositiveInteger*_t) in; - o:=Subst(s,s/c) out; - - //Echo("50 # LapTran(_t,_s,",i,") <-- ",o/c,";"); - `(50 # LapTran(_t,_s,@i ) <-- @o/c ); - - i:=Subst(_t,_t/c_IsPositiveInteger) in; - o:=Subst(s,s*c) out; - - //Echo("50 # LapTran(_t,_s,",i,") <-- ",o/c,";"); - `(50 # LapTran(_t,_s,@i ) <-- @o*c ); - -]; - -// transforms of specific functions -LapTranDef( (_t)^(n_IsConstant), Gamma(n+1)/s^(n+1) ); -LapTranDef( _t, 1/s^2 ); -LapTranDef( Sqrt(_t), Sqrt(Pi)/(2*s^(3/2)) ); -LapTranDef( c_IsFreeOf({t,s}), c/s ); -LapTranDef( Sin(_t), 1/(s^2+1) ); -LapTranDef( Cos(_t), s/(s^2+1) ); -LapTranDef( Sinh(_t), c/(s^2-1) ); -LapTranDef( Cosh(_t), s/(s^2-1) ); -LapTranDef( Exp(_t), 1/(s-1) ); -LapTranDef( BesselJ(n_IsConstant,_t), (Sqrt(s^2+1)-s)^n /Sqrt(s^2+1) ); -LapTranDef( BesselI(n_IsConstant,_t), (s-Sqrt(s^2+1))^n /Sqrt(s^2-1) ); -LapTranDef( Ln(_t), -(gamma+Ln(s))/s); -LapTranDef( Ln(_t)^2, Pi^2/(6*s)+(gamma+Ln(s))/s ); -LapTranDef( Erf(_t), Exp(s^2/4)*Erfc(s/2)/s ); -LapTranDef( Erf(Sqrt(_t)), 1/(Sqrt(s+1)*s) ); diff -Nru mathpiper-0.0.svn2556/storage/scripts/transforms.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/transforms.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/transforms.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/transforms.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -LaplaceTransform -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/trigsimp.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/trigsimp.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/trigsimp.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/trigsimp.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,457 +0,0 @@ - -/* This file defines TrigSimpCombine. TrigSimpCombine is designed to - simplify expressions like Cos(a)*Sin(b) to additions - only (in effect, removing multiplications between - trigonometric functions). - - The accepted expressions allow additions and multiplications - between trig. functions, and raising trig. functions to an - integer power. - - You can invoke it by calling TrigSimpCombine(f). Examples: - TrigSimpCombine(Cos(a)*Sin(a^2+b)^2) - TrigSimpCombine(Cos(a)*Sin(a)^2) - TrigSimpCombine(Cos(a)^3*Sin(a)^2) - TrigSimpCombine(d*Cos(a)^3*Sin(a)^2) - TrigSimpCombine(Cos(a)^3*Sin(a)^2) - TrigSimpCombine(Cos(a)*Sin(a)) - TrigSimpCombine(Cos(a)*Sin(b)*Cos(c)) - - */ - - -/* FSin, FCos and :*: are used for the internal representation - of the expression to work on: - - a*b -> a:*:b this is used because we want to expand powers, - without the standard engine collapsing them back again. - - a*Sin(b) -> FSin(a,b) and a*Cos(b) -> FCos(a,b). This makes - adding and multiplying expressions with trig. functions, non-trig. - functions, constants, etc. a lot easier. -*/ -RuleBase("FSin",{f,x}); -RuleBase("FCos",{f,x}); -RuleBase(":*:",{x,y}); -Infix(":*:",3); - - -IsTrig(f) := (Type(f) = "Sin" Or Type(f) = "Cos"); -IsFTrig(f) := (Type(f) = "FSin" Or Type(f) = "FCos"); -IsMul(f) := (Type(f) = "*"); -IsMulF(f) := (Type(f) = ":*:"); - -IsPow(f):= - (Type(f) = "^" And - IsInteger(f[2]) And - f[2] > 1 - ); - - -/* Convert Sin/Cos to FSin/FCos */ -RuleBase("TrigChange",{f}); -Rule("TrigChange",1,1,Type(f)="Cos") FCos(1,f[1]); -Rule("TrigChange",1,1,Type(f)="Sin") FSin(1,f[1]); - -RuleBase("TrigUnChange",{f}); -Rule("TrigUnChange",1,1,Type(f)="FCos") Cos(f[2]); -Rule("TrigUnChange",1,1,Type(f)="FSin") Sin(f[2]); - - -/* Do a full replacement to internal format on a term. */ -RuleBase("FReplace",{f}); -UnFence("FReplace",1); -Rule("FReplace",1,1,IsMul(f)) Substitute(f[1]) :*: Substitute(f[2]); -Rule("FReplace",1,2,IsPow(f)) (Substitute(f[1]) :*: Substitute(f[1])) :*: Substitute(f[1]^(f[2]-2)); -/* -Rule("FReplace",1,2,IsPow(f)) -[ - Local(trm,i,res,n); - Set(trm,Substitute(f[1])); - Set(n,f[2]); - Set(res,trm); - For(i:=2,i<=n,i++) - [ - Set(res,res :*: trm); - ]; - res; -]; -*/ - -Rule("FReplace",1,3,IsTrig(f)) TrigChange(f); -FTest(f):=(IsMul(f) Or IsPow(f) Or IsTrig(f)); - -/* Central function that converts to internal format */ -FToInternal(f):=Substitute(f,"FTest","FReplace"); - -FReplaceBack(f):=(Substitute(f[1])*Substitute(f[2])); -UnFence("FReplaceBack",1); -FFromInternal(f):=Substitute(f,"IsMulF","FReplaceBack"); - - -/* FLog(s,f):=[WriteString(s:" ");Write(f);NewLine();]; */ - FLog(s,f):=[]; - - -/* FSimpTerm simplifies the current term, wrt. trigonometric functions. */ -RuleBase("FSimpTerm",{f,rlist}); -UnFence("FSimpTerm",2); - -/* Addition: add all the subterms */ -Rule("FSimpTerm",2,1,Type(f) = "+") -[ - Local(result,lst); - lst:=Flatten(f,"+"); - - result:={{},{}}; -FLog("simpadd",lst); - - ForEach(tt,lst) - [ - Local(new); - new:=FSimpTerm(tt,{{},{}}); - result:={Concat(result[1],new[1]),Concat(result[2],new[2])}; - ]; - result; -]; - - -TrigNegate(f):= -[ - UnList({f[0],-(f[1]),f[2]}); -]; - - -FUnTrig(result) := Substitute(result,"IsFTrig","TrigUnChange"); - -Rule("FSimpTerm",2,1,Type(f) = "-" And NrArgs(f)=1) -[ - Local(result); - result:=FSimpTerm(f[1],{{},{}}); - Substitute(result,"IsFTrig","TrigNegate"); -]; -Rule("FSimpTerm",2,1,Type(f) = "-" And NrArgs(f)=2) -[ - Local(result1,result2); - result1:=FSimpTerm(f[1],{{},{}}); - result2:=FSimpTerm(-(f[2]),{{},{}}); - {Concat(result1[1],result2[1]),Concat(result1[2],result2[2])}; -]; - -Rule("FSimpTerm",2,2,Type(f) = ":*:") -[ - FSimpFactor({Flatten(f,":*:")}); -]; -Rule("FSimpTerm",2,3,Type(f) = "FSin") -[ - {rlist[1],f:(rlist[2])}; -]; -Rule("FSimpTerm",2,3,Type(f) = "FCos") -[ - {f:(rlist[1]),rlist[2]}; -]; - -Rule("FSimpTerm",2,4,True) -[ - {(FCos(f,0)):(rlist[1]),rlist[2]}; -]; - -/* FSimpFactor does the difficult part. it gets a list, representing - factors, a*b*c -> {{a,b,c}}, and has to add terms from it. - Special cases to deal with: - - (a+b)*c -> a*c+b*c -> {{a,c},{b,c}} - - {a,b,c} where one of them is not a trig function or an addition: - replace with FCos(b,0), which is b*Cos(0) = b - - otherwise, combine two factors and make them into an addition. - - the lists should get shorter, but the number of lists should - get longer, until there are only single terms to be added. - */ -FSimpFactor(flist):= -[ - Local(rlist); - rlist:={{},{}}; - /* Loop over each term */ - While(flist != {}) - [ - Local(term); -FLog("simpfact",flist); - term:=Head(flist); - flist:=Tail(flist); - FProcessTerm(term); - ]; -FLog("simpfact",flist); - -FLog("rlist",rlist); - rlist; -]; -UnFence("FSimpFactor",1); - - -RuleBase("FProcessTerm",{t}); -UnFence("FProcessTerm",1); - -/* Deal with (a+b)*c -> a*c+b*c */ -Rule("FProcessTerm",1,1,Type(t[1]) = "+") -[ - Local(split,term1,term2); - split:=t[1]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[1]:=split[1]; - term2[1]:=split[2]; - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; -Rule("FProcessTerm",1,1,Type(t[1]) = "-" And NrArgs(t[1]) = 2) -[ - Local(split,term1,term2); - split:=t[1]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[1]:=split[1]; - term2[1]:=split[2]; - DestructiveInsert(term2,1,FCos(-1,0)); - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "-" And NrArgs(t[2]) = 2) -[ - Local(split,term1,term2); - split:=t[2]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[2]:=split[1]; - term2[2]:=split[2]; - DestructiveInsert(term2,1,FCos(-1,0)); - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - -Rule("FProcessTerm",1,1,Type(t[1]) = ":*:") -[ - Local(split,term); - split:=t[1]; - term:=FlatCopy(t); - term[1]:=split[1]; - DestructiveInsert(term,1,split[2]); - DestructiveInsert(flist,1,term); -]; - -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = ":*:") -[ - Local(split,term); - split:=t[2]; - term:=FlatCopy(t); - term[2]:=split[1]; - DestructiveInsert(term,1,split[2]); - DestructiveInsert(flist,1,term); -]; - -Rule("FProcessTerm",1,1,Type(t[1]) = "-" And NrArgs(t[1]) = 1) -[ - Local(split,term); - split:=t[1]; - term:=FlatCopy(t); - term[1]:=split[1]; - DestructiveInsert(term,1,FCos(-1,0)); - DestructiveInsert(flist,1,term); -]; -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "-" And NrArgs(t[2]) = 1) -[ - Local(split,term); - split:=t[2]; - term:=FlatCopy(t); - term[2]:=split[1]; - DestructiveInsert(term,1,FCos(-1,0)); - DestructiveInsert(flist,1,term); -]; - - -/* Deal with (a*(b+c) -> a*b+a*c */ -Rule("FProcessTerm",1,1,Length(t)>1 And Type(t[2]) = "+") -[ - Local(split,term1,term2); - split:=t[2]; - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[2]:=split[1]; - term2[2]:=split[2]; - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - - - -/* Deal with a*FCos(1,b) ->FCos(a,0)*FCos(1,b) */ -Rule("FProcessTerm",1,2,Not(IsFTrig(t[1])) ) -[ - t[1]:=FCos(t[1],0); - DestructiveInsert(flist,1,t); -]; -Rule("FProcessTerm",1,2,Length(t)>1 And Not(IsFTrig(t[2])) ) -[ - t[2]:=FCos(t[2],0); - DestructiveInsert(flist,1,t); -]; - - -Rule("FProcessTerm",1,4,Length(t)=1 And Type(t[1]) = "FCos") -[ - DestructiveInsert(rlist[1],1,t[1]); -]; -Rule("FProcessTerm",1,4,Length(t)=1 And Type(t[1]) = "FSin") -[ - DestructiveInsert(rlist[2],1,t[1]); -]; - -/* Now deal with the real meat: FSin*FCos etc. Reduce the multiplication - of the first two terms to an addition, adding two new terms to - the pipe line. - */ -Rule("FProcessTerm",1,5,Length(t)>1) -[ - Local(x,y,term1,term2,news); - x:=t[1]; - y:=t[2]; - news:=TrigSimpCombineB(x,y); - /* Drop one term */ - t:=Tail(t); - term1:=FlatCopy(t); - term2:=FlatCopy(t); - term1[1]:=news[1]; - term2[1]:=news[2]; - DestructiveInsert(flist,1,term1); - DestructiveInsert(flist,1,term2); -]; - -/* TrigSimpCombineB : take two FSin/FCos factors, and write them out into two terms */ -RuleBase("TrigSimpCombineB",{x,y}); -Rule("TrigSimpCombineB",2,1,Type(x) = "FCos" And Type(y) = "FCos") - { FCos((x[1]*y[1])/2,x[2]+y[2]) , FCos((x[1]*y[1])/2,x[2]-y[2]) }; -Rule("TrigSimpCombineB",2,1,Type(x) = "FSin" And Type(y) = "FSin") - { FCos(-(x[1]*y[1])/2,x[2]+y[2]) , FCos((x[1]*y[1])/2,x[2]-y[2]) }; -Rule("TrigSimpCombineB",2,1,Type(x) = "FSin" And Type(y) = "FCos") - { FSin((x[1]*y[1])/2,x[2]+y[2]) , FSin( (x[1]*y[1])/2,x[2]-y[2]) }; -Rule("TrigSimpCombineB",2,1,Type(x) = "FCos" And Type(y) = "FSin") - { FSin((x[1]*y[1])/2,x[2]+y[2]) , FSin(-(x[1]*y[1])/2,x[2]-y[2]) }; - - -RuleBase("TrigSimpCombine",{f}); -Rule("TrigSimpCombine",1,1,IsList(f)) - Map("TrigSimpCombine",{f}); - -Rule("TrigSimpCombine",1,10,True) -[ - Local(new,varlist); - new:=f; - - /* varlist is used for normalizing the trig. arguments */ - varlist:=VarList(f); - -/* Convert to internal format. */ - new:=FToInternal(new); -FLog("Internal",new); - - /* terms will contain FSin/FCos entries, the final result */ - - /* rlist gathers the true final result */ - Local(terms); - terms:=FSimpTerm(new,{{},{}}); - /* terms now contains two lists: terms[1] is the list of cosines, - and terms[2] the list of sines. - */ -FLog("terms",terms); - - /* cassoc and sassoc will contain the assoc lists with the cos/sin - arguments as key. - */ - Local(cassoc,sassoc); - cassoc:={}; - sassoc:={}; - ForEach(item,terms[1]) - [ - CosAdd(item); - ]; - ForEach(item,terms[2]) - [ - SinAdd(item); - ]; -FLog("cassoc",cassoc); -FLog("sassoc",sassoc); - - /* Now rebuild the normal form */ - Local(result); - result:=0; - -//Echo({cassoc}); -//Echo({sassoc}); - ForEach(item,cassoc) - [ -Log("item",item); - result:=result+Expand(FUnTrig(FFromInternal(item[2])))*Cos(item[1]); - ]; - ForEach(item,sassoc) - [ -Log("item",item); - result:=result+Expand(FUnTrig(FFromInternal(item[2])))*Sin(item[1]); - ]; - - result; -]; - - - -CosAdd(t):= -[ - Local(look,arg); - arg:=Expand(t[2],varlist); - look:=Assoc(arg,cassoc); - If(look = Empty, - [ - arg:=Expand(-arg,varlist); - look:=Assoc(arg,cassoc); - If(look = Empty, - DestructiveInsert(cassoc,1,{arg,t[1]}), - look[2]:=look[2]+t[1] - ); - ] - , - look[2]:=look[2]+t[1] - ); -]; -UnFence("CosAdd",1); - -SinAdd(t):= -[ - Local(look,arg); - arg:=Expand(t[2],varlist); - look:=Assoc(arg,sassoc); - If(look = Empty, - [ - arg:=Expand(-arg,varlist); - look:=Assoc(arg,sassoc); - If(look = Empty, - DestructiveInsert(sassoc,1,{arg,-(t[1])}), - look[2]:=look[2]-(t[1]) - ); - ] - , - look[2]:=look[2]+t[1] - ); -]; -UnFence("SinAdd",1); - - -/* -In( 4 ) = Exp(I*a)*Exp(I*a) -Out( 4 ) = Complex(Cos(a)^2-Sin(a)^2,Cos(a)*Sin(a)+Sin(a)*Cos(a)); -In( 5 ) = Exp(I*a)*Exp(-I*a) -Out( 5 ) = Complex(Cos(a)^2+Sin(a)^2,Sin(a)*Cos(a)-Cos(a)*Sin(a)); - -In( 5 ) = Exp(I*a)*Exp(I*b) -Out( 5 ) = Complex(Cos(a)*Cos(b)-Sin(a)*Sin(b),Cos(a)*Sin(b)+Sin(a)*Cos(b)); -In( 6 ) = Exp(I*a)*Exp(-I*b) -Out( 6 ) = Complex(Cos(a)*Cos(b)+Sin(a)*Sin(b),Sin(a)*Cos(b)-Cos(a)*Sin(b)); - - -*/ - diff -Nru mathpiper-0.0.svn2556/storage/scripts/trigsimp.rep/code.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/trigsimp.rep/code.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/trigsimp.rep/code.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/trigsimp.rep/code.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -TrigSimpCombine -} - diff -Nru mathpiper-0.0.svn2556/storage/scripts/univar.rep/code.mpi mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/code.mpi --- mathpiper-0.0.svn2556/storage/scripts/univar.rep/code.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/code.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,710 +0,0 @@ -/* todos for univariates: - - Factorize -*/ - -UniVarList(expr) := VarList(expr); - - -0 # NormalForm(UniVariate(_var,_first,_coefs)) <-- - ExpandUniVariate(var,first,coefs); - -Function("ExpandUniVariate",{var,first,coefs}) -[ - Local(result,i); - result:=0; - For(i:=Length(coefs),i>0,i--) - [ - Local(term); - term:=NormalForm(coefs[i])*var^(first+i-1); - result:=result+term; - ]; - result; -]; - - -10 # IsUniVar(UniVariate(_var,_first,_coefs)) <-- True; -20 # IsUniVar(_anything) <-- False; - - -RuleBase("UniVariate",{var,first,coefs}); - -Rule("UniVariate",3,10,Length(coefs)>0 And coefs[1]=0) - UniVariate(var,first+1,Tail(coefs)); -Rule("UniVariate",3,1000,IsComplex(var) Or IsList(var)) - ExpandUniVariate(var,first,coefs); - -20 # IsZero(UniVariate(_var,_first,_coefs)) <-- IsZeroVector(coefs); - -RuleBase("Degree",{expr}); -Rule("Degree",1,0, IsUniVar(expr)) -[ - - Local(i,min,max); - min:=expr[2]; - max:=min+Length(expr[3]); - i:=max; - While(i >= min And IsZero(Coef(expr,i))) i--; - i; -]; - -10 # Degree(_poly) <-- Degree(MakeUni(poly)); -10 # Degree(_poly,_var) <-- Degree(MakeUni(poly,var)); - - - -500 # UniVariate(_var,_f1,_c1) + UniVariate(_var,_f2,_c2) <-- -[ - Local(from,result); - Local(curl,curr,left,right); - - Set(curl, f1); - Set(curr, f2); - Set(left, c1); - Set(right, c2); - Set(result, {}); - Set(from, Min(curl,curr)); - - While(And(LessThan(curl,curr),left != {})) - [ - DestructiveAppend(result,Head(left)); - Set(left,Tail(left)); - Set(curl,AddN(curl,1)); - ]; - While(LessThan(curl,curr)) - [ - DestructiveAppend(result,0); - Set(curl,AddN(curl,1)); - ]; - While(And(LessThan(curr,curl), right != {})) - [ - DestructiveAppend(result,Head(right)); - Set(right,Tail(right)); - Set(curr,AddN(curr,1)); - ]; - While(LessThan(curr,curl)) - [ - DestructiveAppend(result,0); - Set(curr,AddN(curr,1)); - ]; - While(And(left != {}, right != {})) - [ - DestructiveAppend(result,Head(left)+Head(right)); - Set(left, Tail(left)); - Set(right, Tail(right)); - ]; - While(left != {}) - [ - DestructiveAppend(result,Head(left)); - Set(left, Tail(left)); - ]; - While(right != {}) - [ - DestructiveAppend(result,Head(right)); - Set(right, Tail(right)); - ]; - - UniVariate(var,from,result); -]; - - -200 # UniVariate(_var,_first,_coefs) + a_IsNumber <-- - UniVariate(var,first,coefs) + UniVariate(var,0,{a}); -200 # a_IsNumber + UniVariate(_var,_first,_coefs) <-- - UniVariate(var,first,coefs) + UniVariate(var,0,{a}); - - -200 # - UniVariate(_var,_first,_coefs) <-- UniVariate(var,first,-coefs); - - -200 # aLeft_IsUniVar - aRight_IsUniVar <-- -[ - Local(from,result); - Local(curl,curr,left,right); - - curl:=aLeft[2]; - curr:=aRight[2]; - left:=aLeft[3]; - right:=aRight[3]; - result:={}; - from:=Min(curl,curr); - - While(curl0) - [ - Set(b,b*b); - If (Not(Equals(BitAnd(m,n), 0)),Set(b,b*a)); - Set(m, ShiftRight(m,1)); - ]; - b; -]; - -200 # aLeft_IsUniVar ^ aRight_IsPositiveInteger <-- - RepeatedSquaresMultiply(aLeft,aRight); - - - -/*TODO this can be made twice as fast!*/ - - -201 # (aLeft_IsUniVar * _aRight)_((IsFreeOf(aLeft[1],aRight))) <-- -[ - aRight*aLeft; -]; - -200 # (_factor * UniVariate(_var,_first,_coefs))_((IsFreeOf(var,factor))) <-- - UniVariate(var,first,coefs*factor); - -200 # (UniVariate(_var,_first,_coefs)/_factor)_((IsFreeOf(var,factor))) <-- - UniVariate(var,first,coefs/factor); - - -ShiftUniVar(UniVariate(_var,_first,_coefs),_fact,_shift) - <-- - [ -//Echo("fact, coefs = ",fact,coefs); - UniVariate(var,first+shift,fact*coefs); - ]; - - -200 # UniVariate(_var,_f1,_c1) * UniVariate(_var,_f2,_c2) <-- -[ - Local(i,j,n,shifted,result); - Set(result,MakeUni(0,var)); -//Echo("c1 = ",var,f1,c1); -//Echo("c2 = ",var,f2,c2); - Set(n,Length(c1)); - For(i:=1,i<=n,i++) - [ -//Echo("before = ",result); -//Echo("parms = ",var,c1,c2,f1,f2,f1+i-1); - Set(result,result+ShiftUniVar(UniVariate(var,f2,c2),MathNth(c1,i),f1+i-1)); -//Echo("after = ",result); - ]; -//Echo("result = ",result); - result; -]; - - -5 # Coef(uv_IsUniVar,order_IsList) <-- -[ - Local(result); - result:={}; - ForEach(item,order) - [ - DestructiveAppend(result,Coef(uv,item)); - ]; - result; -]; - -10 # Coef(uv_IsUniVar,order_IsInteger)_(order=uv[2]+Length(uv[3])) <-- 0; -20 # Coef(uv_IsUniVar,order_IsInteger) <-- uv[3][(order-uv[2])+1]; -30 # Coef(uv_CanBeUni,_order)_(IsInteger(order) Or IsList(order)) <-- Coef(MakeUni(uv),order); - -Function("Coef",{expression,var,order}) - NormalForm(Coef(MakeUni(expression,var),order)); - -10 # LeadingCoef(uv_IsUniVar) <-- Coef(uv,Degree(uv)); - -20 # LeadingCoef(uv_CanBeUni) <-- -[ - Local(uvi); - uvi:=MakeUni(uv); - Coef(uvi,Degree(uvi)); -]; -10 # LeadingCoef(uv_CanBeUni(var),_var) <-- -[ - Local(uvi); - uvi:=MakeUni(uv,var); - Coef(uvi,var,Degree(uvi)); -]; - - -Function("UniTaylor",{taylorfunction,taylorvariable,taylorat,taylororder}) -[ - Local(n,result,dif,polf); - result:={}; - [ - MacroLocal(taylorvariable); - MacroSet(taylorvariable,taylorat); - DestructiveAppend(result,Eval(taylorfunction)); - ]; - dif:=taylorfunction; - polf:=(taylorvariable-taylorat); - For(n:=1,n<=taylororder,n++) - [ - dif:= Deriv(taylorvariable) dif; - MacroLocal(taylorvariable); - MacroSet(taylorvariable,taylorat); - DestructiveAppend(result,(Eval(dif)/n!)); - ]; - UniVariate(taylorvariable,0,result); -]; - - -Function("MakeUni",{expression}) MakeUni(expression,UniVarList(expression)); - -/* Convert normal form to univariate expression */ -RuleBase("MakeUni",{expression,var}); - -5 # MakeUni(_expr,{}) <-- UniVariate(dummyvar,0,{expression}); -6 # MakeUni(_expr,var_IsList) <-- -[ - Local(result,item); - result:=expression; - ForEach(item,var) - [ - result:=MakeUni(result,item); - ]; - result; -]; - -10 # MakeUni(UniVariate(_var,_first,_coefs),_var) <-- - UniVariate(var,first,coefs); - -20 # MakeUni(UniVariate(_v,_first,_coefs),_var) <-- -[ - Local(reslist,item); - reslist:={}; - ForEach(item,expression[3]) - [ - If(IsFreeOf(var,item), - DestructiveAppend(reslist,item), - DestructiveAppend(reslist,MakeUni(item,var)) - ); - ]; - UniVariate(expression[1],expression[2],reslist); -]; - - -LocalSymbols(a,b,var,expression) -[ - 20 # MakeUni(expression_IsFreeOf(var),_var) - <-- UniVariate(var,0,{expression}); - 30 # MakeUni(_var,_var) <-- UniVariate(var,1,{1}); - 30 # MakeUni(_a + _b,_var) <-- MakeUni(a,var) + MakeUni(b,var); - 30 # MakeUni(_a - _b,_var) <-- MakeUni(a,var) - MakeUni(b,var); - 30 # MakeUni( - _b,_var) <-- - MakeUni(b,var); - 30 # MakeUni(_a * _b,_var) <-- MakeUni(a,var) * MakeUni(b,var); - 1 # MakeUni(_a ^ n_IsInteger,_var) <-- MakeUni(a,var) ^ n; - 30 # MakeUni(_a / (b_IsFreeOf(var)),_var) <-- MakeUni(a,var) * (1/b); -]; - - - - -0 # Div(n_IsUniVar,m_IsUniVar)_(Degree(n) < Degree(m)) <-- 0; -0 # Mod(n_IsUniVar,m_IsUniVar)_(Degree(n) < Degree(m)) <-- n; -1 # Div(n_IsUniVar,m_IsUniVar)_ - (n[1] = m[1] And Degree(n) >= Degree(m)) <-- -[ - UniVariate(n[1],0, - UniDivide(Concat(ZeroVector(n[2]),n[3]), - Concat(ZeroVector(m[2]),m[3]))[1]); -]; -1 # Mod(n_IsUniVar,m_IsUniVar)_ - (n[1] = m[1] And Degree(n) >= Degree(m)) <-- -[ - UniVariate(n[1],0, - UniDivide(Concat(ZeroVector(n[2]),n[3]), - Concat(ZeroVector(m[2]),m[3]))[2]); -]; - - - -/* division algo: (for zero-base univariates:) */ -Function("UniDivide",{u,v}) -[ - Local(m,n,q,r,k,j); - m := Length(u)-1; - n := Length(v)-1; - While (m>0 And IsZero(u[m+1])) m--; - While (n>0 And IsZero(v[n+1])) n--; - q := ZeroVector(m-n+1); - r := FlatCopy(u); /* (m should be >= n) */ - For(k:=m-n,k>=0,k--) - [ - q[k+1] := r[n+k+1]/v[n+1]; - For (j:=n+k-1,j>=k,j--) - [ - r[j+1] := r[j+1] - q[k+1]*v[j-k+1]; - ]; - ]; - Local(end); - end:=Length(r); - While (end>n) - [ - DestructiveDelete(r,end); - end:=end-1; - ]; - - {q,r}; -]; - - -DropEndZeroes(list):= -[ - Local(end); - end:=Length(list); - While(list[end] = 0) - [ - DestructiveDelete(list,end); - end:=end-1; - ]; -]; - - - -Function("UniGcd",{u,v}) -[ - Local(l,div,mod,m); - - DropEndZeroes(u); - DropEndZeroes(v); -/* - If(Length(v)>Length(u), - [ - Locap(swap); - swap:=u; - u:=v; - v:=swap; - ] ); - If(Length(u)=Length(v) And v[Length(v)] > u[Length(u)], - [ - Locap(swap); - swap:=u; - u:=v; - v:=swap; - ] ); - */ - - - l:=UniDivide(u,v); - - div:=l[1]; - mod:=l[2]; - - DropEndZeroes(mod); - m := Length(mod); - -/* Echo({"v,mod = ",v,mod}); */ -/* If(m <= 1, */ - If(m = 0, - v, -/* v/v[Length(v)], */ - UniGcd(v,mod)); -]; - - - -0 # Gcd(n_IsUniVar,m_IsUniVar)_ - (n[1] = m[1] And Degree(n) < Degree(m)) <-- Gcd(m,n); - -1 # Gcd(nn_IsUniVar,mm_IsUniVar)_ - (nn[1] = mm[1] And Degree(nn) >= Degree(mm)) <-- -[ - UniVariate(nn[1],0, - UniGcd(Concat(ZeroVector(nn[2]),nn[3]), - Concat(ZeroVector(mm[2]),mm[3]))); -]; - -RuleBase("PSolve",{uni}); - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 1) - -Coef(uni,0)/Coef(uni,1); - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 2) - [ - Local(a,b,c,d); - c:=Coef(uni,0); - b:=Coef(uni,1); - a:=Coef(uni,2); - d:=b*b-4*a*c; - {(-b+Sqrt(d))/(2*a),(-b-Sqrt(d))/(2*a)}; - ]; - - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 3 ) - [ - Local(p,q,r,w,ww,a,b); - Local(coef0,coef1,coef3,adjust); - -/* Get coefficients for a new polynomial, such that the coefficient of - degree 2 is zero: - Take f(x)=a0+a1*x+a2*x^2+a3*x^3 and substitute x = x' + adjust - This gives g(x) = b0+b1*x+b2*x^2+b3*x^3 where - b3 = a3; - b2 = 0 => adjust = (-a2)/(3*a3); - b1 = 2*a2*adjust+3*a3*adjust^2+a1; - b0 = a2*adjust^2+a3*adjust^3+adjust*a1+a0; - - After solving g(x') = 0, return x = x' + adjust. -*/ - - adjust := (-Coef(uni,2))/(3*Coef(uni,3)); - coef3 := Coef(uni,3); - coef1 := 2*Coef(uni,2)*adjust+3*Coef(uni,3)*adjust^2+Coef(uni,1); - coef0 := Coef(uni,2)*adjust^2+Coef(uni,3)*adjust^3+ - adjust*Coef(uni,1)+Coef(uni,0); - - p:=coef3; - q:=coef1/p; - r:=coef0/p; - w:=Complex(-1/2,Sqrt(3/4)); - ww:=Complex(-1/2,-Sqrt(3/4)); - -/* Equation is xxx + qx + r = 0 */ -/* Let x = a + b - a^3 + b^3 + 3(aab + bba) + q(a + b) + r = 0 - a^3 + b^3 + (3ab+q)x + r = 0 - - Let 3ab+q = 0. This is permissible, for we can still find a+b == x - - a^3 + b^3 = -r - (ab)^3 = -q^3/27 - - So a^3 and b^3 are the roots of t^2 + rt - q^3/27 = 0 - - Let - a^3 = -r/2 + Sqrt(q^3/27+ rr/4) - b^3 = -r/2 - Sqrt(q^3/27+ rr/4) - Therefore there are three values for each of a and b. - Clearly if ab = -q/3 is true then (wa)(wwb) == (wb)(wwa) == -q/3 -*/ - - a:=(-r/2 + Sqrt(q^3/27+ r*r/4))^(1/3); - b:=(-r/2 - Sqrt(q^3/27+ r*r/4))^(1/3); - - {a+b+adjust,w*a+ww*b+adjust,ww*a+w*b+adjust}; -]; - -/* -How to solve the quartic equation? - -The equation is x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = 0. -The idea is to write the left-hand side as the difference of two -squares: (x^2 + p x + q)^2 - (s x + t)^2. -Eliminating the parentheses and equation coefficients yields four -equations for the four unknowns p, q, s and t: - a1 = 2p (1) - a2 = p^2 + 2q - s^2 (2) - a3 = 2pq - 2st (3) - a4 = q^2 - t^2 (4) -From the first equation, we find that p = a1/2. Substituting this in -the other three equations and rearranging gives - s^2 = a1^2/4 - a2 + 2q (5) - 2st = a1 q - a3 (6) - t^2 = q^2 - a4 (7) -We now take the square (6) and substitute (5) and (7): - 4 (a1^2/4 - a2 + 2q) (q^2 - a4) = (a1 q - a3)^2 <==> - 8 q^3 - 4 a2 q^2 + (2 a1 a3 - 8 a4) q + 4 a2 a4 - a1^2 a4 - a3^2 = 0. -Miraculously, we got a cubic equation for q. Suppose we can solve this -equation. We can then compute t from (7): t = sqrt(q^2 - a4). If t is -nonzero, we can compute s from (6). Note that we cannot compute s from -(5), since we introduced an extra solution when squaring (6). However, -if t is zero, then no extra solution was introduced and we can safely -use (5). Having found the values of p, q, s and t, we can factor the -difference of squares and solve the quartic: - x^4 + a1 x^3 + a2 x^2 + a3 x + a4 = (x^2 + p x + q)^2 - (s x + t)^2 - = (x^2 + p x + q + s x + t) (x^2 + p x + q - sx - t). -The four roots of the quartic are the two roots of the first quadratic -factor plus the two roots of the second quadratic factor. -*/ - -Rule("PSolve",1,1,IsUniVar(uni) And Degree(uni) = 4 ) -[ - Local(coef4,a1,a2,a3,a4,y,y1,z,t,s); - - coef4:=Coef(uni,4); - a1:=Coef(uni,3)/coef4; - a2:=Coef(uni,2)/coef4; - a3:=Coef(uni,1)/coef4; - a4:=Coef(uni,0)/coef4; - - /* y1 = 2q, with q as above. */ - y1:=Head(PSolve(y^3-a2*y^2+(a1*a3-4*a4)*y+(4*a2*a4-a3^2-a1^2*a4),y)); - t := Sqrt(y1^2/4-a4); - If(t=0, s:=Sqrt(y1+a1^2/4-a2), s:=(a1*y1-2*a3)/(4*t)); - Concat(PSolve(z^2+(a1/2+s)*z+y1/2+t,z), - PSolve(z^2+(a1/2-s)*z+y1/2-t,z)); -]; - -Function("PSolve",{uni,var}) - [ - PSolve(MakeUni(uni,var)); - ]; - - -/* Generate a random polynomial */ - - -RandomPoly(_var,_degree,_coefmin,_coefmax) <-- - NormalForm(UniVariate(var,0,RandomIntegerVector(degree+1,coefmin,coefmax))); - - -/* CanBeUni returns whether the function can be converted to a - * univariate, with respect to a variable. - */ -Function("CanBeUni",{expression}) CanBeUni(UniVarList(expression),expression); - - -/* Accepting an expression as being convertable to univariate */ - -/* Dealing wiht a list of variables. The poly should be expandable - * to each of these variables (smells like tail recursion) - */ -10 # CanBeUni({},_expression) <-- True; -20 # CanBeUni(var_IsList,_expression) <-- - CanBeUni(Head(var),expression) And CanBeUni(Tail(var),expression); - -/* Atom can always be a polynom to any variable */ -30 # CanBeUni(_var,expression_IsAtom) <-- True; -35 # CanBeUni(_var,expression_IsFreeOf(var)) <-- True; - -/* Other patterns supported. */ -40 # CanBeUni(_var,_x + _y) <-- CanBeUni(var,x) And CanBeUni(var,y); -40 # CanBeUni(_var,_x - _y) <-- CanBeUni(var,x) And CanBeUni(var,y); -40 # CanBeUni(_var, + _y) <-- CanBeUni(var,y); -40 # CanBeUni(_var, - _y) <-- CanBeUni(var,y); -40 # CanBeUni(_var,_x * _y) <-- CanBeUni(var,x) And CanBeUni(var,y); -40 # CanBeUni(_var,_x / _y) <-- CanBeUni(var,x) And IsFreeOf(var,y); -/* Special case again: raising powers */ -40 # CanBeUni(_var,_x ^ y_IsInteger)_(y >= 0 And CanBeUni(var,x)) <-- True; -41 # CanBeUni(_var,(x_IsFreeOf(var)) ^ (y_IsFreeOf(var))) <-- True; -50 # CanBeUni(_var,UniVariate(_var,_first,_coefs)) <-- True; -1000 # CanBeUni(_var,_f)_(Not(IsFreeOf(var,f))) <-- False; -1001 # CanBeUni(_var,_f) <-- True; - - - - -10 # Content(UniVariate(_var,_first,_coefs)) <-- Gcd(coefs)*var^first; -20 # Content(poly_CanBeUni) <-- NormalForm(Content(MakeUni(poly))); - -10 # PrimitivePart(UniVariate(_var,_first,_coefs)) <-- - UniVariate(var,0,coefs/Gcd(coefs)); -20 # PrimitivePart(poly_CanBeUni) <-- NormalForm(PrimitivePart(MakeUni(poly))); - -10 # Monic(UniVariate(_var,_first,_coefs)) <-- -[ - DropEndZeroes(coefs); - UniVariate(var,first,coefs/coefs[Length(coefs)]); -]; -20 # Monic(poly_CanBeUni) <-- NormalForm(Monic(MakeUni(poly))); - -30 # Monic(_poly,_var)_CanBeUni(poly,var) <-- NormalForm(Monic(MakeUni(poly,var))); - - -10 # BigOh(UniVariate(_var,_first,_coefs),_var,_degree) <-- - [ - While(first+Length(coefs)>=(degree+1) And Length(coefs)>0) DestructiveDelete(coefs,Length(coefs)); - UniVariate(var,first,coefs); - ]; -20 # BigOh(_uv,_var,_degree)_CanBeUni(uv,var) <-- NormalForm(BigOh(MakeUni(uv,var),var,degree)); - - - -Horner(_e,_v) <-- -[ - Local(uni,coefs,result); - uni := MakeUni(e,v); - coefs:=DestructiveReverse(uni[3]); - result:=0; - - While(coefs != {}) - [ - result := result*v; - result := result+Head(coefs); - coefs := Tail(coefs); - ]; - result:=result*v^uni[2]; - result; -]; - - -DivPoly(_A,_B,_var,_deg) <-- -[ - Local(a,b,c,i,j,denom); - b:=MakeUni(B,var); - denom:=Coef(b,0); - - if (denom = 0) - [ - Local(f); - f:=Content(b); - b:=PrimitivePart(b); - A:=Simplify(A/f); - denom:=Coef(b,0); - ]; - a:=MakeUni(A,var); - - c:=FillList(0,deg+1); - For(i:=0,i<=deg,i++) - [ - Local(sum,j); - sum:=0; - For(j:=0,j0,i--) - [ - Local(term); - exponent := first+i-1; - c:= coefs[i]; - nc := If(IsEven(exponent),c,-c); - term:=NormalForm(nc*var^(exponent*k)); - result:=result+term; - ]; - result; -]; - -// Returns a list of elements of the form {d1,d2,m} -// where -// 1) d1,d2 runs through the square free divisors of n -// 2) d1 divides d2 and d2/d1 is a prime factor of n -// 3) m=Moebius(d1) -// Addapted form: MoebiusDivisorsList - -CyclotomicDivisorsList(n_IsPositiveInteger) <-- -[ - Local(nFactors,f,result,oldresult,x); - nFactors:= Factors(n); - result := {{1,nFactors[1][1],1}}; - nFactors := Tail(nFactors); - ForEach (f,nFactors) - [ - oldresult := result; - ForEach (x,oldresult) - result:=Append(result,{x[1]*f[1],x[2]*f[1],-x[3]}); - ]; - result; -]; - -// CyclotomicFactor(x,a,b): Auxiliary function that constructs the term list of -// the polynomial -// Div(x^a-1,x^b-1) = -// x^(b*(p-1)) + x^(b^*(p-2)) + ... + x^(b) + 1 -// p= a/b, b should divide a - - -CyclotomicFactor(_a,_b) <-- -[ - Local(coef,p,i,j,result); p := a/b; result:= {{b*(p-1),1}}; For (i:= - p-2,i>=0,i--) - DestructiveAppend(result,{b*i,1}); - result; -]; - - -// OldInternalCyclotomic(n,x,WantNormalForm) is the internal implementation -// WantNormalForm is a boolean parameter. If it is true, returns the normal -// form, if it is false returns the UniVariate representation. - -// This (old) implementation makes use of the internal representations of univariate -// polynomials as UniVariate(var,begining,coefficients). -// There is also a version UniVariateCyclotomic(n,x) that returns the -// cyclotomic polynomial in the UniVariate representation. - - -10 # OldInternalCyclotomic(n_IsEven,_x,WantNormalForm_IsBoolean) <-- - [ - Local(k,m,p); - k := 1; - m := n; - While(IsEven(m)) - [ - k := k*2; - m := m/2; - ]; - k := k/2 ; - If(m>1, [ - p := OldInternalCyclotomic(m,x,False); - If (WantNormalForm, SubstituteAndExpandInUniVar(p,k),SubstituteInUniVar(p,k)); - ], - If (WantNormalForm, x^k+1, UniVariateBinomial(x,k,1)) - ); - ]; - -20 # OldInternalCyclotomic(n_IsOdd,_x,WantNormalForm_IsBoolean)_(n>1) <-- -[ - Local(divisors,poly1,poly2,q,d,f,result); - divisors := MoebiusDivisorsList(n); - poly1 :=1 ; - poly2 := 1; - ForEach (d,divisors) - [ - q:=n/d[1]; - f:=UniVariateBinomial(x,q,-1); - If (d[2]=1,poly1:=poly1*f,poly2:=poly2*f); - ]; - result := Div(poly1,poly2); - If(WantNormalForm,NormalForm(result),result); -]; - -10 # OldCyclotomic(1,_x) <-- _x-1; -20 # OldCyclotomic(n_IsInteger,_x) <-- OldInternalCyclotomic(n,x,True); - -// This new implementation makes use of the internal representations of univariate -// polynomials as SparseUniVar(var,termlist). - - -// For n even, we write n= m*k, where k is a Power of 2 -// and m is odd, and redce it to the case m even since: -// -// Cyclotomic(n,x) = Cyclotomic(m,-x^{k/2}) -// -// If m=1, n is a power of 2, and Cyclotomic(n,x)= x^k+1 */ - - -10 # InternalCyclotomic(n_IsEven,_x) <-- - [ - Local(k,m,result,p,t); - k := 1; - m := n; - While(IsEven(m)) - [ - k := k*2; - m := m/2; - ]; - k := k/2 ; - If(m>1, [ - p:= InternalCyclotomic(m,x)[2]; - // Substitute x by -x^k - result:={}; - ForEach(t,p) - DestructiveAppend(result, {t[1]*k,If(IsEven(t[1]),t[2],-t[2])}); - ], - result := {{k,1},{0,1}} // x^k+1 - ); - SparseUniVar(x,result); - ]; - - -// For n odd, the algoritm is based on the formula -// -// Cyclotomic(n,x) := Prod (x^(n/d)-1)^Moebius(d) -// -// where d runs through the divisors of n. - -// We compute in poly1 the product -// of (x^(n/d)-1) with Moebius(d)=1 , and in poly2 the product of these polynomials -// with Moebius(d)=-1. Finally we compute the quotient poly1/poly2 - -// In order to compute this in a efficient way, we use the functions -// CyclotomicDivisorsList and CyclotomicFactors (in order to avoid -// unnecesary polynomial divisions) - - -20 # InternalCyclotomic(n_IsOdd,_x)_(n>1) <-- -[ - Local(divisors,poly1,poly2,q,d,f,coef,i,j,result); - divisors := CyclotomicDivisorsList(n); - poly1 := {{0,1}}; - poly2 := {{0,1}}; - ForEach (d,divisors) - [ - If(InVerboseMode(),Echo("d=",d)); - f:= CyclotomicFactor(n/d[1],n/d[2]); - If (d[3]=1,poly1:=MultiplyTerms(poly1,f),poly2:=MultiplyTerms(poly2,f)); - If(InVerboseMode(), - [ - Echo("poly1=",poly1); - Echo("poly2=",poly2); - ]); - ]; - If(InVerboseMode(),Echo("End ForEach")); - result := If(poly2={{0,1}},poly1,DivTermList(poly1,poly2)); - SparseUniVar(x,result); -]; - - -10 # Cyclotomic(1,_x) <-- x-1; -20 # Cyclotomic(n_IsInteger,_x) <-- ExpandSparseUniVar(InternalCyclotomic(n,x)); - - -// This function returns the Cyclotomic polynomial, but in the univariate -// representation - -10 # UniVariateCyclotomic(1,_x) <-- UniVariate(x,0,{-1,1}); -20 # UniVariateCyclotomic(n_IsInteger,_x) <-- OldInternalCyclotomic(n,x,False); - - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/univar.rep/Cyclotomic.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/Cyclotomic.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/univar.rep/Cyclotomic.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/Cyclotomic.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -Cyclotomic -OldCyclotomic -UniVariateCyclotomic -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/univar.rep/sparse.mpi mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sparse.mpi --- mathpiper-0.0.svn2556/storage/scripts/univar.rep/sparse.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sparse.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,131 +0,0 @@ -// SparceUniVariate(variable,termlist) implements an internal representation -// for univariate polynomials -// termlist is the list of terms in the form {exponent,coeficient} - -RuleBase("SparseUniVar",{var,termlist}); - -300 # SparseUniVar(_var,_terms1) * SparseUniVar(_var,_terms2) <-- -SparseUniVar(var, MultiplyTerms(terms1,terms2)); - -300 # SparseUniVar(_var,_terms1) + SparseUniVar(_var,_terms2) <-- -SparseUniVar(var, AddTerms(terms1,terms2)); - -300 # SparseUniVar(_var,_terms1) - SparseUniVar(_var,_terms2) <-- -SparseUniVar(var, SubstractTerms(terms1,terms2)); - -// Add a term into a termlist: this function assumes that -// 1) the list of terms is sorted in decreasing order of exponents -// 2) there are not two terms with the same exponent. -// 3) There is no term with cero coefficient -// This assumptions are preserved. - -// The parameter begining tell us where to begin the search -// (it is used for increasing the efficency of the algorithms!) -// The function returns the position at which the new term is added plus 1. -// (to be used as begining for sucesive AddTerm calls - -Function("AddTerm",{termlist,term,begining}) -[ - Local(l,i); - l := Length(termlist); - If(term[2]!=0, - [ - i:=begining; -// Fix-me: search by using binary search ? - If (l>=1, While ((i<=l) And (term[1]l, [DestructiveAppend(termlist,term);i++;], - If (term[1]=termlist[i][1], - [ Local(nc); - nc:=termlist[i][2]+term[2]; - If(nc!=0,DestructiveReplace(termlist,i,{term[1],nc}), - [DestructiveDelete(termlist,i);i--;]); - ], DestructiveInsert(termlist,i,term)) - ); - ] - ); - i+1; -]; - - -Function("AddTerms",{terms1,terms2}) -[ - Local(result,begining,t); - begining :=1; - ForEach (t,terms2) - begining :=AddTerm(terms1,t,begining); - terms1; -]; - - -Function("SubstractTerms",{terms1,terms2}) -[ - Local(result,t); - begining :=1 ; - ForEach (t,terms2) - begining := AddTerm(terms1,{t[1],-t[2]},1); - terms1; -]; - -// Multiply a list of terms by a Single tem - -Function("MultiplySingleTerm",{termlist,term}) -[ - Local(result,t); - result:={}; - If(term[2]!=0, - ForEach (t,termlist) - DestructiveAppend(result,{t[1]+term[1],t[2]*term[2]}) ); - result; -]; - - -Function("MultiplyTerms",{terms1,terms2}) -[ - Local(result,t1,t2,begining); - result:={}; - ForEach (t1,terms1) - [ - begining :=1; - ForEach (t2,terms2) - begining := AddTerm(result,{t1[1]+t2[1],t1[2]*t2[2]},1); - ]; - result; -]; - -Function("ExpandSparseUniVar",{s}) -[ - Local(result,t,var,termlist); - result :=0; - var := s[1]; - termlist := s[2]; - ForEach (t,termlist) - [ - Local(term); - term := NormalForm(t[2]*var^t[1]); - result := result + term; - ]; - result; -]; - -// Implements the division of polynomials! - -Function("DivTermList",{a,b}) -[ - Local(q,nq,t,c,begining); - q := {}; - // a[1][1] is the degree of a, b[1][1] is the degree of b - While ((a!={}) And a[1][1]>=b[1][1]) - [ - begining := 1; - If(InVerboseMode(),Echo("degree=",a[1][1])); - nq := {a[1][1]-b[1][1],a[1][2]/b[1][2]}; // a new term of the quotient - DestructiveAppend(q,nq); - // We compute a:= a - nq* b - ForEach (t,b) - begining := AddTerm(a,{t[1]+nq[1],-t[2]*nq[2]},begining); - ]; - // a is the rest at the end - q; -]; - - diff -Nru mathpiper-0.0.svn2556/storage/scripts/univar.rep/sparse.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sparse.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/univar.rep/sparse.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sparse.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -MultiplyTerms -ExpandSparseUniVar -DivTermList -} diff -Nru mathpiper-0.0.svn2556/storage/scripts/univar.rep/sturm.mpi mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sturm.mpi --- mathpiper-0.0.svn2556/storage/scripts/univar.rep/sturm.mpi 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sturm.mpi 1970-01-01 00:00:00.000000000 +0000 @@ -1,289 +0,0 @@ - -SquareFree(_p) <-- -[ - Local(dp,gcd); -//Echo("1..."); - dp:=MakeMultiNomial(`(D(x)(@p)),{x}); -// dp:=dp/MultiLeadingCoef(dp); - -//Echo("2...",dp); - p:=MakeMultiNomial(p,{x}); -//Echo(NormalForm(p)); -//Echo(NormalForm(dp)); - gcd:=MultiGcd(p,dp); -//Echo(NormalForm(gcd)); -//Echo(NormalForm(MultiDivide(p,{gcd})[1][1])); - NormalForm(MultiDivide(p,{gcd})[1][1]); -// Div(p,Gcd(p,Monic(`(D(x)(@p))))); -]; - -/** SturmSequence(p) : generate a Sturm sequence for a polynomial in x. - */ -SturmSequence(_p) <-- -[ - Local(result,i,deg,nt); - result:={p,`D(@x)(@p)}; - deg:=Degree(p); - For(i:=3,i<=deg+1,i++) - [ - nt := -NormalForm(MultiDivide(MM(result[i-2],{x}),{MM(result[i-1],{x})})[2]); - DestructiveAppend(result,nt); - ]; - result; -]; - -10 # SturmVariations(_S,Infinity) <-- -[ - Local(i,s); - s:=FillList(0,Length(S)); - For(i:=1,i<=Length(S),i++) - [ - s[i] := LeadingCoef(S[i]); - ]; - SturmVariations(s); -]; -10 # SturmVariations(_S,-Infinity) <-- -[ - Local(i,s); - s:=FillList(0,Length(S)); - For(i:=1,i<=Length(S),i++) - [ - s[i] := ((-1)^Degree(S[i]))*LeadingCoef(S[i]); - ]; - SturmVariations(s); -]; - -20 # SturmVariations(_S,_x) <-- SturmVariations(Eval(S)); -SturmVariations(_S) <-- -[ - Local(result,prev); -//Echo("S = ",S); - result:=0; - While(Length(S)>0 And IsZero(S[1])) S:=Tail(S); -//Echo("S = ",S); - if (Length(S)>0) - [ - prev:=S[1]; - ForEach(item,Tail(S)) - [ - if(Not IsZero(item)) - [ - if (prev*item < 0) [result++;]; - prev:=item; - ]; - ]; - ]; - result; -]; - - -/** Maximum bound on the absolute value of the roots of a - polynomial p in variable x, according to Knuth: - - Max( Abs(a[n-1]/a[n]) , Abs(a[n-2]/a[n])^(1/2), ... , Abs(a[0]/a[n])^(1/n) ) - - As described in Davenport. - */ - 5 # MaximumBound(_p)_(IsZero(p Where x==0)) <-- MaximumBound(Simplify(p/x)); -10 # MaximumBound(_p)_(Degree(p)>0) <-- -[ - Local(an); - an:=Coef(p,(Degree(p)-1) .. 0)/Coef(p,Degree(p)); - an := N(Eval(Abs(an)^(1/(1 .. Degree(p))))); - Rationalize(2*Max(an)); -]; - -20 # MaximumBound(_p) <-- Infinity; - -10 # MinimumBound(_p)_(IsZero(p Where x==0)) <-- 0; - -20 # MinimumBound(_p)_(Degree(p)>0) <-- -[ - Local(an,result); - an:=Coef(p,1 .. (Degree(p)))/Coef(p,0); - an := N(Eval(Abs(an)^(1/(1 .. Degree(p))))); - - result:=0; - an:=2*Max(an); - if(Not IsZero(an)) [result := 1/an;]; - Simplify(Rationalize(result)); -]; -30 # MinimumBound(_p) <-- -Infinity; - - -BoundRealRoots(_p) <-- -[ - BoundRealRoots(p,MinimumBound(p),MaximumBound(p)); -]; - -BoundRealRoots(_p,_Mmin,_Mmax) <-- -[ - Local(S,N,work,result,Vmin,Vmax,a,b,Va,Vb,c,Vc,x); - - result:={}; - if (IsZero(p Where x==0)) - [ - p:=Simplify(p/x); - result:={{0,0}}; - ]; - S:=SturmSequence(p); - Vmin := SturmVariations(S,-Infinity); - Vmax := SturmVariations(S,Infinity); - -//Echo("Vmin,Vmax = ",Vmin,Vmax); - - N:=Vmin - Vmax; - -//Echo("N = ",N); - -//Echo("Mmin,Mmax = ",Mmin,Mmax); - work:={}; - if (N=1) - [ - result:={{-Mmax,Mmax}}; - ]; - if (N>1) - [ - work := - { - {-Mmax,-Mmin,Vmin,SturmVariations(S,-Mmin)}, - { Mmin, Mmax,SturmVariations(S, Mmin),Vmax} - }; - ]; - -//Echo("Work start = ",work); - While(work != {}) - [ - {a,b,Va,Vb} := Head(work); - work := Tail(work); - c:=(a+b)/2; -//Echo(a,b,c); - Vc := SturmVariations(S,c); - if (IsZero(p Where x == c)) - [ - Local(M,Vcmin,Vcplus,pnew); - pnew := Simplify((p Where x == x+c)/x); - M:=MinimumBound(pnew); -//Echo("Mi = ",M); - Vcmin := SturmVariations(S, c-M); - Vcplus := SturmVariations(S, c+M); - result:=Concat(result,{{c,c}}); - - if (Va = Vcmin+1) - [ - result:=Concat(result,{{a,c-M}}); - ]; - if (Va > Vcmin+1) - [ - work:=Concat(work,{{a,c-M,Va,Vcmin}}); - ]; - if (Vb = Vcplus-1) - [ - result:=Concat(result,{{c+M,b}}); - ]; - if (Vb < Vcplus-1) - [ - work:=Concat(work,{{c+M,b,Vcplus,Vb}}); - ]; - ] - else - [ - if (Va = Vc+1) - [ - result:=Concat(result,{{a,c}}); - ]; - if (Va > Vc+1) - [ - work:=Concat(work,{{a,c,Va,Vc}}); - ]; - if (Vb = Vc-1) - [ - result:=Concat(result,{{c,b}}); - ]; - if (Vb < Vc-1) - [ - work:=Concat(work,{{c,b,Vc,Vb}}); - ]; - ]; - ]; - result; -]; - - -FindRealRoots(_p) <-- -[ -//Echo("0..."); -//Echo("0..."); - p:=SquareFree(Rationalize(p)); -//Echo("1..."); -//Echo("2...",MinimumBound(p)); -//Echo("3...",MaximumBound(p)); - FindRealRoots(p,MinimumBound(p),MaximumBound(p)); -]; - -FindRealRoots(_p,_Mmin,_Mmax) <-- -[ - Local(bounds,result,i,prec,requiredPrec); -//Echo("bounds1"); - bounds := BoundRealRoots(p,Mmin,Mmax); -//Echo("bounds2"); - result:=FillList(0,Length(bounds)); - requiredPrec := BuiltinPrecisionGet(); - BuiltinPrecisionSet(BuiltinPrecisionGet()+2); - prec:=10^-(requiredPrec+1); - - For(i:=1,i<=Length(bounds),i++) - [ - Local(a,b,c,r); - {a,b} := bounds[i]; - c:=N(Eval((a+b)/2)); -//Echo(a,b,c); - r := Fail; -//Echo("newton1",`Hold(Newton(@p,x,@c,@prec,@a,@b))); - if (a != b) [r := `Newton(@p,x,@c,prec,a,b);]; -//Echo("newton2",r," ",CurrentFile(),CurrentLine()); - if (r = Fail) - [ - Local(c,cold,pa,pb,pc); - pa:=(p Where x==a); - pb:=(p Where x==b); - c:=((a+b)/2); - cold := a; - While (Abs(cold-c)>prec) - [ - pc:=(p Where x==c); -//Echo(a,b,c); - if (Abs(pc) < prec) - [ - a:=c; - b:=c; - ] - else if (pa*pc < 0) - [ - b:=c; - pb:=pc; - ] - else - [ - a:=c; - pa:=pc; - ]; - cold:=c; - c:=((a+b)/2); - ]; - r:=c; - ]; - result[i] := N(Eval((r/10)*(10)),requiredPrec); - ]; - BuiltinPrecisionSet(requiredPrec); - result; -]; - -NumRealRoots(_p) <-- -[ - Local(S); - p:=SquareFree(Rationalize(p)); - S:=SturmSequence(p); - SturmVariations(S,-Infinity)-SturmVariations(S,Infinity); -]; - diff -Nru mathpiper-0.0.svn2556/storage/scripts/univar.rep/sturm.mpi.def mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sturm.mpi.def --- mathpiper-0.0.svn2556/storage/scripts/univar.rep/sturm.mpi.def 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/storage/scripts/univar.rep/sturm.mpi.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -SquareFree -SturmSequence -SturmVariations -MaximumBound -MinimumBound -BoundRealRoots -FindRealRoots -NumRealRoots -} diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/cannot_create_user_function_error.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/cannot_create_user_function_error.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/cannot_create_user_function_error.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/cannot_create_user_function_error.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -%mathpiper,def="Simplify" - -10 # Simplify(expr_IsList) <-- MapSingle("Simplify",expr); - -15 # Simplify(Complex(_r,_i)) <-- Complex(Simplify(r),Simplify(i)); - -20 # Simplify((_xex) == (_yex)) <-- (Simplify(xex-yex) == 0); - -20 # Simplify((_xex) > (_yex)) <-- (Simplify(xex-yex) > 0); -20 # Simplify((_xex) < (_yex)) <-- (Simplify(xex-yex) < 0); -20 # Simplify((_xex) >= (_yex)) <-- (Simplify(xex-yex) >= 0); -20 # Simplify((_xex) <= (_yex)) <-- (Simplify(xex-yex) <= 0); -20 # Simplify((_xex) !== (_yex)) <-- (Simplify(xex-yex) !== 0); - -// conditionals -25 # Simplify(if (_a) _b) <-- "if" @ {Simplify(a), Simplify(b)}; -25 # Simplify(_a else _b) <-- "else" @ {Simplify(a), Simplify(b)}; - - -//Testing with Simplify(1+1/x) -50 # Simplify(_expr) <-- -[ - Local(s,g); - - s := MultiSimp(Eval(expr)); - - If(IsRationalFunction(s) And ( Type(Numerator(s)) != "Numer") And ( Type(Denominator(s)) != "Denom"), - [ - Echo("s ",s); - Echo("Numerator(s) ", Numerator(s)); - Echo("Denominator(s) ", Denominator(s)); - g := Gcd(Numerator(s),Denominator(s)); - Echo("g ",g); - If( InVerboseMode(), - [ - Show(10,expr); - Show(11,s); - Show(12,Equals(s,expr)); - Show(13,g); - NewLine(); - ] - ); - - If( s=expr, - [ - If( Equals(Numerator(expr),-Denominator(expr)), s := -1 ); - /* And here one can put other simplifications, as they are developed */ - ], - [ - s := Simplify((Numerator(expr)/g))/Simplify(Denominator(expr)/g); - - If(InVerboseMode(),Tell(14,s)); - ] - ); - s; - ], - [ - s; - ] - ); -]; - - -10 # IsRationalFunction(x_IsRationalOrNumber) <-- False; -15 # IsRationalFunction(_x)_(Type(x)="/") <-- True; -60000 # IsRationalFunction(_x) <-- False; - -%/mathpiper - - - -%mathpiper_docs,name="Simplify",categories="User Functions;Expression Simplification" -*CMD Simplify --- try to simplify an expression -*STD -*CALL - Simplify(expr) - -*PARMS - -{expr} -- expression to simplify - -*DESC - -This function tries to simplify the expression {expr} as much -as possible. It does this by grouping powers within terms, and then -grouping similar terms. - -*E.G. - - In> a*b*a^2/b-a^3 - Out> (b*a^3)/b-a^3; - In> Simplify(a*b*a^2/b-a^3) - Out> 0; - -*SEE TrigSimpCombine, RadSimp -%/mathpiper_docs diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,140 @@ + +%mathpiper +CASCompare(expressions) := +[ + Local(count,e,me, answer); + + count := 1; + + ForEach(e,expressions) + [ + If(IsList(e), [answer := e[2]; e := e[1];]); + + Echo("#",count ,"Exercise: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); + + + //Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); + Echo("MathPiper: ",Eval(FromString(e:";") Read())); + + //me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; + me := ToString()[WriteString("(");Write(Atom(e));WriteString(")");]; + Echo("Maxima:",Maxima(me)); + + count := count + 1; + + ]; + +]; +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper,title="page 55 exercises 1a. +Echo("pp.55 exercises. 1a "); +NewLine(); + +expressions :={ +{"x^2*x^3","x^5"}, +{"x^(1/2)*x^(1/3)","x^(5/6)"}, +{"x^a*x^b","x^(a+b)"}, +{"(x^2)^3","x^6"}, +{"(x^a)^2","x^(2*a)"}, +{"(x^2)^(1/2)","|x|"}, +{"(x^(1/2))^2","x"}, +{"(x^2)^a","x^(2*a)"}, +{"(x*y)^2","x^2*y^2"}, +{"(x*y)^(1/3)","x^(1/3)*y^(1/3)"}, +{"(x*y)^a","x^a*y^a"}, + +}; + +CASCompare(expressions); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + pp.55 exercises. 1a + + #1 Exercise: x^2*x^3 Answer: "x^5" + MathPiper: x^5 + Maxima:(%o700) x^5 + + #2 Exercise: x^(1/2)*x^(1/3) Answer: "x^(5/6)" + MathPiper: Sqrt(x)*x^(1/3) + Maxima:(%o701) x^(5/6) + + #3 Exercise: x^a*x^b Answer: "x^(a+b)" + MathPiper: x^(b+a) + Maxima:(%o702) x^(b+a) + + #4 Exercise: (x^2)^3 Answer: "x^6" + MathPiper: x^6 + Maxima:(%o703) x^6 + + #5 Exercise: (x^a)^2 Answer: "x^(2*a)" + MathPiper: x^a^2 + Maxima:(%o704) x^(2*a) + + #6 Exercise: (x^2)^(1/2) Answer: "|x|" + MathPiper: Sqrt(x^2) + Maxima:(%o705) abs(x) + + #7 Exercise: (x^(1/2))^2 Answer: "x" + MathPiper: x + Maxima:(%o706) x + + #8 Exercise: (x^2)^a Answer: "x^(2*a)" + MathPiper: x^2^a + Maxima:(%o707) abs(x)^(2*a) + + #9 Exercise: (x*y)^2 Answer: "x^2*y^2" + MathPiper: (x*y)^2 + Maxima:(%o708) x^2*y^2 + + #10 Exercise: (x*y)^(1/3) Answer: "x^(1/3)*y^(1/3)" + MathPiper: (x*y)^(1/3) + Maxima:(%o709) x^(1/3)*y^(1/3) + + #11 Exercise: (x*y)^a Answer: "x^a*y^a" + MathPiper: (x*y)^a + Maxima:(%o710) (x*y)^a +. %/output + + + + + +%mathpiper,title="page 55 exercises 2a. +Echo("pp.55 exercises. 1a "); +NewLine(); + +expressions :={ +{"2*x+3*x","5*x"}, +{"(1+x)+2*(1+x)","3*(1+x)"}, +{"2*x+Sqrt(2)*x","(2+Sqrt(2))*x"}, +{"a*x + b*x","(a+b)*x"}, +{"(a+b)*x","a*x+b*x)"}, +{"2*(x+y)","2*x+2*y"}, +{"-(x+y)","-x-y"}, +{"a*(x+y)","a*x+a*y"}, +}; + +//CASCompare(expressions); + +%/mathpiper + + %output,preserve="false" + Result: {{"2*x+3*x","5*x"},{"(1+x)+2*(1+x)","3*(1+x)"},{"2*x+Sqrt(2)*x","(2+Sqrt(2))*x"},{"a*x + b*x","(a+b)*x"},{"(a+b)*x","a*x+b*x)"},{"2*(x+y)","2*x+2*y"},{"-(x+y)","-x-y"},{"a*(x+y)","a*x+a*y"}} + + Side Effects: + pp.55 exercises. 1a +. %/output + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/computer_algebra_elementary_algorithms_cohen.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,140 +0,0 @@ - -%mathpiper -CASCompare(expressions) := -[ - Local(count,e,me, answer); - - count := 1; - - ForEach(e,expressions) - [ - If(IsList(e), [answer := e[2]; e := e[1];]); - - Echo("#",count ,"Exercise: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); - - - //Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); - Echo("MathPiper: ",Eval(FromString(e:";") Read())); - - //me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; - me := ToString()[WriteString("(");Write(Atom(e));WriteString(")");]; - Echo("Maxima:",Maxima(me)); - - count := count + 1; - - ]; - -]; -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - -%mathpiper,title="page 55 exercises 1a. -Echo("pp.55 exercises. 1a "); -NewLine(); - -expressions :={ -{"x^2*x^3","x^5"}, -{"x^(1/2)*x^(1/3)","x^(5/6)"}, -{"x^a*x^b","x^(a+b)"}, -{"(x^2)^3","x^6"}, -{"(x^a)^2","x^(2*a)"}, -{"(x^2)^(1/2)","|x|"}, -{"(x^(1/2))^2","x"}, -{"(x^2)^a","x^(2*a)"}, -{"(x*y)^2","x^2*y^2"}, -{"(x*y)^(1/3)","x^(1/3)*y^(1/3)"}, -{"(x*y)^a","x^a*y^a"}, - -}; - -CASCompare(expressions); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - pp.55 exercises. 1a - - #1 Exercise: x^2*x^3 Answer: "x^5" - MathPiper: x^5 - Maxima:(%o700) x^5 - - #2 Exercise: x^(1/2)*x^(1/3) Answer: "x^(5/6)" - MathPiper: Sqrt(x)*x^(1/3) - Maxima:(%o701) x^(5/6) - - #3 Exercise: x^a*x^b Answer: "x^(a+b)" - MathPiper: x^(b+a) - Maxima:(%o702) x^(b+a) - - #4 Exercise: (x^2)^3 Answer: "x^6" - MathPiper: x^6 - Maxima:(%o703) x^6 - - #5 Exercise: (x^a)^2 Answer: "x^(2*a)" - MathPiper: x^a^2 - Maxima:(%o704) x^(2*a) - - #6 Exercise: (x^2)^(1/2) Answer: "|x|" - MathPiper: Sqrt(x^2) - Maxima:(%o705) abs(x) - - #7 Exercise: (x^(1/2))^2 Answer: "x" - MathPiper: x - Maxima:(%o706) x - - #8 Exercise: (x^2)^a Answer: "x^(2*a)" - MathPiper: x^2^a - Maxima:(%o707) abs(x)^(2*a) - - #9 Exercise: (x*y)^2 Answer: "x^2*y^2" - MathPiper: (x*y)^2 - Maxima:(%o708) x^2*y^2 - - #10 Exercise: (x*y)^(1/3) Answer: "x^(1/3)*y^(1/3)" - MathPiper: (x*y)^(1/3) - Maxima:(%o709) x^(1/3)*y^(1/3) - - #11 Exercise: (x*y)^a Answer: "x^a*y^a" - MathPiper: (x*y)^a - Maxima:(%o710) (x*y)^a -. %/output - - - - - -%mathpiper,title="page 55 exercises 2a. -Echo("pp.55 exercises. 1a "); -NewLine(); - -expressions :={ -{"2*x+3*x","5*x"}, -{"(1+x)+2*(1+x)","3*(1+x)"}, -{"2*x+Sqrt(2)*x","(2+Sqrt(2))*x"}, -{"a*x + b*x","(a+b)*x"}, -{"(a+b)*x","a*x+b*x)"}, -{"2*(x+y)","2*x+2*y"}, -{"-(x+y)","-x-y"}, -{"a*(x+y)","a*x+a*y"}, -}; - -//CASCompare(expressions); - -%/mathpiper - - %output,preserve="false" - Result: {{"2*x+3*x","5*x"},{"(1+x)+2*(1+x)","3*(1+x)"},{"2*x+Sqrt(2)*x","(2+Sqrt(2))*x"},{"a*x + b*x","(a+b)*x"},{"(a+b)*x","a*x+b*x)"},{"2*(x+y)","2*x+2*y"},{"-(x+y)","-x-y"},{"a*(x+y)","a*x+a*y"}} - - Side Effects: - pp.55 exercises. 1a -. %/output - - diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,71 @@ +%mathpiper + +/* +This is the beginnings of a Kind function which will return: + +1) If u is an atomic expression, return the type of the expression. + +2) If u is a compund expression, return the operator at the root of the + expression tree. + +pp.104 "Computer Algebra And Symbolic Computation: Elementary Algorithms" Cohen. + +*/ +Retract("Kind",*); + +RuleBase("Kind",{u}); + +//HoldArg("Kind",u); + + + +10 # Kind(_u) <-- +[ + Write(u,,); + + Local(result); + + if(IsInteger(u)) + [ + result := integer; + Echo(1); + ] + else if(IsString(u)) + [ + result := string; + Echo(2); + ] + else if(IsList(u)) + [ + result := list; + Echo(3); + ] + else if(Not IsBound(Eval(u))) + [ + result := symbol; + Echo(10); + ] + else + [ + ]; + + + result; +]; + + +Kind({3}); + +%/mathpiper + + %output,preserve="false" + Result: list + + Side Effects: + {3},3 +. %/output + + + + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/computer_algebra_cohen/kosan/Kind.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -%mathpiper - -/* -This is the beginnings of a Kind function which will return: - -1) If u is an atomic expression, return the type of the expression. - -2) If u is a compund expression, return the operator at the root of the - expression tree. - -pp.104 "Computer Algebra And Symbolic Computation: Elementary Algorithms" Cohen. - -*/ -Retract("Kind",*); - -RuleBase("Kind",{u}); - -//HoldArg("Kind",u); - - - -10 # Kind(_u) <-- -[ - Write(u,,); - - Local(result); - - if(IsInteger(u)) - [ - result := integer; - Echo(1); - ] - else if(IsString(u)) - [ - result := string; - Echo(2); - ] - else if(IsList(u)) - [ - result := list; - Echo(3); - ] - else if(Not IsBound(Eval(u))) - [ - result := symbol; - Echo(10); - ] - else - [ - ]; - - - result; -]; - - -Kind({3}); - -%/mathpiper - - %output,preserve="false" - Result: list - - Side Effects: - {3},3 -. %/output - - - - - diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/factors_rational_number_bug.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/factors_rational_number_bug.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/factors_rational_number_bug.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/factors_rational_number_bug.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,11 @@ +%mathpiper + +10 # Factors(p_IsRational)_(Denominator(p) != 1) <-- {{Factor(Numerator(p)) / Factor(Denominator(p)) , 1}}; + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/factors_rational_number_bug.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/factors_rational_number_bug.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/factors_rational_number_bug.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/factors_rational_number_bug.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -%mathpiper - -10 # Factors(p_IsRational)_(Denominator(p) != 1) <-- {{Factor(Numerator(p)) / Factor(Denominator(p)) , 1}}; - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/geogebra_interaction.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/geogebra_interaction.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/geogebra_interaction.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/geogebra_interaction.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,117 @@ + +%* +Create 3 points A, B and C in GeoGebra. +*/ + + +%mathpiper,title="" + +/* +The GeoGebra() function is used to tell the system which GeoGebra objects +should be inserted into the MathPiper environment. The names of the +objects are sent to the GeoGebra() function in a comma separated list. +*/ +GeoGebra()["updateObjects"] := "A,B,C,f,g"; + + +/* +GeoGebraPoint() is an experimental function which directly places points +into GeoGebra. The first parameter is the name of the point, the second +parameter is its x coordinate, and the third parameter is the name of +its y coordinate. +*/ +GeoGebraPoint("A",1,2); + +GeoGebraPoint("B",2,2); + +GeoGebraPoint("C",1,1); + +%/mathpiper + + %output,preserve="false" + Result: java.lang.Boolean +. %/output + + +%mathpiper, output="latex" +ax := A["coords"]["x"]; +ay := A["coords"]["y"]; +bx := B["coords"]["x"]; +by := B["coords"]["y"]; +cx := C["coords"]["x"]; +cy := C["coords"]["y"]; + +%/mathpiper + + %hoteqn,preserve="false" + Result: 1.0 +. %/hoteqn + + + +%mathpiper, output="geogebra" +bez1(a,b,r) := a*(1-r)+b*r; +bez2(a,b,c,r) := bez1(a,b,r)*(1-r) + bez1(b,c,r)*r; +f(x) := Expand(bez2(ax,bx,cx,x)); +f(x); +%/mathpiper + + %geogebra,preserve="false" + Result: 2.0*x-2.0*x^2+1 +. %/geogebra + + %output,preserve="false" + GeoGebra updated. +. %/output + + + + + + + +%mathpiper, output="geogebra" +g(x) := Expand(bez2(ay,by,cy,x)); +g(x); +%/mathpiper + + %geogebra,preserve="false" + Result: 2.0-x^2 +. %/geogebra + + %output,preserve="false" + GeoGebra updated. +. %/output + + + + + + +%geogebra, clear="false" +curve : curve[f(t),g(t),t,0,1] +%/geogebra + + %output,preserve="false" + GeoGebra updated. +. %/output + + + +%mathpiper, output="latex" +{f(x), g(x)}; +%/mathpiper + + %hoteqn,preserve="false" + Result: \left(2x-2x^{2}+1,2-x^{2}\right) +. %/hoteqn + + %output,preserve="false" + HotEqn updated. +. %/output + + + + + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/geogebra_interaction.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/geogebra_interaction.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/geogebra_interaction.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/geogebra_interaction.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ - -%* -Create 3 points A, B and C in GeoGebra. -*/ - - -%mathpiper,title="" - -/* -The GeoGebra() function is used to tell the system which GeoGebra objects -should be inserted into the MathPiper environment. The names of the -objects are sent to the GeoGebra() function in a comma separated list. -*/ -GeoGebra()["updateObjects"] := "A,B,C,f,g"; - - -/* -GeoGebraPoint() is an experimental function which directly places points -into GeoGebra. The first parameter is the name of the point, the second -parameter is its x coordinate, and the third parameter is the name of -its y coordinate. -*/ -GeoGebraPoint("A",1,2); - -GeoGebraPoint("B",2,2); - -GeoGebraPoint("C",1,1); - -%/mathpiper - - %output,preserve="false" - Result: java.lang.Boolean -. %/output - - -%mathpiper, output="latex" -ax := A["coords"]["x"]; -ay := A["coords"]["y"]; -bx := B["coords"]["x"]; -by := B["coords"]["y"]; -cx := C["coords"]["x"]; -cy := C["coords"]["y"]; - -%/mathpiper - - %hoteqn,preserve="false" - Result: 1.0 -. %/hoteqn - - - -%mathpiper, output="geogebra" -bez1(a,b,r) := a*(1-r)+b*r; -bez2(a,b,c,r) := bez1(a,b,r)*(1-r) + bez1(b,c,r)*r; -f(x) := Expand(bez2(ax,bx,cx,x)); -f(x); -%/mathpiper - - %geogebra,preserve="false" - Result: 2.0*x-2.0*x^2+1 -. %/geogebra - - %output,preserve="false" - GeoGebra updated. -. %/output - - - - - - - -%mathpiper, output="geogebra" -g(x) := Expand(bez2(ay,by,cy,x)); -g(x); -%/mathpiper - - %geogebra,preserve="false" - Result: 2.0-x^2 -. %/geogebra - - %output,preserve="false" - GeoGebra updated. -. %/output - - - - - - -%geogebra, clear="false" -curve : curve[f(t),g(t),t,0,1] -%/geogebra - - %output,preserve="false" - GeoGebra updated. -. %/output - - - -%mathpiper, output="latex" -{f(x), g(x)}; -%/mathpiper - - %hoteqn,preserve="false" - Result: \left(2x-2x^{2}+1,2-x^{2}\right) -. %/hoteqn - - %output,preserve="false" - HotEqn updated. -. %/output - - - - - - diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/high_school_tests.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/high_school_tests.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/high_school_tests.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/high_school_tests.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,998 @@ + + +%mathpiper +Echo("pp.100. Express the following in lowest terms. The letter symbols that appear represent positive integers."); +NewLine(); + + +equations1 := { +{"18/48","3/8"}, +"85/100", +{"56/-12","-14/3"}, +"-91/49", +{"(32*a^2)/(16*a)","2*a"}, +"(45*x^3*y)/(-15*y^2)", +{"(a*b*c)/(c*d)","a*b/d"}, +"(2*x + 2)/(x + 1)", +{"(2*a - 1)/(b - 2*a*b)","-1/b"}, +"(a*b)/(b*a)", +{"(6*a + 4)/(12*a)","(3*a+2)/(6*a)"}, +"(a + 1)/(a*b + b)", +{"(14 - 7*x)/(21)","(2-x)/3"}, +"(3*x - x^2)/(x^2 - x)",//x is not equal to 1. +{"(a^2 + 7*a)/(a^2)","(a+7)/a"}, +"(x^2 - 3*x)/(6*x - 2*x^2)",//x is not equal to 3. +{"(5*a^2 - a)/(5*a - 1)","a"}, +"(10*a^2 - 2*a)/(10*a^2 + 2*a)", +}; + +count := 1; +ForEach(e,equations1) +[ + If(IsList(e), [answer := e[2]; e := e[1];]); + + + Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); + + //Echo(PrettyForm(e)); + + + Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); + + me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; + Echo("Maxima:",Maxima(me)); + + count := count + 1; + +]; + +count - 1; + +%/mathpiper + + %output,preserve="false" + Result: 18 + + Side Effects: + pp.100. Express the following in lowest terms. The letter symbols that appear represent positive integers. + + #1 Problem: 18/48 Answer: "3/8" + MathPiper: 3/8 + Maxima:(%o543) 3/8 + + #2 Problem: 85/100 + MathPiper: 17/20 + Maxima:(%o544) 17/20 + + #3 Problem: 56/-12 Answer: "-14/3" + MathPiper: (-14)/3 + Maxima:(%o545) -14/3 + + #4 Problem: -91/49 + MathPiper: (-13)/7 + Maxima:(%o546) -13/7 + + #5 Problem: (32*a^2)/(16*a) Answer: "2*a" + MathPiper: 2*a + Maxima:(%o547) 2*a + + #6 Problem: (45*x^3*y)/(-15*y^2) + MathPiper: (-3*x^3)/y + Maxima:(%o548) -3*x^3/y + + #7 Problem: (a*b*c)/(c*d) Answer: "a*b/d" + MathPiper: (a*b)/d + Maxima:(%o549) a*b/d + + #8 Problem: (2*x + 2)/(x + 1) + MathPiper: 2 + Maxima:(%o550) 2 + + #9 Problem: (2*a - 1)/(b - 2*a*b) Answer: "-1/b" + MathPiper: (2*a-1)/(b*(1-2*a)) + Maxima:(%o551) -1/b + + #10 Problem: (a*b)/(b*a) + MathPiper: 1 + Maxima:(%o552) 1 + + #11 Problem: (6*a + 4)/(12*a) Answer: "(3*a+2)/(6*a)" + MathPiper: (3*a+2)/(6*a) + Maxima:(%o553) (3*a+2)/(6*a) + + #12 Problem: (a + 1)/(a*b + b) + MathPiper: 1/b + Maxima:(%o554) 1/b + + #13 Problem: (14 - 7*x)/(21) Answer: "(2-x)/3" + MathPiper: (2-x)/3 + Maxima:(%o555) -(x-2)/3 + + #14 Problem: (3*x - x^2)/(x^2 - x) + MathPiper: (3-x)/(x-1) + Maxima:(%o556) -(x-3)/(x-1) + + #15 Problem: (a^2 + 7*a)/(a^2) Answer: "(a+7)/a" + MathPiper: (a+7)/a + Maxima:(%o557) (a+7)/a + + #16 Problem: (x^2 - 3*x)/(6*x - 2*x^2) + MathPiper: (x-3)/(2*(3-x)) + Maxima:(%o558) -1/2 + + #17 Problem: (5*a^2 - a)/(5*a - 1) Answer: "a" + MathPiper: a + Maxima:(%o559) a + + #18 Problem: (10*a^2 - 2*a)/(10*a^2 + 2*a) + MathPiper: (5*a-1)/(5*a+1) + Maxima:(%o560) (5*a-1)/(5*a+1) +. %/output + + + + + + + + +%mathpiper +Echo("pp.105. Perform the following additions. Express each result in lowest terms. The letter symbols that appear represent positive integers."); +NewLine(); + + +equations1 := { +{"2/3 + 5/3","7/3"}, +"1/9 + 4/9 + 5/9", +{"2/7 + 3/7 + 5/7","10/7"}, +"a/y + b/y + c/y", +{"a/x + 3*a/x + 4*a/x","8*a/x"}, +"x/(x+y) + x/(x + y)", +{"a/(a + 1) + 1/(a + 1)","1"}, +"2/3 + 4/5", +{"3 + 7/6 + 2/3","29/6"}, +"y/3 + 2*y/9", +{"3*y + y/5","16*y/5"}, +"x/2 + x/3 + x/4", +{"4/a + 3/(2*a)","11/(2*a)"}, +"1/a + 1/b + 1/c", +{"b*c + 1/c","(b*c^2+1)/c"}, +"x/(x+y) + 7", +{"1/(2*m) + (a + 3)/(4*m)","(a+5)/(4*m)"}, +"9/x^2 + 4/x", +{"a/(x + y) + b/(x + y)","(a+b)/(x+y)"}, +"1/a + 3/(a*b) + 2/b", +{"2*x/a + 3*y/b","(2*b*x+3*a*y)/(a*b)"}, +"2/a + 7/(a*b*c) + 6/c", +}; + +count := 1; +ForEach(e,equations1) +[ + If(IsList(e), [answer := e[2]; e := e[1];]); + + + Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); + + //Echo(PrettyForm(e)); + + Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); + + me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; + Echo("Maxima:",Maxima(me)); + + count := count + 1; + +]; + +count - 1; + +%/mathpiper + + %output,preserve="false" + Result: 22 + + Side Effects: + pp.105. Perform the following additions. Express each result in lowest terms. The letter symbols that appear represent positive integers. + + #1 Problem: 2/3 + 5/3 Answer: "7/3" + MathPiper: 7/3 + Maxima:(%o385) 7/3 + + #2 Problem: 1/9 + 4/9 + 5/9 + MathPiper: 10/9 + Maxima:(%o386) 10/9 + + #3 Problem: 2/7 + 3/7 + 5/7 Answer: "10/7" + MathPiper: 10/7 + Maxima:(%o387) 10/7 + + #4 Problem: a/y + b/y + c/y + MathPiper: (a+b+c)/y + Maxima:(%o388) (c+b+a)/y + + #5 Problem: a/x + 3*a/x + 4*a/x Answer: "8*a/x" + MathPiper: (8*a)/x + Maxima:(%o389) 8*a/x + + #6 Problem: x/(x+y) + x/(x + y) + MathPiper: (2*x)/(x+y) + Maxima:(%o390) 2*x/(y+x) + + #7 Problem: a/(a + 1) + 1/(a + 1) Answer: "1" + MathPiper: 1 + Maxima:(%o391) 1 + + #8 Problem: 2/3 + 4/5 + MathPiper: 22/15 + Maxima:(%o392) 22/15 + + #9 Problem: 3 + 7/6 + 2/3 Answer: "29/6" + MathPiper: 29/6 + Maxima:(%o393) 29/6 + + #10 Problem: y/3 + 2*y/9 + MathPiper: (5*y)/9 + Maxima:(%o394) 5*y/9 + + #11 Problem: 3*y + y/5 Answer: "16*y/5" + MathPiper: (16*y)/5 + Maxima:(%o395) 16*y/5 + + #12 Problem: x/2 + x/3 + x/4 + MathPiper: (13*x)/12 + Maxima:(%o396) 13*x/12 + + #13 Problem: 4/a + 3/(2*a) Answer: "11/(2*a)" + MathPiper: (11*a)/(2*a^2) + Maxima:(%o397) 11/(2*a) + + #14 Problem: 1/a + 1/b + 1/c + MathPiper: (a*b+a*c+b*c)/(a*b*c) + Maxima:(%o398) ((b+a)*c+a*b)/(a*b*c) + + #15 Problem: b*c + 1/c Answer: "(b*c^2+1)/c" + MathPiper: (b*c^2+1)/c + Maxima:(%o399) (b*c^2+1)/c + + #16 Problem: x/(x+y) + 7 + MathPiper: (8*x+7*y)/(x+y) + Maxima:(%o400) (7*y+8*x)/(y+x) + + #17 Problem: 1/(2*m) + (a + 3)/(4*m) Answer: "(a+5)/(4*m)" + MathPiper: (m*a+5*m)/(4*m^2) + Maxima:(%o401) (a+5)/(4*m) + + #18 Problem: 9/x^2 + 4/x + MathPiper: (4*x^2+9*x)/x^3 + Maxima:(%o402) (4*x+9)/x^2 + + #19 Problem: a/(x + y) + b/(x + y) Answer: "(a+b)/(x+y)" + MathPiper: (a+b)/(x+y) + Maxima:(%o403) (b+a)/(y+x) + + #20 Problem: 1/a + 3/(a*b) + 2/b + MathPiper: (2*a^2*b+a*b^2+3*a*b)/(a^2*b^2) + Maxima:(%o404) (b+2*a+3)/(a*b) + + #21 Problem: 2*x/a + 3*y/b Answer: "(2*b*x+3*a*y)/(a*b)" + MathPiper: (2*x*b+3*a*y)/(a*b) + Maxima:(%o405) (3*a*y+2*b*x)/(a*b) + + #22 Problem: 2/a + 7/(a*b*c) + 6/c + MathPiper: (6*a^2*b*c+2*a*b*c^2+7*a*c)/(a^2*b*c^2) + Maxima:(%o406) (2*b*c+6*a*b+7)/(a*b*c) +. %/output + + + + + +%mathpiper +Echo("pp.112. Find the following products. Express each result in lowest terms. The letter symbols represent positive integers."); +NewLine(); + + +equations1 := { +{"3*(4/9)","4/3"}, +{"5*(7/11)",""}, +{"2/3*6","4"}, +{"5/8*4/15",""}, +{"91/119*34/39","2/3"}, +{"a/b*1/a",""}, +{"(3*a)/(2*b)*(5*a^2)/(9*b)","(5*a^3)/(6*b^2)"}, +{"(a/b)*(a/b)",""}, +{"(1/x^2)*(2/3)*(x/4)","1/(6*x)"}, +{"(m^2/n)*(n/m^2)",""}, +{"((a^2+a*x)/3)*(6/(a+x))","2*a"}, +{"((2*x+12)/(x+5))*((3*x+15)/(x+6))",""}, +{"((x + 1)/x)*(x^2/(x^2+x))","1"}, +{"((4*x*y)/(x+3))*((3*x^2+9*x)/(16*y^2))",""}, +{"(2/6)*(1/2)*(3/4)","1/8"}, +{"(a/2)*(4/a^2)*(3/5)",""}, +{"((3*x+12)/x)*(2*x^2/(x+4))","6*x"}, +{"(y^3/(15*x+6))*((5*x+2)/y)",""}, +{"((2*a+b)/(7*a*b))*3*b^2/(4*a+2*b)","(3*b)/(14*a)"}, +{"(5/(a^3+a^2*y))*((a^2+a*y)/25)",""}, +{"((2*a^2+3*a^2)/b)*(b^3/a^2)","5*b^2"}, +{"((4*y+4)/7)*(14/(2*y^2+2*y))",""}, +{"skip",""}, +{"skip",""}, +{"(4*a+4)/4","a+1"}, +{"(2*x+6)/2",""}, +{"(a^2+a)/a","a+1"}, +{"(a*x+a*y)/a",""}, +}; + +count := 1; +ForEach(e,equations1) +[ + If(IsList(e), [answer := e[2]; e := e[1];]); + + + Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); + + //Echo(PrettyForm(e)); + + Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); + + me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; + Echo("Maxima:",Maxima(me)); + + count := count + 1; + +]; + +count - 1; + +%/mathpiper + + %output,preserve="false" + Result: 28 + + Side Effects: + pp.112. Find the following products. Express each result in lowest terms. The letter symbols represent positive integers. + + #1 Problem: 3*(4/9) Answer: "4/3" + MathPiper: 4/3 + Maxima:(%o429) 4/3 + + #2 Problem: 5*(7/11) Answer: "" + MathPiper: 35/11 + Maxima:(%o430) 35/11 + + #3 Problem: 2/3*6 Answer: "4" + MathPiper: 4 + Maxima:(%o431) 4 + + #4 Problem: 5/8*4/15 Answer: "" + MathPiper: 1/6 + Maxima:(%o432) 1/6 + + #5 Problem: 91/119*34/39 Answer: "2/3" + MathPiper: 2/3 + Maxima:(%o433) 2/3 + + #6 Problem: a/b*1/a Answer: "" + MathPiper: 1/b + Maxima:(%o434) 1/b + + #7 Problem: (3*a)/(2*b)*(5*a^2)/(9*b) Answer: "(5*a^3)/(6*b^2)" + MathPiper: (5*a^3)/(6*b^2) + Maxima:(%o435) 5*a^3/(6*b^2) + + #8 Problem: (a/b)*(a/b) Answer: "" + MathPiper: a^2/b^2 + Maxima:(%o436) a^2/b^2 + + #9 Problem: (1/x^2)*(2/3)*(x/4) Answer: "1/(6*x)" + MathPiper: 1/(6*x) + Maxima:(%o437) 1/(6*x) + + #10 Problem: (m^2/n)*(n/m^2) Answer: "" + MathPiper: 1 + Maxima:(%o438) 1 + + #11 Problem: ((a^2+a*x)/3)*(6/(a+x)) Answer: "2*a" + MathPiper: 2*a + Maxima:(%o439) 2*a + + #12 Problem: ((2*x+12)/(x+5))*((3*x+15)/(x+6)) Answer: "" + MathPiper: 6 + Maxima:(%o440) 6 + + #13 Problem: ((x + 1)/x)*(x^2/(x^2+x)) Answer: "1" + MathPiper: 1 + Maxima:(%o441) 1 + + #14 Problem: ((4*x*y)/(x+3))*((3*x^2+9*x)/(16*y^2)) Answer: "" + MathPiper: (3*x^2)/(4*y) + Maxima:(%o442) 3*x^2/(4*y) + + #15 Problem: (2/6)*(1/2)*(3/4) Answer: "1/8" + MathPiper: 1/8 + Maxima:(%o443) 1/8 + + #16 Problem: (a/2)*(4/a^2)*(3/5) Answer: "" + MathPiper: 6/(5*a) + Maxima:(%o444) 6/(5*a) + + #17 Problem: ((3*x+12)/x)*(2*x^2/(x+4)) Answer: "6*x" + MathPiper: 6*x + Maxima:(%o445) 6*x + + #18 Problem: (y^3/(15*x+6))*((5*x+2)/y) Answer: "" + MathPiper: y^2/3 + Maxima:(%o446) y^2/3 + + #19 Problem: ((2*a+b)/(7*a*b))*3*b^2/(4*a+2*b) Answer: "(3*b)/(14*a)" + MathPiper: (3*b)/(14*a) + Maxima:(%o447) 3*b/(14*a) + + #20 Problem: (5/(a^3+a^2*y))*((a^2+a*y)/25) Answer: "" + MathPiper: 1/(5*a) + Maxima:(%o448) 1/(5*a) + + #21 Problem: ((2*a^2+3*a^2)/b)*(b^3/a^2) Answer: "5*b^2" + MathPiper: 5*b^2 + Maxima:(%o449) 5*b^2 + + #22 Problem: ((4*y+4)/7)*(14/(2*y^2+2*y)) Answer: "" + MathPiper: 4/y + Maxima:(%o450) 4/y + + #23 Problem: skip Answer: "" + MathPiper: skip + Maxima:(%o451) skip + + #24 Problem: skip Answer: "" + MathPiper: skip + Maxima:(%o452) skip + + #25 Problem: (4*a+4)/4 Answer: "a+1" + MathPiper: a+1 + Maxima:(%o453) a+1 + + #26 Problem: (2*x+6)/2 Answer: "" + MathPiper: x+3 + Maxima:(%o454) x+3 + + #27 Problem: (a^2+a)/a Answer: "a+1" + MathPiper: a+1 + Maxima:(%o455) a+1 + + #28 Problem: (a*x+a*y)/a Answer: "" + MathPiper: x+y + Maxima:(%o456) y+x +. %/output + + + + + + + + + + + + + + + + + + + +%mathpiper +Echo("pp.130. Problems 1-24: Perform the following divisions. Express results in lowest terms. The letter symbols represent positive integers."); +NewLine(); + + +equations1 := { +{"(7/8)/(2/3)","21/16"}, +{"4/(3/5)",""}, +{"(3/5)/4","3/20"}, +{"(a/b)/a",""}, +{"a/(a/b)","b"}, +{"((x+y)/x)/x",""}, +{"x/((x+y)/x)","x^2/(x+y)"}, +{"(x/y)/(y/x)",""}, +{"(x/(x+y))/(x/y)","y/(x+y)"}, +{"a/(a*b)",""}, +{"(a*b)/a","b"}, +{"(x/2)/((5*x^2)/8)",""}, +{"((a+b)/a)/(b/a)","(a+b)/b"}, +{"((a+b)/a)/(a/b)",""}, +{"((2*a)/(3*b))/((4*a)/27)","9/(2*b)"}, +{"(a/(a+b))/((3*a)/(a*c+b*c))",""}, +{"((5*x+10)/x^2)/(5/x)","(x+2)/x"}, +{"((x*y+x)/(y))/((a*y+a)/(y^2))",""}, +{"(y^2/(15*x+6))/(y/(5*x+2))","y/3"}, +{"((3*x+12)/x)/((x+4)/(2*x^2))",""}, +{"(5/(a^3+a^2*y))/(25/(a^2+a*y))","1/(5*a)"}, +{"((2*a+b)/(7*a*b))/((4*a+2*b)/(3*b^2))",""}, +{"((4*y+4)/7)/((2*y^2+2*y)/14)","4/y"}, +{"((2*a^2+3*a^2)/b)/(a^2/b^3)",""}, +{"skip",""}, +{"skip",""},//26. +{"(1/2+1/3)/(1/4+1/5)",""}, +{"(1/x+1/y)/(2/x+2/y)",""}, +{"(8+3/4)*(2/3)",""}, +{"(4+1/3)*(6+1/2)",""}, +{"(2+1/2)/(5+1/3)",""},//31. +{"(6+1/2)+(14+1/3)",""}, +{"(4+2/7)/(3+1/3)",""}, +{"(4+2/7)*(3+1/3)",""}, +{"(1/x+3)/(4+2/x)",""}, +{"((x+y)/4)/((2*x+2*y)/8)",""},//36. +{"((1+x)/3)/((3+3*x)/7)",""}, +{"(3-1/x^2)/(2+1/x)",""}, +{"(a/2+b/3)/((3*a+2*b)/5)",""}, +{"(2/a+3/b)/(5/a+4/b)",""},//40 + +}; + +count := 1; +ForEach(e,equations1) +[ + If(IsList(e), [answer := e[2]; e := e[1];]); + + + Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); + + //Echo(PrettyForm(e)); + + Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); + + me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; + Echo("Maxima:",Maxima(me)); + + count := count + 1; + +]; + +count - 1; + +%/mathpiper + + %output,preserve="false" + Result: 40 + + Side Effects: + pp.130. Problems 1-24: Perform the following divisions. Express results in lowest terms. The letter symbols represent positive integers. + + #1 Problem: (7/8)/(2/3) Answer: "21/16" + MathPiper: 21/16 + Maxima:(%o471) 21/16 + + #2 Problem: 4/(3/5) Answer: "" + MathPiper: 20/3 + Maxima:(%o472) 20/3 + + #3 Problem: (3/5)/4 Answer: "3/20" + MathPiper: 3/20 + Maxima:(%o473) 3/20 + + #4 Problem: (a/b)/a Answer: "" + MathPiper: 1/b + Maxima:(%o474) 1/b + + #5 Problem: a/(a/b) Answer: "b" + MathPiper: b + Maxima:(%o475) b + + #6 Problem: ((x+y)/x)/x Answer: "" + MathPiper: (x+y)/x^2 + Maxima:(%o476) (y+x)/x^2 + + #7 Problem: x/((x+y)/x) Answer: "x^2/(x+y)" + MathPiper: x^2/(x+y) + Maxima:(%o477) x^2/(y+x) + + #8 Problem: (x/y)/(y/x) Answer: "" + MathPiper: x^2/y^2 + Maxima:(%o478) x^2/y^2 + + #9 Problem: (x/(x+y))/(x/y) Answer: "y/(x+y)" + MathPiper: y/(x+y) + Maxima:(%o479) y/(y+x) + + #10 Problem: a/(a*b) Answer: "" + MathPiper: 1/b + Maxima:(%o480) 1/b + + #11 Problem: (a*b)/a Answer: "b" + MathPiper: b + Maxima:(%o481) b + + #12 Problem: (x/2)/((5*x^2)/8) Answer: "" + MathPiper: 4/(5*x) + Maxima:(%o482) 4/(5*x) + + #13 Problem: ((a+b)/a)/(b/a) Answer: "(a+b)/b" + MathPiper: (a+b)/b + Maxima:(%o483) (b+a)/b + + #14 Problem: ((a+b)/a)/(a/b) Answer: "" + MathPiper: ((a+b)*b)/a^2 + Maxima:(%o484) (b^2+a*b)/a^2 + + #15 Problem: ((2*a)/(3*b))/((4*a)/27) Answer: "9/(2*b)" + MathPiper: 9/(2*b) + Maxima:(%o485) 9/(2*b) + + #16 Problem: (a/(a+b))/((3*a)/(a*c+b*c)) Answer: "" + MathPiper: c/3 + Maxima:(%o486) c/3 + + #17 Problem: ((5*x+10)/x^2)/(5/x) Answer: "(x+2)/x" + MathPiper: (x+2)/x + Maxima:(%o487) (x+2)/x + + #18 Problem: ((x*y+x)/(y))/((a*y+a)/(y^2)) Answer: "" + MathPiper: (x*y)/a + Maxima:(%o488) x*y/a + + #19 Problem: (y^2/(15*x+6))/(y/(5*x+2)) Answer: "y/3" + MathPiper: y/3 + Maxima:(%o489) y/3 + + #20 Problem: ((3*x+12)/x)/((x+4)/(2*x^2)) Answer: "" + MathPiper: 6*x + Maxima:(%o490) 6*x + + #21 Problem: (5/(a^3+a^2*y))/(25/(a^2+a*y)) Answer: "1/(5*a)" + MathPiper: 1/(5*a) + Maxima:(%o491) 1/(5*a) + + #22 Problem: ((2*a+b)/(7*a*b))/((4*a+2*b)/(3*b^2)) Answer: "" + MathPiper: (3*b)/(14*a) + Maxima:(%o492) 3*b/(14*a) + + #23 Problem: ((4*y+4)/7)/((2*y^2+2*y)/14) Answer: "4/y" + MathPiper: 4/y + Maxima:(%o493) 4/y + + #24 Problem: ((2*a^2+3*a^2)/b)/(a^2/b^3) Answer: "" + MathPiper: 5*b^2 + Maxima:(%o494) 5*b^2 + + #25 Problem: skip Answer: "" + MathPiper: skip + Maxima:(%o495) skip + + #26 Problem: skip Answer: "" + MathPiper: skip + Maxima:(%o496) skip + + #27 Problem: (1/2+1/3)/(1/4+1/5) Answer: "" + MathPiper: 50/27 + Maxima:(%o497) 50/27 + + #28 Problem: (1/x+1/y)/(2/x+2/y) Answer: "" + MathPiper: 1/2 + Maxima:(%o498) 1/2 + + #29 Problem: (8+3/4)*(2/3) Answer: "" + MathPiper: 35/6 + Maxima:(%o499) 35/6 + + #30 Problem: (4+1/3)*(6+1/2) Answer: "" + MathPiper: 169/6 + Maxima:(%o500) 169/6 + + #31 Problem: (2+1/2)/(5+1/3) Answer: "" + MathPiper: 15/32 + Maxima:(%o501) 15/32 + + #32 Problem: (6+1/2)+(14+1/3) Answer: "" + MathPiper: 125/6 + Maxima:(%o502) 125/6 + + #33 Problem: (4+2/7)/(3+1/3) Answer: "" + MathPiper: 9/7 + Maxima:(%o503) 9/7 + + #34 Problem: (4+2/7)*(3+1/3) Answer: "" + MathPiper: 100/7 + Maxima:(%o504) 100/7 + + #35 Problem: (1/x+3)/(4+2/x) Answer: "" + MathPiper: (3*x+1)/(2*(2*x+1)) + Maxima:(%o505) (3*x+1)/(4*x+2) + + #36 Problem: ((x+y)/4)/((2*x+2*y)/8) Answer: "" + MathPiper: 1 + Maxima:(%o506) 1 + + #37 Problem: ((1+x)/3)/((3+3*x)/7) Answer: "" + MathPiper: 7/9 + Maxima:(%o507) 7/9 + + #38 Problem: (3-1/x^2)/(2+1/x) Answer: "" + MathPiper: (3*x^2-1)/(x*(2*x+1)) + Maxima:(%o508) (3*x^2-1)/(2*x^2+x) + + #39 Problem: (a/2+b/3)/((3*a+2*b)/5) Answer: "" + MathPiper: 5/6 + Maxima:(%o509) 5/6 + + #40 Problem: (2/a+3/b)/(5/a+4/b) Answer: "" + MathPiper: (3*a+2*b)/(4*a+5*b) + Maxima:(%o510) (2*b+3*a)/(5*b+4*a) +. %/output + + + + + + +%mathpiper +Echo("pp.130. Problems 27-40: Perform the following calculations. Express results in lowest terms. In exercises in which letter symbols appear, tell what values of the letter symbols must be excluded. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded."); +NewLine(); + + +equations1 := { +{"((1/2)+(1/3))/((1/4)+(1/5))",""}, +{"((1/x)+(1/y))/((2/x)+(2/y))",""}, +{"(8+(2/3))*(2/3)",""}, +{"(4+(1/3))+(6+(1/2))",""}, +{"(2+(1/2))/(5+(1/3))",""}, +{"(6+(1/2))+(14+(1/3))",""},//32. +{"(4+(2/7))/(3+(1/3))",""}, +{"(4+(2/7))*(3+(1/3))",""}, +{"((1/x)+3)/(4+(2/x))",""}, +{"((x+y)/4)/((2*x+2*y)/8)",""},//36. +{"((1+x)/3)/((3+3*x)/7)",""}, +{"(3-(1/x^2))/(2+(1/x))",""}, +{"((a/2)+(b/3))/((3*a+2*b)/5)",""}, +{"((2/a)+(3/b))/((5/a)+(4/b))",""}, + +}; + +count := 27; +ForEach(e,equations1) +[ + If(IsList(e), [answer := e[2]; e := e[1];]); + + + Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); + + //Echo(PrettyForm(e)); + + Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); + + me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; + Echo("Maxima:",Maxima(me)); + + count := count + 1; + +]; + +count - 1; + +%/mathpiper + + %output,preserve="false" + Result: 40 + + Side Effects: + pp.130. Problems 27-40: Perform the following calculations. Express results in lowest terms. In exercises in which letter symbols appear, tell what values of the letter symbols must be excluded. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded. + + #27 Problem: ((1/2)+(1/3))/((1/4)+(1/5)) Answer: "" + MathPiper: 50/27 + Maxima:(%o511) 50/27 + + #28 Problem: ((1/x)+(1/y))/((2/x)+(2/y)) Answer: "" + MathPiper: 1/2 + Maxima:(%o512) 1/2 + + #29 Problem: (8+(2/3))*(2/3) Answer: "" + MathPiper: 52/9 + Maxima:(%o513) 52/9 + + #30 Problem: (4+(1/3))+(6+(1/2)) Answer: "" + MathPiper: 65/6 + Maxima:(%o514) 65/6 + + #31 Problem: (2+(1/2))/(5+(1/3)) Answer: "" + MathPiper: 15/32 + Maxima:(%o515) 15/32 + + #32 Problem: (6+(1/2))+(14+(1/3)) Answer: "" + MathPiper: 125/6 + Maxima:(%o516) 125/6 + + #33 Problem: (4+(2/7))/(3+(1/3)) Answer: "" + MathPiper: 9/7 + Maxima:(%o517) 9/7 + + #34 Problem: (4+(2/7))*(3+(1/3)) Answer: "" + MathPiper: 100/7 + Maxima:(%o518) 100/7 + + #35 Problem: ((1/x)+3)/(4+(2/x)) Answer: "" + MathPiper: (3*x+1)/(2*(2*x+1)) + Maxima:(%o519) (3*x+1)/(4*x+2) + + #36 Problem: ((x+y)/4)/((2*x+2*y)/8) Answer: "" + MathPiper: 1 + Maxima:(%o520) 1 + + #37 Problem: ((1+x)/3)/((3+3*x)/7) Answer: "" + MathPiper: 7/9 + Maxima:(%o521) 7/9 + + #38 Problem: (3-(1/x^2))/(2+(1/x)) Answer: "" + MathPiper: (3*x^2-1)/(x*(2*x+1)) + Maxima:(%o522) (3*x^2-1)/(2*x^2+x) + + #39 Problem: ((a/2)+(b/3))/((3*a+2*b)/5) Answer: "" + MathPiper: 5/6 + Maxima:(%o523) 5/6 + + #40 Problem: ((2/a)+(3/b))/((5/a)+(4/b)) Answer: "" + MathPiper: (3*a+2*b)/(4*a+5*b) + Maxima:(%o524) (2*b+3*a)/(5*b+4*a) +. %/output + + + + + + + + +%mathpiper +Echo("pp.130. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded."); +NewLine(); + + +equations1 := { +{"(4/(2*x))-((3*x)/5)+(6/x)",""}, +{"(8/(x+3))+5+(3/7)",""}, +{"(2/(y+2))-(3/(y+2))",""}, +{"(3/(2*x-1))+4-(x/(1-2*x))",""}, +{"((6*a)/(2*a-3))-(9/(2*a-3))",""}, +{"((a*x)/(x+a))*((x+a)/(x*a))",""}, +{"((m-4)/12)*(18/(m^2-4*m))",""},//47 +{"((x*y-x)/y)/((a*y-a)/(y^2))",""}, +{"((2*a-b)/(a+b))-((2*a-2*b)/(a+b))",""}, +{"((2*a)/(a-b))+(a/(b-a))",""}, +{"(b/(3*a))-((a-1)/(5*b))",""}, +{"((a*b+a*c)/(b*m+b*n))/((b+c)/(m+n))",""},//52. +{"((2*x+8)/(3*x-9))*(3/(x+4))",""}, +{"((x^2+y^2)/(m+n))-((x^2-y^2)/(m+n))",""}, +{"(1/2)-((a-1)/a)+((a-2)/a^2)",""}, +{"((3/(x-4)))-(4/(x-4))",""}, +{"(7/(a-b))-(5/(b-a))",""}, +{"((2*x))",""}, +}; + +count := 41; +ForEach(e,equations1) +[ + If(IsList(e), [answer := e[2]; e := e[1];]); + + + Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); + + //Echo(PrettyForm(e)); + + Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); + + me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; + Echo("Maxima:",Maxima(me)); + + count := count + 1; + +]; + +count - 1; + +%/mathpiper + + %output,preserve="false" + Result: 58 + + Side Effects: + pp.130. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded. + + #41 Problem: (4/(2*x))-((3*x)/5)+(6/x) Answer: "" + MathPiper: (40*x-3*x^3)/(5*x^2) + Maxima:(%o525) -(3*x^2-40)/(5*x) + + #42 Problem: (8/(x+3))+5+(3/7) Answer: "" + MathPiper: (2*(19*x+85))/(7*(x+3)) + Maxima:(%o526) (38*x+170)/(7*x+21) + + #43 Problem: (2/(y+2))-(3/(y+2)) Answer: "" + MathPiper: (-(y+2))/(y^2+4*y+4) + Maxima:(%o527) -1/(y+2) + + #44 Problem: (3/(2*x-1))+4-(x/(1-2*x)) Answer: "" + MathPiper: (11*x-18*x^2-1)/(4*x-4*x^2-1) + Maxima:(%o528) (9*x-1)/(2*x-1) + + #45 Problem: ((6*a)/(2*a-3))-(9/(2*a-3)) Answer: "" + MathPiper: 3 + Maxima:(%o529) 3 + + #46 Problem: ((a*x)/(x+a))*((x+a)/(x*a)) Answer: "" + MathPiper: 1 + Maxima:(%o530) 1 + + #47 Problem: ((m-4)/12)*(18/(m^2-4*m)) Answer: "" + MathPiper: 3/(2*m) + Maxima:(%o531) 3/(2*m) + + #48 Problem: ((x*y-x)/y)/((a*y-a)/(y^2)) Answer: "" + MathPiper: (x*y)/a + Maxima:(%o532) x*y/a + + #49 Problem: ((2*a-b)/(a+b))-((2*a-2*b)/(a+b)) Answer: "" + MathPiper: (a*b+b^2)/(a^2+2*a*b+b^2) + Maxima:(%o533) b/(b+a) + + #50 Problem: ((2*a)/(a-b))+(a/(b-a)) Answer: "" + MathPiper: (a*b-a^2)/(2*a*b-a^2-b^2) + Maxima:(%o534) -a/(b-a) + + #51 Problem: (b/(3*a))-((a-1)/(5*b)) Answer: "" + MathPiper: (5*b^2+3*a-3*a^2)/(15*b*a) + Maxima:(%o535) (5*b^2-3*a^2+3*a)/(15*a*b) + + #52 Problem: ((a*b+a*c)/(b*m+b*n))/((b+c)/(m+n)) Answer: "" + MathPiper: a/b + Maxima:(%o536) a/b + + #53 Problem: ((2*x+8)/(3*x-9))*(3/(x+4)) Answer: "" + MathPiper: (2*(x+4))/(x^2+x-12) + Maxima:(%o537) 2/(x-3) + + #54 Problem: ((x^2+y^2)/(m+n))-((x^2-y^2)/(m+n)) Answer: "" + MathPiper: (2*y^2*m+2*y^2*n)/(m^2+2*m*n+n^2) + Maxima:(%o538) 2*y^2/(n+m) + + #55 Problem: (1/2)-((a-1)/a)+((a-2)/a^2) Answer: "" + MathPiper: (4*a^2-a^3-4*a)/(2*a^3) + Maxima:(%o539) -(a^2-4*a+4)/(2*a^2) + + #56 Problem: ((3/(x-4)))-(4/(x-4)) Answer: "" + MathPiper: (4-x)/(x^2-8*x+16) + Maxima:(%o540) -1/(x-4) + + #57 Problem: (7/(a-b))-(5/(b-a)) Answer: "" + MathPiper: (12*(b-a))/(2*a*b-a^2-b^2) + Maxima:(%o541) -12/(b-a) + + #58 Problem: ((2*x)) Answer: "" + MathPiper: 2*x + Maxima:(%o542) 2*x +. %/output + + + + + + + + + + + + +%mathpiper +//Manipulating symbolic equations. + +z := a*b==c; +z+5; +z-5; +z*2; +z/6; +z^2; +Sqrt(z); + +//Implement symbolic arithmetic so that m := 144 == 20 * a + b; n := 136 == 10 * a + b;c := m-n; works. +%/mathpiper diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/high_school_tests.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/high_school_tests.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/high_school_tests.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/high_school_tests.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,998 +0,0 @@ - - -%mathpiper -Echo("pp.100. Express the following in lowest terms. The letter symbols that appear represent positive integers."); -NewLine(); - - -equations1 := { -{"18/48","3/8"}, -"85/100", -{"56/-12","-14/3"}, -"-91/49", -{"(32*a^2)/(16*a)","2*a"}, -"(45*x^3*y)/(-15*y^2)", -{"(a*b*c)/(c*d)","a*b/d"}, -"(2*x + 2)/(x + 1)", -{"(2*a - 1)/(b - 2*a*b)","-1/b"}, -"(a*b)/(b*a)", -{"(6*a + 4)/(12*a)","(3*a+2)/(6*a)"}, -"(a + 1)/(a*b + b)", -{"(14 - 7*x)/(21)","(2-x)/3"}, -"(3*x - x^2)/(x^2 - x)",//x is not equal to 1. -{"(a^2 + 7*a)/(a^2)","(a+7)/a"}, -"(x^2 - 3*x)/(6*x - 2*x^2)",//x is not equal to 3. -{"(5*a^2 - a)/(5*a - 1)","a"}, -"(10*a^2 - 2*a)/(10*a^2 + 2*a)", -}; - -count := 1; -ForEach(e,equations1) -[ - If(IsList(e), [answer := e[2]; e := e[1];]); - - - Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); - - //Echo(PrettyForm(e)); - - - Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); - - me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; - Echo("Maxima:",Maxima(me)); - - count := count + 1; - -]; - -count - 1; - -%/mathpiper - - %output,preserve="false" - Result: 18 - - Side Effects: - pp.100. Express the following in lowest terms. The letter symbols that appear represent positive integers. - - #1 Problem: 18/48 Answer: "3/8" - MathPiper: 3/8 - Maxima:(%o543) 3/8 - - #2 Problem: 85/100 - MathPiper: 17/20 - Maxima:(%o544) 17/20 - - #3 Problem: 56/-12 Answer: "-14/3" - MathPiper: (-14)/3 - Maxima:(%o545) -14/3 - - #4 Problem: -91/49 - MathPiper: (-13)/7 - Maxima:(%o546) -13/7 - - #5 Problem: (32*a^2)/(16*a) Answer: "2*a" - MathPiper: 2*a - Maxima:(%o547) 2*a - - #6 Problem: (45*x^3*y)/(-15*y^2) - MathPiper: (-3*x^3)/y - Maxima:(%o548) -3*x^3/y - - #7 Problem: (a*b*c)/(c*d) Answer: "a*b/d" - MathPiper: (a*b)/d - Maxima:(%o549) a*b/d - - #8 Problem: (2*x + 2)/(x + 1) - MathPiper: 2 - Maxima:(%o550) 2 - - #9 Problem: (2*a - 1)/(b - 2*a*b) Answer: "-1/b" - MathPiper: (2*a-1)/(b*(1-2*a)) - Maxima:(%o551) -1/b - - #10 Problem: (a*b)/(b*a) - MathPiper: 1 - Maxima:(%o552) 1 - - #11 Problem: (6*a + 4)/(12*a) Answer: "(3*a+2)/(6*a)" - MathPiper: (3*a+2)/(6*a) - Maxima:(%o553) (3*a+2)/(6*a) - - #12 Problem: (a + 1)/(a*b + b) - MathPiper: 1/b - Maxima:(%o554) 1/b - - #13 Problem: (14 - 7*x)/(21) Answer: "(2-x)/3" - MathPiper: (2-x)/3 - Maxima:(%o555) -(x-2)/3 - - #14 Problem: (3*x - x^2)/(x^2 - x) - MathPiper: (3-x)/(x-1) - Maxima:(%o556) -(x-3)/(x-1) - - #15 Problem: (a^2 + 7*a)/(a^2) Answer: "(a+7)/a" - MathPiper: (a+7)/a - Maxima:(%o557) (a+7)/a - - #16 Problem: (x^2 - 3*x)/(6*x - 2*x^2) - MathPiper: (x-3)/(2*(3-x)) - Maxima:(%o558) -1/2 - - #17 Problem: (5*a^2 - a)/(5*a - 1) Answer: "a" - MathPiper: a - Maxima:(%o559) a - - #18 Problem: (10*a^2 - 2*a)/(10*a^2 + 2*a) - MathPiper: (5*a-1)/(5*a+1) - Maxima:(%o560) (5*a-1)/(5*a+1) -. %/output - - - - - - - - -%mathpiper -Echo("pp.105. Perform the following additions. Express each result in lowest terms. The letter symbols that appear represent positive integers."); -NewLine(); - - -equations1 := { -{"2/3 + 5/3","7/3"}, -"1/9 + 4/9 + 5/9", -{"2/7 + 3/7 + 5/7","10/7"}, -"a/y + b/y + c/y", -{"a/x + 3*a/x + 4*a/x","8*a/x"}, -"x/(x+y) + x/(x + y)", -{"a/(a + 1) + 1/(a + 1)","1"}, -"2/3 + 4/5", -{"3 + 7/6 + 2/3","29/6"}, -"y/3 + 2*y/9", -{"3*y + y/5","16*y/5"}, -"x/2 + x/3 + x/4", -{"4/a + 3/(2*a)","11/(2*a)"}, -"1/a + 1/b + 1/c", -{"b*c + 1/c","(b*c^2+1)/c"}, -"x/(x+y) + 7", -{"1/(2*m) + (a + 3)/(4*m)","(a+5)/(4*m)"}, -"9/x^2 + 4/x", -{"a/(x + y) + b/(x + y)","(a+b)/(x+y)"}, -"1/a + 3/(a*b) + 2/b", -{"2*x/a + 3*y/b","(2*b*x+3*a*y)/(a*b)"}, -"2/a + 7/(a*b*c) + 6/c", -}; - -count := 1; -ForEach(e,equations1) -[ - If(IsList(e), [answer := e[2]; e := e[1];]); - - - Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); - - //Echo(PrettyForm(e)); - - Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); - - me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; - Echo("Maxima:",Maxima(me)); - - count := count + 1; - -]; - -count - 1; - -%/mathpiper - - %output,preserve="false" - Result: 22 - - Side Effects: - pp.105. Perform the following additions. Express each result in lowest terms. The letter symbols that appear represent positive integers. - - #1 Problem: 2/3 + 5/3 Answer: "7/3" - MathPiper: 7/3 - Maxima:(%o385) 7/3 - - #2 Problem: 1/9 + 4/9 + 5/9 - MathPiper: 10/9 - Maxima:(%o386) 10/9 - - #3 Problem: 2/7 + 3/7 + 5/7 Answer: "10/7" - MathPiper: 10/7 - Maxima:(%o387) 10/7 - - #4 Problem: a/y + b/y + c/y - MathPiper: (a+b+c)/y - Maxima:(%o388) (c+b+a)/y - - #5 Problem: a/x + 3*a/x + 4*a/x Answer: "8*a/x" - MathPiper: (8*a)/x - Maxima:(%o389) 8*a/x - - #6 Problem: x/(x+y) + x/(x + y) - MathPiper: (2*x)/(x+y) - Maxima:(%o390) 2*x/(y+x) - - #7 Problem: a/(a + 1) + 1/(a + 1) Answer: "1" - MathPiper: 1 - Maxima:(%o391) 1 - - #8 Problem: 2/3 + 4/5 - MathPiper: 22/15 - Maxima:(%o392) 22/15 - - #9 Problem: 3 + 7/6 + 2/3 Answer: "29/6" - MathPiper: 29/6 - Maxima:(%o393) 29/6 - - #10 Problem: y/3 + 2*y/9 - MathPiper: (5*y)/9 - Maxima:(%o394) 5*y/9 - - #11 Problem: 3*y + y/5 Answer: "16*y/5" - MathPiper: (16*y)/5 - Maxima:(%o395) 16*y/5 - - #12 Problem: x/2 + x/3 + x/4 - MathPiper: (13*x)/12 - Maxima:(%o396) 13*x/12 - - #13 Problem: 4/a + 3/(2*a) Answer: "11/(2*a)" - MathPiper: (11*a)/(2*a^2) - Maxima:(%o397) 11/(2*a) - - #14 Problem: 1/a + 1/b + 1/c - MathPiper: (a*b+a*c+b*c)/(a*b*c) - Maxima:(%o398) ((b+a)*c+a*b)/(a*b*c) - - #15 Problem: b*c + 1/c Answer: "(b*c^2+1)/c" - MathPiper: (b*c^2+1)/c - Maxima:(%o399) (b*c^2+1)/c - - #16 Problem: x/(x+y) + 7 - MathPiper: (8*x+7*y)/(x+y) - Maxima:(%o400) (7*y+8*x)/(y+x) - - #17 Problem: 1/(2*m) + (a + 3)/(4*m) Answer: "(a+5)/(4*m)" - MathPiper: (m*a+5*m)/(4*m^2) - Maxima:(%o401) (a+5)/(4*m) - - #18 Problem: 9/x^2 + 4/x - MathPiper: (4*x^2+9*x)/x^3 - Maxima:(%o402) (4*x+9)/x^2 - - #19 Problem: a/(x + y) + b/(x + y) Answer: "(a+b)/(x+y)" - MathPiper: (a+b)/(x+y) - Maxima:(%o403) (b+a)/(y+x) - - #20 Problem: 1/a + 3/(a*b) + 2/b - MathPiper: (2*a^2*b+a*b^2+3*a*b)/(a^2*b^2) - Maxima:(%o404) (b+2*a+3)/(a*b) - - #21 Problem: 2*x/a + 3*y/b Answer: "(2*b*x+3*a*y)/(a*b)" - MathPiper: (2*x*b+3*a*y)/(a*b) - Maxima:(%o405) (3*a*y+2*b*x)/(a*b) - - #22 Problem: 2/a + 7/(a*b*c) + 6/c - MathPiper: (6*a^2*b*c+2*a*b*c^2+7*a*c)/(a^2*b*c^2) - Maxima:(%o406) (2*b*c+6*a*b+7)/(a*b*c) -. %/output - - - - - -%mathpiper -Echo("pp.112. Find the following products. Express each result in lowest terms. The letter symbols represent positive integers."); -NewLine(); - - -equations1 := { -{"3*(4/9)","4/3"}, -{"5*(7/11)",""}, -{"2/3*6","4"}, -{"5/8*4/15",""}, -{"91/119*34/39","2/3"}, -{"a/b*1/a",""}, -{"(3*a)/(2*b)*(5*a^2)/(9*b)","(5*a^3)/(6*b^2)"}, -{"(a/b)*(a/b)",""}, -{"(1/x^2)*(2/3)*(x/4)","1/(6*x)"}, -{"(m^2/n)*(n/m^2)",""}, -{"((a^2+a*x)/3)*(6/(a+x))","2*a"}, -{"((2*x+12)/(x+5))*((3*x+15)/(x+6))",""}, -{"((x + 1)/x)*(x^2/(x^2+x))","1"}, -{"((4*x*y)/(x+3))*((3*x^2+9*x)/(16*y^2))",""}, -{"(2/6)*(1/2)*(3/4)","1/8"}, -{"(a/2)*(4/a^2)*(3/5)",""}, -{"((3*x+12)/x)*(2*x^2/(x+4))","6*x"}, -{"(y^3/(15*x+6))*((5*x+2)/y)",""}, -{"((2*a+b)/(7*a*b))*3*b^2/(4*a+2*b)","(3*b)/(14*a)"}, -{"(5/(a^3+a^2*y))*((a^2+a*y)/25)",""}, -{"((2*a^2+3*a^2)/b)*(b^3/a^2)","5*b^2"}, -{"((4*y+4)/7)*(14/(2*y^2+2*y))",""}, -{"skip",""}, -{"skip",""}, -{"(4*a+4)/4","a+1"}, -{"(2*x+6)/2",""}, -{"(a^2+a)/a","a+1"}, -{"(a*x+a*y)/a",""}, -}; - -count := 1; -ForEach(e,equations1) -[ - If(IsList(e), [answer := e[2]; e := e[1];]); - - - Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); - - //Echo(PrettyForm(e)); - - Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); - - me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; - Echo("Maxima:",Maxima(me)); - - count := count + 1; - -]; - -count - 1; - -%/mathpiper - - %output,preserve="false" - Result: 28 - - Side Effects: - pp.112. Find the following products. Express each result in lowest terms. The letter symbols represent positive integers. - - #1 Problem: 3*(4/9) Answer: "4/3" - MathPiper: 4/3 - Maxima:(%o429) 4/3 - - #2 Problem: 5*(7/11) Answer: "" - MathPiper: 35/11 - Maxima:(%o430) 35/11 - - #3 Problem: 2/3*6 Answer: "4" - MathPiper: 4 - Maxima:(%o431) 4 - - #4 Problem: 5/8*4/15 Answer: "" - MathPiper: 1/6 - Maxima:(%o432) 1/6 - - #5 Problem: 91/119*34/39 Answer: "2/3" - MathPiper: 2/3 - Maxima:(%o433) 2/3 - - #6 Problem: a/b*1/a Answer: "" - MathPiper: 1/b - Maxima:(%o434) 1/b - - #7 Problem: (3*a)/(2*b)*(5*a^2)/(9*b) Answer: "(5*a^3)/(6*b^2)" - MathPiper: (5*a^3)/(6*b^2) - Maxima:(%o435) 5*a^3/(6*b^2) - - #8 Problem: (a/b)*(a/b) Answer: "" - MathPiper: a^2/b^2 - Maxima:(%o436) a^2/b^2 - - #9 Problem: (1/x^2)*(2/3)*(x/4) Answer: "1/(6*x)" - MathPiper: 1/(6*x) - Maxima:(%o437) 1/(6*x) - - #10 Problem: (m^2/n)*(n/m^2) Answer: "" - MathPiper: 1 - Maxima:(%o438) 1 - - #11 Problem: ((a^2+a*x)/3)*(6/(a+x)) Answer: "2*a" - MathPiper: 2*a - Maxima:(%o439) 2*a - - #12 Problem: ((2*x+12)/(x+5))*((3*x+15)/(x+6)) Answer: "" - MathPiper: 6 - Maxima:(%o440) 6 - - #13 Problem: ((x + 1)/x)*(x^2/(x^2+x)) Answer: "1" - MathPiper: 1 - Maxima:(%o441) 1 - - #14 Problem: ((4*x*y)/(x+3))*((3*x^2+9*x)/(16*y^2)) Answer: "" - MathPiper: (3*x^2)/(4*y) - Maxima:(%o442) 3*x^2/(4*y) - - #15 Problem: (2/6)*(1/2)*(3/4) Answer: "1/8" - MathPiper: 1/8 - Maxima:(%o443) 1/8 - - #16 Problem: (a/2)*(4/a^2)*(3/5) Answer: "" - MathPiper: 6/(5*a) - Maxima:(%o444) 6/(5*a) - - #17 Problem: ((3*x+12)/x)*(2*x^2/(x+4)) Answer: "6*x" - MathPiper: 6*x - Maxima:(%o445) 6*x - - #18 Problem: (y^3/(15*x+6))*((5*x+2)/y) Answer: "" - MathPiper: y^2/3 - Maxima:(%o446) y^2/3 - - #19 Problem: ((2*a+b)/(7*a*b))*3*b^2/(4*a+2*b) Answer: "(3*b)/(14*a)" - MathPiper: (3*b)/(14*a) - Maxima:(%o447) 3*b/(14*a) - - #20 Problem: (5/(a^3+a^2*y))*((a^2+a*y)/25) Answer: "" - MathPiper: 1/(5*a) - Maxima:(%o448) 1/(5*a) - - #21 Problem: ((2*a^2+3*a^2)/b)*(b^3/a^2) Answer: "5*b^2" - MathPiper: 5*b^2 - Maxima:(%o449) 5*b^2 - - #22 Problem: ((4*y+4)/7)*(14/(2*y^2+2*y)) Answer: "" - MathPiper: 4/y - Maxima:(%o450) 4/y - - #23 Problem: skip Answer: "" - MathPiper: skip - Maxima:(%o451) skip - - #24 Problem: skip Answer: "" - MathPiper: skip - Maxima:(%o452) skip - - #25 Problem: (4*a+4)/4 Answer: "a+1" - MathPiper: a+1 - Maxima:(%o453) a+1 - - #26 Problem: (2*x+6)/2 Answer: "" - MathPiper: x+3 - Maxima:(%o454) x+3 - - #27 Problem: (a^2+a)/a Answer: "a+1" - MathPiper: a+1 - Maxima:(%o455) a+1 - - #28 Problem: (a*x+a*y)/a Answer: "" - MathPiper: x+y - Maxima:(%o456) y+x -. %/output - - - - - - - - - - - - - - - - - - - -%mathpiper -Echo("pp.130. Problems 1-24: Perform the following divisions. Express results in lowest terms. The letter symbols represent positive integers."); -NewLine(); - - -equations1 := { -{"(7/8)/(2/3)","21/16"}, -{"4/(3/5)",""}, -{"(3/5)/4","3/20"}, -{"(a/b)/a",""}, -{"a/(a/b)","b"}, -{"((x+y)/x)/x",""}, -{"x/((x+y)/x)","x^2/(x+y)"}, -{"(x/y)/(y/x)",""}, -{"(x/(x+y))/(x/y)","y/(x+y)"}, -{"a/(a*b)",""}, -{"(a*b)/a","b"}, -{"(x/2)/((5*x^2)/8)",""}, -{"((a+b)/a)/(b/a)","(a+b)/b"}, -{"((a+b)/a)/(a/b)",""}, -{"((2*a)/(3*b))/((4*a)/27)","9/(2*b)"}, -{"(a/(a+b))/((3*a)/(a*c+b*c))",""}, -{"((5*x+10)/x^2)/(5/x)","(x+2)/x"}, -{"((x*y+x)/(y))/((a*y+a)/(y^2))",""}, -{"(y^2/(15*x+6))/(y/(5*x+2))","y/3"}, -{"((3*x+12)/x)/((x+4)/(2*x^2))",""}, -{"(5/(a^3+a^2*y))/(25/(a^2+a*y))","1/(5*a)"}, -{"((2*a+b)/(7*a*b))/((4*a+2*b)/(3*b^2))",""}, -{"((4*y+4)/7)/((2*y^2+2*y)/14)","4/y"}, -{"((2*a^2+3*a^2)/b)/(a^2/b^3)",""}, -{"skip",""}, -{"skip",""},//26. -{"(1/2+1/3)/(1/4+1/5)",""}, -{"(1/x+1/y)/(2/x+2/y)",""}, -{"(8+3/4)*(2/3)",""}, -{"(4+1/3)*(6+1/2)",""}, -{"(2+1/2)/(5+1/3)",""},//31. -{"(6+1/2)+(14+1/3)",""}, -{"(4+2/7)/(3+1/3)",""}, -{"(4+2/7)*(3+1/3)",""}, -{"(1/x+3)/(4+2/x)",""}, -{"((x+y)/4)/((2*x+2*y)/8)",""},//36. -{"((1+x)/3)/((3+3*x)/7)",""}, -{"(3-1/x^2)/(2+1/x)",""}, -{"(a/2+b/3)/((3*a+2*b)/5)",""}, -{"(2/a+3/b)/(5/a+4/b)",""},//40 - -}; - -count := 1; -ForEach(e,equations1) -[ - If(IsList(e), [answer := e[2]; e := e[1];]); - - - Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); - - //Echo(PrettyForm(e)); - - Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); - - me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; - Echo("Maxima:",Maxima(me)); - - count := count + 1; - -]; - -count - 1; - -%/mathpiper - - %output,preserve="false" - Result: 40 - - Side Effects: - pp.130. Problems 1-24: Perform the following divisions. Express results in lowest terms. The letter symbols represent positive integers. - - #1 Problem: (7/8)/(2/3) Answer: "21/16" - MathPiper: 21/16 - Maxima:(%o471) 21/16 - - #2 Problem: 4/(3/5) Answer: "" - MathPiper: 20/3 - Maxima:(%o472) 20/3 - - #3 Problem: (3/5)/4 Answer: "3/20" - MathPiper: 3/20 - Maxima:(%o473) 3/20 - - #4 Problem: (a/b)/a Answer: "" - MathPiper: 1/b - Maxima:(%o474) 1/b - - #5 Problem: a/(a/b) Answer: "b" - MathPiper: b - Maxima:(%o475) b - - #6 Problem: ((x+y)/x)/x Answer: "" - MathPiper: (x+y)/x^2 - Maxima:(%o476) (y+x)/x^2 - - #7 Problem: x/((x+y)/x) Answer: "x^2/(x+y)" - MathPiper: x^2/(x+y) - Maxima:(%o477) x^2/(y+x) - - #8 Problem: (x/y)/(y/x) Answer: "" - MathPiper: x^2/y^2 - Maxima:(%o478) x^2/y^2 - - #9 Problem: (x/(x+y))/(x/y) Answer: "y/(x+y)" - MathPiper: y/(x+y) - Maxima:(%o479) y/(y+x) - - #10 Problem: a/(a*b) Answer: "" - MathPiper: 1/b - Maxima:(%o480) 1/b - - #11 Problem: (a*b)/a Answer: "b" - MathPiper: b - Maxima:(%o481) b - - #12 Problem: (x/2)/((5*x^2)/8) Answer: "" - MathPiper: 4/(5*x) - Maxima:(%o482) 4/(5*x) - - #13 Problem: ((a+b)/a)/(b/a) Answer: "(a+b)/b" - MathPiper: (a+b)/b - Maxima:(%o483) (b+a)/b - - #14 Problem: ((a+b)/a)/(a/b) Answer: "" - MathPiper: ((a+b)*b)/a^2 - Maxima:(%o484) (b^2+a*b)/a^2 - - #15 Problem: ((2*a)/(3*b))/((4*a)/27) Answer: "9/(2*b)" - MathPiper: 9/(2*b) - Maxima:(%o485) 9/(2*b) - - #16 Problem: (a/(a+b))/((3*a)/(a*c+b*c)) Answer: "" - MathPiper: c/3 - Maxima:(%o486) c/3 - - #17 Problem: ((5*x+10)/x^2)/(5/x) Answer: "(x+2)/x" - MathPiper: (x+2)/x - Maxima:(%o487) (x+2)/x - - #18 Problem: ((x*y+x)/(y))/((a*y+a)/(y^2)) Answer: "" - MathPiper: (x*y)/a - Maxima:(%o488) x*y/a - - #19 Problem: (y^2/(15*x+6))/(y/(5*x+2)) Answer: "y/3" - MathPiper: y/3 - Maxima:(%o489) y/3 - - #20 Problem: ((3*x+12)/x)/((x+4)/(2*x^2)) Answer: "" - MathPiper: 6*x - Maxima:(%o490) 6*x - - #21 Problem: (5/(a^3+a^2*y))/(25/(a^2+a*y)) Answer: "1/(5*a)" - MathPiper: 1/(5*a) - Maxima:(%o491) 1/(5*a) - - #22 Problem: ((2*a+b)/(7*a*b))/((4*a+2*b)/(3*b^2)) Answer: "" - MathPiper: (3*b)/(14*a) - Maxima:(%o492) 3*b/(14*a) - - #23 Problem: ((4*y+4)/7)/((2*y^2+2*y)/14) Answer: "4/y" - MathPiper: 4/y - Maxima:(%o493) 4/y - - #24 Problem: ((2*a^2+3*a^2)/b)/(a^2/b^3) Answer: "" - MathPiper: 5*b^2 - Maxima:(%o494) 5*b^2 - - #25 Problem: skip Answer: "" - MathPiper: skip - Maxima:(%o495) skip - - #26 Problem: skip Answer: "" - MathPiper: skip - Maxima:(%o496) skip - - #27 Problem: (1/2+1/3)/(1/4+1/5) Answer: "" - MathPiper: 50/27 - Maxima:(%o497) 50/27 - - #28 Problem: (1/x+1/y)/(2/x+2/y) Answer: "" - MathPiper: 1/2 - Maxima:(%o498) 1/2 - - #29 Problem: (8+3/4)*(2/3) Answer: "" - MathPiper: 35/6 - Maxima:(%o499) 35/6 - - #30 Problem: (4+1/3)*(6+1/2) Answer: "" - MathPiper: 169/6 - Maxima:(%o500) 169/6 - - #31 Problem: (2+1/2)/(5+1/3) Answer: "" - MathPiper: 15/32 - Maxima:(%o501) 15/32 - - #32 Problem: (6+1/2)+(14+1/3) Answer: "" - MathPiper: 125/6 - Maxima:(%o502) 125/6 - - #33 Problem: (4+2/7)/(3+1/3) Answer: "" - MathPiper: 9/7 - Maxima:(%o503) 9/7 - - #34 Problem: (4+2/7)*(3+1/3) Answer: "" - MathPiper: 100/7 - Maxima:(%o504) 100/7 - - #35 Problem: (1/x+3)/(4+2/x) Answer: "" - MathPiper: (3*x+1)/(2*(2*x+1)) - Maxima:(%o505) (3*x+1)/(4*x+2) - - #36 Problem: ((x+y)/4)/((2*x+2*y)/8) Answer: "" - MathPiper: 1 - Maxima:(%o506) 1 - - #37 Problem: ((1+x)/3)/((3+3*x)/7) Answer: "" - MathPiper: 7/9 - Maxima:(%o507) 7/9 - - #38 Problem: (3-1/x^2)/(2+1/x) Answer: "" - MathPiper: (3*x^2-1)/(x*(2*x+1)) - Maxima:(%o508) (3*x^2-1)/(2*x^2+x) - - #39 Problem: (a/2+b/3)/((3*a+2*b)/5) Answer: "" - MathPiper: 5/6 - Maxima:(%o509) 5/6 - - #40 Problem: (2/a+3/b)/(5/a+4/b) Answer: "" - MathPiper: (3*a+2*b)/(4*a+5*b) - Maxima:(%o510) (2*b+3*a)/(5*b+4*a) -. %/output - - - - - - -%mathpiper -Echo("pp.130. Problems 27-40: Perform the following calculations. Express results in lowest terms. In exercises in which letter symbols appear, tell what values of the letter symbols must be excluded. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded."); -NewLine(); - - -equations1 := { -{"((1/2)+(1/3))/((1/4)+(1/5))",""}, -{"((1/x)+(1/y))/((2/x)+(2/y))",""}, -{"(8+(2/3))*(2/3)",""}, -{"(4+(1/3))+(6+(1/2))",""}, -{"(2+(1/2))/(5+(1/3))",""}, -{"(6+(1/2))+(14+(1/3))",""},//32. -{"(4+(2/7))/(3+(1/3))",""}, -{"(4+(2/7))*(3+(1/3))",""}, -{"((1/x)+3)/(4+(2/x))",""}, -{"((x+y)/4)/((2*x+2*y)/8)",""},//36. -{"((1+x)/3)/((3+3*x)/7)",""}, -{"(3-(1/x^2))/(2+(1/x))",""}, -{"((a/2)+(b/3))/((3*a+2*b)/5)",""}, -{"((2/a)+(3/b))/((5/a)+(4/b))",""}, - -}; - -count := 27; -ForEach(e,equations1) -[ - If(IsList(e), [answer := e[2]; e := e[1];]); - - - Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); - - //Echo(PrettyForm(e)); - - Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); - - me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; - Echo("Maxima:",Maxima(me)); - - count := count + 1; - -]; - -count - 1; - -%/mathpiper - - %output,preserve="false" - Result: 40 - - Side Effects: - pp.130. Problems 27-40: Perform the following calculations. Express results in lowest terms. In exercises in which letter symbols appear, tell what values of the letter symbols must be excluded. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded. - - #27 Problem: ((1/2)+(1/3))/((1/4)+(1/5)) Answer: "" - MathPiper: 50/27 - Maxima:(%o511) 50/27 - - #28 Problem: ((1/x)+(1/y))/((2/x)+(2/y)) Answer: "" - MathPiper: 1/2 - Maxima:(%o512) 1/2 - - #29 Problem: (8+(2/3))*(2/3) Answer: "" - MathPiper: 52/9 - Maxima:(%o513) 52/9 - - #30 Problem: (4+(1/3))+(6+(1/2)) Answer: "" - MathPiper: 65/6 - Maxima:(%o514) 65/6 - - #31 Problem: (2+(1/2))/(5+(1/3)) Answer: "" - MathPiper: 15/32 - Maxima:(%o515) 15/32 - - #32 Problem: (6+(1/2))+(14+(1/3)) Answer: "" - MathPiper: 125/6 - Maxima:(%o516) 125/6 - - #33 Problem: (4+(2/7))/(3+(1/3)) Answer: "" - MathPiper: 9/7 - Maxima:(%o517) 9/7 - - #34 Problem: (4+(2/7))*(3+(1/3)) Answer: "" - MathPiper: 100/7 - Maxima:(%o518) 100/7 - - #35 Problem: ((1/x)+3)/(4+(2/x)) Answer: "" - MathPiper: (3*x+1)/(2*(2*x+1)) - Maxima:(%o519) (3*x+1)/(4*x+2) - - #36 Problem: ((x+y)/4)/((2*x+2*y)/8) Answer: "" - MathPiper: 1 - Maxima:(%o520) 1 - - #37 Problem: ((1+x)/3)/((3+3*x)/7) Answer: "" - MathPiper: 7/9 - Maxima:(%o521) 7/9 - - #38 Problem: (3-(1/x^2))/(2+(1/x)) Answer: "" - MathPiper: (3*x^2-1)/(x*(2*x+1)) - Maxima:(%o522) (3*x^2-1)/(2*x^2+x) - - #39 Problem: ((a/2)+(b/3))/((3*a+2*b)/5) Answer: "" - MathPiper: 5/6 - Maxima:(%o523) 5/6 - - #40 Problem: ((2/a)+(3/b))/((5/a)+(4/b)) Answer: "" - MathPiper: (3*a+2*b)/(4*a+5*b) - Maxima:(%o524) (2*b+3*a)/(5*b+4*a) -. %/output - - - - - - - - -%mathpiper -Echo("pp.130. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded."); -NewLine(); - - -equations1 := { -{"(4/(2*x))-((3*x)/5)+(6/x)",""}, -{"(8/(x+3))+5+(3/7)",""}, -{"(2/(y+2))-(3/(y+2))",""}, -{"(3/(2*x-1))+4-(x/(1-2*x))",""}, -{"((6*a)/(2*a-3))-(9/(2*a-3))",""}, -{"((a*x)/(x+a))*((x+a)/(x*a))",""}, -{"((m-4)/12)*(18/(m^2-4*m))",""},//47 -{"((x*y-x)/y)/((a*y-a)/(y^2))",""}, -{"((2*a-b)/(a+b))-((2*a-2*b)/(a+b))",""}, -{"((2*a)/(a-b))+(a/(b-a))",""}, -{"(b/(3*a))-((a-1)/(5*b))",""}, -{"((a*b+a*c)/(b*m+b*n))/((b+c)/(m+n))",""},//52. -{"((2*x+8)/(3*x-9))*(3/(x+4))",""}, -{"((x^2+y^2)/(m+n))-((x^2-y^2)/(m+n))",""}, -{"(1/2)-((a-1)/a)+((a-2)/a^2)",""}, -{"((3/(x-4)))-(4/(x-4))",""}, -{"(7/(a-b))-(5/(b-a))",""}, -{"((2*x))",""}, -}; - -count := 41; -ForEach(e,equations1) -[ - If(IsList(e), [answer := e[2]; e := e[1];]); - - - Echo("#",count ,"Problem: ",e, If(IsBound(answer),ToString()[WriteString(" Answer: " );Write(answer);Clear(answer);],"") ); - - //Echo(PrettyForm(e)); - - Echo("MathPiper: ",Simplify(Eval(FromString(e:";") Read()))); - - me := ToString()[WriteString("ratsimp(");Write(Atom(e));WriteString(")");]; - Echo("Maxima:",Maxima(me)); - - count := count + 1; - -]; - -count - 1; - -%/mathpiper - - %output,preserve="false" - Result: 58 - - Side Effects: - pp.130. Problems 41-63: Combine the following expressions into a single fraction in lowest terms. Indicate the values of the letter symbols which must be excluded. - - #41 Problem: (4/(2*x))-((3*x)/5)+(6/x) Answer: "" - MathPiper: (40*x-3*x^3)/(5*x^2) - Maxima:(%o525) -(3*x^2-40)/(5*x) - - #42 Problem: (8/(x+3))+5+(3/7) Answer: "" - MathPiper: (2*(19*x+85))/(7*(x+3)) - Maxima:(%o526) (38*x+170)/(7*x+21) - - #43 Problem: (2/(y+2))-(3/(y+2)) Answer: "" - MathPiper: (-(y+2))/(y^2+4*y+4) - Maxima:(%o527) -1/(y+2) - - #44 Problem: (3/(2*x-1))+4-(x/(1-2*x)) Answer: "" - MathPiper: (11*x-18*x^2-1)/(4*x-4*x^2-1) - Maxima:(%o528) (9*x-1)/(2*x-1) - - #45 Problem: ((6*a)/(2*a-3))-(9/(2*a-3)) Answer: "" - MathPiper: 3 - Maxima:(%o529) 3 - - #46 Problem: ((a*x)/(x+a))*((x+a)/(x*a)) Answer: "" - MathPiper: 1 - Maxima:(%o530) 1 - - #47 Problem: ((m-4)/12)*(18/(m^2-4*m)) Answer: "" - MathPiper: 3/(2*m) - Maxima:(%o531) 3/(2*m) - - #48 Problem: ((x*y-x)/y)/((a*y-a)/(y^2)) Answer: "" - MathPiper: (x*y)/a - Maxima:(%o532) x*y/a - - #49 Problem: ((2*a-b)/(a+b))-((2*a-2*b)/(a+b)) Answer: "" - MathPiper: (a*b+b^2)/(a^2+2*a*b+b^2) - Maxima:(%o533) b/(b+a) - - #50 Problem: ((2*a)/(a-b))+(a/(b-a)) Answer: "" - MathPiper: (a*b-a^2)/(2*a*b-a^2-b^2) - Maxima:(%o534) -a/(b-a) - - #51 Problem: (b/(3*a))-((a-1)/(5*b)) Answer: "" - MathPiper: (5*b^2+3*a-3*a^2)/(15*b*a) - Maxima:(%o535) (5*b^2-3*a^2+3*a)/(15*a*b) - - #52 Problem: ((a*b+a*c)/(b*m+b*n))/((b+c)/(m+n)) Answer: "" - MathPiper: a/b - Maxima:(%o536) a/b - - #53 Problem: ((2*x+8)/(3*x-9))*(3/(x+4)) Answer: "" - MathPiper: (2*(x+4))/(x^2+x-12) - Maxima:(%o537) 2/(x-3) - - #54 Problem: ((x^2+y^2)/(m+n))-((x^2-y^2)/(m+n)) Answer: "" - MathPiper: (2*y^2*m+2*y^2*n)/(m^2+2*m*n+n^2) - Maxima:(%o538) 2*y^2/(n+m) - - #55 Problem: (1/2)-((a-1)/a)+((a-2)/a^2) Answer: "" - MathPiper: (4*a^2-a^3-4*a)/(2*a^3) - Maxima:(%o539) -(a^2-4*a+4)/(2*a^2) - - #56 Problem: ((3/(x-4)))-(4/(x-4)) Answer: "" - MathPiper: (4-x)/(x^2-8*x+16) - Maxima:(%o540) -1/(x-4) - - #57 Problem: (7/(a-b))-(5/(b-a)) Answer: "" - MathPiper: (12*(b-a))/(2*a*b-a^2-b^2) - Maxima:(%o541) -12/(b-a) - - #58 Problem: ((2*x)) Answer: "" - MathPiper: 2*x - Maxima:(%o542) 2*x -. %/output - - - - - - - - - - - - -%mathpiper -//Manipulating symbolic equations. - -z := a*b==c; -z+5; -z-5; -z*2; -z/6; -z^2; -Sqrt(z); - -//Implement symbolic arithmetic so that m := 144 == 20 * a + b; n := 136 == 10 * a + b;c := m-n; works. -%/mathpiper diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/jas.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/jas.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/jas.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/jas.mpw 2010-05-05 07:07:01.000000000 +0000 @@ -0,0 +1,40 @@ +%mathpiper,title="" + +/* +I renamed your program JasAccess so that it can be used as the +primary class which MathPiper will use to access JAS (for now, +at least.). +*/ + +jas := JavaNew("org.mathpiper.builtin.library.jas.JasAccess"); + +//Note: debug output is sent to the Activity Log. +JavaCall(jas,"setDebug",True); + +resultSet := JavaCall(jas,"factorPolyInt","x**2-9", "x"); + +iterator := JavaCall(resultSet,"iterator"); + +While(JavaValue(JavaCall(iterator,"hasNext")) = True) +[ + entrySet := JavaCall(iterator,"next"); + + factor := JavaValue(JavaCall(entrySet,"getKey")); + + multiplicity := JavaValue(JavaCall(entrySet,"getValue")); + + Echo(factor, multiplicity); +]; + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + x - 3 1 + x + 3 1 + +. %/output + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/local_pattern_matching.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/local_pattern_matching.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/local_pattern_matching.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/local_pattern_matching.mpw 2010-07-13 20:51:29.000000000 +0000 @@ -0,0 +1,458 @@ +%mathpiper +E := A(x,y) + B(x,y,z); +F := Deriv(z) E; +Echo("F: ",F); +G := ( F /: { (Deriv(_var)(_w))_(IsFreeOf(var,w)) <- 0 } ); + +//G := ( (Deriv(z)A(x,y)) /: {(Deriv(_var)(_w))_(IsFreeOf(var,w)) <- Echo("KALI ",,,var,,,w)} ); +//G := ( (Deriv(z)A(x,y)) /: {(Deriv(_var)(_w)) <- Echo("KALI ",,,var,,,w)} ); + // (Deriv(_var)(_x / _y))_(IsFreeOf(var,y)) <-- (Deriv(var) x) / y; +//WriteString("E = "); Echo(E); +//WriteString("F = "); Echo(F); +WriteString("G = "); Echo(G); + +/*1 # (Deriv(_var)(_w))_(IsFreeOf(var,w)) <-- 0; +G := Eval(F) ; +WriteString("G = "); Echo(G);NewLine(); +*/ + + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + F: (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) + G = 0+(Deriv(z)B(x,y,z)) +. %/output + + + F: (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) + G = (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) + + F: (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) + G = 0+(Deriv(z)B(x,y,z)) + G = Deriv(z)B(x,y,z) + + + + + +%mathpiper +(b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)}; +%/mathpiper + + + + + + +%mathpiper,output="trace" + +//(b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)}; + +Retract("LocProcessSingle",*); + +40 # LocProcessSingle(pat_IsFunction <- _exp) <-- +[ + Local(justPattern, postPredicate); + + If(Type(pat) = "_", + [ + justPattern := pat[1]; + postPredicate := pat[2]; + ], + [ + justPattern := pat; + postPredicate := True; + ] + ); + + { {justPattern[0],PatternCreate(justPattern,postPredicate)},exp }; +]; + + +//TraceExcept("MacroLocal,ApplyPure,Apply,MapSingle,+,ForEach,*,++,>=,<=,:=,IsUniVar,IsNumber,IsNegativeNumber,For,IsInfinity,IsMatrix,IsNonObject,SubtractN,-,MathSign,IsGeneric,Or,IsString,AbsN,UnFence,LocalSymbols,GreaterThan,Retract,=,UnList,Hold,Equals,IsFunction,Listify,Head,Nth,MathNth,Type,Prog,And,NotEquals,Local,Tail,DefLoadFunction,Not,IsInteger,Set,String,Length,If,List,MakeVector,IsList,LessThan,While,DestructiveReverse,MacroSet,Eval,DestructiveInsert,AddN,IsAtom,Atom,ConcatStrings", (b + c) * (d + e) /: {(x_IsAtom + _y)_(IsZero(0)) <- Echo(x,,,y)} ); + + +%/mathpiper + + %mathpiper_trace,preserve="false" + Result: True +. %/mathpiper_trace + + + + + + + +%mathpiper,output="trace" + +//(b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)}; + +Retract("LocProcessSingle",*); + +40 # LocProcessSingle(pat_IsFunction <- _exp) <-- +[ + { {pat[0],PatternCreate(pat,True)},exp }; +]; + +//10 # LocProcessSingle({_pat,_post,_exp}) <-- { {pat[0],PatternCreate(pat,post)},exp }; + +//20 # LocProcessSingle({pat_IsFunction,_exp}) <-- { {pat[0],PatternCreate(pat,True)},exp }; + +//30 # LocProcessSingle({pat_IsAtom,_exp}) <-- { pat,exp }; + +//50 # LocProcessSingle(pat_IsAtom <- _exp) <-- { pat,exp }; + +TraceExcept("MacroLocal,ApplyPure,Apply,MapSingle,+,ForEach,*,++,>=,<=,:=,IsUniVar,IsNumber,IsNegativeNumber,For,IsInfinity,IsMatrix,IsNonObject,SubtractN,-,MathSign,IsGeneric,Or,IsString,AbsN,UnFence,LocalSymbols,GreaterThan,Retract,=,UnList,Hold,Equals,IsFunction,Listify,Head,Nth,MathNth,Type,Prog,And,NotEquals,Local,Tail,DefLoadFunction,Not,IsInteger,Set,String,Length,If,List,MakeVector,IsList,LessThan,While,DestructiveReverse,MacroSet,Eval,DestructiveInsert,AddN,IsAtom,Atom,ConcatStrings", (b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)} ); + + +%/mathpiper + + + + + + + +%mathpiper + +E := A(x,y) + B(x,y,z); +F := Deriv(z) E; +G := ( Eval(F) /: { (Deriv(_var)(_w))_(IsFreeOf(var,w)) <- 0 } ); +WriteString("E = "); Echo(E); +WriteString("F = "); Echo(F); +WriteString("G = "); Echo(G); +WriteString("G simplified = "); Echo(Simplify(G)); + +1 # (Deriv(_var)(_w))_(IsFreeOf(var,w)) <-- 0; +G := Eval(F) ; +WriteString("G = "); Echo(G);NewLine(); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + E = A(x,y)+B(x,y,z) + F = Deriv(z)B(x,y,z) + G = Deriv(z)B(x,y,z) + G simplified = Deriv(z)B(x,y,z) + G = Deriv(z)B(x,y,z) +. %/output + + + + + +(x_IsBound + y_IsOdd) <- m1, + (x_IsBound + y_IsEven) <- m3, + + +%mathpiper + +Hold((a + b) * (1 + 2) * (2 + 1) * (1/2 + c) * (3/4 + d) ) /: + { + (x_IsOdd + y_IsEven) <- m1, + (x_IsEven + y_IsOdd) <- m2, + (x_IsRational + y_IsAtom)_(Denominator(x) = 2) <- m3, + }; + +%/mathpiper + + %output,preserve="false" + Result: (a+b)*m1*m2*m3*(3/4+d) +. %/output + + + +%mathpiper + +Hold( (b + c) * (d + 1) * (4 + d) ) /: + { + + (x_IsBound + y_IsBound) <- m2, + + }; + +%/mathpiper + + %output,preserve="false" + Result: m2*m2*m2 +. %/output + + +%mathpiper,output="trace" +//(b + c) * (d + e) /: {(x_IsAtom + y_IsAtom) <- m1}; + +functions := "MacroLocal,ApplyPure,Apply,MapSingle,+,ForEach,*,++,>=,<=,<,:=,IsUniVar,IsNumber,IsNegativeNumber,For,IsInfinity,IsMatrix,IsNonObject,SubtractN,-,MathSign,IsGeneric,Or,IsString,AbsN,UnFence,LocalSymbols,GreaterThan,Retract,=,UnList,Hold,Equals,IsFunction,Listify,Head,Nth,MathNth,Type,Prog,And,NotEquals,Local,Tail,DefLoadFunction,Not,IsInteger,Set,String,Length,If,List,MakeVector,IsList,LessThan,While,DestructiveReverse,MacroSet,Eval,DestructiveInsert,AddN,IsAtom,Atom,ConcatStrings"; +TraceExcept(functions,(b + c) * (d + 1) * (4 + d) /: + { + + (x_IsBound + y_IsBound) <- m2, + + } + ); + +%/mathpiper + + %mathpiper_trace,preserve="false" + Result: m2*m2*m2 + + Side Effects: + Enter<**** user rulebase>{(/:, (b+c)*(d+1)*(4+d)/:{x_IsBound+y_IsBound<-m2}); + Enter<**** user rulebase>{(<-, x_IsBound+y_IsBound<-m2); + Arg(left -> x_IsBound+y_IsBound); + Arg(right -> m2); + Leave<**** user rulebase>}(x_IsBound+y_IsBound<-m2 -> x_IsBound+y_IsBound<-m2, Local variables: right -> m2, left -> (+ (_ x IsBound )(_ y IsBound ))m2, ); + Arg(arg1 -> (b+c)*(d+1)*(d+4)); + Arg(arg2 -> {x_IsBound+y_IsBound<-m2}); + **** Rule in function (/:) matched: Precedence: 10, Parameters: arg1, arg2, Predicates: (Pattern) True, Variables: expression, patterns, Types: Variable, Variable, Body: [ Set(patterns, LocProcess(patterns)); MacroSubstitute(expression, "LocPredicate", "LocChange");] + Enter<**** user rulebase>{(LocProcess, LocProcess(patterns)); + Arg(patterns -> {x_IsBound+y_IsBound<-m2}); + **** Rule in function (LocProcess) matched: Precedence: 1025, Parameters: patterns, Predicates: None., Body: [ MapSingle("LocProcessSingle", patterns);] + Enter<**** user rulebase>{(LocProcessSingle, LocProcessSingle(x_IsBound+y_IsBound<-m2)); + Enter<**** user rulebase>{(<-, x_IsBound+y_IsBound<-m2); + Arg(left -> x_IsBound+y_IsBound); + Arg(right -> m2); + Leave<**** user rulebase>}(x_IsBound+y_IsBound<-m2 -> x_IsBound+y_IsBound<-m2, Local variables: right -> m2, left -> (+ (_ x IsBound )(_ y IsBound ))m2, ); + Arg(arg1 -> x_IsBound+y_IsBound<-m2); + **** Rule in function (LocProcessSingle) matched: Precedence: 40, Parameters: arg1, Predicates: (Pattern) IsFunction(pat), True, Variables: pat, exp, Types: Sublist, Body: [ Local(justPattern, postPredicate); If(Type(pat)="_", [ justPattern:=pat[1]; postPredicate:=pat[2];], [ justPattern:=pat; postPredicate:=True;]); {{justPattern[0], PatternCreate(justPattern, postPredicate)}, exp};] + Enter{(PatternCreate, PatternCreate(justPattern,postPredicate)); + Arg(parameter1 -> x_IsBound+y_IsBound); + Arg(parameter2 -> True); + Leave}(PatternCreate(justPattern,postPredicate) -> Pattern, Local variables: postPredicate -> True, justPattern -> (+ (_ x IsBound )(_ y IsBound )), exp -> m2, pat -> (+ (_ x IsBound )(_ y IsBound ))m2, arg1 -> (<- (+ (_ x IsBound )(_ y IsBound ))m2 ), ); + Leave<**** user rulebase>}(LocProcessSingle(x_IsBound+y_IsBound<-m2) -> {{+,Pattern},m2}, Local variables: exp -> m2, pat -> (+ (_ x IsBound )(_ y IsBound ))m2, arg1 -> (<- (+ (_ x IsBound )(_ y IsBound ))m2 ), ); + Leave<**** user rulebase>}(LocProcess(patterns) -> {{{+,Pattern},m2}}, Local variables: patterns -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), ); + Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(expression,LocPredicate,LocChange)); + Arg(body -> (b+c)*(d+1)*(d+4)); + Arg(predicate -> LocPredicate); + Arg(change -> LocChange); + **** Rule in function (MacroSubstitute) matched: Precedence: 1025, Parameters: body, predicate, change, Predicates: None., Body: [ `MacroSubstitute(Hold(@body));] + Enter{(`, `MacroSubstitute(Hold(@body))); + Arg(parameter1 -> MacroSubstitute(Hold(@body))); + Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold((b+c)*(d+1)*(d+4)))); + Arg(body -> (b+c)*(d+1)*(d+4)); + Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold((b+c)*(d+1)*(d+4)))); + Arg(arg1 -> (b+c)*(d+1)*(d+4)); + **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPatternMatches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {{{+,Pattern},m2}}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); + Leave<**** user rulebase>}(LocPredicate(Hold((b+c)*(d+1)*(d+4))) -> False, Local variables: exp -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> False, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter{(`, `IsFunction(Hold(@body))); + Arg(parameter1 -> IsFunction(Hold(@body))); + Leave}(`IsFunction(Hold(@body)) -> True, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + **** Rule in function (MacroSubstitute) matched: Precedence: 2, Parameters: body, Predicates: `IsFunction(Hold(@body)), Body: [ `ApplyPure("MacroMapArgs", {Hold(Hold(@body)), "MacroSubstitute"});] + Enter{(`, `ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); + Arg(parameter1 -> ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); + Enter{(MacroMapArgs, MacroMapArgs(Hold((b+c)*(d+1)*(d+4)),MacroSubstitute)); + Arg(expr -> Hold((b+c)*(d+1)*(d+4))); + Arg(oper -> MacroSubstitute); + **** Rule in function (MacroMapArgs) matched: Precedence: 1025, Parameters: expr, oper, Predicates: None., Body: [ Local(ex, tl, op); Set(op, @oper); Set(ex, Listify(@expr)); Set(tl, Tail(ex)); UnList(Concat({ex[1]}, `MacroMapSingle(@op, Hold(@tl))));], Substituted Macro Body: [ Local(ex,tl,op); Set(op,"MacroSubstitute"); Set(ex,Listify(Hold((b+c)*(d+1)*(d+4)))); Set(tl,Tail(ex)); UnList(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))));] + Enter{(Concat, Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl)))); + Enter{(`, `MacroMapSingle(@op,Hold(@tl))); + Arg(parameter1 -> MacroMapSingle(@op,Hold(@tl))); + Enter<**** user rulebase>{(MacroMapSingle, MacroMapSingle(MacroSubstitute,Hold({(b+c)*(d+1),d+4}))); + Arg($func15 -> MacroSubstitute); + Arg($list15 -> {(b+c)*(d+1),d+4}); + **** Rule in function (MacroMapSingle) matched: Precedence: 1025, Parameters: $func15, $list15, Predicates: None., Body: [ Local(mapsingleresult); mapsingleresult:={}; ForEach(mapsingleitem, $list15)[ DestructiveInsert(mapsingleresult, 1, `ApplyPure($func15, {Hold(Hold(@mapsingleitem))}));]; DestructiveReverse(mapsingleresult);] + Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold((b+c)*(d+1)))); + Arg(body -> (b+c)*(d+1)); + Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold((b+c)*(d+1)))); + Arg(arg1 -> (b+c)*(d+1)); + **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPatternMatches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {{{+,Pattern},m2}}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); + Leave<**** user rulebase>}(LocPredicate(Hold((b+c)*(d+1))) -> False, Local variables: exp -> (* (+ b c )(+ d 1 )), arg1 -> (* (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> False, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter{(`, `IsFunction(Hold(@body))); + Arg(parameter1 -> IsFunction(Hold(@body))); + Leave}(`IsFunction(Hold(@body)) -> True, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + **** Rule in function (MacroSubstitute) matched: Precedence: 2, Parameters: body, Predicates: `IsFunction(Hold(@body)), Body: [ `ApplyPure("MacroMapArgs", {Hold(Hold(@body)), "MacroSubstitute"});] + Enter{(`, `ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); + Arg(parameter1 -> ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); + Enter{(MacroMapArgs, MacroMapArgs(Hold((b+c)*(d+1)),MacroSubstitute)); + Arg(expr -> Hold((b+c)*(d+1))); + Arg(oper -> MacroSubstitute); + **** Rule in function (MacroMapArgs) matched: Precedence: 1025, Parameters: expr, oper, Predicates: None., Body: [ Local(ex, tl, op); Set(op, @oper); Set(ex, Listify(@expr)); Set(tl, Tail(ex)); UnList(Concat({ex[1]}, `MacroMapSingle(@op, Hold(@tl))));], Substituted Macro Body: [ Local(ex,tl,op); Set(op,"MacroSubstitute"); Set(ex,Listify(Hold((b+c)*(d+1)))); Set(tl,Tail(ex)); UnList(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))));] + Enter{(Concat, Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl)))); + Enter{(`, `MacroMapSingle(@op,Hold(@tl))); + Arg(parameter1 -> MacroMapSingle(@op,Hold(@tl))); + Enter<**** user rulebase>{(MacroMapSingle, MacroMapSingle(MacroSubstitute,Hold({b+c,d+1}))); + Arg($func15 -> MacroSubstitute); + Arg($list15 -> {b+c,d+1}); + **** Rule in function (MacroMapSingle) matched: Precedence: 1025, Parameters: $func15, $list15, Predicates: None., Body: [ Local(mapsingleresult); mapsingleresult:={}; ForEach(mapsingleitem, $list15)[ DestructiveInsert(mapsingleresult, 1, `ApplyPure($func15, {Hold(Hold(@mapsingleitem))}));]; DestructiveReverse(mapsingleresult);] + Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold(b+c))); + Arg(body -> b+c); + Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold(b+c))); + Arg(arg1 -> b+c); + **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPatternMatches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {{{+,Pattern},m2}}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); + Enter{(PatternMatches, PatternMatches(head[2],exp)); + Arg(parameter1 -> Pattern); + Arg(parameter2 -> b+c); + Enter{(IsBound, IsBound(x)); + Arg(parameter1 -> x); + Leave}(IsBound(x) -> True, Local variables: y -> c, x -> b c, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter{(IsBound, IsBound(y)); + Arg(parameter1 -> y); + Leave}(IsBound(y) -> True, Local variables: y -> c, x -> b c, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(PatternMatches(head[2],exp) -> True, Local variables: y -> c, x -> b c, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); + Leave<**** user rulebase>}(LocPredicate(Hold(b+c)) -> True, Local variables: exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> True, Local variables: body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + **** Rule in function (MacroSubstitute) matched: Precedence: 1, Parameters: body, Predicates: `ApplyPure(predicate,{Hold(Hold(@body))})=True, Body: [ `ApplyPure(change, {Hold(Hold(@body))});] + Enter{(`, `ApplyPure(change,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(change,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocChange, LocChange(Hold(b+c))); + Arg(arg1 -> b+c); + **** Rule in function (LocChange) matched: Precedence: 0, Parameters: arg1, Predicates: (Pattern) True, Variables: exp, Types: Variable, Body: $LocResult12 + Leave<**** user rulebase>}(LocChange(Hold(b+c)) -> m2, Local variables: exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(change,{Hold(Hold(@body))}) -> m2, Local variables: body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroSubstitute(Hold(b+c)) -> m2, Local variables: body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2, Local variables: mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold(d+1))); + Arg(body -> d+1); + Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold(d+1))); + Arg(arg1 -> d+1); + **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPatternMatches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {{{+,Pattern},m2}}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); + Enter{(PatternMatches, PatternMatches(head[2],exp)); + Arg(parameter1 -> Pattern); + Arg(parameter2 -> d+1); + Enter{(IsBound, IsBound(x)); + Arg(parameter1 -> x); + Leave}(IsBound(x) -> True, Local variables: y -> 1, x -> d 1, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter{(IsBound, IsBound(y)); + Arg(parameter1 -> y); + Leave}(IsBound(y) -> True, Local variables: y -> 1, x -> d 1, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(PatternMatches(head[2],exp) -> True, Local variables: y -> 1, x -> d 1, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); + Leave<**** user rulebase>}(LocPredicate(Hold(d+1)) -> True, Local variables: exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> True, Local variables: body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + **** Rule in function (MacroSubstitute) matched: Precedence: 1, Parameters: body, Predicates: `ApplyPure(predicate,{Hold(Hold(@body))})=True, Body: [ `ApplyPure(change, {Hold(Hold(@body))});] + Enter{(`, `ApplyPure(change,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(change,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocChange, LocChange(Hold(d+1))); + Arg(arg1 -> d+1); + **** Rule in function (LocChange) matched: Precedence: 0, Parameters: arg1, Predicates: (Pattern) True, Variables: exp, Types: Variable, Body: $LocResult12 + Leave<**** user rulebase>}(LocChange(Hold(d+1)) -> m2, Local variables: exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(change,{Hold(Hold(@body))}) -> m2, Local variables: body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroSubstitute(Hold(d+1)) -> m2, Local variables: body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2, Local variables: mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroMapSingle(MacroSubstitute,Hold({b+c,d+1})) -> {m2,m2}, Local variables: $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`MacroMapSingle(@op,Hold(@tl)) -> {m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Arg(parameter1 -> {ex[1]}); + Arg(parameter2 -> `MacroMapSingle(@op,Hold(@tl))); + Leave}(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))) -> {*,m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(MacroMapArgs(Hold((b+c)*(d+1)),MacroSubstitute) -> m2*m2, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute}) -> m2*m2, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroSubstitute(Hold((b+c)*(d+1))) -> m2*m2, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2*m2, Local variables: mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); + Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold(d+4))); + Arg(body -> d+4); + Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold(d+4))); + Arg(arg1 -> d+4); + **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPatternMatches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {{{+,Pattern},m2}}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); + Enter{(PatternMatches, PatternMatches(head[2],exp)); + Arg(parameter1 -> Pattern); + Arg(parameter2 -> d+4); + Enter{(IsBound, IsBound(x)); + Arg(parameter1 -> x); + Leave}(IsBound(x) -> True, Local variables: y -> 4, x -> d 4, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter{(IsBound, IsBound(y)); + Arg(parameter1 -> y); + Leave}(IsBound(y) -> True, Local variables: y -> 4, x -> d 4, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(PatternMatches(head[2],exp) -> True, Local variables: y -> 4, x -> d 4, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Enter<**** user rulebase>{(!=, tr!={}); + Arg(aLeft -> {}); + Arg(aRight -> {}); + **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight + Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); + Leave<**** user rulebase>}(LocPredicate(Hold(d+4)) -> True, Local variables: exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> True, Local variables: body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + **** Rule in function (MacroSubstitute) matched: Precedence: 1, Parameters: body, Predicates: `ApplyPure(predicate,{Hold(Hold(@body))})=True, Body: [ `ApplyPure(change, {Hold(Hold(@body))});] + Enter{(`, `ApplyPure(change,{Hold(Hold(@body))})); + Arg(parameter1 -> ApplyPure(change,{Hold(Hold(@body))})); + Enter<**** user rulebase>{(LocChange, LocChange(Hold(d+4))); + Arg(arg1 -> d+4); + **** Rule in function (LocChange) matched: Precedence: 0, Parameters: arg1, Predicates: (Pattern) True, Variables: exp, Types: Variable, Body: $LocResult12 + Leave<**** user rulebase>}(LocChange(Hold(d+4)) -> m2, Local variables: exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(change,{Hold(Hold(@body))}) -> m2, Local variables: body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroSubstitute(Hold(d+4)) -> m2, Local variables: body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2, Local variables: mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroMapSingle(MacroSubstitute,Hold({(b+c)*(d+1),d+4})) -> {m2*m2,m2}, Local variables: $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`MacroMapSingle(@op,Hold(@tl)) -> {m2*m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Arg(parameter1 -> {ex[1]}); + Arg(parameter2 -> `MacroMapSingle(@op,Hold(@tl))); + Leave}(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))) -> {*,m2*m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(MacroMapArgs(Hold((b+c)*(d+1)*(d+4)),MacroSubstitute) -> m2*m2*m2, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute}) -> m2*m2*m2, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroSubstitute(Hold((b+c)*(d+1)*(d+4))) -> m2*m2*m2, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave}(`MacroSubstitute(Hold(@body)) -> m2*m2*m2, Local variables: change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}(MacroSubstitute(expression,LocPredicate,LocChange) -> m2*m2*m2, Local variables: change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); + Leave<**** user rulebase>}((b+c)*(d+1)*(4+d)/:{x_IsBound+y_IsBound<-m2} -> m2*m2*m2, Local variables: patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); +. %/mathpiper_trace + + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/local_pattern_matching.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/local_pattern_matching.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/local_pattern_matching.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/local_pattern_matching.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,458 +0,0 @@ -%mathpiper -E := A(x,y) + B(x,y,z); -F := Deriv(z) E; -Echo("F: ",F); -G := ( F /: { (Deriv(_var)(_w))_(IsFreeOf(var,w)) <- 0 } ); - -//G := ( (Deriv(z)A(x,y)) /: {(Deriv(_var)(_w))_(IsFreeOf(var,w)) <- Echo("KALI ",,,var,,,w)} ); -//G := ( (Deriv(z)A(x,y)) /: {(Deriv(_var)(_w)) <- Echo("KALI ",,,var,,,w)} ); - // (Deriv(_var)(_x / _y))_(IsFreeOf(var,y)) <-- (Deriv(var) x) / y; -//WriteString("E = "); Echo(E); -//WriteString("F = "); Echo(F); -WriteString("G = "); Echo(G); - -/*1 # (Deriv(_var)(_w))_(IsFreeOf(var,w)) <-- 0; -G := Eval(F) ; -WriteString("G = "); Echo(G);NewLine(); -*/ - - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - F: (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) - G = 0+(Deriv(z)B(x,y,z)) -. %/output - - - F: (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) - G = (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) - - F: (Deriv(z)A(x,y))+(Deriv(z)B(x,y,z)) - G = 0+(Deriv(z)B(x,y,z)) - G = Deriv(z)B(x,y,z) - - - - - -%mathpiper -(b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)}; -%/mathpiper - - - - - - -%mathpiper,output="trace" - -//(b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)}; - -Retract("LocProcessSingle",*); - -40 # LocProcessSingle(pat_IsFunction <- _exp) <-- -[ - Local(justPattern, postPredicate); - - If(Type(pat) = "_", - [ - justPattern := pat[1]; - postPredicate := pat[2]; - ], - [ - justPattern := pat; - postPredicate := True; - ] - ); - - { {justPattern[0],Pattern'Create(justPattern,postPredicate)},exp }; -]; - - -//TraceExcept("MacroLocal,ApplyPure,Apply,MapSingle,+,ForEach,*,++,>=,<=,:=,IsUniVar,IsNumber,IsNegativeNumber,For,IsInfinity,IsMatrix,IsNonObject,SubtractN,-,MathSign,IsGeneric,Or,IsString,AbsN,UnFence,LocalSymbols,GreaterThan,Retract,=,UnList,Hold,Equals,IsFunction,Listify,Head,Nth,MathNth,Type,Prog,And,NotEquals,Local,Tail,DefLoadFunction,Not,IsInteger,Set,String,Length,If,List,MakeVector,IsList,LessThan,While,DestructiveReverse,MacroSet,Eval,DestructiveInsert,AddN,IsAtom,Atom,ConcatStrings", (b + c) * (d + e) /: {(x_IsAtom + _y)_(IsZero(0)) <- Echo(x,,,y)} ); - - -%/mathpiper - - %mathpiper_trace,preserve="false" - Result: True -. %/mathpiper_trace - - - - - - - -%mathpiper,output="trace" - -//(b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)}; - -Retract("LocProcessSingle",*); - -40 # LocProcessSingle(pat_IsFunction <- _exp) <-- -[ - { {pat[0],Pattern'Create(pat,True)},exp }; -]; - -//10 # LocProcessSingle({_pat,_post,_exp}) <-- { {pat[0],Pattern'Create(pat,post)},exp }; - -//20 # LocProcessSingle({pat_IsFunction,_exp}) <-- { {pat[0],Pattern'Create(pat,True)},exp }; - -//30 # LocProcessSingle({pat_IsAtom,_exp}) <-- { pat,exp }; - -//50 # LocProcessSingle(pat_IsAtom <- _exp) <-- { pat,exp }; - -TraceExcept("MacroLocal,ApplyPure,Apply,MapSingle,+,ForEach,*,++,>=,<=,:=,IsUniVar,IsNumber,IsNegativeNumber,For,IsInfinity,IsMatrix,IsNonObject,SubtractN,-,MathSign,IsGeneric,Or,IsString,AbsN,UnFence,LocalSymbols,GreaterThan,Retract,=,UnList,Hold,Equals,IsFunction,Listify,Head,Nth,MathNth,Type,Prog,And,NotEquals,Local,Tail,DefLoadFunction,Not,IsInteger,Set,String,Length,If,List,MakeVector,IsList,LessThan,While,DestructiveReverse,MacroSet,Eval,DestructiveInsert,AddN,IsAtom,Atom,ConcatStrings", (b + c) * (d + e) /: {(x_IsAtom + _y) <- Echo(x,,,y)} ); - - -%/mathpiper - - - - - - - -%mathpiper - -E := A(x,y) + B(x,y,z); -F := Deriv(z) E; -G := ( Eval(F) /: { (Deriv(_var)(_w))_(IsFreeOf(var,w)) <- 0 } ); -WriteString("E = "); Echo(E); -WriteString("F = "); Echo(F); -WriteString("G = "); Echo(G); -WriteString("G simplified = "); Echo(Simplify(G)); - -1 # (Deriv(_var)(_w))_(IsFreeOf(var,w)) <-- 0; -G := Eval(F) ; -WriteString("G = "); Echo(G);NewLine(); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - E = A(x,y)+B(x,y,z) - F = Deriv(z)B(x,y,z) - G = Deriv(z)B(x,y,z) - G simplified = Deriv(z)B(x,y,z) - G = Deriv(z)B(x,y,z) -. %/output - - - - - -(x_IsBound + y_IsOdd) <- m1, - (x_IsBound + y_IsEven) <- m3, - - -%mathpiper - -Hold((a + b) * (1 + 2) * (2 + 1) * (1/2 + c) * (3/4 + d) ) /: - { - (x_IsOdd + y_IsEven) <- m1, - (x_IsEven + y_IsOdd) <- m2, - (x_IsRational + y_IsAtom)_(Denominator(x) = 2) <- m3, - }; - -%/mathpiper - - %output,preserve="false" - Result: (a+b)*m1*m2*m3*(3/4+d) -. %/output - - - -%mathpiper - -Hold( (b + c) * (d + 1) * (4 + d) ) /: - { - - (x_IsBound + y_IsBound) <- m2, - - }; - -%/mathpiper - - %output,preserve="false" - Result: m2*m2*m2 -. %/output - - -%mathpiper,output="trace" -//(b + c) * (d + e) /: {(x_IsAtom + y_IsAtom) <- m1}; - -functions := "MacroLocal,ApplyPure,Apply,MapSingle,+,ForEach,*,++,>=,<=,<,:=,IsUniVar,IsNumber,IsNegativeNumber,For,IsInfinity,IsMatrix,IsNonObject,SubtractN,-,MathSign,IsGeneric,Or,IsString,AbsN,UnFence,LocalSymbols,GreaterThan,Retract,=,UnList,Hold,Equals,IsFunction,Listify,Head,Nth,MathNth,Type,Prog,And,NotEquals,Local,Tail,DefLoadFunction,Not,IsInteger,Set,String,Length,If,List,MakeVector,IsList,LessThan,While,DestructiveReverse,MacroSet,Eval,DestructiveInsert,AddN,IsAtom,Atom,ConcatStrings"; -TraceExcept(functions,(b + c) * (d + 1) * (4 + d) /: - { - - (x_IsBound + y_IsBound) <- m2, - - } - ); - -%/mathpiper - - %mathpiper_trace,preserve="false" - Result: m2*m2*m2 - - Side Effects: - Enter<**** user rulebase>{(/:, (b+c)*(d+1)*(4+d)/:{x_IsBound+y_IsBound<-m2}); - Enter<**** user rulebase>{(<-, x_IsBound+y_IsBound<-m2); - Arg(left -> x_IsBound+y_IsBound); - Arg(right -> m2); - Leave<**** user rulebase>}(x_IsBound+y_IsBound<-m2 -> x_IsBound+y_IsBound<-m2, Local variables: right -> m2, left -> (+ (_ x IsBound )(_ y IsBound ))m2, ); - Arg(arg1 -> (b+c)*(d+1)*(d+4)); - Arg(arg2 -> {x_IsBound+y_IsBound<-m2}); - **** Rule in function (/:) matched: Precedence: 10, Parameters: arg1, arg2, Predicates: (Pattern) True, Variables: expression, patterns, Types: Variable, Variable, Body: [ Set(patterns, LocProcess(patterns)); MacroSubstitute(expression, "LocPredicate", "LocChange");] - Enter<**** user rulebase>{(LocProcess, LocProcess(patterns)); - Arg(patterns -> {x_IsBound+y_IsBound<-m2}); - **** Rule in function (LocProcess) matched: Precedence: 1025, Parameters: patterns, Predicates: None., Body: [ MapSingle("LocProcessSingle", patterns);] - Enter<**** user rulebase>{(LocProcessSingle, LocProcessSingle(x_IsBound+y_IsBound<-m2)); - Enter<**** user rulebase>{(<-, x_IsBound+y_IsBound<-m2); - Arg(left -> x_IsBound+y_IsBound); - Arg(right -> m2); - Leave<**** user rulebase>}(x_IsBound+y_IsBound<-m2 -> x_IsBound+y_IsBound<-m2, Local variables: right -> m2, left -> (+ (_ x IsBound )(_ y IsBound ))m2, ); - Arg(arg1 -> x_IsBound+y_IsBound<-m2); - **** Rule in function (LocProcessSingle) matched: Precedence: 40, Parameters: arg1, Predicates: (Pattern) IsFunction(pat), True, Variables: pat, exp, Types: Sublist, Body: [ Local(justPattern, postPredicate); If(Type(pat)="_", [ justPattern:=pat[1]; postPredicate:=pat[2];], [ justPattern:=pat; postPredicate:=True;]); {{justPattern[0], Pattern'Create(justPattern, postPredicate)}, exp};] - Enter{(Pattern'Create, Pattern'Create(justPattern,postPredicate)); - Arg(parameter1 -> x_IsBound+y_IsBound); - Arg(parameter2 -> True); - Leave}(Pattern'Create(justPattern,postPredicate) -> Pattern, Local variables: postPredicate -> True, justPattern -> (+ (_ x IsBound )(_ y IsBound )), exp -> m2, pat -> (+ (_ x IsBound )(_ y IsBound ))m2, arg1 -> (<- (+ (_ x IsBound )(_ y IsBound ))m2 ), ); - Leave<**** user rulebase>}(LocProcessSingle(x_IsBound+y_IsBound<-m2) -> {{+,Pattern},m2}, Local variables: exp -> m2, pat -> (+ (_ x IsBound )(_ y IsBound ))m2, arg1 -> (<- (+ (_ x IsBound )(_ y IsBound ))m2 ), ); - Leave<**** user rulebase>}(LocProcess(patterns) -> {{{+,Pattern},m2}}, Local variables: patterns -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), ); - Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(expression,LocPredicate,LocChange)); - Arg(body -> (b+c)*(d+1)*(d+4)); - Arg(predicate -> LocPredicate); - Arg(change -> LocChange); - **** Rule in function (MacroSubstitute) matched: Precedence: 1025, Parameters: body, predicate, change, Predicates: None., Body: [ `MacroSubstitute(Hold(@body));] - Enter{(`, `MacroSubstitute(Hold(@body))); - Arg(parameter1 -> MacroSubstitute(Hold(@body))); - Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold((b+c)*(d+1)*(d+4)))); - Arg(body -> (b+c)*(d+1)*(d+4)); - Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold((b+c)*(d+1)*(d+4)))); - Arg(arg1 -> (b+c)*(d+1)*(d+4)); - **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPattern'Matches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {{{+,Pattern},m2}}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); - Leave<**** user rulebase>}(LocPredicate(Hold((b+c)*(d+1)*(d+4))) -> False, Local variables: exp -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> False, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter{(`, `IsFunction(Hold(@body))); - Arg(parameter1 -> IsFunction(Hold(@body))); - Leave}(`IsFunction(Hold(@body)) -> True, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - **** Rule in function (MacroSubstitute) matched: Precedence: 2, Parameters: body, Predicates: `IsFunction(Hold(@body)), Body: [ `ApplyPure("MacroMapArgs", {Hold(Hold(@body)), "MacroSubstitute"});] - Enter{(`, `ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); - Arg(parameter1 -> ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); - Enter{(MacroMapArgs, MacroMapArgs(Hold((b+c)*(d+1)*(d+4)),MacroSubstitute)); - Arg(expr -> Hold((b+c)*(d+1)*(d+4))); - Arg(oper -> MacroSubstitute); - **** Rule in function (MacroMapArgs) matched: Precedence: 1025, Parameters: expr, oper, Predicates: None., Body: [ Local(ex, tl, op); Set(op, @oper); Set(ex, Listify(@expr)); Set(tl, Tail(ex)); UnList(Concat({ex[1]}, `MacroMapSingle(@op, Hold(@tl))));], Substituted Macro Body: [ Local(ex,tl,op); Set(op,"MacroSubstitute"); Set(ex,Listify(Hold((b+c)*(d+1)*(d+4)))); Set(tl,Tail(ex)); UnList(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))));] - Enter{(Concat, Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl)))); - Enter{(`, `MacroMapSingle(@op,Hold(@tl))); - Arg(parameter1 -> MacroMapSingle(@op,Hold(@tl))); - Enter<**** user rulebase>{(MacroMapSingle, MacroMapSingle(MacroSubstitute,Hold({(b+c)*(d+1),d+4}))); - Arg($func15 -> MacroSubstitute); - Arg($list15 -> {(b+c)*(d+1),d+4}); - **** Rule in function (MacroMapSingle) matched: Precedence: 1025, Parameters: $func15, $list15, Predicates: None., Body: [ Local(mapsingleresult); mapsingleresult:={}; ForEach(mapsingleitem, $list15)[ DestructiveInsert(mapsingleresult, 1, `ApplyPure($func15, {Hold(Hold(@mapsingleitem))}));]; DestructiveReverse(mapsingleresult);] - Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold((b+c)*(d+1)))); - Arg(body -> (b+c)*(d+1)); - Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold((b+c)*(d+1)))); - Arg(arg1 -> (b+c)*(d+1)); - **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPattern'Matches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {{{+,Pattern},m2}}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); - Leave<**** user rulebase>}(LocPredicate(Hold((b+c)*(d+1))) -> False, Local variables: exp -> (* (+ b c )(+ d 1 )), arg1 -> (* (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> False, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter{(`, `IsFunction(Hold(@body))); - Arg(parameter1 -> IsFunction(Hold(@body))); - Leave}(`IsFunction(Hold(@body)) -> True, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - **** Rule in function (MacroSubstitute) matched: Precedence: 2, Parameters: body, Predicates: `IsFunction(Hold(@body)), Body: [ `ApplyPure("MacroMapArgs", {Hold(Hold(@body)), "MacroSubstitute"});] - Enter{(`, `ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); - Arg(parameter1 -> ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute})); - Enter{(MacroMapArgs, MacroMapArgs(Hold((b+c)*(d+1)),MacroSubstitute)); - Arg(expr -> Hold((b+c)*(d+1))); - Arg(oper -> MacroSubstitute); - **** Rule in function (MacroMapArgs) matched: Precedence: 1025, Parameters: expr, oper, Predicates: None., Body: [ Local(ex, tl, op); Set(op, @oper); Set(ex, Listify(@expr)); Set(tl, Tail(ex)); UnList(Concat({ex[1]}, `MacroMapSingle(@op, Hold(@tl))));], Substituted Macro Body: [ Local(ex,tl,op); Set(op,"MacroSubstitute"); Set(ex,Listify(Hold((b+c)*(d+1)))); Set(tl,Tail(ex)); UnList(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))));] - Enter{(Concat, Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl)))); - Enter{(`, `MacroMapSingle(@op,Hold(@tl))); - Arg(parameter1 -> MacroMapSingle(@op,Hold(@tl))); - Enter<**** user rulebase>{(MacroMapSingle, MacroMapSingle(MacroSubstitute,Hold({b+c,d+1}))); - Arg($func15 -> MacroSubstitute); - Arg($list15 -> {b+c,d+1}); - **** Rule in function (MacroMapSingle) matched: Precedence: 1025, Parameters: $func15, $list15, Predicates: None., Body: [ Local(mapsingleresult); mapsingleresult:={}; ForEach(mapsingleitem, $list15)[ DestructiveInsert(mapsingleresult, 1, `ApplyPure($func15, {Hold(Hold(@mapsingleitem))}));]; DestructiveReverse(mapsingleresult);] - Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold(b+c))); - Arg(body -> b+c); - Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold(b+c))); - Arg(arg1 -> b+c); - **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPattern'Matches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {{{+,Pattern},m2}}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); - Enter{(Pattern'Matches, Pattern'Matches(head[2],exp)); - Arg(parameter1 -> Pattern); - Arg(parameter2 -> b+c); - Enter{(IsBound, IsBound(x)); - Arg(parameter1 -> x); - Leave}(IsBound(x) -> True, Local variables: y -> c, x -> b c, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter{(IsBound, IsBound(y)); - Arg(parameter1 -> y); - Leave}(IsBound(y) -> True, Local variables: y -> c, x -> b c, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(Pattern'Matches(head[2],exp) -> True, Local variables: y -> c, x -> b c, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); - Leave<**** user rulebase>}(LocPredicate(Hold(b+c)) -> True, Local variables: exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> True, Local variables: body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - **** Rule in function (MacroSubstitute) matched: Precedence: 1, Parameters: body, Predicates: `ApplyPure(predicate,{Hold(Hold(@body))})=True, Body: [ `ApplyPure(change, {Hold(Hold(@body))});] - Enter{(`, `ApplyPure(change,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(change,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocChange, LocChange(Hold(b+c))); - Arg(arg1 -> b+c); - **** Rule in function (LocChange) matched: Precedence: 0, Parameters: arg1, Predicates: (Pattern) True, Variables: exp, Types: Variable, Body: $LocResult12 - Leave<**** user rulebase>}(LocChange(Hold(b+c)) -> m2, Local variables: exp -> (+ b c ), arg1 -> (+ b c ), body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(change,{Hold(Hold(@body))}) -> m2, Local variables: body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroSubstitute(Hold(b+c)) -> m2, Local variables: body -> (+ b c ), mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2, Local variables: mapsingleitem -> (+ b c ), foreachtail -> (List (+ b c )(+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold(d+1))); - Arg(body -> d+1); - Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold(d+1))); - Arg(arg1 -> d+1); - **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPattern'Matches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {{{+,Pattern},m2}}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); - Enter{(Pattern'Matches, Pattern'Matches(head[2],exp)); - Arg(parameter1 -> Pattern); - Arg(parameter2 -> d+1); - Enter{(IsBound, IsBound(x)); - Arg(parameter1 -> x); - Leave}(IsBound(x) -> True, Local variables: y -> 1, x -> d 1, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter{(IsBound, IsBound(y)); - Arg(parameter1 -> y); - Leave}(IsBound(y) -> True, Local variables: y -> 1, x -> d 1, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(Pattern'Matches(head[2],exp) -> True, Local variables: y -> 1, x -> d 1, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); - Leave<**** user rulebase>}(LocPredicate(Hold(d+1)) -> True, Local variables: exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> True, Local variables: body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - **** Rule in function (MacroSubstitute) matched: Precedence: 1, Parameters: body, Predicates: `ApplyPure(predicate,{Hold(Hold(@body))})=True, Body: [ `ApplyPure(change, {Hold(Hold(@body))});] - Enter{(`, `ApplyPure(change,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(change,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocChange, LocChange(Hold(d+1))); - Arg(arg1 -> d+1); - **** Rule in function (LocChange) matched: Precedence: 0, Parameters: arg1, Predicates: (Pattern) True, Variables: exp, Types: Variable, Body: $LocResult12 - Leave<**** user rulebase>}(LocChange(Hold(d+1)) -> m2, Local variables: exp -> (+ d 1 ), arg1 -> (+ d 1 ), body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(change,{Hold(Hold(@body))}) -> m2, Local variables: body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroSubstitute(Hold(d+1)) -> m2, Local variables: body -> (+ d 1 ), mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2, Local variables: mapsingleitem -> (+ d 1 ), foreachtail -> (List (+ d 1 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (+ b c )(+ d 1 )), $item22 -> mapsingleitem, mapsingleresult -> (List m2 ), $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroMapSingle(MacroSubstitute,Hold({b+c,d+1})) -> {m2,m2}, Local variables: $list15 -> (List (+ b c )(+ d 1 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`MacroMapSingle(@op,Hold(@tl)) -> {m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Arg(parameter1 -> {ex[1]}); - Arg(parameter2 -> `MacroMapSingle(@op,Hold(@tl))); - Leave}(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))) -> {*,m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (+ b c )(+ d 1 )), ex -> (List * (+ b c )(+ d 1 )), body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(MacroMapArgs(Hold((b+c)*(d+1)),MacroSubstitute) -> m2*m2, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute}) -> m2*m2, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroSubstitute(Hold((b+c)*(d+1))) -> m2*m2, Local variables: body -> (* (+ b c )(+ d 1 )), mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2*m2, Local variables: mapsingleitem -> (* (+ b c )(+ d 1 )), foreachtail -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List ), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter{(`, `ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Arg(parameter1 -> ApplyPure($func15,{Hold(Hold(@mapsingleitem))})); - Enter<**** user rulebase>{(MacroSubstitute, MacroSubstitute(Hold(d+4))); - Arg(body -> d+4); - Enter{(`, `ApplyPure(predicate,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(predicate,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocPredicate, LocPredicate(Hold(d+4))); - Arg(arg1 -> d+4); - **** Rule in function (LocPredicate) matched: Precedence: 10, Parameters: arg1, Predicates: (Pattern) IsFunction(exp), True, Variables: exp, Types: Variable, Body: [ Local(tr, result, head); tr:=patterns; result:=False; While(tr!={})[ Set(head, Head(Head(tr))); If(NotIsAtom(head)Andexp[0]=head[1]AndPattern'Matches(head[2], exp), [ Set($LocResult12, Eval(Head(Tail(Head(tr))))); Set(result, True); Set(tr, {});], [ Set(tr, Tail(tr));]);]; result;] - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {{{+,Pattern},m2}}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> True, Local variables: aRight -> (List ), aLeft -> (List (List (List + [BuiltinObject])m2 )), ); - Enter{(Pattern'Matches, Pattern'Matches(head[2],exp)); - Arg(parameter1 -> Pattern); - Arg(parameter2 -> d+4); - Enter{(IsBound, IsBound(x)); - Arg(parameter1 -> x); - Leave}(IsBound(x) -> True, Local variables: y -> 4, x -> d 4, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter{(IsBound, IsBound(y)); - Arg(parameter1 -> y); - Leave}(IsBound(y) -> True, Local variables: y -> 4, x -> d 4, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(Pattern'Matches(head[2],exp) -> True, Local variables: y -> 4, x -> d 4, head -> (List + [BuiltinObject]), result -> False, tr -> (List (List (List + [BuiltinObject])m2 )), exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Enter<**** user rulebase>{(!=, tr!={}); - Arg(aLeft -> {}); - Arg(aRight -> {}); - **** Rule in function (!=) matched: Precedence: 1025, Parameters: aLeft, aRight, Predicates: None., Body: NotaLeft=aRight - Leave<**** user rulebase>}(tr!={} -> False, Local variables: aRight -> (List ), aLeft -> (List ), ); - Leave<**** user rulebase>}(LocPredicate(Hold(d+4)) -> True, Local variables: exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(predicate,{Hold(Hold(@body))}) -> True, Local variables: body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - **** Rule in function (MacroSubstitute) matched: Precedence: 1, Parameters: body, Predicates: `ApplyPure(predicate,{Hold(Hold(@body))})=True, Body: [ `ApplyPure(change, {Hold(Hold(@body))});] - Enter{(`, `ApplyPure(change,{Hold(Hold(@body))})); - Arg(parameter1 -> ApplyPure(change,{Hold(Hold(@body))})); - Enter<**** user rulebase>{(LocChange, LocChange(Hold(d+4))); - Arg(arg1 -> d+4); - **** Rule in function (LocChange) matched: Precedence: 0, Parameters: arg1, Predicates: (Pattern) True, Variables: exp, Types: Variable, Body: $LocResult12 - Leave<**** user rulebase>}(LocChange(Hold(d+4)) -> m2, Local variables: exp -> (+ d 4 ), arg1 -> (+ d 4 ), body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(change,{Hold(Hold(@body))}) -> m2, Local variables: body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroSubstitute(Hold(d+4)) -> m2, Local variables: body -> (+ d 4 ), mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure($func15,{Hold(Hold(@mapsingleitem))}) -> m2, Local variables: mapsingleitem -> (+ d 4 ), foreachtail -> (List (+ d 4 )), $body22 -> (Prog (DestructiveInsert mapsingleresult 1 (` (ApplyPure $func15 (List (Hold (Hold (@ mapsingleitem )))))))), $list22 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $item22 -> mapsingleitem, mapsingleresult -> (List (* m2 m2 )), $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroMapSingle(MacroSubstitute,Hold({(b+c)*(d+1),d+4})) -> {m2*m2,m2}, Local variables: $list15 -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), $func15 -> "MacroSubstitute", op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`MacroMapSingle(@op,Hold(@tl)) -> {m2*m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Arg(parameter1 -> {ex[1]}); - Arg(parameter2 -> `MacroMapSingle(@op,Hold(@tl))); - Leave}(Concat({ex[1]},`MacroMapSingle(@op,Hold(@tl))) -> {*,m2*m2,m2}, Local variables: op -> "MacroSubstitute", tl -> (List (* (+ b c )(+ d 1 ))(+ d 4 )), ex -> (List * (* (+ b c )(+ d 1 ))(+ d 4 )), body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(MacroMapArgs(Hold((b+c)*(d+1)*(d+4)),MacroSubstitute) -> m2*m2*m2, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`ApplyPure(MacroMapArgs,{Hold(Hold(@body)),MacroSubstitute}) -> m2*m2*m2, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroSubstitute(Hold((b+c)*(d+1)*(d+4))) -> m2*m2*m2, Local variables: body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave}(`MacroSubstitute(Hold(@body)) -> m2*m2*m2, Local variables: change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}(MacroSubstitute(expression,LocPredicate,LocChange) -> m2*m2*m2, Local variables: change -> "LocChange", predicate -> "LocPredicate", body -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); - Leave<**** user rulebase>}((b+c)*(d+1)*(4+d)/:{x_IsBound+y_IsBound<-m2} -> m2*m2*m2, Local variables: patterns -> (List (List (List + [BuiltinObject])m2 )), expression -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), arg2 -> (List (<- (+ (_ x IsBound )(_ y IsBound ))m2 )), arg1 -> (* (* (+ b c )(+ d 1 ))(+ d 4 )), ); -. %/mathpiper_trace - - - diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/myMatch_new.mpt mathpiper-0.81f+dfsg1/tests/manual_tests/myMatch_new.mpt --- mathpiper-0.0.svn2556/tests/manual_tests/myMatch_new.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/myMatch_new.mpt 2010-07-13 20:51:29.000000000 +0000 @@ -243,7 +243,7 @@ MacroRuleBase(patternoper,MakeVector(arg,arity)); ] ); - Set(patt,Pattern'Create(patternvars,postpredicate)); + Set(patt,PatternCreate(patternvars,postpredicate)); MacroRulePattern(patternoper,arity,patternprecedence,patt)patternright; True; ] @@ -251,7 +251,7 @@ Arg(Local(patternflat,patternvars,patt,patternoper,arity),{Local(patternflat,patternvars,patt,patternoper,arity),Set(patternflat,Listify(patternleft)),Set(patternvars,Tail(patternflat)),Set(patternoper,String(Head(patternflat))),Set(arity,Length(patternvars)),DefLoadFunction(patternoper),If(Not RuleBaseDefined(patternoper,arity),[ MacroRuleBase(patternoper,MakeVector(arg,arity)); ] -),Set(patt,Pattern'Create(patternvars,postpredicate)),MacroRulePattern(patternoper,arity,patternprecedence,patt)patternright,True}); +),Set(patt,PatternCreate(patternvars,postpredicate)),MacroRulePattern(patternoper,arity,patternprecedence,patt)patternright,True}); Enter{(Local,Local(patternflat,patternvars,patt,patternoper,arity)); Arg(patternflat,{patternflat,patternvars,patt,patternoper,arity}); Leave}(Local(patternflat,patternvars,patt,patternoper,arity),True); diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/options_test.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/options_test.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/options_test.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/options_test.mpw 2010-03-03 07:22:54.000000000 +0000 @@ -0,0 +1,60 @@ +%mathpiper +Retract("tstSolve",*); + +RulebaseListed("tstSolve",{expression, variable, optionsList}); + +//Handle no option call. +5 # tstSolve(_expression, _variable) <-- tstSolve(expression, variable, {}); + + +//Main routine. It will automatically accept 2 or more option calls because the +//options come in a list. +10 # tstSolve(_expression, _variable, optionsList_IsList) <-- +[ + Local(options); + + Echo(expression, variable, optionsList); + + options := OptionsToAssociativeList(optionsList); + + Echo("All submitted options: ", options); + + Echo("The roots option is set to ", options["roots"]); +]; + + +//Handle a single option call because the option does not come in a list for some reason. +20 # tstSolve(_expression, _variable, _singleOption) <-- tstSolve(expression, variable, {singleOption}); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +//No option call. +In> tstSolve(x^2+x,x) +Result: {} +Side Effects: +x^2+x x {} +All submitted options: {} +The roots option is set to Empty + + + //One option call. +In> TestSolve(x^2+x,x,roots->R) +Result: TestSolve(x^2+x,x,roots->R) + + +//Multiple option call. +In> tstSolve(x^2+x,x,roots->R, option2 -> 15, option3 -> test) +Result: {{"option3","test"},{"option2","15"},{"roots","R"}} +Side Effects: +x^2+x x {roots->R,option2->15,option3->test} +All submitted options: {{"option3","test"},{"option2","15"},{"roots","R"}} +The roots option is set to R diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/resampling_statistics.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/resampling_statistics.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/resampling_statistics.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/resampling_statistics.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,823 @@ + +%mathpiper + +Use("org/mathpiper/assembledscripts/proposed.rep/statistics.mpi"); +Use("org/mathpiper/assembledscripts/proposed.rep/geogebra.mpi"); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + + + + +%mathpiper,title="two boys." + +boysAndGirls := {}; +ForEach(trial, 1 .. 100) +[ + child1 := Round(Random()); + child2 := Round(Random()); + + boysAndGirls := Append( boysAndGirls, {child1, child2} ); +]; + +boysOnly := Remove(boysAndGirls,{0,0}); + +Echo("Trials :", boysOnly); + +oneBoy := Count(boysOnly, {1,0}) + Count(boysOnly, {0,1}); + +twoBoys := Count(boysOnly, {1,1}); + +Echo("One boy: ", oneBoy); + +Echo("Two boys: ", twoBoys); + +Echo("At least one boy: ", Length(boysOnly),N( (oneBoy + twoBoys)/Length(boysAndGirls))); + + +N(twoBoys/ Length(boysOnly)); + + +%/mathpiper + + %output,preserve="false" + Result: 0.2564102564 + + Side Effects: + Trials :{{1,1},{0,1},{1,1},{0,1},{0,1},{0,1},{0,1},{1,1},{1,1},{1,1},{0,1},{1,1},{0,1},{0,1},{1,0},{1,1},{1,1},{1,0},{0,1},{0,1},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{1,1},{1,1},{1,0},{1,0},{1,1},{1,0},{1,1},{1,0},{0,1},{0,1},{1,0},{0,1},{1,0},{0,1},{0,1},{1,0},{1,1},{0,1},{0,1},{1,0},{0,1},{0,1},{1,1},{0,1},{1,0},{0,1},{0,1},{1,0},{1,0},{0,1},{0,1},{1,0},{0,1},{0,1},{0,1},{1,0},{1,1},{1,0},{1,0},{1,0},{0,1},{1,0},{1,1},{1,0},{1,1},{0,1},{1,0},{0,1},{1,1},{1,1},{1,1},{1,0}} + One boy: 58 + Two boys: 20 + At least one boy: 78 0.78 +. %/output + + + + + + + + +%mathpiper,title="Gold example on pp.82 chapter 6." + +ships := {{gold, gold}, {gold, silver}, {silver, silver}}; + +score := {}; + + +Repeat(1000) +[ + ship := RandomPick(ships); + + ship := Shuffle(ship); + + If(Count(ship,gold) = 2, score := Append(score,success) ); + + If(Count(ship,silver) = 1, + If(ship[1] = gold, score := Append(score,failure)) + ); + + + +]; +initialGoldCount := Length(score); +goldGoldCount := Count(score,success); + +result := N(goldGoldCount/initialGoldCount); + +Echo(initialGoldCount,,,goldGoldCount,,,result); + +%/mathpiper + + + + + + + + + + +%mathpiper,title="Three door problem pp.83 chapter 6." + +firstPickScore := {}; +secondPickScore := {}; + + +Repeat(1000) +[ + doors := Shuffle( {empty, prize, empty} ); + + firstPick := doors[1]; + + If(doors[2] = empty, secondPick := doors[3], secondPick := doors[2]); + + firstPickScore := Append(firstPickScore, firstPick); + secondPickScore := Append(secondPickScore, secondPick); +]; + +Echo("First Pick: ", Count(firstPickScore,prize)); +Echo("Second Pick: ", Count(secondPickScore,prize)); + + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + First Pick: 263 + Second Pick: 737 +. %/output + + + + + + + + + +%mathpiper,title="Two of a kind problem pp.85 chapter 6." + +pairsCount := 0; + +deck := Concat(1 .. 13, 1 .. 13, 1 .. 13, 1 .. 13); + +trials := 100; + +Repeat(trials) +[ + deck := Shuffle(deck); + + hand := Take(deck,5); + + //Echo(hand); + + handPairCount := 0; + ForEach(card,1 .. 13) + [ + If(Count(hand,card) = 2, handPairCount := handPairCount + 1); + ]; + + If(handPairCount = 1, pairsCount := pairsCount + 1); + +]; + + +Echo("Probability of a single pair: ", N(pairsCount/trials) ); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + Probability of a single pair: 0.52 +. %/output + + + + + + + + +%mathpiper,title="Two pairs vs. three of a kind problem pp.90 chapter 6." + +pairsCount := 0; +threeOfAKindCount := 0; + +deck := Concat(1 .. 13, 1 .. 13, 1 .. 13, 1 .. 13); + +trials := 1000; + +Repeat(trials) +[ + + deck := Shuffle(deck); + + hand := Take(deck,5); + + //Echo(hand); + + handPairCount := 0; + handThreeOfAKindCount := 0; + ForEach(card,1 .. 13) + + [ + If(Count(hand,card) = 2, handPairCount := handPairCount + 1); + If(Count(hand,card) = 3, handThreeOfAKindCount := handThreeOfAKindCount + 1); + ]; + + If(handPairCount = 2, pairsCount := pairsCount + 1); + If(handThreeOfAKindCount = 1, threeOfAKindCount := threeOfAKindCount + 1); + +]; + +Echo("Probability of two pairs: ", N(pairsCount/trials) ); +Echo("Probability of three of a kind: ", N(threeOfAKindCount/trials) ); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + Probability of two pairs: 0.052 + Probability of three of a kind: 0.028 +. %/output + + + + + + + + + +%mathpiper,title="Birthday match from page 97 chapter 7." + +birthdayMatchCounter := 0; +trials := 50; +Repeat(trials) +[ + birthdays := RandomIntegerVector(25,1,365); + + dayCounter := 1; + While(dayCounter <= 365) + [ + If(Count(birthdays,dayCounter) >= 2, [birthdayMatchCounter := birthdayMatchCounter + 1; dayCounter := 366;]); + dayCounter := dayCounter + 1; + ]; + +]; + + + Echo(birthdayMatchCounter,,,trials); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 31 , 50 +. %/output + + + + + + + + +%mathpiper,title="Birthday the same as August 1st" + +birthdayMatchCounter := 0; + +trials := 1000; +Repeat(trials) +[ + targetPersonBirthday := 213; + + birthdays := RandomIntegerVector(25,1,365); + + If( Contains(birthdays, targetPersonBirthday), birthdayMatchCounter++); + +]; + + + Echo(birthdayMatchCounter,,,trials,,,N(birthdayMatchCounter/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 81 , 1000 , 0.081 +. %/output + + + + +%mathpiper,title="Three daughters example pp.97 chapter 7." + +trials := 100; + +successes := 0; + +Repeat(trials) +[ + sample := RandomSymbolVector( {{boy,1/2}, {girl,1/2} },4); + //Echo(sample); + + If(Count(sample,girl) = 3, successes := successes + 1); + +]; + +Echo(successes,,,trials); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 27 , 100 +. %/output + + + + + + + +%mathpiper,title="5 shot basketball example pp.102 chapter 7." + +trials := 100; + +successes := 0; + +Repeat(trials) +[ + sample := RandomSymbolVector({{hit,1/4}, {miss,3/4}},5); + + If(Count(sample,hit) >= 3, successes := successes + 1); + +]; + +Echo(successes,,,trials); + +%/mathpiper + + + + + + + + +%mathpiper,title="Archery example pp.104 chapter 7." + +trials := 100; + +successes := 0; + +Repeat(trials) +[ + sample := RandomSymbolVector({{black,10/100}, {white,60/100}, {miss,30/100}},3); + + If(Count(sample,black)= 1 And Count(sample,white) = 2, successes := successes + 1); + +]; + +Echo(successes,,,trials); + +%/mathpiper + + + + + + + + + +%mathpiper,title="Sum of hammers and handle lengths pp. 108" + +sample := {}; +trials := 100; +Repeat(trials) +[ + handleLength := RandomSymbol({{10.0,20/100},{10.1,30/100},{10.2,30/100},{10.3,20/100}}); + headLength := RandomSymbol({{2.0,20/100},{2.1,20/100},{2.2,30/100},{2.3,20/100},{2.4,10/100}}); + + totalLength := handleLength + headLength; + + sample := Append(sample, totalLength); + +]; + + +givenLength := 12.4; +overOrEqual := 0; +ForEach(element, sample) +[ + If(element >= givenLength, overOrEqual := overOrEqual + 1); + +]; + +mean := Mean(sample); + +Echo(overOrEqual,,,trials,,,mean); + +%/mathpiper + + + + + + + +%mathpiper,title="Flipping pennies pp.110 chapter 7." + +trials := 2; +emptyCount := 0; + +Repeat(trials) +[ + stack1 := 10; + stack2 := 10; + + iterations := Repeat(200) + [ + flip := RandomSymbol({{head,1/2},{tail,1/2}}); + + If(flip = head, [stack1++; stack2--;], [stack1--; stack2++;] ); + + If(stack1 = 0 Or stack2 = 0, Break() ); + + ]; + + Echo({stack1,,,stack2,,,iterations}); + If(stack1 = 0 Or stack2 = 0, emptyCount++); + +]; + +{emptyCount,trials}; + + +%/mathpiper + + + + + + +%mathpiper,title="capacirators example pp. 112 chapter 7." + +daysToEmptyList := {}; +trials := 50; +Repeat(trials) +[ + warehouseCount := 12; + + dayCounter := 0; + + daysToEmpty := Repeat() + [ + morning := RandomSymbol({{used,6/10},{not_used,4/10}}); + If(morning = used, warehouseCount--); + If(warehouseCount = 0, Break()); + + afternoon := RandomSymbol({{used,6/10},{not_used,4/10}}); + If(afternoon = used, warehouseCount--); + If(warehouseCount = 0, Break()); + + + If(Mod(dayCounter,3) = 0, warehouseCount := warehouseCount + 2); + + //Echo(warehouseCount, dayCounter, Mod(dayCounter,3)); + + dayCounter++; + + ]; + + daysToEmptyList := Append(daysToEmptyList, daysToEmpty); + +]; + +Echo("Average days to empty: ", Mean(daysToEmptyList)); + + +%/mathpiper + + + + + + + +%mathpiper,title="Random walk example at the end of chapter 7." + +targetPositions := {{3,2}, {-1,-4}}; + +successCount := 0; + +trials := 500; +Repeat(trials) +[ + currentPosition := {0,0}; + walkPath := {}; + Repeat(12) + [ + step:= RandomSymbol({{{1,0},1/4},{{-1,0},1/4},{{0,1},1/4},{{0,-1},1/4}}); + + currentPosition := currentPosition + step; + + //walkPath := Append(walkPath,currentPosition); + + If(Contains(targetPositions, currentPosition), [successCount++; Break();]); + + ]; + //Write(walkPath); +]; + +{successCount, trials, N(successCount/trials)}; +%/mathpiper + + %output,preserve="false" + Result: {35,500,0.07} +. %/output + + + + +%mathpiper,title="case 1 example pp. 119 chapter 8." + +balls := {1,2,3,4,5,6}; + +successCount := 0; + +trials := 1000; +Repeat(trials) +[ + sample := Sample(balls,3); + + If(sample = {1,2,3}, successCount++); +]; + +Echo(successCount,,,trials,,,N(successCount/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 36 , 5000 , 0.0072 +. %/output + + + + +%mathpiper,title="case 2 example pp. 120 chapter 8." + +balls := {1,2,3,4,5,6}; + +successCount := 0; + +trials := 1000; +Repeat(trials) +[ + sample := Sample(balls,3); + + If(IsSubset({1,2,3},sample), successCount++); +]; + +Echo(successCount,,,trials,,,N(successCount/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 49 , 1000 , 0.049 +. %/output + + + + + + +%mathpiper,title="case 3 example pp. 121 chapter 8." + +balls := {1,2,3,4,5,6}; + +successCount := 0; + +trials := 1000; +Repeat(trials) +[ + sample := Sample(balls,3); + + If( (IsOdd(sample[1]) And IsEven(sample[2])) Or (IsOdd(sample[2]) And IsEven(sample[3])), successCount++); +]; + +Echo(successCount,,,trials,,,N(successCount/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 588 , 1000 , 0.588 +. %/output + + + + + + +%mathpiper,title="case 4 example pp. 120 chapter 8." + +balls := {1,2,3,4,5,6}; + +successCount := 0; + +trials := 1000; +Repeat(trials) +[ + sample := Sample(balls,3); + + If(Length(Select("IsOdd",sample)) = 2, successCount++); +]; + +Echo(successCount,,,trials,,,N(successCount/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 423 , 1000 , 0.423 +. %/output + + + + + +%mathpiper,title="case 5a example pp. 121 chapter 8." + +balls := {1,2,3,4,5,6}; + +successCount := 0; + +trials := 1000; +Repeat(trials) +[ + sample := Sample(balls,3); + + If(sample[1] = 1 Or sample[2] = 2 Or sample[3] = 3, successCount++); +]; + +Echo(successCount,,,trials,,,N(successCount/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 421 , 1000 , 0.421 +. %/output + + + + +%mathpiper,title="case 5b example pp. 121 chapter 8." + +balls := {1,2,3,4,5,6}; + +successCount := 0; + +trials := 10000; +Repeat(trials) +[ + sample := Sample(balls,6); + + If(sample = {1,2,3,4,5,6}, successCount++); +]; + +Echo(successCount,,,trials,,,N(successCount/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 19 , 10000 , 0.0019 +. %/output + + + + + + + + +%mathpiper,title="example 8-1 50 girls and boys pp. 122." + +class := Concat(FillList(boy,25), FillList(girl,25)); + +samples := {}; + +trials := 100; + +Repeat(trials) +[ + class := Shuffle(class); + + sample := Take(class,5); + + samples := Count(sample,girl) : samples; + +]; + +successCount := Count(samples,4); + +Echo(successCount,,,trials,,,N(successCount/trials)); + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + 14 , 100 , 0.14 +. %/output + + +%mathpiper,title="Extra code for example 8-1" +GeoGebraHistogram(samples); + +%/mathpiper + + %output,preserve="false" + Result: true +. %/output + + + + + + +%mathpiper,title="Example 8-2 9 spades pp. 125" + +samples := {}; + +trials := 100; + +deck := Concat(FillList(spades,13), FillList(diamonds,13), FillList(hearts,13), FillList(clubs,13)); +//test := {}; +//counter := 0; +Repeat(trials) +[ + + (deck := Shuffle(deck)); + + (hand := Take(deck,13)); + + //test := Count(hand, spades) : test; + + (If(Count(hand, spades) = 9, Count(hand, clubs) : samples)); + + //If(Mod(counter,100) = 0, SysOut("Trial # ",,, counter)); + //counter++; +]; + +samples; + +%/mathpiper + + %output,preserve="false" + Result: {} +. %/output + + + + +%mathpiper,title="Extra code for example 8-2" +//The probability of obtaining 9 spades seems to be very low. + +N( (Combinations(13,9) * Combinations(39,4)) / Combinations(52,13) ); + +%/mathpiper + + %output,preserve="false" + Result: 0.00009261135311 +. %/output + + + +%mathpiper,title="Extra code for example 8-2" +GeoGebraHistogram(test); + +%/mathpiper + + %output,preserve="false" + Result: true +. %/output + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/resampling_statistics.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/resampling_statistics.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/resampling_statistics.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/resampling_statistics.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,809 +0,0 @@ - -%mathpiper - -Use("org/mathpiper/assembledscripts/proposed.rep/statistics.mpi"); -Use("org/mathpiper/assembledscripts/proposed.rep/geogebra.mpi"); - -%/mathpiper - - %output,preserve="false" - Result: True -. %/output - - - - - - -%mathpiper,title="two boys." - -boysAndGirls := {}; -ForEach(trial, 1 .. 100) -[ - child1 := Round(Random()); - child2 := Round(Random()); - - boysAndGirls := Append( boysAndGirls, {child1, child2} ); -]; - -boysOnly := Remove(boysAndGirls,{0,0}); - -Echo("Trials :", boysOnly); - -oneBoy := Count(boysOnly, {1,0}) + Count(boysOnly, {0,1}); - -twoBoys := Count(boysOnly, {1,1}); - -Echo("One boy: ", oneBoy); - -Echo("Two boys: ", twoBoys); - -Echo("At least one boy: ", Length(boysOnly),N( (oneBoy + twoBoys)/Length(boysAndGirls))); - - -N(twoBoys/ Length(boysOnly)); - - -%/mathpiper - - %output,preserve="false" - Result: 0.2564102564 - - Side Effects: - Trials :{{1,1},{0,1},{1,1},{0,1},{0,1},{0,1},{0,1},{1,1},{1,1},{1,1},{0,1},{1,1},{0,1},{0,1},{1,0},{1,1},{1,1},{1,0},{0,1},{0,1},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{1,1},{1,1},{1,0},{1,0},{1,1},{1,0},{1,1},{1,0},{0,1},{0,1},{1,0},{0,1},{1,0},{0,1},{0,1},{1,0},{1,1},{0,1},{0,1},{1,0},{0,1},{0,1},{1,1},{0,1},{1,0},{0,1},{0,1},{1,0},{1,0},{0,1},{0,1},{1,0},{0,1},{0,1},{0,1},{1,0},{1,1},{1,0},{1,0},{1,0},{0,1},{1,0},{1,1},{1,0},{1,1},{0,1},{1,0},{0,1},{1,1},{1,1},{1,1},{1,0}} - One boy: 58 - Two boys: 20 - At least one boy: 78 0.78 -. %/output - - - - - - - - -%mathpiper,title="Gold example on pp.82 chapter 6." - -ships := {{gold, gold}, {gold, silver}, {silver, silver}}; - -score := {}; - - -Repeat(1000) -[ - ship := RandomPick(ships); - - ship := Shuffle(ship); - - If(Count(ship,gold) = 2, score := Append(score,success) ); - - If(Count(ship,silver) = 1, - If(ship[1] = gold, score := Append(score,failure)) - ); - - - -]; -initialGoldCount := Length(score); -goldGoldCount := Count(score,success); - -result := N(goldGoldCount/initialGoldCount); - -Echo(initialGoldCount,,,goldGoldCount,,,result); - -%/mathpiper - - - - - - - - - - -%mathpiper,title="Three door problem pp.83 chapter 6." - -firstPickScore := {}; -secondPickScore := {}; - - -Repeat(1000) -[ - doors := Shuffle( {empty, prize, empty} ); - - firstPick := doors[1]; - - If(doors[2] = empty, secondPick := doors[3], secondPick := doors[2]); - - firstPickScore := Append(firstPickScore, firstPick); - secondPickScore := Append(secondPickScore, secondPick); -]; - -Echo("First Pick: ", Count(firstPickScore,prize)); -Echo("Second Pick: ", Count(secondPickScore,prize)); - - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - First Pick: 263 - Second Pick: 737 -. %/output - - - - - - - - - -%mathpiper,title="Two of a kind problem pp.85 chapter 6." - -pairsCount := 0; - -deck := Concat(1 .. 13, 1 .. 13, 1 .. 13, 1 .. 13); - -trials := 100; - -Repeat(trials) -[ - deck := Shuffle(deck); - - hand := Take(deck,5); - - //Echo(hand); - - handPairCount := 0; - ForEach(card,1 .. 13) - [ - If(Count(hand,card) = 2, handPairCount := handPairCount + 1); - ]; - - If(handPairCount = 1, pairsCount := pairsCount + 1); - -]; - - -Echo("Probability of a single pair: ", N(pairsCount/trials) ); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - Probability of a single pair: 0.52 -. %/output - - - - - - - - -%mathpiper,title="Two pairs vs. three of a kind problem pp.90 chapter 6." - -pairsCount := 0; -threeOfAKindCount := 0; - -deck := Concat(1 .. 13, 1 .. 13, 1 .. 13, 1 .. 13); - -trials := 1000; - -Repeat(trials) -[ - - deck := Shuffle(deck); - - hand := Take(deck,5); - - //Echo(hand); - - handPairCount := 0; - handThreeOfAKindCount := 0; - ForEach(card,1 .. 13) - - [ - If(Count(hand,card) = 2, handPairCount := handPairCount + 1); - If(Count(hand,card) = 3, handThreeOfAKindCount := handThreeOfAKindCount + 1); - ]; - - If(handPairCount = 2, pairsCount := pairsCount + 1); - If(handThreeOfAKindCount = 1, threeOfAKindCount := threeOfAKindCount + 1); - -]; - -Echo("Probability of two pairs: ", N(pairsCount/trials) ); -Echo("Probability of three of a kind: ", N(threeOfAKindCount/trials) ); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - Probability of two pairs: 0.052 - Probability of three of a kind: 0.028 -. %/output - - - - - - - - - -%mathpiper,title="Birthday match from page 97 chapter 7." - -birthdayMatchCounter := 0; -trials := 50; -Repeat(trials) -[ - birthdays := RandomIntegerVector(25,1,365); - - dayCounter := 1; - While(dayCounter <= 365) - [ - If(Count(birthdays,dayCounter) >= 2, [birthdayMatchCounter := birthdayMatchCounter + 1; dayCounter := 366;]); - dayCounter := dayCounter + 1; - ]; - -]; - - - Echo(birthdayMatchCounter,,,trials); - -%/mathpiper - - - - - - - - -%mathpiper,title="Birthday the same as August 1st" - -birthdayMatchCounter := 0; - -trials := 1000; -Repeat(trials) -[ - targetPersonBirthday := 213; - - birthdays := RandomIntegerVector(25,1,365); - - If( Contains(birthdays, targetPersonBirthday), birthdayMatchCounter++); - -]; - - - Echo(birthdayMatchCounter,,,trials,,,N(birthdayMatchCounter/trials)); - -%/mathpiper - - - - -%mathpiper,title="Three daughters example pp.97 chapter 7." - -trials := 100; - -successes := 0; - -Repeat(trials) -[ - sample := RandomSymbolVector( {{boy,1/2}, {girl,1/2} },4); - //Echo(sample); - - If(Count(sample,girl) = 3, successes := successes + 1); - -]; - -Echo(successes,,,trials); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 27 , 100 -. %/output - - - - - - - -%mathpiper,title="5 shot basketball example pp.102 chapter 7." - -trials := 100; - -successes := 0; - -Repeat(trials) -[ - sample := RandomSymbolVector({{hit,1/4}, {miss,3/4}},5); - - If(Count(sample,hit) >= 3, successes := successes + 1); - -]; - -Echo(successes,,,trials); - -%/mathpiper - - - - - - - - -%mathpiper,title="Archery example pp.104 chapter 7." - -trials := 100; - -successes := 0; - -Repeat(trials) -[ - sample := RandomSymbolVector({{black,10/100}, {white,60/100}, {miss,30/100}},3); - - If(Count(sample,black)= 1 And Count(sample,white) = 2, successes := successes + 1); - -]; - -Echo(successes,,,trials); - -%/mathpiper - - - - - - - - - -%mathpiper,title="Sum of hammers and handle lengths pp. 108" - -sample := {}; -trials := 100; -Repeat(trials) -[ - handleLength := RandomSymbol({{10.0,20/100},{10.1,30/100},{10.2,30/100},{10.3,20/100}}); - headLength := RandomSymbol({{2.0,20/100},{2.1,20/100},{2.2,30/100},{2.3,20/100},{2.4,10/100}}); - - totalLength := handleLength + headLength; - - sample := Append(sample, totalLength); - -]; - - -givenLength := 12.4; -overOrEqual := 0; -ForEach(element, sample) -[ - If(element >= givenLength, overOrEqual := overOrEqual + 1); - -]; - -mean := Mean(sample); - -Echo(overOrEqual,,,trials,,,mean); - -%/mathpiper - - - - - - - -%mathpiper,title="Flipping pennies pp.110 chapter 7." - -trials := 2; -emptyCount := 0; - -Repeat(trials) -[ - stack1 := 10; - stack2 := 10; - - iterations := Repeat(200) - [ - flip := RandomSymbol({{head,1/2},{tail,1/2}}); - - If(flip = head, [stack1++; stack2--;], [stack1--; stack2++;] ); - - If(stack1 = 0 Or stack2 = 0, Break() ); - - ]; - - Echo({stack1,,,stack2,,,iterations}); - If(stack1 = 0 Or stack2 = 0, emptyCount++); - -]; - -{emptyCount,trials}; - - -%/mathpiper - - - - - - -%mathpiper,title="capacirators example pp. 112 chapter 7." - -daysToEmptyList := {}; -trials := 50; -Repeat(trials) -[ - warehouseCount := 12; - - dayCounter := 0; - - daysToEmpty := Repeat() - [ - morning := RandomSymbol({{used,6/10},{not_used,4/10}}); - If(morning = used, warehouseCount--); - If(warehouseCount = 0, Break()); - - afternoon := RandomSymbol({{used,6/10},{not_used,4/10}}); - If(afternoon = used, warehouseCount--); - If(warehouseCount = 0, Break()); - - - If(Mod(dayCounter,3) = 0, warehouseCount := warehouseCount + 2); - - //Echo(warehouseCount, dayCounter, Mod(dayCounter,3)); - - dayCounter++; - - ]; - - daysToEmptyList := Append(daysToEmptyList, daysToEmpty); - -]; - -Echo("Average days to empty: ", Mean(daysToEmptyList)); - - -%/mathpiper - - - - - - - -%mathpiper,title="Random walk example at the end of chapter 7." - -targetPositions := {{3,2}, {-1,-4}}; - -successCount := 0; - -trials := 500; -Repeat(trials) -[ - currentPosition := {0,0}; - walkPath := {}; - Repeat(12) - [ - step:= RandomSymbol({{{1,0},1/4},{{-1,0},1/4},{{0,1},1/4},{{0,-1},1/4}}); - - currentPosition := currentPosition + step; - - //walkPath := Append(walkPath,currentPosition); - - If(Contains(targetPositions, currentPosition), [successCount++; Break();]); - - ]; - //Write(walkPath); -]; - -{successCount, trials, N(successCount/trials)}; -%/mathpiper - - %output,preserve="false" - Result: {35,500,0.07} -. %/output - - - - -%mathpiper,title="case 1 example pp. 119 chapter 8." - -balls := {1,2,3,4,5,6}; - -successCount := 0; - -trials := 1000; -Repeat(trials) -[ - sample := Sample(balls,3); - - If(sample = {1,2,3}, successCount++); -]; - -Echo(successCount,,,trials,,,N(successCount/trials)); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 36 , 5000 , 0.0072 -. %/output - - - - -%mathpiper,title="case 2 example pp. 120 chapter 8." - -balls := {1,2,3,4,5,6}; - -successCount := 0; - -trials := 1000; -Repeat(trials) -[ - sample := Sample(balls,3); - - If(IsSubset({1,2,3},sample), successCount++); -]; - -Echo(successCount,,,trials,,,N(successCount/trials)); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 49 , 1000 , 0.049 -. %/output - - - - - - -%mathpiper,title="case 3 example pp. 121 chapter 8." - -balls := {1,2,3,4,5,6}; - -successCount := 0; - -trials := 1000; -Repeat(trials) -[ - sample := Sample(balls,3); - - If( (IsOdd(sample[1]) And IsEven(sample[2])) Or (IsOdd(sample[2]) And IsEven(sample[3])), successCount++); -]; - -Echo(successCount,,,trials,,,N(successCount/trials)); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 588 , 1000 , 0.588 -. %/output - - - - - - -%mathpiper,title="case 4 example pp. 120 chapter 8." - -balls := {1,2,3,4,5,6}; - -successCount := 0; - -trials := 1000; -Repeat(trials) -[ - sample := Sample(balls,3); - - If(Length(Select("IsOdd",sample)) = 2, successCount++); -]; - -Echo(successCount,,,trials,,,N(successCount/trials)); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 423 , 1000 , 0.423 -. %/output - - - - - -%mathpiper,title="case 5a example pp. 121 chapter 8." - -balls := {1,2,3,4,5,6}; - -successCount := 0; - -trials := 1000; -Repeat(trials) -[ - sample := Sample(balls,3); - - If(sample[1] = 1 Or sample[2] = 2 Or sample[3] = 3, successCount++); -]; - -Echo(successCount,,,trials,,,N(successCount/trials)); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 421 , 1000 , 0.421 -. %/output - - - - -%mathpiper,title="case 5b example pp. 121 chapter 8." - -balls := {1,2,3,4,5,6}; - -successCount := 0; - -trials := 10000; -Repeat(trials) -[ - sample := Sample(balls,6); - - If(sample = {1,2,3,4,5,6}, successCount++); -]; - -Echo(successCount,,,trials,,,N(successCount/trials)); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 19 , 10000 , 0.0019 -. %/output - - - - - - - - -%mathpiper,title="example 8-1 50 girls and boys pp. 122." - -class := Concat(FillList(boy,25), FillList(girl,25)); - -samples := {}; - -trials := 100; - -Repeat(trials) -[ - class := Shuffle(class); - - sample := Take(class,5); - - samples := Count(sample,girl) : samples; - -]; - -successCount := Count(samples,4); - -Echo(successCount,,,trials,,,N(successCount/trials)); - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - 14 , 100 , 0.14 -. %/output - - -%mathpiper,title="Extra code for example 8-1" -GeoGebraHistogram(samples); - -%/mathpiper - - %output,preserve="false" - Result: true -. %/output - - - - - - -%mathpiper,title="Example 8-2 9 spades pp. 125" - -samples := {}; - -trials := 100; - -deck := Concat(FillList(spades,13), FillList(diamonds,13), FillList(hearts,13), FillList(clubs,13)); -//test := {}; -//counter := 0; -Repeat(trials) -[ - - (deck := Shuffle(deck)); - - (hand := Take(deck,13)); - - //test := Count(hand, spades) : test; - - (If(Count(hand, spades) = 9, Count(hand, clubs) : samples)); - - //If(Mod(counter,100) = 0, SysOut("Trial # ",,, counter)); - //counter++; -]; - -samples; - -%/mathpiper - - %output,preserve="false" - Result: {} -. %/output - - - - -%mathpiper,title="Extra code for example 8-2" -//The probability of obtaining 9 spades seems to be very low. - -N( (Combinations(13,9) * Combinations(39,4)) / Combinations(52,13) ); - -%/mathpiper - - %output,preserve="false" - Result: 0.00009261135311 -. %/output - - - -%mathpiper,title="Extra code for example 8-2" -GeoGebraHistogram(test); - -%/mathpiper - - %output,preserve="false" - Result: true -. %/output - - diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/TestFactors.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/TestFactors.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/TestFactors.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/TestFactors.mpw 2010-01-27 05:35:17.000000000 +0000 @@ -0,0 +1,295 @@ +%mathpiper,title="TestFactors" + +//######################################################################## +// T E S T I N G T E S T I N G T E S T I N G +//######################################################################## + +// a bunch of expressions for testing +expressions := {}; + +// REAL Integers ----------------------------------------------------------- +Push( expressions, {24,{{2,3},{3,1}}} ); + +// Gaussian Integers ----------------------------------------------------------- +Push( expressions, {G(157+28*I), {{Complex(5,2),1},{Complex(-29,6),1}}}); +Push( expressions, {G(1), {}}); // is this the correct behavior? why not {{}} or {{1,1}}? +Push( expressions, {G(-1), {}}); // is this the correct behavior? +Push( expressions, {G(I), {}}); // is this the correct behavior? +Push( expressions, {G(0), {}}); // is this the correct behavior? +Push( expressions, {G(2), {{Complex(1,1),1},{Complex(1,-1),1}}}); +Push( expressions, {G(-2), {{Complex(1,1),1},{Complex(1,-1),1}}}); +Push( expressions, {G(3), {{3,1}}}); +Push( expressions, {G(3*I), {{3,1}}}); +Push( expressions, {G(4), {{Complex(1,1),2},{Complex(1,-1),2}}}); +Push( expressions, {G(-5*I), {{Complex(2,1),1},{Complex(2,-1),1}}}); +Push( expressions, {G(Complex(1,1)^11*163^4),{{Complex(1,1),11},{163,4}}}); + +// Univariate Polynomials --------------------------------------------- +Push( expressions, {-7*x-14*y,{{7,1},{x+2*y,1}} } ); +Push( expressions, {x^2-4,{{x+2,1},{x-2,1}}} ); +Push( expressions, {x^2+2*x+1,{{x+1,2}}} ); +Push( expressions, {-9*x^2+45*x-36,{{9,1},{x-4,1},{x-1,1}}} ); +Push( expressions, {9*x^2-1,{{3*x-1,1},{3*x+1,1}}} ); +Push( expressions, {4*x^3+12*x^2-40*x,{{4,1},{x+5,1},{x-2,1},{x,1}}} ); +Push( expressions, {32*x^3+32*x^2-70*x-75,{{4*x+5,2},{2*x-3,1}}} ); +Push( expressions, {3*x^3-12*x^2-2*x+8,{{3*x^2-2,1},{x-4,1}}} ); +Push( expressions, {x^3+3*x^2-25*x-75,{{x-5,1},{x+5,1},{x+3,1}}} ); +Push( expressions, {2*x^3-30*x^2+12*x^4,{{2,1},{x,2},{3*x+5,1},{2*x-3,1}}} ); +Push( expressions, {5*x^7-20*x^6+25*x^5-20*x^4+25*x^3-20*x^2+20*x,{{5,1},{x,1},{x^2+x+1,1},{x^2-x+1,1},{x-2,2}}} ); +Push( expressions, {(2/5)*x^2-2*x-(12/5), {{2/5,1},{x+1,1},{x-6,1}}} ); +Push( expressions, {.4*x^2-2*x-2.4, {{2/5,1},{x+1,1},{x-6,1}}} ); +Push( expressions, {x^3+1, {{x+1,1},{x^2-x+1,1}}} ); +Push( expressions, {x^4-1, {{x+1,1},{x-1,1},{x^2+1,1}}} ); +Push( expressions, {x^5-1, {{x-1,1},{x^4+x^3+x^2+x+1,1}}} ); +Push( expressions, {x^5+1, {{x+1,1},{x^4-x^3+x^2-x+1,1}}} ); + +// Bivariate Polynomials --------------------------------------------- +Push( expressions, {x^2-a^2, {{x+a,1},{x-a,1}}} ); +Push( expressions, {a^2+2*a*b+b^2,{{a+b,2}}} ); +Push( expressions, {x^3-y^3, {{x-y,1},{x^2+x*y+y^2,1}}} ); +Push( expressions, {x^3+a^3, {{x+a,1},{x^2-a*x+a^2,1}}} ); +Push( expressions, {x^6-a^6, {{x+a,1},{x-a,1},{x^2+x*a+a^2,1},{x^2-x*a+a^2,1}}} ); +Push( expressions, {3*x^2-x*y-10*y^2, {{3*x+5*y,1},{x-2*y,1}} } ); + +// Non-Integral Powers ----------------------------------------------- +Push( expressions, {9*x^2.0 -1,{{3*x-1,1},{3*x+1,1}}} ); + +//Push( expressions, {,{{},{},{},{}}} ); +EchoTime() [ +NewLine(2); Tell("TEST Factors() and GaussianFactors()"); +expressions := Reverse(expressions); +Local(i); i := 0; +ForEach(q,expressions) +[ + i := i + 1; + Check(i<40, ">>>>> FORCED STOP <<<<<"); + f := q[1]; + g := q[2]; + Tell("-------------------------------------------------------------------"); + Tell(i); + If( q[1][0] != G, + [ + Tell(">>> Test Factors() on polynomial: ",f); + stk := {}; + r := (xFactors(f)); + SysOut(" Factors(f)=",r); + ], + [ + f := f[1]; + Tell(">>> Test GaussianFactors() on expression: ",f); + stk := {}; + r := GaussianFactors(f); + SysOut(" GaussianFactors(f)=",r); + ] + ); + rmg := Simplify(Expand(UnFlatten(r-g,"+",0))); + If( IsZero(rmg) Or IsZeroVector(rmg), + SysOut(" Answer is CORRECT"), + SysOut(" Answer is WRONG: it should be ",g) + ); +]; +NewLine(); +]; // EchoTime() + +%/mathpiper + + %output,preserve="false" + Result: True + + Side Effects: + + + << TEST Factors() and GaussianFactors()>> + << ------------------------------------------------------------------->> + << 1 >> + << >>> Test Factors() on polynomial: >> f : 24 + Factors(f)={{2,3},{3,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 2 >> + << >>> Test GaussianFactors() on expression: >> f : Complex(157,28) + GaussianFactors(f)={{Complex(5,2),1},{Complex(-29,6),1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 3 >> + << >>> Test GaussianFactors() on expression: >> f : 1 + GaussianFactors(f)={} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 4 >> + << >>> Test GaussianFactors() on expression: >> f : -1 + GaussianFactors(f)={} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 5 >> + << >>> Test GaussianFactors() on expression: >> f : Complex(0,1) + GaussianFactors(f)={} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 6 >> + << >>> Test GaussianFactors() on expression: >> f : 0 + GaussianFactors(f)={} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 7 >> + << >>> Test GaussianFactors() on expression: >> f : 2 + GaussianFactors(f)={{Complex(1,1),1},{Complex(1,-1),1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 8 >> + << >>> Test GaussianFactors() on expression: >> f : -2 + GaussianFactors(f)={{Complex(1,1),1},{Complex(1,-1),1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 9 >> + << >>> Test GaussianFactors() on expression: >> f : 3 + GaussianFactors(f)={{3,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 10 >> + << >>> Test GaussianFactors() on expression: >> f : Complex(0,3) + GaussianFactors(f)={{3,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 11 >> + << >>> Test GaussianFactors() on expression: >> f : 4 + GaussianFactors(f)={{Complex(1,1),2},{Complex(1,-1),2}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 12 >> + << >>> Test GaussianFactors() on expression: >> f : Complex(0,-5) + GaussianFactors(f)={{Complex(2,1),1},{Complex(2,-1),1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 13 >> + << >>> Test GaussianFactors() on expression: >> f : Complex(-22589176352,22589176352) + GaussianFactors(f)={{Complex(1,1),11},{163,4}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 14 >> + << >>> Test Factors() on polynomial: >> f : -(7*x+14*y) + Factors(f)={{7,1},{2*y+x,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 15 >> + << >>> Test Factors() on polynomial: >> f : x^2-4 + Factors(f)={{x-2,1},{x+2,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 16 >> + << >>> Test Factors() on polynomial: >> f : x^2+2*x+1 + Factors(f)={{x+1,2}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 17 >> + << >>> Test Factors() on polynomial: >> f : 45*x-9*x^2-36 + Factors(f)={{9,1},{x-4,1},{x-1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 18 >> + << >>> Test Factors() on polynomial: >> f : 9*x^2-1 + Factors(f)={{3*x-1,1},{3*x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 19 >> + << >>> Test Factors() on polynomial: >> f : 4*x^3+12*x^2-40*x + Factors(f)={{4,1},{x,1},{x+5,1},{x-2,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 20 >> + << >>> Test Factors() on polynomial: >> f : 32*x^3+32*x^2-70*x-75 + Factors(f)={{4*x+5,2},{2*x-3,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 21 >> + << >>> Test Factors() on polynomial: >> f : 3*x^3-12*x^2-2*x+8 + Factors(f)={{3*x^2-2,1},{x-4,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 22 >> + << >>> Test Factors() on polynomial: >> f : x^3+3*x^2-25*x-75 + Factors(f)={{x-5,1},{x+5,1},{x+3,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 23 >> + << >>> Test Factors() on polynomial: >> f : 2*x^3-30*x^2+12*x^4 + Factors(f)={{2,1},{x,2},{3*x+5,1},{2*x-3,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 24 >> + << >>> Test Factors() on polynomial: >> f : 5*x^7-20*x^6+25*x^5-20*x^4+25*x^3-20*x^2+20*x + Factors(f)={{5,1},{x,1},{x-2,2},{x^2-x+1,1},{x^2+x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 25 >> + << >>> Test Factors() on polynomial: >> f : (2*x^2)/5-2*x-12/5 + Factors(f)={{2/5,1},{x-6,1},{x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 26 >> + << >>> Test Factors() on polynomial: >> f : .4*x^2-2*x-2.4 + Factors(f)={{2/5,1},{x-6,1},{x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 27 >> + << >>> Test Factors() on polynomial: >> f : x^3+1 + Factors(f)={{x+1,1},{x^2-x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 28 >> + << >>> Test Factors() on polynomial: >> f : x^4-1 + Factors(f)={{x^2+1,1},{x-1,1},{x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 29 >> + << >>> Test Factors() on polynomial: >> f : x^5-1 + Factors(f)={{x-1,1},{x^4+x^3+x^2+x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 30 >> + << >>> Test Factors() on polynomial: >> f : x^5+1 + Factors(f)={{x+1,1},{x^4-x^3+x^2-x+1,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 31 >> + << >>> Test Factors() on polynomial: >> f : x^2-a^2 + Factors(f)={{x-a,1},{a+x,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 32 >> + << >>> Test Factors() on polynomial: >> f : a^2+2*a*b+b^2 + Factors(f)={{a+b,2}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 33 >> + << >>> Test Factors() on polynomial: >> f : x^3-y^3 + Factors(f)={{x-y,1},{y^2+y*x+x^2,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 34 >> + << >>> Test Factors() on polynomial: >> f : x^3+a^3 + Factors(f)={{a+x,1},{a^2-a*x+x^2,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 35 >> + << >>> Test Factors() on polynomial: >> f : x^6-a^6 + Factors(f)={{a+x,1},{a^2-a*x+x^2,1},{x-a,1},{a^2+a*x+x^2,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 36 >> + << >>> Test Factors() on polynomial: >> f : 3*x^2-x*y-10*y^2 + Factors(f)={{3*x+5*y,1},{x-2*y,1}} + Answer is CORRECT + << ------------------------------------------------------------------->> + << 37 >> + << >>> Test Factors() on polynomial: >> f : 9*x^2.0-1 + Factors(f)={{3*x-1,1},{3*x+1,1}} + Answer is CORRECT + + 30.050427084 seconds taken. + +. %/output + + + + diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/TestFactors.mrw mathpiper-0.81f+dfsg1/tests/manual_tests/TestFactors.mrw --- mathpiper-0.0.svn2556/tests/manual_tests/TestFactors.mrw 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/TestFactors.mrw 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -%mathpiper,title="TestFactors" - -//######################################################################## -// T E S T I N G T E S T I N G T E S T I N G -//######################################################################## - -// a bunch of expressions for testing -expressions := {}; -Push( expressions, {24,{{2,3},{3,1}}} ); -Push( expressions, {-7*x-14*y,{{-7,1},{x+2*y,1}} } ); -Push( expressions, {x^2-4,{{x+2,1},{x-2,1}}} ); -Push( expressions, {x^2+2*x+1,{{x+1,2}}} ); -Push( expressions, {-9*x^2+45*x-36,{{-9,1},{x-4,1},{x-1,1}}} ); -Push( expressions, {x^2-a^2,{{x+a,1},{x-a,1}}} ); -Push( expressions, {9*x^2-1,{{3*x-1,1},{3*x+1,1}}} ); -Push( expressions, {x^3-y^3,{{x-y,1},{x^2+x*y+y^2,1}}} ); -Push( expressions, {4*x^3+12*x^2-40*x,{{4,1},{x+5,1},{x-2,1},{x,1}}} ); -Push( expressions, {32*x^3+32*x^2-70*x-75,{{4*x+5,2},{2*x-3,1}}} ); -Push( expressions, {3*x^3-12*x^2-2*x+8,{{3*x^2-2,1},{x-4,1}}} ); -Push( expressions, {x^3+3*x^2-25*x-75,{{x-5,1},{x+5,1},{x+3,1}}} ); -Push( expressions, {2*x^3-30*x^2+12*x^4,{{2,1},{x,2},{3*x+5,1},{2*x-3,1}}} ); -Push( expressions, {5*x^7-20*x^6+25*x^5-20*x^4+25*x^3-20*x^2+20*x,{{5,1},{x,1},{x^2+x+1,1},{x^2-x+1,1},{x-2,2}}} ); -Push( expressions, {(2/5)*x^2-2*x-(12/5), {{2/5,1},{x+1,1},{x-6,1}}} ); -Push( expressions, {0.4*x^2-2*x-2.4, {{2/5,1},{x+1,1},{x-6,1}}} ); -Push( expressions, {9*x^2.0 -1,{{3*x-1,1},{3*x+1,1}}} ); -//Push( expressions, {,{{},{},{},{}}} ); - -NewLine(2); Tell("TEST Factors()"); -expressions := Reverse(expressions); -Local(i); i := 0; -ForEach(q,expressions) -[ - i := i + 1; - Check(i<20, ">>>>> FORCED STOP <<<<<"); - f := q[1]; - g := q[2]; - Tell("-------------------------------------------------------------------"); - Tell(i); - Tell(">>> Test Factors() on polynomial: ",f); - stk := {}; - r := Factors(f); - SysOut(" Factors(f)=",r); - rmg := Simplify(Expand(UnFlatten(r-g,"+",0))); - If( IsZero(rmg) Or IsZeroVector(rmg), - SysOut(" Answer is CORRECT"), - SysOut(" Answer is WRONG: it should be ",g) - ); -]; - -%/mathpiper - - %output,preserve="false" - Result: True - - Side Effects: - << TEST Factors()>> - << ------------------------------------------------------------------->> - << 1 >> - << >>> Test Factors() on polynomial: >> f : 24 - Factors(f)={{2,3},{3,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 2 >> - << >>> Test Factors() on polynomial: >> f : -(7*x+14*y) - Factors(f)={{-7,1},{x+2*y,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 3 >> - << >>> Test Factors() on polynomial: >> f : x^2-4 - Factors(f)={{x-2,1},{x+2,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 4 >> - << >>> Test Factors() on polynomial: >> f : x^2+2*x+1 - Factors(f)={{x+1,2}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 5 >> - << >>> Test Factors() on polynomial: >> f : 45*x-9*x^2-36 - Factors(f)={{-9,1},{x-1,1},{x-4,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 6 >> - << >>> Test Factors() on polynomial: >> f : x^2-a^2 - Factors(f)={{x+a,1},{x-a,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 7 >> - << >>> Test Factors() on polynomial: >> f : 9*x^2-1 - Factors(f)={{3*x+1,1},{3*x-1,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 8 >> - << >>> Test Factors() on polynomial: >> f : x^3-y^3 - Factors(f)={{x-y,1},{x^2+y*x+y^2,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 9 >> - << >>> Test Factors() on polynomial: >> f : 4*x^3+12*x^2-40*x - Factors(f)={{4,1},{x,1},{x-2,1},{x+5,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 10 >> - << >>> Test Factors() on polynomial: >> f : 32*x^3+32*x^2-70*x-75 - Factors(f)={{2*x-3,1},{4*x+5,2}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 11 >> - << >>> Test Factors() on polynomial: >> f : 3*x^3-12*x^2-2*x+8 - Factors(f)={{x-4,1},{3*x^2-2,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 12 >> - << >>> Test Factors() on polynomial: >> f : x^3+3*x^2-25*x-75 - Factors(f)={{x+3,1},{x+5,1},{x-5,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 13 >> - << >>> Test Factors() on polynomial: >> f : 2*x^3-30*x^2+12*x^4 - Factors(f)={{2,1},{x,2},{2*x-3,1},{3*x+5,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 14 >> - << >>> Test Factors() on polynomial: >> f : 5*x^7-20*x^6+25*x^5-20*x^4+25*x^3-20*x^2+20*x - Factors(f)={{5,1},{x,1},{x-2,2},{x^2+x+1,1},{x^2-x+1,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 15 >> - << >>> Test Factors() on polynomial: >> f : (2*x^2)/5-2*x-12/5 - Factors(f)={{2/5,1},{x+1,1},{x-6,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 16 >> - << >>> Test Factors() on polynomial: >> f : 0.4*x^2-2*x-2.4 - Factors(f)={{2/5,1},{x+1,1},{x-6,1}} - Answer is CORRECT - << ------------------------------------------------------------------->> - << 17 >> - << >>> Test Factors() on polynomial: >> f : 9*x^2.0-1 - Factors(f)={{9*x^2.0-1,1}} - Answer is WRONG: it should be {{3*x-1,1},{3*x+1,1}} -. %/output - - - - diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/xSingle_test_solve.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/xSingle_test_solve.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/xSingle_test_solve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/xSingle_test_solve.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,52 @@ +%mathpiper + +Use("proposed.rep/xSolve.mpi"); + +%/mathpiper + + + +%mathpiper,def="xSingle_test_solve",scope="private" + +//######################################################################## +// T E S T I N G T E S T I N G T E S T I N G +//######################################################################## + +// a bunch of expressions for testing +expressions := {}; + +Push( expressions, {3/(x^2+x-2)-1/(x^2-1)-7/(2*(x^2+3*x+2))==0,{x==3}}); +Push( expressions, {3/(x^2+x-2)-1/(x^2-1)==7/(2*(x^2+3*x+2)),{x==3}}); + + +NewLine(2); Tell("TEST xSolve()"); +expressions := Reverse(expressions); +Local(i); i := 0; +ForEach(q,expressions) +[ + i := i + 1; + Check(i<50, ">>>>> FORCED STOP <<<<<"); + f := q[1]; + If( f = blank, + [ + i := i - 1; + NewLine(); + ], + [ + g := q[2]; + Tell("-------------------------------------------------------------------"); + Tell(i); + Tell(">>> Test xSolve() on the expression: ",f); + stk := {}; + r := xSolve(f,x); + SysOut(" xSolve(f,x) ==> ",r); + rmg := Simplify(Expand(UnFlatten(r-g,"+",0))); + If( IsZero(rmg) Or IsZeroVector(rmg), + SysOut(" Answer is CORRECT"), + SysOut(" Answer is WRONG: it should be ",g) + ); + ] + ); +]; + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/xTermsTest.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/xTermsTest.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/xTermsTest.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/xTermsTest.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,50 @@ +%mathpiper + +Use("proposed.rep/xSolve.mpi"); + +%/mathpiper + + %output,preserve="false" + Result: True +. %/output + + + +%mathpiper,scope="private" + +// a bunch of expressions for testing +expressions := {}; +Push( expressions, 4 ); +Push( expressions, -4 ); +Push( expressions, 3*y^2 - Sin(Pi*y) ); +Push( expressions, a*x+b*x^2 ); +Push( expressions, -a*x+b*x^2 ); +Push( expressions, -a*x-b*x^2 ); +Push( expressions, +a*x+b*x^2 ); +Push( expressions, a*x + b*x^2-c/x+d/x^2 ); +Push( expressions, a1/(b1+c1*x^2) ); +Push( expressions, x+Sin(x) ); +Push( expressions, x-Sin(x) ); +Push( expressions, a*x+Sin(x) ); +Push( expressions, Sin(x)-x ); +Push( expressions, Sqrt(x) ); +Push( expressions, Sqrt(1/x) ); +Push( expressions, Sqrt(1/(x^2+1)) ); +Push( expressions, Sqrt((1-x)/(1+x)) ); +Push( expressions, 1/x+1/x^2 ); +Push( expressions, a/(x+1)+b/(x-1) ); +Push( expressions, (1-x)^(3/2) ); +Push( expressions, a*(x-3*x^2) ); +Push( expressions, (x+2*x^3)/c ); + +nn := Length( expressions ); +For( i:=1, i<=nn, i++ ) +[ + f := PopBack( expressions ); + Echo("-------------------------------------------------------------------"); + Echo(">>> new expression: ",f); + //r:=V(xTerms(f)); + r:=xTerms2(f); + Echo({r}); +]; +%/mathpiper diff -Nru mathpiper-0.0.svn2556/tests/manual_tests/xTestSolve.mpw mathpiper-0.81f+dfsg1/tests/manual_tests/xTestSolve.mpw --- mathpiper-0.0.svn2556/tests/manual_tests/xTestSolve.mpw 1970-01-01 00:00:00.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/manual_tests/xTestSolve.mpw 2009-12-29 02:06:43.000000000 +0000 @@ -0,0 +1,139 @@ +%mathpiper,title="xTestSolve" + +Use("proposed.rep/xSolve.mpi"); + +//######################################################################## +// T E S T I N G T E S T I N G T E S T I N G +//######################################################################## + +iDebug := False; +//iDebug := True; + +// a bunch of expressions for testing +expressions := {}; +Push( expressions, {a,{}} ); +Push( expressions, {0,{{x==x}}} ); +Push( expressions, {x-5,{{x==5}}} ); +Push( expressions, {x-a,{{x==a}}} ); +Push( expressions, {12*x+5==29,{{x==2}}} ); +Push( expressions, {5*x-15==5*(x-3),{x==x}} ); +Push( expressions, {5*x-15==5*(x-4),{}} ); + +Push( expressions, {x^2-4,{x==2,x==(-2)}} ); +Push( expressions, {x^2-a^2,{x==a,x==(-a)}} ); +Push( expressions, {2*x^2+9*x==18,{x==3/2,x==(-6)}} ); +Push( expressions, {5*x^2==25*x, {x==0,x==5}} ); + +Push( expressions, {2*x/5-x/3==2,{x==30}}); +Push( expressions, {2/x-3/2==7/(2*x),{x==(-1)}}); +Push( expressions, {2/(x-3)-3/(x+3)==12/(x^2-9),{}}); +Push( expressions, {3/(x^2+x-2)-1/(x^2-1)==7/(2*(x^2+3*x+2)),{x==3}}); +Push( expressions, {1+1/x==6/x^2,{x==2,x==(-3)}}); + +Push( expressions, {Sqrt(x)-3,{x==9}}); +Push( expressions, {Sqrt(x-3),{x==3}}); +Push( expressions, {Sqrt(x-3)==2, {x==7}}); +Push( expressions, {Sqrt(2*x)==Sqrt(x+1), {x==1}}); +Push( expressions, {Sqrt(x)==x, {x==1,x==0}}); +Push( expressions, {Sqrt(x+2)-2*x==1,{x==1/4} } ); +Push( expressions, {Sqrt(x+2)+2*x==1,{x==(5 - Sqrt(41))/8} } ); +Push( expressions, {Sqrt(9*x^2+4)-3*x==1,{x==1/2} } ); +Push( expressions, {Sqrt(x+1)-Sqrt(x)==-2,{} } ); +Push( expressions, {Sqrt(3*x-5)-Sqrt(2*x+3)==-1,{x==3} } ); + +Push( expressions, {Exp(x)==4, {x==Ln(4)}}); +Push( expressions, {Exp(x)==Abs(a), {x==Ln(Abs(a))}}); +Push( expressions, {Ln(x)==4, {x==Exp(4)}}); +Push( expressions, {Ln(x)==a, {x==Exp(a)}}); + +Push( expressions, {(x+6)/2-(3*x+36)/4==4, {x==-40} } ); +Push( expressions, {(x-3)*(x-4)==x^2-2, {x==2} } ); +Push( expressions, {a*x-2*b*c==d,{x==(2*b*c+d)/a} } ); +Push( expressions, {(36-4*x)/(x^2-9)-(2+3*x)/(3-x)==(3*x-2)/(x+3),{x==-2} } ); +Push( expressions, {(x^2-1)^(1/3)==2,{x==3,x==(-3)} } ); + +Push( expressions, {x^4-53*x^2+196==0, {x==(-7),x==(-2),x==2,x==7} } ); +Push( expressions, {x^3-8==0, {x==2,x==-1+I*Sqrt(3),x==-1-I*Sqrt(3)} } ); +Push( expressions, {x^(2/3)+x^(1/3)-2==0, {x==1,x==(-8)} } ); +Push( expressions, {Sqrt(x)-(1/4)*x==1, {x==4} } ); +Push( expressions, {(1/4)*x-Sqrt(x)==-1, {x==4} } ); + +Push( expressions, {{x-y==1,3*x+2*y==13}, {x==3,y==2} } ); +Push( expressions, {{x-y-1==0,2*y+3*x-13==0}, {x==3,y==2} } ); + +//Push( expressions, {, {} } ); + +//Push( expressions, {,{{},{},{},{}}} ); + +NewLine(2); Tell("TEST xSolve()"); +t1 := SystemTimer(); +expressions := Reverse(expressions); +Local(i); i := 0; +Local(iCorrect); iCorrect := 0; +ForEach(q,expressions) +[ + i := i + 1; + Check(i<100, ">>>>> FORCED STOP <<<<<"); + f := q[1]; + If( f = blank, + [ + i := i - 1; + NewLine(); + ], + [ + //If(i=23 Or i=26 Or i=40,iDebug:=True,iDebug:=False); + + Local(vars); + g := q[2]; + NewLine(); + Tell(i,"-------------------------------"); + Tell(">>> Test xSolve() on the expression: ",f); + stk := {}; + vars := VarList(f); + If(IsList(f), + [ + If(iDebug=True,Tell(" system")); + r := xSolve(f,vars); + SysOut(" xSolve(f,vars) ==> ",r); + ], + [ + If(iDebug=True,Tell(" single")); + r := xSolve(f,x); + SysOut(" xSolve(f,x) ==> ",r); + ] + ); + //If(IsList(f),Break()); + rmg := Simplify(Expand(UnFlatten(r-g,"+",0))); + If(iDebug=True,Tell("rmg",rmg)); + If(iDebug And IsList(rmg),Tell(Listify(rmg))); + If( IsZero(rmg) Or IsZeroVector(rmg), + [SysOut(" Answer is CORRECT"); iCorrect:=iCorrect+1;], + [ + If(iDebug=True,Tell("check rmg a little more")); + Local(Lrmg,Lrmg2,Lrmg3); + Lrmg := Listify(rmg); + If(iDebug=True,Tell("Listify rmg",Lrmg)); + If(Lrmg[1] != UnFlatten, + [ + Lrmg2 := Listify(Lrmg[2]); + Lrmg3 := Listify(Lrmg[3]); + If(iDebug=True,Tell("LL",{Lrmg2,Lrmg3})); + If(CloseEnough(Lrmg2[3],Lrmg3[3],10), + [SysOut(" Answer is CORRECT"); iCorrect:=iCorrect+1;], + [SysOut(" Answer is WRONG: should be ",g );] + ); + ], + SysOut(" Answer is WRONG: should be ",g ) + ); + ] + ); + //SysOut(" Answer is WRONG: it should be ",g); + ] + ); +]; +NewLine(2); +Tell("DONE",{iCorrect,i}); +t2 := SystemTimer(); +Echo("Time taken: ",N((t2-t1)/10^9)," sec"); + +%/mathpiper diff -Nru mathpiper-0.0.svn2556/tests/mathpiper_tests.log mathpiper-0.81f+dfsg1/tests/mathpiper_tests.log --- mathpiper-0.0.svn2556/tests/mathpiper_tests.log 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/mathpiper_tests.log 2011-01-18 06:26:27.000000000 +0000 @@ -1,7 +1,10 @@ +Turning stack tracing on: Result: True -***** Sat Sep 12 01:10:44 EDT 2009 ***** -***** Using a new interpreter instance for each test file. ***** -***** MathPiper version: .76i ***** +Side Effects: +Stack tracing is on. + +***** Mon Jan 10 09:55:07 PST 2011 ***** +***** MathPiper version: .81c ***** =========================== arithmetic.mpt: @@ -9,6 +12,7 @@ Result: True Side Effects: + Test suite for Test arithmetic : Test suite for Basic calculations : @@ -19,15 +23,12 @@ --Rounding --Bases --Factorization -Exception: + =========================== binaryfactors.mpt: Result: True -Side Effects: - -Exception: =========================== calculus.mpt: @@ -39,56 +40,57 @@ --Limits Known failure: Limit(k,Infinity)((k-phi)/k)^(k+1/2)=Exp(-phi) --Pslq -Exception: + =========================== canprove.mpt: Result: True Side Effects: -Test suite for Propositional logic theorem prover : -Exception: + +Test suite for Propositional logic theorem prover : + =========================== comments.mpt: Result: True Side Effects: -Test suite for Checking comment syntax supported : -Exception: + +Test suite for Checking comment syntax supported : + =========================== complex.mpt: Result: True Side Effects: -Known failure: (Limit(n,Infinity)(n^2*I^n)/(n^3+1))=0 -Exception: +Known failure: (Limit(n,Infinity)(n^2*I^n)/(n^3+1))=0 + =========================== c_tex_form.mpt: Result: True Side Effects: + Test suite for TeXForm()... : --IsCFormable -Exception: + =========================== cyclotomic.mpt: Result: True Side Effects: -Test suite for Cyclotomic Polynomials : -Exception: + +Test suite for Cyclotomic Polynomials : + =========================== deriv.mpt: Result: True -Side Effects: - -Exception: =========================== dimensions.mpt: @@ -96,7 +98,7 @@ Side Effects: ---- Dimensions (Tensor Rank) -Exception: + =========================== dot.mpt: @@ -104,15 +106,16 @@ Side Effects: ---- Dot -Exception: + =========================== GaussianIntegers.mpt: Result: True Side Effects: -Test suite for Gaussian Integers : -Exception: + +Test suite for Gaussian Integers : + =========================== includetestfiles: is not a MathPiper test file. @@ -121,17 +124,15 @@ Result: True +=========================== +issues.mpt: + +Result: True + Side Effects: -****************** -tests/scripts/integrate.mpt: 28 -Integrate(x)Sin(x)/(2*y+4) - evaluates to -(-Cos(x))/(2*y+4) - which differs from -(-Cos(x))/(2*(y+2)) -****************** -Exception: +Test suite for Problems reported as Issues : + =========================== io.mpt: @@ -139,15 +140,12 @@ Side Effects: --Error reporting -Exception: + =========================== journal.mpt: Result: True -Side Effects: - -Exception: =========================== linalg.mpt: @@ -172,13 +170,14 @@ --Inverse --SolveMatrix --Trace -Exception: + =========================== lists.mpt: Result: True Side Effects: + Test suite for VarList : --BubbleSort --HeapSort @@ -189,23 +188,21 @@ --Binary searching --AssocDelete ---- Arithmetic Operations -Exception: + =========================== logic_simplify_test.mpt: Result: True Side Effects: -Test suite for CNF : -Exception: + +Test suite for CNF : + =========================== macro.mpt: Result: True -Side Effects: - -Exception: =========================== mathpiper_tests.log: is not a MathPiper test file. @@ -216,15 +213,16 @@ Side Effects: ---- MatrixPower -Exception: + =========================== multivar.mpt: Result: True Side Effects: -Test suite for Test arithmetic : -Exception: + +Test suite for Test arithmetic : + =========================== nthroot.mpt: @@ -232,7 +230,7 @@ Side Effects: ---- NthRoot -Exception: + =========================== numbers.mpt: @@ -242,7 +240,7 @@ --Integer logarithms and roots --Factorial --Random numbers -Exception: + =========================== numerics.mpt: @@ -250,408 +248,83 @@ Side Effects: ****************** -tests/scripts/numerics.mpt: 9 - -RoundTo(N(Sqrt(2),5)-1.41421,5) - evaluates to --0.00001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 16 - -RoundTo(N(Pi,70)-3.1415926535897932384626433832795028841971693993751058209749445923078164062862,70) - evaluates to --0.0000000004102067615 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 18 - -RoundTo(N(Sec(2),9)-(-2.402997962),9) - evaluates to -0.000000002 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 20 - -RoundTo(N(Cot(2),9)-(-0.457657554),9) - evaluates to --0.000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 21 - -RoundTo(N(Sinh(2),10)-3.6268604078,10) - evaluates to --0.000000006 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 23 - -RoundTo(N(ArcSin(2),9)-Complex(1.570796327,1.316957897),9) - evaluates to -Complex(0.000000003,-0.000000007) - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 24 - -RoundTo(N(ArcCos(2),9)-Complex(0,-1.316957897),9) - evaluates to -Complex(0,0.000000007) - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 26 - -RoundTo(N(ArcSinh(2),9)-1.443635475,9) - evaluates to --0.000000005 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 27 - -RoundTo(N(ArcCosh(2),9)-1.316957897,9) - evaluates to --0.000000007 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 29 - -RoundTo(N(ArcTanh(2),9)-Complex(0.549306144,1.570796327),9) - evaluates to -Complex(0.000000001,0.000000003) - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 42 - -RoundTo(RoundTo(N(Sin(2.0)),49)-0.9092974268256816953960198659117448427022549714479,49) - evaluates to -0.0000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 47 - -RoundTo(RoundTo(N(Sin(2.0)),50)-0.90929742682568169539601986591174484270225497144789,50) - evaluates to -0.00000000000000000000000000000000000000000000000003 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 52 - -RoundTo(RoundTo(N(Sin(2.0)),51)-0.90929742682568169539601986591174484270225497144789,51) - evaluates to -0.000000000000000000000000000000000000000000000000021 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 62 - -RoundTo(RoundTo(N(Tan(20.0)),49)-2.2371609442247422652871732477303491783724839749188,49) - evaluates to -0.0000000000000000000000000000000000000000000000002 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 67 - -RoundTo(RoundTo(N(Exp(10.32),54),54)-30333.2575962246035600343483350109621778376486335450125,48) - evaluates to -0.000000000000000000000000000000000000000000000013 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 72 - -RoundTo(RoundTo(N(Ln(10.32/4.07)),49)-0.93044076059891305468974486564632598071134270468,49) - evaluates to -0.0000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 77 - -RoundTo(RoundTo(N(1.3^10.32),48)-14.99323664825717956473936947123246987802978985306,48) - evaluates to -0.00000000000000000000000000000000000000000000004 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 82 - -RoundTo(RoundTo(N(Sqrt(5.3),51),51)-2.302172886644267644194841586420201850185830282633675,51) - evaluates to --0.00000000000000000000000000000000000000000000000002 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 106 - -RoundTo(RoundTo(N(ArcSin(0.32)),49)-0.3257294872946301593103199105324500784354180998123,49) - evaluates to -0.0000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 111 - -RoundTo(RoundTo(N(Sin(N(ArcSin(0.1234567)))),49)-0.1234567,49) - evaluates to -0.0000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 118 - -RoundTo(RoundTo(N((1-Sin(N(ArcSin(1-10^(-25)))))*10^25),25)-1.,25) - evaluates to --0.0000000000000000000000002 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 123 - -RoundTo(N(ArcSin(N(Sin(1.234567),50)),50)-N(1.234567,50),49) - evaluates to -0.0000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 128 - -RoundTo(RoundTo(N(ArcCos(0.32)),49)-1.2450668395002664599210017811073013636631665998753,49) - evaluates to --0.0000000000000000000000000000000000000000000000003 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 133 - -RoundTo(RoundTo(N(ArcTan(0.32)),49)-0.3097029445424561999173808103924156700884366304804,49) - evaluates to -0.0000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 138 +tests/scripts4/numerics.mpt: 193 -RoundTo(RoundTo(N(Cos(N(ArcCos(0.1234567)))),49)-0.1234567,49) +newrepL[1]-newrepR[1] evaluates to -0.0000000000000000000000000000000000000000000000001 +-53768446116670492691 which differs from 0 ****************** ****************** -tests/scripts/numerics.mpt: 187 +tests/scripts4/numerics.mpt: 195 -RoundTo(RoundTo(N(Internal'GammaNum(10.5)),13)-1133278.3889487855673,13) +newrepL[1]-newrepR[1] evaluates to -0.0000002144327 +-6282627216144394152 which differs from 0 ****************** ****************** -tests/scripts/numerics.mpt: 192 +tests/scripts4/numerics.mpt: 282 -RoundTo(RoundTo(N(Gamma(10.5)),13)-1133278.3889487855673,13) +newrepL[1]-newrepR[1] evaluates to -0.0000002144327 +-3357578071772547517286808 which differs from 0 ****************** ****************** -tests/scripts/numerics.mpt: 219 +tests/scripts4/numerics.mpt: 287 -RoundTo(RoundTo(N(Zeta(40)),19)-1.0000000000009094948,19) +newrepL[1]-newrepR[1] evaluates to -0.0000000000000000002 +406993831 which differs from 0 ****************** -****************** -tests/scripts/numerics.mpt: 224 - -RoundTo(RoundTo(N(Zeta(1.5)),19)-2.6123753486854883433,19) - evaluates to --0.0000000000000000003 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 283 - -RoundTo(N(BesselJ(0,.5))-RoundTo(.93846980724081290422840467359971262556892679709682,50),50) - evaluates to --0.00000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 284 - -RoundTo(N(BesselJ(0,.9))-RoundTo(.80752379812254477730240904228745534863542363027564,50),50) - evaluates to --0.00000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 285 - -RoundTo(N(BesselJ(0,.99999))-RoundTo(.76520208704756659155313775543958045290339472808482,50),50) - evaluates to --0.00000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 291 - -RoundTo(N(BesselJ(11,11))-RoundTo(.20101400990926940339478738551009382430831534125484,50),50) - evaluates to --0.00000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 293 - -RoundTo(RoundTo(N(BesselJ(1,10)),50)-RoundTo(.04347274616886143666974876802585928830627286711859,50),50) - evaluates to -0.00000000000000000000000000000000000000000000000011 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 294 - -RoundTo(N(BesselJ(10,10))-RoundTo(.20748610663335885769727872351875342803274461128682,50),50) - evaluates to --0.00000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 295 - -RoundTo(RoundTo(N(BesselJ(1,3.6)),50)-RoundTo(.09546554717787640384570674422606098601943275490885,50),50) - evaluates to -0.00000000000000000000000000000000000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 300 - -RoundTo(N(Erf(Sqrt(0.8)),20),19) - evaluates to -0.7940967892679316913 - which differs from -0.7940967892679316912 -****************** -****************** -tests/scripts/numerics.mpt: 303 - -RoundTo(N(Erf(50*I+20)/10^910,22),19) - evaluates to -Complex(1.093171190029095858,0.0047546330693181896) - which differs from -Complex(1.093171190029095854,0.0047546330693181896) -****************** --Gamma constant ****************** -tests/scripts/numerics.mpt: 308 +tests/scripts4/numerics.mpt: 318 -RoundTo(Internal'gamma()+0-0.5772156649015328606065120900824024310422,BuiltinPrecisionGet()) +newrepL[1]-newrepR[1] evaluates to -0.0000000000000000000000000000000000000001 +2 which differs from 0 ****************** -****************** -tests/scripts/numerics.mpt: 311 -RoundTo(RoundTo(Internal'gamma()+0,19)-0.5772156649015328606,19) - evaluates to -0.0000000000000000001 - which differs from -0 -****************** -****************** -tests/scripts/numerics.mpt: 312 - -RoundTo(RoundTo(N(1/2+gamma+Pi),19)-4.2188083184913260991,19) - evaluates to --0.0000000000000000001 - which differs from -0 -****************** -Exception: =========================== nummethods.mpt: Result: True -Side Effects: - -Exception: =========================== ode.mpt: Result: True Side Effects: +**** THE ODE TEST HAS BEEN TEMPORARILY REMOVED BECAUSE IT CAUSED AN INFINITE RECURSION **** -Exception: =========================== openmath.mpt: Result: True Side Effects: -Test suite for Converting to and from OpenMath expressions : -Exception: + +Test suite for Converting to and from OpenMath expressions : + =========================== orthopoly.mpt: Result: True Side Effects: -Test suite for Testing orthogonal polynomials : -Exception: + +Test suite for Testing orthogonal polynomials : + =========================== outer.mpt: @@ -659,79 +332,62 @@ Side Effects: ---- Outer -Exception: + =========================== piper_test.bat: is not a MathPiper test file. =========================== plots.mpt: -Result: False +Result: True Side Effects: ****************** -tests/scripts/plots.mpt: 6 +tests/scripts4/plots.mpt: 6 -ToString()Write(Plot2D(a,-1:1,output->data,points->4,depth->0)) +PipeToString()Write(Plot2D(a,-1:1,output->data,points->4,depth->0)) evaluates to "{{{-1,-1},{-0.5,-0.5},{0.0,0.0},{0.5,0.5},{1,1}}}" which differs from "{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}" ****************** ****************** -tests/scripts/plots.mpt: 7 +tests/scripts4/plots.mpt: 7 -ToString()Write(Plot2D(b,b->-1:1,output->data,points->4)) +PipeToString()Write(Plot2D(b,b->-1:1,output->data,points->4)) evaluates to "{{{-1,-1},{-0.5,-0.5},{0.0,0.0},{0.5,0.5},{1,1}}}" which differs from "{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}" ****************** ****************** -tests/scripts/plots.mpt: 14 +tests/scripts4/plots.mpt: 14 -ToString()Write(Plot3DS(a,-1:1,-1:1,output->data,points->2)) +PipeToString()Write(Plot3DS(a,-1:1,-1:1,output->data,points->2)) evaluates to "{{{-1,-1,-1},{-1,0,-1},{-1,1,-1},{0,-1,0},{0,0,0},{0,1,0},{1,-1,1},{1,0,1},{1,1,1}}}" which differs from "{{{-1,-1,-1},{-1,0,-1},{-1,1.,-1},{0,-1,0},{0,0,0},{0,1.,0},{1.,-1,1.},{1.,0,1.},{1.,1.,1.}}}" ****************** ****************** -tests/scripts/plots.mpt: 14 +tests/scripts4/plots.mpt: 14 -ToString()Write(Plot3DS(x1,x1->-1:1,x2->-1:1,output->data,points->2)) +PipeToString()Write(Plot3DS(x1,x1->-1:1,x2->-1:1,output->data,points->2)) evaluates to "{{{-1,-1,0.1011417762},{-1,0,0.1011417762},{-1,1,0.1011417762},{0,-1,0.1011417762},{0,0,0.1011417762},{0,1,0.1011417762},{1,-1,0.1011417762},{1,0,0.1011417762},{1,1,0.1011417762}}}" which differs from "{{{-1,-1,-1},{-1,0,-1},{-1,1.,-1},{0,-1,0},{0,0,0},{0,1.,0},{1.,-1,1.},{1.,0,1.},{1.,1.,1.}}}" ****************** -****************** -tests/scripts/plots.mpt: 23 - -RoundTo(RoundTo(f(3),BuiltinPrecisionGet())-0.6666666667,BuiltinPrecisionGet()) - evaluates to -0.0000000001 - which differs from -0 -****************** -****************** -tests/scripts/plots.mpt: 26 -RoundTo(RoundTo(f1(3),BuiltinPrecisionGet())-0.6666666667,BuiltinPrecisionGet()) - evaluates to -0.0000000001 - which differs from -0 -****************** -Exception: =========================== poly.mpt: Result: True Side Effects: -Test suite for Polynomials : -Exception: + +Test suite for Polynomials : + =========================== predicates.mpt: @@ -742,27 +398,9 @@ --Boolean Operations --NumberCompares --comparisons in exponential notation -****************** -tests/scripts/predicates.mpt: 79 - -1.0000000000000000000000000000111>1 - evaluates to -False - which differs from -True -****************** -****************** -tests/scripts/predicates.mpt: 80 - -0.999999999999999999999999999992<1 - evaluates to -False - which differs from -True -****************** --Matrix predicates ****************** -tests/scripts/predicates.mpt: 121 +tests/scripts4/predicates.mpt: 123 HasFuncArith(a*b+f({b,c}),List) evaluates to @@ -778,7 +416,7 @@ ------ IsMatrix ------ IsMatrix(IsInteger) ------ IsSquareMatrix -Exception: + =========================== programming.mpt: @@ -790,42 +428,26 @@ --MapSingle --Function definitions --LocalVariables -Exception: + =========================== radsimp.mpt: Result: True Side Effects: -Test suite for Testing simplifying nested radicals : -Exception: + +Test suite for Testing simplifying nested radicals : + =========================== regress.mpt: Result: True Side Effects: -Test suite for Regression on bug reports : -****************** -tests/scripts/regress.mpt: 192 -RoundTo(RoundTo(N(ArcSin(0.0000000321232123),50),50)-0.00000003212321230000000552466124302049336784679316,50) - evaluates to -0.000000000000000000000005524661243 - which differs from -0 -****************** -****************** -tests/scripts/regress.mpt: 304 - -RoundTo(N(Cos(Pi*.5))-0,BuiltinPrecisionGet()) - evaluates to --0.0000000002 - which differs from -0 -****************** +Test suite for Regression on bug reports : ****************** -tests/scripts/regress.mpt: 326 +tests/scripts4/regress.mpt: 328 (Integrate(x,a,b)Cos(x)^2)-((b-Sin((-2)*b)/2)/2-(a-Sin((-2)*a)/2)/2) evaluates to @@ -835,28 +457,26 @@ ****************** Known failure: (Limit(x,Infinity)x^n/Ln(x))=Infinity Known failure: (Limit(x,0,Right)x^(Ln(a)/(1+Ln(x))))=a -Known failure: Gcd(10,3.3)!=3.3AndGcd(10,3.3)!=1 -Known failure: (D(z)Conjugate(z))=Undefined +Known failure: Gcd(10,3.3)!=3.3 And Gcd(10,3.3)!=1 +Known failure: (Differentiate(z)Conjugate(z))=Undefined Known failure: ArcCos(Cos(beta))!=beta Known failure: (Limit(n,Infinity)n^5/2^n)=0 -Known failure: RoundTo(RoundTo(N(Cot(2),9),9),N(Cot(2),9),9)=0 -Exception: +Known failure: RoundTo(RoundTo(N(Cot(2),9),9),N(Cot(2),9),9)=0 + =========================== scopestack.mpt: Result: True -Side Effects: - -Exception: =========================== simplify.mpt: Result: True Side Effects: -Test suite for Simplify : -Exception: + +Test suite for Simplify : + =========================== solve.mpt: @@ -865,18 +485,16 @@ Side Effects: --Solve --PSolve -Exception:In function "If" : -bad argument number 1(counting from 1) : +-- Linear +-- Quadratic +-- Cubic +-- Quartic -The offending argument NotApply(compare,{left,right}) evaluated to NotComplex(2.00000000000000000000000000001,0.000000000000000... Source file: tests/scripts/solve.mpt Line number: 176 =========================== sturm.mpt: Result: True -Side Effects: - -Exception: =========================== sums.mpt: @@ -885,23 +503,24 @@ Side Effects: --Taylor ****************** -tests/scripts/sums.mpt: 339 +tests/scripts4/sums.mpt: 339 -$pp2091 +$pp2187 evaluates to Taylor'LPS(1,{-2,0,1/3,0},t,Taylor'LPS'ScalarMult(-1,Taylor'LPS(1,{2,0,(-1)/3,0},t,Taylor'LPS'ScalarMult(2,Taylor'LPS(1,{1,0,(-1)/6,0},t,Sin(t)))))) which differs from Taylor'LPS(1,{-2,0,1/3,0},t,Taylor'LPS'ScalarMult(-2,Taylor'LPS(1,{1,0,(-1)/6,0},t,Sin(t)))) ****************** -Exception: + =========================== tensors.mpt: Result: True Side Effects: -Test suite for Tensors : -Exception: + +Test suite for Tensors : + =========================== test-yacas-c-version: is not a MathPiper test file. @@ -912,28 +531,21 @@ Side Effects: ---- Trace -Exception: -=========================== -transforms.mpt: - -Result: True - -Side Effects: -Exception: =========================== -tr.mpt: +transforms.mpt: Result: True -Side Effects: ----- Tr (trace of tensor) -Exception: =========================== : is not a MathPiper test file. ***** Tests complete ***** -Exception Count: 1 +Exception Count: 0 +GlobalVariables: Result: True + +Side Effects: +{$a73,$a994,$assumptions78,$b73,$b994,$bernoulli1Threshold56,$CacheOfConstantsN1,$CFormAllFunctions63,$cformMathFunctions61,$cformRegularOps60,$cindent62,$ClearScreenString40,$complexReduce54,$Debug'FileLines40,$Debug'FileLoaded40,$Debug'NrLines40,$ErrorTableau59,$formulaMaxWidth68,$GlobalStack19,$intpred72,$knownOrthoPoly71,$knownRNGDists50,$knownRNGEngines50,$lastcoef48,$LocResult74,$mathExpThreshold52,$mNum33,$n'max58,$nNum33,$NthRoot'Table162,$numericMode2,$omindent65,$omsymbol67,$omsymbolreverse67,$omtoken66,$options989,$p02187,$p12187,$p22187,$p32187,$p42,$p42187,$p993,$pc242187,$pc352187,$pc462187,$pc572187,$pc682187,$pj2187,$pj402187,$pj502187,$pj512187,$pj522187,$pj532187,$pj542187,$pju02187,$pp2187,$RandSeed51,$res36,$res79,$rFormMathFunctions45,$rFormRegularOps44,$RIndent46,$simple994,$st1011,$TeXFormGreekLetters69,$TeXFormMathFunctions270,$TeXFormMathFunctions70,$TeXFormRegularOps69,$TeXFormRegularPrefixOps69,$TeXFormSpecialNames69,$Verbose41,%,I,LoadResult} diff -Nru mathpiper-0.0.svn2556/tests/scripts/arithmetic.mpt mathpiper-0.81f+dfsg1/tests/scripts/arithmetic.mpt --- mathpiper-0.0.svn2556/tests/scripts/arithmetic.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/arithmetic.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,166 +0,0 @@ - -NextTest("Test arithmetic"); - -NextTest("Basic calculations"); -Verify(3 + 2 , 5); -Verify(3-7, -4); -Verify(1 = 2 , 0 = -1); -Verify(5 ^ 2 , 25); - -Verify(IsZero(0.000),True); - -Verify(2/5,Hold(2/5)); -Verify(IsZero(N(2/5)-0.4)); -Verify(IsRational(2),True); -Verify(IsRational(2/5),True); -Verify(IsRational(-2/5),True); -Verify(IsRational(2.0/5),False); -Verify(IsRational(Pi/2),False); -Verify(Numerator(2/5),2); -Verify(Denominator(2/5),5); - -VerifyArithmetic(10,5,8); -VerifyArithmetic(10000000000,5,8); -VerifyArithmetic(10,50,80); -VerifyArithmetic(10000,50,88); - -Verify(4!,24); -Verify(BinomialCoefficient(2,1),2); - -NextTest("Testing math stuff"); -Verify(1*a,a); -Verify(a*1,a); -Verify(0*a,0); -Verify(a*0,0); -Verify(aa-aa,0); - -Verify(2+3,5); -Verify(2*3,6); - -Verify(2+3*4,14); -Verify(3*4+2,14); -Verify(3*(4+2),18); -Verify((4+2)*3,18); - -Verify(15/5,3); - -Verify(-2+3,1); -Verify(-2.01+3.01,1.); - -Verify(0+a,a); -Verify(a+0,a); -Verify(aa-aa,0); - -Testing("IntegerOperations"); -Verify(1<<10,1024); -Verify(1024>>10,1); -Verify(Mod(10,3),1); -Verify(Div(10,3),3); -Verify(GcdN(55,10),5); - -Verify(Mod(2,Infinity),2); -Verify(Mod({0,1,2,3,4,5,6},2),{0,1,0,1,0,1,0}); -Verify(Mod({0,1,2,3,4,5,6},{2,2,2,2,2,2,2}),{0,1,0,1,0,1,0}); - -Testing("PowerN"); -// was broken in the gmp version -Verify(PowerN(19, 0), 1); -Verify(PowerN(1, -1), 1); -Verify(PowerN(1, -2), 1); -Verify(IsZero(PowerN(10, -2)- 0.01)); -Verify(PowerN(2, 3), 8); -NumericEqual(PowerN(2, -3), 0.125,BuiltinPrecisionGet()); - -Testing("Rounding"); -Verify(Floor(1.2),1); -Verify(Floor(-1.2),-2); -Verify(Ceil(1.2),2); -Verify(Ceil(-1.2),-1); -Verify(Round(1.49),1); -Verify(Round(1.51),2); -Verify(Round(-1.49),-1); -Verify(Round(-1.51),-2); - -Testing("Bases"); -Verify(ToBase(16,255),"ff"); -Verify(FromBase(2,"100"),4); - -// conversion between decimal and binary digits -Verify(BitsToDigits(2000, 10), 602); -Verify(DigitsToBits(602, 10), 2000); - -LocalSymbols(f,ft) -[ - f(x,y):=(Div(x,y)*y+Rem(x,y)-x); - ft(x,y):= - [ - Verify(f(x,y),0); - Verify(f(-x,y),0); - Verify(f(x,-y),0); - Verify(f(-x,-y),0); - ]; - ft(10,4); - ft(2.5,1.2); -]; - -Testing("Factorization"); -Verify( -Eval(Factors(447738843)) -, {{3,1},{17,1},{2729,1},{3217,1}} -); - - -//Exponential notation is now supported in the native arithmetic library too... -Verify(2e3+1,2001.); -Verify(2.0e3+1,2001.); -Verify(2.00e3+1,2001.); -Verify(2.000e3+1,2001.); -Verify(2.0000e3+1,2001.); - -Verify(1+2e3,2001.); -Verify(1+2.0e3,2001.); -Verify(1+2.00e3,2001.); -Verify(1+2.000e3,2001.); -Verify(1+2.0000e3,2001.); - -NumericEqual(N(Sqrt(1e4))-100,0,BuiltinPrecisionGet()); -NumericEqual(N(Sqrt(1.0e4))-100,0,BuiltinPrecisionGet()); - -Verify(2.0000e3-1,1999.); -[ - Local(p); - p:=BuiltinPrecisionGet(); - BuiltinPrecisionSet(12);//TODO this will fail if you drop precision to below 12, for some reason. - NumericEqual(RoundTo(10e3*1.2e-3,BuiltinPrecisionGet()),12.,BuiltinPrecisionGet()); - BuiltinPrecisionSet(p); -]; -Verify((10e3*1.2e-4)-1.2,0); - -Verify(IsZero(N(Sin(0.1e1)-Sin(1),30)),True); -[ - /* In Dutch they have a saying "dit verdient geen schoonheidsprijs" ;-) We need to sort this out. - * But a passable result, for now. - */ - Local(diff); - diff := N(Sin(10e-1)-Sin(1),30); -//BuiltinPrecisionSet(20); -//Echo("diff = ",diff); -//Echo("diff > -0.00001 = ",diff > -0.00001); -//Echo("diff < 0.00001 = ",diff < 0.00001); - Verify(diff > -0.00001 And diff < 0.00001,True); -]; - - -/* Jonathan reported a problem with Simplify(-Sqrt(8)/2), which returned some - * complex expression containing greatest common divisors of square roots. - * This was fixed by adding some rules dealing with taking the gcd of two objects - * where at least one is a square root. - */ -Verify(-Sqrt(8)/2,-Sqrt(2)); -Verify(Sqrt(8)/2,Sqrt(2)); -Verify(Gcd(Sqrt(2),Sqrt(2)),Sqrt(2)); -Verify(Gcd(-Sqrt(2),-Sqrt(2)),Sqrt(2)); -Verify(Gcd(Sqrt(2),-Sqrt(2)),Sqrt(2)); -Verify(Gcd(-Sqrt(2),Sqrt(2)),Sqrt(2)); - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/binaryfactors.mpt mathpiper-0.81f+dfsg1/tests/scripts/binaryfactors.mpt --- mathpiper-0.0.svn2556/tests/scripts/binaryfactors.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/binaryfactors.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ - - -TestPoly(poly,requiredResult):= -[ -//Echo(poly); - Local(realResult); - realResult:=BinaryFactors(poly); - Verify(Length(realResult),Length(requiredResult)); - -//Echo(requiredResult,realResult); - Local(intersection); - intersection:={}; - ForEach(item1,requiredResult) - ForEach(item2,realResult) - [ - If(Simplify(item1-item2) = {0,0}, - intersection := (item1:intersection)); - ]; - Verify(Length(realResult),Length(intersection/*Intersection(requiredResult,realResult)*/)); - Verify(Simplify(poly-FW(realResult)),0); -]; - -// Simple factorizations -TestPoly((x+1)*(x-1),{{x+1,1},{x-1,1}}); - -// Simple with multiple factors -TestPoly((x+1)^2,{{x+1,2}}); - -// Test: term with lowest power not zero power -TestPoly(x^2*(x+1)*(x-1),{{x,2},{x+1,1},{x-1,1}}); -TestPoly(x^3*(x+1)*(x-1),{{x,3},{x+1,1},{x-1,1}}); - -// Variable different from x -TestPoly((y+1)*(y-1),{{y+1,1},{y-1,1}}); - -// Test from Wester 1994 test -TestPoly(D(x)(x+1)^20,{{20,1},{x+1,19}}); - -// From regression test, and verify that polys with unfactorizable parts works -TestPoly((x^6-1),{{x^4+x^2+1,1},{x+1,1},{x-1,1}}); - -// Non-monic polynomials -TestPoly((x+13)^2*(3*x-5)^3,{{27,1},{x+13,2},{x-5/3,3}}); -TestPoly((x+13)^2*(4*x-5)^3,{{64,1},{x+13,2},{x-5/4,3}}); - -// Heavy: binary coefficients -TestPoly((x+1024)*(x+2048),{{x+1024,1},{x+2048,1}}); -TestPoly((x+1024)^2*(x+2048)^3,{{x+1024,2},{x+2048,3}}); -TestPoly((16*x+1024)*(x+2048),{{16,1},{x+64,1},{x+2048,1}}); -TestPoly((x+1024)*(x+2047),{{x+1024,1},{x+2047,1}}); -TestPoly((x+1024)*(x+2049),{{x+1024,1},{x+2049,1}}); - -TestPoly((x+1024)*(x-2047),{{x+1024,1},{x-2047,1}}); -TestPoly((x-1024)*(x+2047),{{x-1024,1},{x+2047,1}}); -TestPoly((x-1024)*(x-2047),{{x-1024,1},{x-2047,1}}); - -// Rational coefficients -TestPoly((x+4/7)*(x-5/9),{{x+4/7,1},{x-5/9,1}}); - -// More than two factors ;-) -TestPoly((x+1)*(x-2)*(x+3)*(x-4)*(x+5)*(x-6),{{x+1,1},{x-2,1},{x+3,1},{x-4,1},{x+5,1},{x-6,1}}); - - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/calculus.mpt mathpiper-0.81f+dfsg1/tests/scripts/calculus.mpt --- mathpiper-0.0.svn2556/tests/scripts/calculus.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/calculus.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -f():=[];//Echo(CurrentFile()," line ",CurrentLine()); -Testing("UnaryFunctionInverses"); -Verify(Sin(ArcSin(a)),a); f(); -Verify(Cos(ArcCos(a)),a); f(); - -//TODO ??? Verify(Tan(ArcTan(a)),a); -Verify(ArcSin(Sin(a)),a); f(); -Verify(ArcCos(Cos(a)),a); f(); -//TODO ??? this is not always the correct answer! Verify(ArcTan(Tan(a)),a); -Verify(Tan(Pi/2),Infinity); f(); -Verify(Tan(Pi),0); f(); - -Verify( Limit(x,Infinity) Sin(x), Undefined ); f(); -Verify( Limit(x,Infinity) Cos(x), Undefined ); f(); -Verify( Limit(x,Infinity) Tan(x), Undefined ); f(); -Verify( Limit(x,Infinity) Gamma(x), Infinity ); f(); -Verify( Limit(x,Infinity) Abs(x), Infinity ); f(); -Verify( Limit(x,Infinity) x!, Infinity); f(); -Verify( Sin(x)/Cos(x), Tan(x) ); f(); -Verify( TrigSimpCombine(Sin(x)^2 + Cos(x)^2), 1 ); f(); - -Verify( Sinh(x)-Cosh(x), Exp(-x)); f(); -Verify( Sinh(x)+Cosh(x), Exp(x) ); f(); -Verify( Sinh(x)/Cosh(x), Tanh(x) ); f(); -Verify( Sinh(Infinity), Infinity); f(); -Verify( Sinh(x)*Csch(x), 1); f(); -Verify( 1/Coth(x), Tanh(x) ); f(); -Verify(2+I*3,Complex(2,3)); f(); -Verify(Magnitude(I+1),Sqrt(2)); f(); - -Verify(Re(2+I*3),2); f(); -Verify(Im(2+I*3),3); f(); -// Shouldn't these be in linalg.yts? -Verify(ZeroVector(3),{0,0,0}); f(); -Verify(BaseVector(2,3),{0,1,0}); f(); -Verify(Identity(3),{{1,0,0},{0,1,0},{0,0,1}}); f(); - -Testing("Derivatives"); -Verify(D(x) a,0); f(); -Verify(D(x) x,1); f(); -Verify(D(x) (x+x),2); f(); -Verify(D(x) (x*x),2*x); f(); -Verify(D(x) D(x) Sin(x),-Sin(x)); f(); - -Testing("Limits"); -Verify( Limit(x,0,Right) Ln(x)*Sin(x), 0 ); f(); -KnownFailure( Limit(k,Infinity) ((k-phi)/k)^(k+1/2) = Exp(-phi) ); f(); - -[ - Local(z); - // This function satisfies Laplaces eqn: D(x,2)z + D(y,2)z = 0 - z:= ArcTan((2*x*y)/(x^2 - y^2)); f(); - //TODO, this test is disabled, should it be re-enabled? - // Hangs - // Verify(Simplify((D(x,2) z) + D(y,2) z), 0 ); -]; - - - -Testing("Pslq"); -VerifyPslq(left,right):= -[ - If(left=right, - Verify(True,True), - `Verify(@left,-(@right))); -]; - -VerifyPslq(Pslq({ Pi+2*Exp(1) , Pi , Exp(1) },20),{1,-1,-2}); f(); -VerifyPslq(Pslq({ 2*Pi+3*Exp(1) , Pi , Exp(1) },20),{1,-2,-3}); f(); - - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/canprove.mpt mathpiper-0.81f+dfsg1/tests/scripts/canprove.mpt --- mathpiper-0.0.svn2556/tests/scripts/canprove.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/canprove.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - -NextTest("Propositional logic theorem prover"); - -Verify(CanProve(( (a=>b) And (b=>c) => (a=>c) )),True); -Verify(CanProve((((a=>b) And (b=>c))=> (a=>c) )),True); -Verify(CanProve(( (a=>b) And((b=>c) => (a=>c)))),((Not a Or b)And(Not a Or (b Or c))) ); -//KnownFailure(BadOutput + WhenPreviousLine + IsUncommented); -//And *my* previous line (the KnownFailure) aborts. (witnessed by no report from next line). -Verify(CanProve( True ),True); - -Verify(CanProve(a Or Not a) ,True); -Verify(CanProve(True Or a) ,True); -Verify(CanProve(False Or a) ,a ); -Verify(CanProve(a And Not a) ,False); -Verify(CanProve(a Or b Or (a And b)) ,a Or b ); - -/* Two theorems from the Pure Implicational Calculus (PIC), in which the - * only operator is [material] implication. From the first, all other - * theorems in PIC can be proved using only the two transformation rules: - * 1. Rule of substitution. Uniform replacement in theorems yields theorems. - * 2. Rule of detachment, or modus ponens. If 'a' and 'a=>b' are theorems, then 'b' is a theorem. - * - * 1. Lukasiewicz, Jan, "The Shortest Axiom of the Implicational Calculus - * of Propositions," Proceedings of the Royal Irish Academy, vol. 52, - * Sec. A, No. 3 (1948). [ Can you say "Polish Notation"? ] - * 2. Meredith, David, "On a Property of Certain Propositional Formulae," - * Notre Dame Journal of Formal Logic, vol. XIV, No. 1, January 1973. - */ -Verify(CanProve( /* 1. CCCpqrCCrpCsp */ - ((p=>q) => r) => ((r=>p) => (s=>p)) - ), True); -Verify(CanProve( /* 2. CCpCqrCqCpr */ - (p => (q=>r)) => (q => (p=>r)) - ), True); diff -Nru mathpiper-0.0.svn2556/tests/scripts/comments.mpt mathpiper-0.81f+dfsg1/tests/scripts/comments.mpt --- mathpiper-0.0.svn2556/tests/scripts/comments.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/comments.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ - -NextTest("Checking comment syntax supported"); -[ - Local(a); - /* something here */ - a:= 3; - // test 1 - - // /* test2 */ - - /* // test3 */ - - //Echo({a, Nl()}); - - // Check parsing - a==-b; // This would generate a parse error in Yacas versions 1.0.54 and earlier -]; - - -[ - Local(errorString); - errorString:=""; - TrapError(Check(False,"some error"),errorString:=GetCoreError()); - Verify(IsString(errorString),True); - Verify(Length(errorString)>4,True); -]; -Verify(errorString,errorString); diff -Nru mathpiper-0.0.svn2556/tests/scripts/complex.mpt mathpiper-0.81f+dfsg1/tests/scripts/complex.mpt --- mathpiper-0.0.svn2556/tests/scripts/complex.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/complex.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -Verify( Limit(z,2*I) (I*z^4+3*z^2-10*I), Complex(-12,6) ); -KnownFailure( (Limit(n,Infinity) (n^2*I^n)/(n^3+1)) = 0 ); -Verify( Limit(n,Infinity) n*I^n, Undefined ); - -Verify(1/I, -I); -Verify(I^2, -1); -Verify(2/(1+I), 1-I); -Verify(I^3, -I); -Verify(I^4, 1); -Verify(I^5, I); -Verify(1^I, 1); -Verify(0^I, Undefined); -Verify(I^(-I), Exp(Pi/2)); -Verify((1+I)^33, 65536+I*65536); -Verify((1+I)^(-33), (1-I)/131072); -Verify(Exp(I*Pi), -1); -TestMathPiper((a+b*I)*(c+d*I), (a*c-b*d)+I*(a*d+b*c)); -Verify(Ln(-1), I*Pi); -Verify(Ln(3+4*I), Ln(5)+I*ArcTan(4/3)); - -Verify(Re(2*I-4), -4); -Verify(Im(2*I-4), 2); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/c_tex_form.mpt mathpiper-0.81f+dfsg1/tests/scripts/c_tex_form.mpt --- mathpiper-0.0.svn2556/tests/scripts/c_tex_form.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/c_tex_form.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ -/*Use("texform");*/ - -NextTest("TeXForm()..."); - -/* it worketh no more... -Testing("Realistic example"); -f:=Exp(I*lambda*eta)*w(T*(k+k1+lambda)); -g:=Simplify(Subst(lambda,0) f+(k+k1)*(D(lambda)f)+k*k1*D(lambda)D(lambda)f ); -Verify(TeXForm(g), ...); -*/ - -Verify( -TeXForm(Hold(Cos(A-B)*Sqrt(C+D)-(a+b)*c^d+2*I+Complex(a+b,a-b)/Complex(0,1))) -,"$\\cos \\left( A - B\\right) \\sqrt{C + D} - \\left( a + b\\right) c ^{d} + 2 \\imath + \\frac{a + b + \\imath \\left( a - b\\right) }{\\imath } $" -); - -Verify( -TeXForm(Hold(Exp(A*B)/C/D/(E+F)*G-(-(a+b)-(c-d))-b^(c^d) -(a^b)^c)) -,"$\\frac{\\frac{\\frac{\\exp \\left( A B\\right) }{C} }{D} }{E + F} G - \\left( - \\left( a + b\\right) - \\left( c - d\\right) \\right) - b ^{c ^{d}} - \\left( a ^{b}\\right) ^{c}$" -); - -Verify( -TeXForm(Hold(Cos(A-B)*Sin(a)*f(b,c,d*(e+1))*Sqrt(C+D)-(g(a+b)^(c+d))^(c+d))) -,"$\\cos \\left( A - B\\right) \\sin a f\\left( b, c, d \\left( e + 1\\right) \\right) \\sqrt{C + D} - \\left( g\\left( a + b\\right) ^{c + d}\\right) ^{c + d}$" -); - -// testing latest features: \\cdot, %, (a/b)^n, BinomialCoefficient(), BesselI, OrthoH -Verify( -TeXForm(3*2^n+Hold(x*10!) + (x/y)^2 + BinomialCoefficient(x,y) + BesselI(n,x) + Max(a,b) + OrthoH(n,x)) -, "$3\\cdot 2 ^{n} + x\\cdot 10! + \\left( \\frac{x}{y} \\right) ^{2} + {x \\choose y} + I _{n}\\left( x\\right) + \\max \\left( a, b\\right) + H _{n}\\left( x\\right) $" -); - -/* this fails because of a bug that D(x) f(y) does not go to 0 */ /* -Verify( -TeXForm(3*D(x)f(x,y,z)*Cos(Omega)*Mod(Sin(a)*4,5/a^b)) -,"$3 \\left( \\frac{\\partial}{\\partial x}f\\left( x, y, z\\right) \\right) \\left( \\cos \\Omega \\right) \\left( 4 \\left( \\sin a\\right) \\right) \\bmod \\frac{5}{a ^{b}} $" -); -*/ - -Verify( -TeXForm(Hold(D(x)f(x))) -,"$\\frac{d}{d x}f\\left( x\\right) $"); - -Verify( -TeXForm(Hold(Not (c<0) And (a+b)*c>= -d^e And (c<=0 Or b+1>0) Or a!=0 And Not (p=q))) -,"$ \\neg c < 0\\wedge \\left( a + b\\right) c\\geq - d ^{e}\\wedge \\left( c\\leq 0\\vee b + 1 > 0\\right) \\vee a\\neq 0\\wedge \\neg p = q$" -); - - -Verify( -TeXForm((D(x)f(x,y,z))*Cos(Omega)*Mod(Sin(a)*4,5/a^b)) -,"$\\left( \\frac{\\partial}{\\partial x}f\\left( x, y, z\\right) \\right) \\cos \\Omega \\left( 4 \\sin a\\right) \\bmod \\frac{5}{a ^{b}} $" -); - - -Verify( -TeXForm(Pi+Exp(1)-Theta-Integrate(x,x1,3/g(Pi))2*theta(x)*Exp(1/x)) -,"$\\pi + \\exp \\left( 1\\right) - \\Theta - \\int _{x_{1}} ^{\\frac{3}{g\\left( \\pi \\right) } } 2 \\theta \\left( x\\right) \\exp \\left( \\frac{1}{x} \\right) dx$" -); - -Verify( -TeXForm({a[3]*b[5]-c[1][2],{a,b,c,d}}) -,"$\\left( a _{3} b _{5} - c _{\\left( 1, 2\\right) }, \\left( a, b, c, d\\right) \\right) $" -); - -Bodied("aa", 200); -Infix("bar", 100); - -Verify( -TeXForm(aa(x,y) z + 1 bar y!) -,"$aa\\left( x, y\\right) z + 1\\mathrm{ bar }y!$" -); - -Verify( -TeXForm(x^(1/3)+x^(1/2)) -, "$\\sqrt[3]{x} + \\sqrt{x}$" -); - -/* -Verify( -TeXForm() -,"" -); -*/ - -Verify( -CForm(Hold(Cos(A-B)*Sin(a)*func(b,c,d*(e+Pi))*Sqrt(Abs(C)+D)-(g(a+b)^(c+d))^(c+d))) -,"cos(A - B) * sin(a) * func(b, c, d * ( e + Pi) ) * sqrt(fabs(C) + D) - pow(pow(g(a + b), c + d), c + d)" -); - -Verify( -CForm(Hold([i:=0;While(i<10)[i++; a:=a+Floor(i);];])) -, "{ - i = 0; - while(i < 10) - { - ++(i); - a = a + floor(i); - } - ; - ; - } -" -); - -/* Check that we can still force numbers to be floats in stead of integers if we want to */ -Verify( -CForm(Hold([i:=0.;While(i<10.)[i++; a:=a+Floor(i);];])) -, "{ - i = 0.; - while(i < 10.) - { - ++(i); - a = a + floor(i); - } - ; - ; - } -" -); - - -Testing("IsCFormable"); -Verify( -IsCFormable(e+Pi*Cos(A-B)/3-Floor(3.14)*2) -, True -); -Verify( -IsCFormable(e+Pi*Cos(A-B)/3-Floor(3.14)*2+bad'func(x+y)) -, False -); -Verify( -IsCFormable(e+Pi*Cos(A-B)/3-Floor(3.14)*2+bad'func(x+y), {bad'func}) -, True -); -Verify( -IsCFormable([i:=0;While(i<10)[i++; a:=a+i;];]) -, True -); -Verify( -IsCFormable([i:=0;While(i<10)[i++; a:=a+i; {};];]) -, False -); diff -Nru mathpiper-0.0.svn2556/tests/scripts/cyclotomic.mpt mathpiper-0.81f+dfsg1/tests/scripts/cyclotomic.mpt --- mathpiper-0.0.svn2556/tests/scripts/cyclotomic.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/cyclotomic.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -NextTest("Cyclotomic Polynomials"); - -Verify(Cyclotomic(1,x),x-1); -Verify(Cyclotomic(5,x),x^4+x^3+x^2+x+1); -Verify(Cyclotomic(8,z),z^4+1); -Verify(Cyclotomic(10,y),y^4-y^3+y^2-y+1); -Verify(Cyclotomic(15,x),x^8-x^7+x^5-x^4+x^3-x+1); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/deriv.mpt mathpiper-0.81f+dfsg1/tests/scripts/deriv.mpt --- mathpiper-0.0.svn2556/tests/scripts/deriv.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/deriv.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -TestMathPiper(Deriv(x)Ln(x),1/x); -TestMathPiper(Deriv(x)Exp(x),Exp(x)); -TestMathPiper(Deriv(x)(x^4+x^3+x^2+x+1),4*x^3+3*x^2+2*x+1); -TestMathPiper(Deriv(x)Sin(x),Cos(x)); -TestMathPiper(Deriv(x)Cos(x),-Sin(x)); -TestMathPiper(Deriv(x)Sinh(x),Cosh(x)); -TestMathPiper(Deriv(x)Cosh(x),Sinh(x)); -TestMathPiper(Deriv(x)ArcCos(x),-1/Sqrt(1-x^2)); -TestMathPiper(Deriv(x)ArcSin(x),1/Sqrt(1-x^2)); -TestMathPiper(Deriv(x)ArcTan(x),1/(x^2+1)); -TestMathPiper(Deriv(x)Sech(x),-Sech(x)*Tanh(x)); diff -Nru mathpiper-0.0.svn2556/tests/scripts/dimensions.mpt mathpiper-0.81f+dfsg1/tests/scripts/dimensions.mpt --- mathpiper-0.0.svn2556/tests/scripts/dimensions.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/dimensions.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -////// -// $Id: dimensions.yts,v 1.2 2006/03/26 12:49:15 ayalpinkus Exp $ -// Tests for Dimensions -////// - -Testing("-- Dimensions (Tensor Rank)"); - -Verify(Dimensions(a),{}); -Verify(Dimensions({}),{0}); -Verify(Dimensions({a,b}),{2}); -Verify(Dimensions({{}}),{1,0}); -Verify(Dimensions({{a}}),{1,1}); -Verify(Dimensions({{},a}),{2}); -Verify(Dimensions({{a},b}),{2}); -Verify(Dimensions({{},{}}),{2,0}); -Verify(Dimensions({{},{{}}}),{2}); -Verify(Dimensions({{a,b},{c}}),{2}); -Verify(Dimensions({{a,b},{c,d}}),{2,2}); -Verify(Dimensions({{a,b},{c,d},{e,f}}),{3,2}); -Verify(Dimensions({{a,b,c},{d,e,f},{g,h,i}}),{3,3}); -Verify(Dimensions({{a,b,c},{d,e,f}}),{2,3}); -Verify(Dimensions({{{a,b}},{{c,d}}}), {2,1,2}); -Verify(Dimensions({{{{a},{b}}},{{{c},d}}}),{2,1,2}); -Verify(Dimensions({{{{{a,b}}}},{{{c,d}}}}),{2,1,1}); -Verify(Dimensions({{{{{a,b}}}},{{{c},{d}}}}),{2,1}); -Verify(Dimensions({{{}}}),{1,1,0}); -Verify(Dimensions({{{a}}}),{1,1,1}); -Verify(Dimensions({{{{a}}},{{{b}}}}),{2,1,1,1}); -Verify(Dimensions({{{{a},{b}}},{{{c},{d}}}}),{2,1,2,1}); -Verify(Dimensions({{{{a,b}}},{{{c,d}}}}),{2,1,1,2}); -Verify(Dimensions({{{{a,b}},{{c,d}}}}),{1,2,1,2}); -Verify(Dimensions({{{{{{a,b},{c}}}}},{{{d},{e,f,g}}}}), {2,1}); - -////// -////// diff -Nru mathpiper-0.0.svn2556/tests/scripts/dot.mpt mathpiper-0.81f+dfsg1/tests/scripts/dot.mpt --- mathpiper-0.0.svn2556/tests/scripts/dot.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/dot.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -////// -// $Id: dot.yts,v 1.2 2006/03/26 12:49:15 ayalpinkus Exp $ -// Tests for Dot -////// - -Testing("-- Dot"); - -// vector . vector -Verify(Dot({},{}),0); -Verify(Dot({},a),Hold(Dot({},a))); -Verify(Dot(a,{}),Hold(Dot(a,{}))); -Verify(Dot({a},{}),Hold(Dot({a},{}))); -Verify(Dot({},{a}),Hold(Dot({},{a}))); -Verify(Dot({a},{b}),a*b); -Verify(Dot({a},{b,c}),Hold(Dot({a},{b,c}))); -Verify(Dot({a,b},{c}),Hold(Dot({a,b},{c}))); -Verify(Dot({a,b},{c,d}),a*c+b*d); -Verify(Dot({a,b},{c,{d}}),Hold(Dot({a,b},{c,{d}}))); -Verify(Dot({a,{b}},{c,d}),Hold(Dot({a,{b}},{c,d}))); -Verify(Dot({a,b},{c,d,e}),Hold(Dot({a,b},{c,d,e}))); -Verify(Dot({a,b,c},{d,e}),Hold(Dot({a,b,c},{d,e}))); -Verify(Dot({1,2,3},{4,5,6}),32); - -// matrix . vector -Verify(Dot({{}},{}),{0}); -Verify(Dot({{}},{1}),Hold(Dot({{}},{1}))); -Verify(Dot({{},{}},{}),{0,0}); -Verify(Dot({{a}},{b}),{a*b}); -Verify(Dot({{a},{b}},{c}),{a*c,b*c}); -Verify(Dot({{1},{2}},{2}),{2,4}); -Verify(Dot({{1,2,3},{4,5,6}},{7,8,9}),{50,122}); - -// vector . matrix -Verify(Dot({},{{}}),Hold(Dot({},{{}}))); -Verify(Dot({},{{},{}}),Hold(Dot({},{{},{}}))); -Verify(Dot({1},{{}}),Hold(Dot({1},{{}}))); -Verify(Dot({1},{{},{}}),Hold(Dot({1},{{},{}}))); -Verify(Dot({a,b},{{c},{d}}),{a*c+b*d}); -Verify(Dot({1,2,3},{{4,5},{6,7},{8,9}}),{40,46}); - -// matrix . matrix -Verify(Dot({{}},{{}}),Hold(Dot({{}},{{}}))); -Verify(Dot({{a}},{{}}),Hold(Dot({{a}},{{}}))); -Verify(Dot({{}},{{b}}),Hold(Dot({{}},{{b}}))); -Verify(Dot({{1,2},{3,4},{5,6}},{{1,2,3},{4,5,6}}),{{9,12,15},{19,26,33},{29,40,51}}); -Verify(Dot({{1,2,3},{4,5,6}},{{1,2},{3,4},{5,6}}),{{22,28},{49,64}}); - -////// diff -Nru mathpiper-0.0.svn2556/tests/scripts/GaussianIntegers.mpt mathpiper-0.81f+dfsg1/tests/scripts/GaussianIntegers.mpt --- mathpiper-0.0.svn2556/tests/scripts/GaussianIntegers.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/GaussianIntegers.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ - -NextTest("Gaussian Integers"); - -/* TestGaussianFactors: test if Gaussian Factors Really works! -Computes in r the product of the factors, and checks if each -one is a Gaussian prime and if r is associated to z (i.e. if r/z -is a Gaussian Unit */ -TestGaussianFactors(z_IsGaussianInteger) <-- -[ - Local(r,gfactors,Ok); -// Echo("TestGaussianFactors: factoring ",z); - gfactors := GaussianFactors(z); -// Echo(gfactors); - Ok := True; - r :=1; - ForEach(p,gfactors) - [ - r := r*p[1]^p[2]; - Ok := Ok And IsGaussianPrime(p[1]); - ]; -// Echo(r); - Ok := Ok And IsGaussianUnit(r/z); - If(Ok,True,Echo("FAILED: GaussianFactors(", z, ")=", gfactors, " which is wrong.")); -]; - -TestGaussianFactors((9!)+1); -TestGaussianFactors(2+3*I); -TestGaussianFactors(-1+2*I); -TestGaussianFactors(17); -TestGaussianFactors(41); - -Verify(GaussianFactors(157+28*I), {{Complex(5,2),1},{Complex(-29,6),1}}); -Verify(GaussianFactors(1), {}); // is this the correct behavior? why not {{}} or {{1,1}}? -Verify(GaussianFactors(-1), {}); // is this the correct behavior? -Verify(GaussianFactors(I), {}); // is this the correct behavior? -Verify(GaussianFactors(0), {}); // is this the correct behavior? -Verify(GaussianFactors(2), {{Complex(1,1),1},{Complex(1,-1),1}}); -Verify(GaussianFactors(-2), {{Complex(1,1),1},{Complex(1,-1),1}}); -Verify(GaussianFactors(3), {{3,1}}); -Verify(GaussianFactors(3*I), {{3,1}}); -Verify(GaussianFactors(4), {{Complex(1,1),2},{Complex(1,-1),2}}); -Verify(GaussianFactors(-5*I), {{Complex(2,1),1},{Complex(2,-1),1}}); -Verify(GaussianFactors(Complex(1,1)^11*163^4),{{Complex(1,1),11},{163,4}}); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/includetestfiles mathpiper-0.81f+dfsg1/tests/scripts/includetestfiles --- mathpiper-0.0.svn2556/tests/scripts/includetestfiles 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/includetestfiles 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ - -NORMAL_TESTFILES = \ - openmath.mpt macro.mpt arithmetic.mpt c_tex_form.mpt calculus.mpt canprove.mpt \ - comments.mpt complex.mpt deriv.mpt dimensions.mpt dot.mpt journal.mpt \ - integrate.mpt lists.mpt logic_simplify_test.mpt matrixpower.mpt \ - nthroot.mpt outer.mpt predicates.mpt ode.mpt \ - tensors.mpt trace.mpt tr.mpt multivar.mpt numbers.mpt io.mpt \ - programming.mpt regress.mpt simplify.mpt solve.mpt sums.mpt \ - transforms.mpt radsimp.mpt linalg.mpt orthopoly.mpt poly.mpt numerics.mpt \ - scopestack.mpt plots.mpt GaussianIntegers.mpt nummethods.mpt sturm.mpt \ - cyclotomic.mpt binaryfactors.mpt - -SPECIAL_TESTFILES = ../manmake/wester-1994.mpt - -TESTFILES = $(NORMAL_TESTFILES) $(SPECIAL_TESTFILES) -QUICKTESTFILES = simplify.mpt sturm.mpt - diff -Nru mathpiper-0.0.svn2556/tests/scripts/integrate.mpt mathpiper-0.81f+dfsg1/tests/scripts/integrate.mpt --- mathpiper-0.0.svn2556/tests/scripts/integrate.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/integrate.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ - -// verify that unknown integrals don't simplify -Verify(Integrate(x,a,b)Exp(Sin(x)),Integrate(x,a,b)Exp(Sin(x))); -Verify(Integrate(x )Exp(Sin(x)),Integrate(x )Exp(Sin(x))); - -// Verify that Yacas cannot integrate these expressions. -// Yacas needs to return the integration unevaluated, or -// return a correct answer (if it happens to be able to do -// these integrals in the future). -TestNonIntegrable(_expr) <-- Verify(Type(expr) = "Integrate",True); - -// The following two used to get the interpreter into an infinite -// loop. Fixed in version 1.0.51 -// FIXED!!! TestNonIntegrable(Integrate(x)(x*Ln(x))); -TestNonIntegrable(Integrate(x)Sin(Exp(x))); -Verify(Integrate(x) x^(-1),Ln(x)); // Well done Jonathan! ;-) -Verify(Integrate(x) 1/x,Ln(x) ); - -Verify(Integrate(x) 1/x^2, -x^ -1 ); -Verify(Integrate(x) 6/x^2, (-6)*x^-1); -Verify(Integrate(x) 3/Sin(x),3*Ln(1/Sin(x)-Cos(x)/Sin(x)) ); - -Verify(Integrate(x) Ln(x), x*Ln(x)-x ); -Verify(Integrate(x) x^5000, x^5001/5001 ); -Verify(Integrate(x) 1/Tan(x), Ln(Sin(x)) ); -Verify(Integrate(x) 1/Cosh(x)^2, Tanh(x) ); -Verify(Integrate(x) 1/Sqrt(3-x^2), ArcSin(x/Sqrt(3)) ); -Verify(Integrate(x) Erf(x), x*Erf(x)+1/(Exp(x^2)*Sqrt(Pi)) ); -Verify(Integrate(x) Sin(x)/(2*y+4),(-Cos(x))/(2*(y+2))); - - -TestNonIntegrable(Integrate(x) x^(1/x)); -TestNonIntegrable(Integrate(x) x^(Sin(x))); -TestNonIntegrable(Integrate(x) Exp(x^2)); -TestNonIntegrable(Integrate(x) Sin(x^2)); - -TestMathPiper(Integrate(x,0,A)Sin(x),1 - Cos(A)); -TestMathPiper(Integrate(x,0,A)x^2,(A^3)/3); -TestMathPiper(Integrate(x,0,A)Sin(B*x),1/B-Cos(A*B)/B); -TestMathPiper(Integrate(x,0,A)(x^2+2*x+1)/(x+1),(A^2)/2+A); -TestMathPiper(Integrate(x,0,A)(x+1)/(x^2+2*x+1),Ln(A+1)); - -// Check that threaded integration works -Verify((Integrate(x,0,1) {1,x*x,1+x})-{1,1/3,3/2},{0,0,0}); - - -// Test MatchLinear: code heavily used with integration -LocalSymbols(TestMatchLinearTrue,TestMatchLinearFalse) [ - - TestMatchLinearTrue(_var,_expr,_expected) <-- - [ - Local(a,b); - Verify(MatchLinear(var,expr),True); - a:=Simplify(Matched'a()-expected[1]); - b:=Simplify(Matched'b()-expected[2]); - `TestMathPiper(@a,0); - `TestMathPiper(@b,0); - ]; - TestMatchLinearFalse(_var,_expr) <-- - [ - Local(a,b); - Verify(MatchLinear(var,expr),False); - ]; - - TestMatchLinearTrue(x,(R+1)*x+(T-1),{(R+1),(T-1)}); - TestMatchLinearTrue(x,x+T,{1,T}); - TestMatchLinearTrue(x,a*x+b,{a,b}); - TestMatchLinearFalse(x,Sin(x)*x+(T-1)); - TestMatchLinearFalse(x,x+Sin(x)); - -]; - diff -Nru mathpiper-0.0.svn2556/tests/scripts/io.mpt mathpiper-0.81f+dfsg1/tests/scripts/io.mpt --- mathpiper-0.0.svn2556/tests/scripts/io.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/io.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -Testing("Error reporting"); - -// generate no errors -Verify(IsError(), False); -Verify(IsError("testing"), False); -Verify(Assert("testing") 1=1, True); -Verify(IsError(), False); -Verify(IsError("testing"), False); -Verify(Assert("testing1234", {1,2,3,4}) 1=1, True); -Verify(IsError(), False); -Verify(IsError("testing"), False); -Verify(IsError("testing1234"), False); - -Verify(ToString()DumpErrors(), ""); - -// generate some errors -Verify(Assert("testing") 1=0, False); -Verify(IsError(), True); -Verify(IsError("testing"), True); -Verify(IsError("testing1234"), False); -Verify(Assert("testing1234", {1,2,3,4}) 1=0, False); -Verify(IsError(), True); -Verify(IsError("testing"), True); -Verify(IsError("testing1234"), True); - -// report errors -Verify(ToString()DumpErrors(), "Error: testing -Error: testing1234: {1, 2, 3, 4} -"); - -// no more errors now -Verify(IsError(), False); -Verify(IsError("testing"), False); -Verify(IsError("testing1234"), False); - -// generate some more errors -Verify(Assert("testing") 1=0, False); -Verify(Assert("testing1234", {1,2,3,4}) 1=0, False); -Verify(GetError("testing1234567"), False); - -// handle errors -Verify(GetError("testing"), True); -Verify(IsError(), True); -Verify(IsError("testing"), True); -Verify(IsError("testing1234"), True); - -Verify(ClearError("testing"), True); -Verify(IsError(), True); -Verify(IsError("testing"), False); -Verify(IsError("testing1234"), True); -// no more "testing" error -Verify(ClearError("testing"), False); -Verify(IsError(), True); -Verify(IsError("testing"), False); -Verify(IsError("testing1234"), True); - -Verify(GetError("testing1234"), {1,2,3,4}); -Verify(IsError(), True); -Verify(IsError("testing"), False); -Verify(IsError("testing1234"), True); - -Verify(ClearError("testing1234"), True); -Verify(IsError(), False); -Verify(IsError("testing"), False); -Verify(IsError("testing1234"), False); -Verify(ClearError("testing1234"), False); diff -Nru mathpiper-0.0.svn2556/tests/scripts/journal.mpt mathpiper-0.81f+dfsg1/tests/scripts/journal.mpt --- mathpiper-0.0.svn2556/tests/scripts/journal.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/journal.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ - -/* - * This file contains tests to check constructs used in the - * tutorials and journal entries. - */ - -Verify(1+1,2); -Verify("This text","This text"); -Verify(2+3,5); -Verify(3*4,12); -Verify(-(3*4),-12); -Verify(2+3*4,14); -Verify(6/3,2); -Verify(1/3,1/3); -Verify(IsNumber(N(1/3)),True); -Verify(Sin(Pi),0); -Verify(Min(5,1,3,-5,10),-5); -Verify(Sqrt(2),Sqrt(2)); -Verify({1,2,3},{1,2,3}); -Verify({a,b,c}[2],b); -Verify("abc"[2],"b"); - - -// Etcetera.... PLEASECHECK TODO fill out this file - - - - -/* From derivatives example, I am using ^0.5 there because of the - * fact that Yacas replaces x^(1/2) with Sqrt(x). - */ -Verify(x^(1/2),Sqrt(x)); - - - - - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/linalg.mpt mathpiper-0.81f+dfsg1/tests/scripts/linalg.mpt --- mathpiper-0.0.svn2556/tests/scripts/linalg.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/linalg.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,176 +0,0 @@ - - -Testing("LeviCivita"); -Verify(LeviCivita({1,2,3}),1); -Verify(LeviCivita({2,1,3}),-1); -Verify(LeviCivita({1,1,3}),0); - -Testing("VectorProducts"); -[ - Local(l,m,n); - l:={1,0,0}; - m:={0,1,0}; - n:={0,0,1}; - - Verify(l X m, {0,0,1}); - Verify(m X n, {1,0,0}); - Verify(n X l, {0,1,0}); - Verify(l X n, {0,-1,0}); - - Verify(l . m, 0); - Verify(m . n, 0); - Verify(n . l, 0); - - Verify(l . l, 1); -]; - - -[ - Local(a,b); - -/* Strangeness: change variable below into a, and the crossproducts - * later on fail! - */ - a:={1,2,3}; - b:={3,1,5}; - Verify( a . b , 20); - Verify(CrossProduct({1,2,3} , {4,2,5}) , {4,7,-6}); -]; -Verify(aa,Hold(aa)); - -[ - Local(a,b); - NextTest("Inproduct"); - a:={1,2,3}; - b:={3,1,5}; - Verify( a . b , 20); -]; - -Verify(CrossProduct({1,2,3} , {4,2,5}) , {4,7,-6}); -Verify({1,2,3} X {4,2,5},{4,7,-6}); -Clear(a,b); - -NextTest("Identity matrices"); -Verify(Identity(4), - { {1, 0, 0, 0} , - {0, 1, 0, 0} , - {0, 0, 1, 0} , - {0, 0, 0, 1} }); - - -NextTest("Check linear algebra"); -/* Normalize */ -Testing("Normalize"); -Verify(Normalize({3,4}),{3/5,4/5}); -/* DiagonalMatrix */ -Testing("DiagonalMatrix"); -Verify(DiagonalMatrix({2,3,4}),{{2,0,0},{0,3,0},{0,0,4}}); -/* ZeroMatrix */ -Testing("ZeroMatrix"); -Verify(ZeroMatrix(2,3),{{0,0,0},{0,0,0}}); -/* Transpose */ -Testing("Transpose"); -Verify(Transpose({{a,b},{c,d}}),{{a,c},{b,d}}); -/* Determinant */ -Testing("Determinant"); -Verify(Determinant({{2,3},{3,1}}),-7); -Verity( Determinant(ToeplitzMatrix(1 .. 10)), -2816 ); -// check that Determinant gives correct symbolic result -TestMathPiper(Determinant({{a,b},{c,d}}),a*d-b*c); - -[ - Local(ll); - ll:={ {1,2,3}, - {2,-1,4}, - {3,4,3} - }; - /* CoFactor */ - Testing("CoFactor"); - Verify(N(CoFactor(ll,1,2)),6); - /* Minor */ - Testing("Minor"); - Verify(N(Minor(ll,1,2)),-6); - /* Inverse */ - Testing("Inverse"); - Verify(Inverse(ll)*ll,Identity(3)); - /* SolveMatrix */ - Testing("SolveMatrix"); - Verify(ll*SolveMatrix(ll,{1,2,3}),{1,2,3}); - /* Trace */ - Testing("Trace"); - Verify(Trace(ll),1-1+3); - /* IsVector */ - Verify(IsList(ll),True); - Verify(IsList({1,2,3}),True); - /* IsMatrix */ - Verify(IsMatrix(ll),True); - Clear(ll); -]; - -[ - Local(A); - Verify( IsSymmetric(Identity(10)), True ); - Verify( IsOrthogonal(2*Identity(10)), False ); - A := {{1,2,2},{2,1,-2},{-2,2,-1}}; - Verify( IsOrthogonal(A/3), True ); - Verity( IsSymmetric(Identity(10)), True ); - Verify( IsSymmetric({{1}}),True ); - A := {{1,0,0,0,1},{0,2,0,0,0},{0,0,3,0,0},{0,0,0,4,0},{1,0,0,0,5}}; - Verify( IsSymmetric(A),True ); - A := {{0,2,0,0,1},{0,0,3,0,0},{0,0,0,4,0},{1,0,0,0,5}}; - Verify( IsSymmetric(A),False); - A := {{0,-1},{1,0}}; - Verify( IsSkewSymmetric(A), True ); - Verify( IsSkewSymmetric(Identity(10)), False ); - Verify( IsSkewSymmetric(ZeroMatrix(10,10)), True ); - Verify( IsIdempotent(Identity(20)), True ); - Verify( IsIdempotent(ZeroMatrix(10,10)), True ); -]; - -Verify( VandermondeMatrix({1,2,3,4}),{{1,1,1,1},{1,2,3,4},{1,4,9,16},{1,8,27,64}}); - -Verify( JacobianMatrix( {x^4*y,Cos(y)}, { x, y}), {{4*x^3*y,x^4},{0,-Sin(y)}} ); - -Verify( WronskianMatrix( {Sin(x),Cos(x)}, x) , {{Sin(x),Cos(x)},{Cos(x),-Sin(x)}} ); - -Verify( Determinant(HilbertMatrix(5)), 1/266716800000 ); - -Verify( HilbertMatrix(6)*HilbertInverseMatrix(6), Identity(6) ); - -Verify( FrobeniusNorm({{1,2},{3,4}}), Sqrt(30) ); - -Verify( Norm({1,2,3}), Sqrt(14) ); - -Verify( OrthogonalBasis({{1,1,0},{2,0,1},{2,2,1}}) , {{1,1,0},{1,-1,1},{-1/3,1/3,2/3}} ); -Verify( OrthogonalBasis({{1,0,1,0},{1,1,1,0},{0,1,0,1}}), {{1,0,1,0},{0,1,0,0},{0,0,0,1}} ); -Verify( OrthonormalBasis({{1,0,1,0},{1,1,1,0},{0,1,0,1}}), - {{Sqrt(1/2),0,Sqrt(1/2),0},{0,1,0,0},{0,0,0,1}} ); -Verify( OrthonormalBasis({{1,1,1},{0,1,1},{0,0,1}}), - {{Sqrt(1/3),Sqrt(1/3),Sqrt(1/3)}, - {-Sqrt(2/3),Sqrt(1/6),Sqrt(1/6)}, - {0,-Sqrt(1/2),Sqrt(1/2)}} ); - -[ - Local(A,b); - A:={{1,2,4},{1,3,9},{1,4,16}}; - b:={2,4,7}; - Verify( MatrixSolve(A,b) , {1,(-1)/2,1/2} ); - A:={{2,4,-2,-2},{1,2,4,-3},{-3,-3,8,-2},{-1,1,6,-3}}; - b:={-4,5,7,7}; - Verify( MatrixSolve(A,b), {1,2,3,4} ); -]; - -[ - Local(A,R); - A:={{4,-2,4,2},{-2,10,-2,-7},{4,-2,8,4},{2,-7,4,7}}; - R:=Cholesky(A); - Verify( R, {{2,-1,2,1},{0,3,0,-2},{0,0,2,1},{0,0,0,1}} ); - Verify( A, Transpose(R)*R ); -]; - -[ - Local(A,L,U); - A:={{2,1,1},{2,2,-1},{4,-1,6}}; - {L,U} := LU(A); - Verify( L*U, A ); -]; diff -Nru mathpiper-0.0.svn2556/tests/scripts/lists.mpt mathpiper-0.81f+dfsg1/tests/scripts/lists.mpt --- mathpiper-0.0.svn2556/tests/scripts/lists.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/lists.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ - -Verify(Intersection({aa,b,c},{b,c,d}),{b,c}); -Verify(Union({aa,b,c},{b,c,d}),{aa,b,c,d}); -Verify(Difference({aa,b,c},{b,c,d}),{aa}); - -NextTest("VarList"); -Verify(VarList(x^2+y^3) , {x , y}); -Verify(List(1,2,3),{1 , 2 , 3}); - -Testing("BubbleSort"); -Verify(BubbleSort({2,3,1},"<"),{1,2,3}); -Verify(BubbleSort({2,3,1},">"),{3,2,1}); - -Testing("HeapSort"); -Verify(HeapSort({2,3,1},"<"),{1,2,3}); -Verify(HeapSort({2,1,3},">"),{3,2,1}); -Verify(HeapSort({7,3,1,2,6},"<"),{1,2,3,6,7}); -Verify(HeapSort({6,7,1,3,2},">"),{7,6,3,2,1}); - -Verify(Type(Cos(x)),"Cos"); -Verify(NrArgs(Cos(x)),1); -Verify(Contains({a,b,c},b),True); -Verify(Contains({a,b,c},d),False); - -Verify(Append({a,b,c},d),{a,b,c,d}); -Verify(RemoveDuplicates({a,b,b,c}),{a,b,c}); -Verify(Count({a,b,b,c},b),2); -Verify(VarList(x*Cos(x)),{x}); - - -[ - Local(l); - l:={1,2,3}; - DestructiveDelete(l,1); - Verify(l,{2,3}); - DestructiveInsert(l,1,1); - Verify(l,{1,2,3}); - l[1] := 2; - Verify(l,{2,2,3}); - l[1] := 1; - DestructiveDelete(l,3); - Verify(l,{1,2}); - DestructiveInsert(l,3,3); - Verify(l,{1,2,3}); - DestructiveDelete(FlatCopy(l),1); - Verify(l,{1,2,3}); -]; - -Verify(Table(i!,i,1,4,1),{1,2,6,24}); -Verify(PermutationsList({a,b,c}),{{a,b,c},{a,c,b},{c,a,b},{b,a,c},{b,c,a},{c,b,a}}); - -Testing("ListOperations"); -Verify(First({a,b,c}),a); -Verify(Rest({a,b,c}),{b,c}); -Verify(DestructiveReverse({a,b,c}),{c,b,a}); -Verify(UnList({a,b,c}),a(b,c)); -Verify(Listify(a(b,c)),{a,b,c}); - -Verify(Delete({a,b,c},2),{a,c}); -Verify(Insert({a,c},2,b),{a,b,c}); - -Testing("Length"); -Verify(Length({a,b}),2); -Verify(Length({}),0); - -Testing("Nth"); -Verify(Nth({a,b},1),a); -Verify({a,b,c}[2],b); - -Testing("Concat"); -Verify(Concat({a,b},{c,d}),{a,b,c,d}); -//This is simply not true!!! Verify(Hold(Concat({a,b},{c,d})),Concat({a,b},{c,d})); - - -Testing("Binary searching"); -Verify(BSearch(100,{{n},n^2-15}), -1); -Verify(BSearch(100,{{n},n^2-16}), 4); -Verify(BSearch(100,{{n},n^2-100002}), -1); -Verify(BSearch(100,{{n},n^2-0}), -1); -Verify(FindIsq(100,{{n},n^2-15}), 3); -Verify(FindIsq(100,{{n},n^2-16}), 4); -Verify(FindIsq(100,{{n},n^2-100002}), 100); -Verify(FindIsq(100,{{n},n^2-0}), 1); - -Verify(Difference(FuncList(a*b/c*d), {*,/}), {}); -Verify(Difference(FuncListArith(0*x*Sin(a/b)*Ln(Cos(y-z)+Sin(a))), {*,Ln,Sin}), {}); -Verify(Difference(VarListArith(x+a*y^2-1), {x,a,y^2}), {}); - -Verify(Difference(FuncList(IsCFormable([i:=0;While(i<10)[i++; a--; a:=a+i; {};];])), {IsCFormable,Prog,:=,While,<,++,--,Atom("+"),List}), {}); -Verify(FuncList({1,2,3}),{List}); -Verify(FuncList({{},{}}),{List}); -Verify(FuncList({}),{List}); - -Testing("AssocDelete"); -[ - Local(hash); - hash:={{"A",1},{"A",2},{"B",3},{"B",4}}; - AssocDelete(hash,{"B",3}); - Verify(hash, {{"A",1},{"A",2},{"B",4}}); - Verify(AssocDelete(hash,"A"),True); - Verify(hash, {{"A",2},{"B",4}}); - Verify(AssocDelete(hash,"C"),False); - Verify(hash, {{"A",2},{"B",4}}); - AssocDelete(hash,"A"); - Verify(hash, {{"B",4}}); - AssocDelete(hash, {"A",2}); - AssocDelete(hash,"A"); - Verify(hash, {{"B",4}}); - Verify(AssocDelete(hash,"B"),True); - Verify(hash, {}); - Verify(AssocDelete(hash,"A"),False); - Verify(hash, {}); -]; -Testing("-- Arithmetic Operations"); -Verifiy(1+{3,4},{4,5}); -Verifiy({3,4}+1,{4,5}); -Verifiy({1}+{3,4},Hold({1}+{3,4})); -Verifiy({3,4}+{1},Hold({3,4}+{1})); -Verifiy({1,2}+{3,4},{4,6}); -Verifiy(1-{3,4},{-2,-3}); -Verifiy({3,4}-1,{2,3}); -Verifiy({1}-{3,4},Hold({1}-{3,4})); -Verifiy({3,4}-{1},Hold({3,4}-{1})); -Verifiy({1,2}-{3,4},{-2,-2}); -Verifiy(2*{3,4},{6,8}); -Verifiy({3,4}*2,{6,8}); -Verifiy({2}*{3,4},Hold({2}*{3,4})); -Verifiy({3,4}*{2},Hold({3,4}*{2})); -Verifiy({1,2}*{3,4},{3,8}); -Verifiy(2/{3,4},{2/3,1/2}); -Verifiy({3,4}/2,{3/2,2}); -Verifiy({2}/{3,4},Hold({2}/{3,4})); -Verifiy({3,4}/{2},Hold({3,4}/{2})); -Verifiy({1,2}/{3,4},{1/3,1/2}); -Verifiy(2^{3,4},{8,16}); -Verifiy({3,4}^2,{9,16}); -Verifiy({2}^{3,4},Hold({2}^{3,4})); -Verifiy({3,4}^{2},Hold({3,4}^{2})); -Verifiy({1,2}^{3,4},{1,16}); - -// non-destructive Reverse operation -[ - Local(lst,revlst); - lst:={a,b,c,13,19}; - revlst:=Reverse(lst); - Verify(revlst,{19,13,c,b,a}); - Verify(lst,{a,b,c,13,19}); -]; -Verify(IsBound(lst),False); -Verify(IsBound(revlst),False); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/logic_simplify_test.mpt mathpiper-0.81f+dfsg1/tests/scripts/logic_simplify_test.mpt --- mathpiper-0.0.svn2556/tests/scripts/logic_simplify_test.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/logic_simplify_test.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ - -//Use("logic.ys"); - - -NextTest("CNF"); - - -/* - The main point is that CNF should return an answer in CNF, that is, - as a conjunction of disjuncts. -*/ -Verify(CNF(A And A), A); -Verify(CNF(A And True), A); - - -Verify(CNF(A And False), False); -Verify(CNF(A Or True), True); -Verify(CNF(A Or False), A); -Verify(CNF(A Or Not A), True); -Verify(CNF(A And Not A), False); - - -Verify(CNF((A And B) Or (A And B)), A And B); -Verify(CNF(A Or (A And B)), A And(A Or B)); -Verify(CNF((A => B) And A), (Not A Or B)And A); -Verify(CNF((A And B) And A), (A And B) And A); -Verify(CNF(Not (A And B) And A), (Not A Or Not B) And A); - -Verify(CanProve((A Or B) And Not A), B And Not A); -Verify(CanProve((A Or B) And (Not A Or C)), (A Or B) And (C Or Not A)); -Verify(CanProve((B Or A) And (Not A Or C)), (A Or B) And (C Or Not A)); -Verify(CanProve( A And (A Or B Or C)), A); -Verify(CanProve( A And (Not A Or B Or C)), A And (B Or C)); - -// this is a test of contradication, A==3 should kick A==2 out as they're contradictory -Verify(CanProve( A==3 And (A==2 Or B Or C)), A-3==0 And (B Or C)); -//TODO Verify(CanProve( A==3 And (A<2 Or B Or C)), A-3==0 And (B Or C)); -//TODO Verify(CanProve( A==3 And (A>2 Or B Or C)), (A-3==0) And (((A-2) > 0) Or B Or C)); - -Verify(CanProve(Not(Not (p_2-NULL==0))Or Not(p_2-NULL==0)), True); - - - - -LogicTest({A},A And A, A); -LogicTest({A},A And True, A); -LogicTest({A},A And False, False); -LogicTest({A},A Or True, True); -LogicTest({A},A Or False, A); -LogicTest({A},A Or Not A, True); -LogicTest({A},A And Not A, False); -LogicTest({A,B},(A And B) Or (A And B), A And B); -LogicTest({A,B},A Or (A And B), A And(A Or B)); -LogicTest({A,B},(A And B) And A, (A And B) And A); -LogicTest({A,B},Not (A And B) And A, (Not A Or Not B) And A); -LogicTest({A,B},(A Or B) And Not A, B And Not A); -LogicTest({A,B,C},(A Or B) And (Not A Or C), (A Or B) And (C Or Not A)); -LogicTest({A,B,C},(B Or A) And (Not A Or C), (A Or B) And (C Or Not A)); -LogicTest({A,B,C}, A And (A Or B Or C), A); -LogicTest({A,B,C}, A And (Not A Or B Or C), A And (B Or C)); - - - - -LogicTest({A},CNF(A And A), A); -LogicTest({A},CNF(A And True), A); - - -LogicTest({A},CNF(A And False), False); -LogicTest({A},CNF(A Or True), True); -LogicTest({A},CNF(A Or False), A); -LogicTest({A},CNF(A Or Not A), True); -LogicTest({A},CNF(A And Not A), False); - - -LogicTest({A,B},CNF((A And B) Or (A And B)), A And B); -LogicTest({A,B},CNF(A Or (A And B)), A And(A Or B)); -LogicTest({A,B},CNF((A => B) And A), (Not A Or B)And A); -LogicTest({A,B},CNF((A And B) And A), (A And B) And A); -LogicTest({A,B},CNF(Not (A And B) And A), (Not A Or Not B) And A); - -LogicTest({A,B},CanProve((A Or B) And Not A), B And Not A); -LogicTest({A,B,C},CanProve((A Or B) And (Not A Or C)), (A Or B) And (C Or Not A)); -LogicTest({A,B,C},CanProve((B Or A) And (Not A Or C)), (A Or B) And (C Or Not A)); -LogicTest({A,B,C},CanProve( A And (A Or B Or C)), A); -LogicTest({A,B,C},CanProve( A And (Not A Or B Or C)), A And (B Or C)); - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/macro.mpt mathpiper-0.81f+dfsg1/tests/scripts/macro.mpt --- mathpiper-0.0.svn2556/tests/scripts/macro.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/macro.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ - -[ - Local(a,b,c,d); - DefMacroRuleBase(foo,{a,b}); - - // Simple check - foo(_c,_d) <-- {@c,@d}; - Verify(foo(2,3),Hold({2,3})); - - Macro("foo",{a}) {@a,a}; - a:=A; - Verify(foo(B),{B,A}); - Retract(foo,1); - Retract(foo,2); - Verify(foo(2,3),foo(2,3)); - Verify(foo(B),foo(B)); -]; - -[ - Local(a,i,tot); - a:=100; - Retract(forloop,4); - Macro(forloop,{init,pred,inc,body}) - [ - @init; - While(@pred) - [ - @body; - @inc; - ]; - True; - ]; - tot:=0; - forloop(i:=1,i<=10,i++,tot:=tot+a*i); - Verify(i,11); - Verify(tot,5500); -]; - -[ - Macro("bar",{list,...}) Length(@list); - Verify(bar(a,b,list,bar,list),5); -]; - -[ - Local(x,y,z); - y:=x; - Verify(`{@x,@y},{x,x}); - z:=u; - y:={@z,@z}; - Verify(`{@x,@y},{x,{@z,@z}}); - Verify(`{@x,`(@y)},{x,{@u,@u}}); - y:=Hold(`{@z,@z}); - - Verify(`{@x,@y},{x,{u,u}}); - Verify(`{@x,`(@y)},{x,{u,u}}); -]; - -// check that a macro can reach a local from the calling environment. -[ - Macro(foo,{x}) a*(@x); - Function(bar,{x}) - [ - Local(a); - a:=2; - foo(x); - ]; - Verify(bar(3),6); -]; - -//check that with nested backquotes expansion only expands the top-level expression -[ - Local(a,b); - a:=2; - b:=3; - Verify( - `[ - Local(c); - c:=@a+@b; - `((@c)*(@c)); - ],25); -]; - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/mathpiper_tests.log mathpiper-0.81f+dfsg1/tests/scripts/mathpiper_tests.log --- mathpiper-0.0.svn2556/tests/scripts/mathpiper_tests.log 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/mathpiper_tests.log 1970-01-01 00:00:00.000000000 +0000 @@ -1,382 +0,0 @@ - -=========================== -matrixpower.mpt: Result: True -Side Effects: - - -=========================== -binaryfactors.mpt: Result: True -Side Effects: - - -=========================== -radsimp.mpt: Result: True -Side Effects: - - -=========================== -io.mpt: Result: True -Side Effects: - - -=========================== -poly.mpt: Result: True -Side Effects: - - -=========================== -plots.mpt: Result: True -Side Effects: -****************** -plots.mpt: 6 - -tostring()write(plot2d(a,-1:1,output=data,points=4,depth=0)) - evaluates to -"{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1,1}}}" - which differs from -"{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}" -****************** -****************** -plots.mpt: 7 - -tostring()write(plot2d(b,b= -1:1,output=data,points=4)) - evaluates to -"{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1,1}}}" - which differs from -"{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}" -****************** -****************** -plots.mpt: 14 - -tostring()write(plot3ds(a,-1:1,-1:1,output=data,points=2)) - evaluates to -"{{{-1,-1,-1},{-1,0,-1},{-1,1,-1},{0,-1,0},{0,0,0},{0,1,0},{1,-1,1},{1,0,1},{1,1,1}}}" - which differs from -"{{{-1,-1,-1},{-1,0,-1},{-1,1.,-1},{0,-1,0},{0,0,0},{0,1.,0},{1.,-1,1.},{1.,0,1.},{1.,1.,1.}}}" -****************** -****************** -plots.mpt: 14 - -tostring()write(plot3ds(x1,x1= -1:1,x2= -1:1,output=data,points=2)) - evaluates to -"{{{-1,-1,-1},{-1,0,-1},{-1,1,-1},{0,-1,0},{0,0,0},{0,1,0},{1,-1,1},{1,0,1},{1,1,1}}}" - which differs from -"{{{-1,-1,-1},{-1,0,-1},{-1,1.,-1},{0,-1,0},{0,0,0},{0,1.,0},{1.,-1,1.},{1.,0,1.},{1.,1.,1.}}}" -****************** - - -=========================== -dot.mpt: Result: True -Side Effects: - - -=========================== -numbers.mpt: Result: True -Side Effects: - - -=========================== -integrate.mpt: Result: True -Side Effects: - - -=========================== -regress.mpt: Result: True -Side Effects: -known failure: (limit(x,infinity)x^n/ln(x))=infinity -known failure: (limit(x,0,right)x^(ln(a)/(1+ln(x))))=a -known failure: gcd(10,3.3)!=3.3 and gcd(10,3.3)!=1 -known failure: (d(z)conjugate(z))=undefined -known failure: arccos(cos(beta))!=beta -known failure: (limit(n,infinity)n^5/2^n)=0 -known failure: roundto(roundto(n(cot(2),9),9),n(cot(2),9),9)=0 - - -=========================== -sturm.mpt: Result: True -Side Effects: -****************** -sturm.mpt: 59 - -verifyzero(p.p) - evaluates to -false - which differs from -true -****************** - - -=========================== -lists.mpt: Result: True -Side Effects: - - -=========================== -multivar.mpt: Result: True -Side Effects: - - -=========================== -outer.mpt: Result: True -Side Effects: - - -=========================== -tensors.mpt: Result: True -Side Effects: - - -=========================== -programming.mpt: Result: True -Side Effects: - - -=========================== -complex.mpt: Result: True -Side Effects: -known failure: (limit(n,infinity)(n^2*i^n)/(n^3+1))=0 - - -=========================== -orthopoly.mpt: Result: True -Side Effects: - - -=========================== -calculus.mpt: Result: True -Side Effects: -known failure: limit(k,infinity)((k-phi)/k)^(k+1/2)=exp(-phi) - - -=========================== -GaussianIntegers.mpt: Result: True -Side Effects: - - -=========================== -nthroot.mpt: Result: True -Side Effects: - - -=========================== -deriv.mpt: Result: True -Side Effects: - - -=========================== -journal.mpt: Result: True -Side Effects: - - -=========================== -macro.mpt: Result: True -Side Effects: - - -=========================== -c_tex_form.mpt: Result: True -Side Effects: -****************** -c_tex_form.mpt: 58 - -texform(pi+exp(1)-theta-(integrate(x,x1,3/g(pi))2*theta(x)*exp(1/x))) - evaluates to -"$\pi + \exp \left( 1\right) - \theta - \int _{0.10114177619107067585} ^{\frac{3}{g\left( \pi \right) } } 2 \theta \left( x\right) \exp \left( \frac{1}{x} \right) dx$" - which differs from -"$\pi + \exp \left( 1\right) - \theta - \int _{x_{1}} ^{\frac{3}{g\left( \pi \right) } } 2 \theta \left( x\right) \exp \left( \frac{1}{x} \right) dx$" -****************** - - -=========================== -arithmetic.mpt: Result: True -Side Effects: - - -=========================== -tr.mpt: Result: True -Side Effects: - - -=========================== -openmath.mpt: Result: True -Side Effects: - - -=========================== -ode.mpt: Result: True -Side Effects: - - -=========================== -predicates.mpt: Result: True -Side Effects: -****************** -predicates.mpt: 117 - -hasfunc(a*b+f({b,c}),list) - evaluates to -false - which differs from -true -****************** - - -=========================== -simplify.mpt: Result: True -Side Effects: - - -=========================== -solve.mpt: Result: True -Side Effects: -****************** -solve.mpt: 176 - -roundto(roots[3]-2,10) - evaluates to -0.00002 - which differs from -0 -****************** - - -=========================== -logic_simplify_test.mpt: Result: True -Side Effects: - - -=========================== -trace.mpt: Result: True -Side Effects: - - -=========================== -sums.mpt: Result: True -Side Effects: - - -=========================== -nummethods.mpt: Result: True -Side Effects: -****************** -nummethods.mpt: 11 - -roundto(roundto(sumtaylornum(1,{{k},1/k!},{{k},1/k},21),21)-2.718281828459045235359,21) - evaluates to -2e-21 - which differs from -0 -****************** -****************** -nummethods.mpt: 12 - -roundto(roundto(sumtaylornum(1,{{k},1/k!},21),21)-2.718281828459045235359,21) - evaluates to -2e-21 - which differs from -0 -****************** - - -=========================== -dimensions.mpt: Result: True -Side Effects: - - -=========================== -scopestack.mpt: Result: True -Side Effects: - - -=========================== -numerics.mpt: Result: True -Side Effects: -****************** -numerics.mpt: 21 - -roundto(n(sinh(2),10)-3.6268604078,10) - evaluates to --1e-10 - which differs from -0 -****************** -****************** -numerics.mpt: 25 - -roundto(n(arctan(2*i),12)-n(complex(1.57079632679,0.54930614433),12),11) - evaluates to -1e-11 - which differs from -0 -****************** -****************** -numerics.mpt: 28 - -roundto(n(arccosh(-2),8)-complex(-1.3169579,3.14159265),8) - evaluates to --1e-8 - which differs from -0 -****************** -****************** -numerics.mpt: 29 - -roundto(n(arctanh(2),9)-complex(0.549306144,1.570796327),9) - evaluates to -1e-9 - which differs from -0 -****************** -****************** -numerics.mpt: 99 - -roundto(roundto([local(x);x:=newton(x*exp(x)-4,x,1,10^(-49));n(x*exp(x));],49)-4.,49) - evaluates to -1e-49 - which differs from -0 -****************** -****************** -numerics.mpt: 219 - -roundto(roundto(n(zeta(40)),19)-1.0000000000009094948,19) - evaluates to --0.2308785779493382222 - which differs from -0 -****************** -****************** -numerics.mpt: 303 - -roundto(n(erf(50*i+20)/10^910,22),19) - evaluates to -complex(1.093171190029095854,0.0047546330693181896) - which differs from -complex(1.0931711900290958541,0.0047546330693181896) -****************** - - -=========================== -linalg.mpt: Result: True -Side Effects: - - -=========================== -cyclotomic.mpt: Result: True -Side Effects: - - -=========================== -canprove.mpt: Result: True -Side Effects: - - -=========================== -comments.mpt: Result: True -Side Effects: - - -=========================== -transforms.mpt: Result: True -Side Effects: - diff -Nru mathpiper-0.0.svn2556/tests/scripts/matrixpower.mpt mathpiper-0.81f+dfsg1/tests/scripts/matrixpower.mpt --- mathpiper-0.0.svn2556/tests/scripts/matrixpower.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/matrixpower.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -////// -// test for MatrixPower (dr) -////// - -Testing("-- MatrixPower"); - -//Verify(MatrixPower(,),); -Verify(MatrixPower(a,0),Hold(MatrixPower(a,0))); -Verify(MatrixPower(a,n),Hold(MatrixPower(a,n))); -Verify(MatrixPower({a},0),Hold(MatrixPower({a},0))); -Verify(MatrixPower({a},n),Hold(MatrixPower({a},n))); -Verify(MatrixPower({{a}},0),{{1}}); -Verify(MatrixPower({{a}},1),{{a}}); -Verify(MatrixPower({{a}},-1),{{1/a}}); -Verify(MatrixPower({{a}},3/5),Hold(MatrixPower({{a}},3/5))); -Verify(MatrixPower({{a}},10),{{a^10}}); -Verify(MatrixPower({{a}},-10),{{1/a^10}}); -Verify(MatrixPower({{a}},n),Hold(MatrixPower({{a}},n))); - -Verify(MatrixPower({{1,2},{3,4}},0),{{1,0},{0,1}}); -Verify(MatrixPower({{1,2},{3,4}},1),{{1,2},{3,4}}); -Verify(MatrixPower({{1,2},{3,4}},2),{{7,10},{15,22}}); -Verify(MatrixPower({{1,2},{3,4}},3),{{37,54},{81,118}}); -Verify(MatrixPower({{1,2},{3,4}},4),{{199,290},{435,634}}); -Verify(MatrixPower({{1,2},{3,4}},5),{{1069,1558},{2337,3406}}); -Verify(MatrixPower({{1,2},{3,4}},7),{{30853,44966},{67449,98302}}); -Verify(MatrixPower({{1,2},{3,4}},13),{{741736909,1081027478},{1621541217,2363278126}}); - -Verify(MatrixPower({{1,2},{3,4}},-1),{{-2,1},{3/2,-1/2}}); -Verify(MatrixPower({{1,2},{3,4}},-2),{{11/2,-5/2},{-15/4,7/4}}); -Verify(MatrixPower({{1,2},{3,4}},-3),{{-59/4,27/4},{81/8,-37/8}}); -Verify(MatrixPower({{1,2},{3,4}},-4),{{317/8,-145/8},{-435/16,199/16}}); -Verify(MatrixPower({{1,2},{3,4}},-5),{{-1703/16,779/16},{2337/32,-1069/32}}); -////// -////// diff -Nru mathpiper-0.0.svn2556/tests/scripts/multivar.mpt mathpiper-0.81f+dfsg1/tests/scripts/multivar.mpt --- mathpiper-0.0.svn2556/tests/scripts/multivar.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/multivar.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - -NextTest("Test arithmetic"); - -TestMathPiper(NormalForm(MM((x+y)^5)),y^5+5*x*y^4+10*x^2*y^3+10*x^3*y^2+5*x^4*y+x^5); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/nthroot.mpt mathpiper-0.81f+dfsg1/tests/scripts/nthroot.mpt --- mathpiper-0.0.svn2556/tests/scripts/nthroot.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/nthroot.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -////// -// $Id: nthroot.yts,v 1.3 2006/03/26 12:49:15 ayalpinkus Exp $ -// tests for NthRoot -////// - -Testing("-- NthRoot"); - -// you need to use UnList for this one as -1 is actually -(1), eg. a unary function (minus) -// applied to a positive integer (1). UnList evaluates its arguments, resulting in a negative -// integer (-1). -Verify(NthRoot(-1,2),UnList({NthRoot,-1,2})); - -Verify(NthRoot(2,1),Hold(NthRoot(2,1))); -Verify(NthRoot(2,2),{1,2}); -Verify(NthRoot(12,2),{2,3}); -Verify(NthRoot(12,3),{1,12}); -Verify(NthRoot(27,3),{3,1}); -Verify(NthRoot(17*13,2),{1,17*13}); -Verify(NthRoot(17*17*13,2),{17,13}); -Verify(NthRoot(17*17*17*13,2),{17,17*13}); -Verify(NthRoot(17*17*17*13,3),{17,13}); -Verify(NthRoot(17*17*17*17*13*13,2),{17*17*13,1}); -Verify(NthRoot(17*17*17*17*13*13,3),{17,17*13*13}); -Verify(NthRoot(17*17*17*17*13*13,4),{17,13*13}); -Verify(NthRoot(17*17*17*17*13*13,5),{1,17*17*17*17*13*13}); - -////// -////// \ No newline at end of file diff -Nru mathpiper-0.0.svn2556/tests/scripts/numbers.mpt mathpiper-0.81f+dfsg1/tests/scripts/numbers.mpt --- mathpiper-0.0.svn2556/tests/scripts/numbers.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/numbers.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ - -f():=[]; //Echo(CurrentLine()); - -Verify( CatalanNumber(6), 132 ); f(); -Verify( CatalanNumber(10), 16796 ); f(); - - -Testing("Integer logarithms and roots"); - -Verify(IntLog(23^45, 67), 33); f(); - -Verify(IntLog(1, 67), 0); f(); -Verify(IntLog(2, 67), 0); f(); -Verify(IntLog(0, 67), 0); f(); -Verify(IntLog(1, 1), Undefined); f(); -Verify(IntLog(2, 1), Undefined); f(); -Verify(IntLog(256^8, 4), 32); f(); -Verify(IntLog(256^8-1, 4), 31); f(); -Verify(IntNthRoot(65537^33, 11), 281487861809153); f(); - -Testing("Factorial"); -Verify(261! - 261*260!, 0); f(); -Verify(300! / 250!, 251***300); f(); - -Verify(Repunit(3), 111 ); f(); -Verify(HarmonicNumber(5), 137/60 ); f(); - -Verify( Subfactorial(0), 1 ); f(); -Verify( Subfactorial(21), 18795307255050944540 ); f(); - -Verify( Divisors(180), 18 ); f(); - - -Verify( IsAmicablePair(200958394875 ,209194708485 ), True ); f(); -Verify( IsAmicablePair(220,284),True ); f(); - -Verify( IsComposite(100), True ); f(); -Verify( IsComposite(1), False ); f(); -Verify( IsComposite(37), False ); f(); - -Verify( IsTwinPrime(71), True ); f(); -Verify( IsTwinPrime(1), False ); f(); -Verify( IsTwinPrime(22), False ); f(); - -Verify( DigitalRoot(18), 9 ); f(); -Verify( DigitalRoot(15), 6 ); f(); - -Verify( IsIrregularPrime(37), True ); f(); -Verify( IsIrregularPrime(59), True ); f(); -Verify( IsIrregularPrime(1), False ); f(); -Verify( IsIrregularPrime(11), False ); f(); - -Verify( Gcd( 324 + 1608*I, -11800 + 7900*I ),Complex(-52,16) ); f(); -// I changed from Complex(-4,4) to Complex(4,4) as the GaussianGcd algorithm suddenly returned this instead. -// However, as it turned out it was a bug in FloorN, introduced when -// we moved to the new number classes (so the numbers did not get converted -// to string and back any more). The number got prematurely truncated with -// this test case (regression test added to regress.yts also). -Verify( Gcd( 7300 + 12*I, 2700 + 100*I), Complex(-4,4) ); f(); - -VerifyGaussianGcd(x,y):= -[ - Local(gcd); - gcd:=Gcd(x,y); -// Echo(x/gcd); -// Echo(y/gcd); - Verify(IsGaussianInteger(x/gcd) And IsGaussianInteger(y/gcd),True); -]; -VerifyGaussianGcd(324 + 1608*I, -11800 + 7900*I); -VerifyGaussianGcd(7300 + 12*I, 2700 + 100*I); -VerifyGaussianGcd(120-I*200,-336+50*I); -//TODO we can expand this with randomized tests - -Verify( Lcm({7,11,13,17}), 7*11*13*17 ); f(); -Verify( IsCoprime(11,13), True ); f(); -Verify( IsCoprime(1 .. 10), False ); f(); -Verify( IsCoprime({9,40}), True ); f(); - -Verify( IsCarmichaelNumber( {561,1105,1729,2465,2821,6601,8911} ),{True,True,True,True,True,True,True} ); f(); -Verify( IsCarmichaelNumber( {0,1,2,1727,2463,2823,6603} ),{False,False,False,False,False,False,False} ); f(); - -Verify(IsSmallPrime(137),True); f(); -Verify(IsSmallPrime(138),False); f(); -Verify(IsSmallPrime(65537),True); f(); -Verify(IsSmallPrime(65539),False); f(); -Verify(IsPrime(65539),True); f(); -Verify(RabinMiller(1037),False); f(); -Verify(RabinMiller(1038),False); f(); -Verify(RabinMiller(1039),True); f(); -Verify(NextPrime(65537), 65539); f(); -Verify(NextPrime(97192831),97192841); f(); -Verify(NextPrime(14987234876128361),14987234876128369); f(); -Verify(IsPrime(0),False); f(); -Verify(IsPrime(-1),False); f(); -Verify(IsPrime(1),False); f(); -Verify(IsPrime(2),True); f(); -Verify(IsPrime(3),True); f(); -Verify(IsPrime(4),False); f(); -Verify(IsPrime(5),True); f(); -Verify(IsPrime(6),False); f(); -Verify(IsPrime(7),True); f(); -Verify(IsPrime(-60000000000),False); f(); -Verify(IsPrime(6.1),False); f(); - - -Testing("Random numbers"); -Local(r1, r2, r3, x1, x2, x3); - -r1:=RngCreate(); // create a default RNG object, return structure - f(); -r2:=RngCreate(12345); // create RNG object with given seed - f(); -RandomSeed(12345); // initialize the global RNG with the same seed - f(); -r3:=RngCreate(seed->12345, engine->advanced, dist->gauss); // test advanced options - f(); -Rng(r1); f(); -Rng(r1); f(); -x1:=Rng(r2); f(); -Verify(x1, Random()); f(); -x2:=Rng(r2); f(); -x3:=Rng(r3); f(); - -Verify(Rng(r3)=x3, False); f(); -Verify(x1=x2, False); f(); -RngSeed(r2, 12345); f(); -Verify(Rng(r2), x1); // reproducible number -Verify(Rng(r2), x2); // reproducible number -RngSeed(r3, 12345); -Verify(Rng(r3), x3); // reproducible number - f(); -Verify(PartitionsP(1),1); f(); -Verify(PartitionsP(2),2); f(); -Verify(PartitionsP(3),3); f(); -Verify(PartitionsP(4),5); f(); -Verify(PartitionsP(13),101); f(); -// This takes about 18 seconds, useful for benchmarking -//Verify( PartitionsP(4096), 6927233917602120527467409170319882882996950147283323368445315320451 ); - -Verify(Euler(16),19391512145); f(); -Verify(EulerArray(8), {1,0,-1,0,5,0,-61,0,1385}); f(); - -Verify(JacobiSymbol(165,1), 1); f(); -Verify(JacobiSymbol(1,3), 1); f(); -Verify(JacobiSymbol(1,13), 1); f(); -Verify(JacobiSymbol(2,15), 1); f(); -Verify(JacobiSymbol(3,15), 0); f(); -Verify(JacobiSymbol(7,15), -1); f(); -Verify(JacobiSymbol(3,7), -1); f(); -Verify(JacobiSymbol(0,3), 0); f(); -Verify(JacobiSymbol(0,1), 1); f(); -Verify(JacobiSymbol(1323132412,31312317), -1); f(); -Verify(JacobiSymbol(57173571,1976575123), 1); f(); -Verify(JacobiSymbol(-3,5), -1); f(); diff -Nru mathpiper-0.0.svn2556/tests/scripts/numerics.mpt mathpiper-0.81f+dfsg1/tests/scripts/numerics.mpt --- mathpiper-0.0.svn2556/tests/scripts/numerics.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/numerics.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,327 +0,0 @@ -/* Numerical testers - all confirmed with Matlab 6r12.0 */ - -f():=[];//Echo(CurrentLine()); - - - - -BuiltinPrecisionSet(10); - -NumericEqual(N(Sqrt(2),5), 1.41421,5); // no idea where the problem is -NumericEqual(N(N(1+Pi,20)-Pi,20),1,20); // "N" should have "HoldArg" in some way, so inner "N" is evaluated with outer precision 20 - -/* Got the first digits of Pi from the following page: - http://www.cecm.sfu.ca/projects/ISC/dataB/isc/C/pi10000.txt - Just checking that Yacas agrees. -*/ -NumericEqual(N(Pi,70),3.1415926535897932384626433832795028841971693993751058209749445923078164062862,70); - -NumericEqual( N(Sec(2),9), -2.402997962, 9); -NumericEqual( N(Csc(2),9), 1.09975017,9); -NumericEqual( N(Cot(2),9), -0.457657554, 9); -NumericEqual( N(Sinh(2),10), 3.6268604078,10); // matter of discussion whether rounding should be to nearest - -NumericEqual( N(ArcSin(2), 9), Complex(1.570796327,1.316957897),9); -NumericEqual( N(ArcCos(2),9), Complex(0,-1.316957897),9); -NumericEqual( N(ArcTan(2*I), 12), N(Complex(1.57079632679,0.54930614433),12),11); // calculating to precision+1 because RoundTo rounds... cluttering the last digit with round-off -NumericEqual( N(ArcSinh(2), 9), 1.443635475,9); -NumericEqual( N(ArcCosh(2), 9), 1.316957897,9); -NumericEqual( N(ArcCosh(-2), 8), Complex(-1.3169579,3.14159265),8); -NumericEqual( N(ArcTanh(2), 9), Complex(0.549306144,1.570796327),9); - -/* Numerical tests - all confirmed with Maple */ -BuiltinPrecisionSet(50); - -NumericEqual( -RoundTo(N(Pi), 50) -, 3.14159265358979323846264338327950288419716939937511 -, 50); - -NumericEqual( -RoundTo(N(Sin(2.0)), 49) -, 0.9092974268256816953960198659117448427022549714479 -,49); - -NumericEqual( -RoundTo(N(Sin(2.0)), 50) -, 0.90929742682568169539601986591174484270225497144789 -,50); - -NumericEqual( -RoundTo(N(Sin(2.0)), 51) -, 0.90929742682568169539601986591174484270225497144789 -,51); - -NumericEqual( -RoundTo(N(Cos(20.0)), 49) -, 0.4080820618133919860622678609276449570992995103163 -, 49); f(); - -NumericEqual( -RoundTo(N(Tan(20.0)), 49) -, 2.2371609442247422652871732477303491783724839749188 -, 49); f(); - -NumericEqual( -RoundTo(N(Exp(10.32),54), 54) -, 30333.2575962246035600343483350109621778376486335450125 -,48); f(); // This one rounds off the wrong direction (125 rounded to 12 iso 13). But alas, change was needed because new interpretation means the required precision was actually higher (not number of decimals after point, but total number of digits were meant). - -NumericEqual( -RoundTo(N(Ln(10.32/4.07)), 49) -, 0.93044076059891305468974486564632598071134270468 -, 49); f(); - -NumericEqual( -RoundTo(N(1.3^10.32), 48) -, 14.99323664825717956473936947123246987802978985306 -, 48); f(); - -NumericEqual( -RoundTo(N(Sqrt(5.3),51), 51) -, 2.302172886644267644194841586420201850185830282633675 -,51); f(); // increased to 51 digits so round-off is obviously downwards (previous rounding was defendably wrong) - -// this failed in gmp due to broken SqrtN() -NumericEqual( -RoundTo(N(Sqrt(25.3)), 50) -, 5.0299105359837166789719353820984438468186649281130 -,50); - -// this failed due to broken RoundTo() -NumericEqual( -RoundTo(PowerN(13, -23), 50) -, 0.23949855470974885180294666343025235387321690490245e-25 -, 50); - -NumericEqual( -RoundTo([Local(x);x:=Newton(x*Exp(x)-4,x,1,10^(-49)); N(x*Exp(x));], 49) -, 4. -,49); f(); -Verify(Newton(x^2+1,x,1,0.1,-3,3), Fail); f(); -NumericEqual(Newton(x^2-1,x,1,0.1,-3,3), 1.,BuiltinPrecisionGet()); f(); - -NumericEqual( -RoundTo(N(ArcSin(0.32)), 49) -, 0.3257294872946301593103199105324500784354180998123 -,49); f(); - -NumericEqual( -RoundTo(N(Sin(N(ArcSin(0.1234567)))), 49) -, 0.1234567 -,49); f(); - -/* ArcSin(x) for x close to 1 */ - -NumericEqual( -RoundTo(N( (1-Sin(N(ArcSin(1-10^(-25)))))*10^25), 25) -, 1. -, 25); f(); - -NumericEqual( -N(ArcSin(N(Sin(1.234567),50)),50) -, N(1.234567,50) -, 49); f(); // calculating to precision+1 because RoundTo rounds... cluttering the last digit with round-off - -NumericEqual( -RoundTo(N(ArcCos(0.32)), 49) -, 1.2450668395002664599210017811073013636631665998753 -, 49); f(); - -NumericEqual( -RoundTo(N(ArcTan(0.32)), 49) -, 0.3097029445424561999173808103924156700884366304804 -, 49); f(); - -NumericEqual( -RoundTo(N(Cos(N(ArcCos(0.1234567)))), 49) -, 0.1234567 -, 49); - -NumericEqual( -RoundTo(N(ArcCos(N(Cos(1.234567)))), 49) -, 1.234567 -, 49); - -NumericEqual( -RoundTo(N(Tan(N(ArcTan(20)))), 46) // large roundoff error on Tan() calculation due to subtraction from Pi/2 -- unavoidable loss of precision -, 20. -, 46); -//KnownFailure( -NumericEqual( -RoundTo(N(Tan(N(ArcTan(500000)))), 38) -, 500000. -//) -, 38); - -BuiltinPrecisionSet(60); // obviously, 50 is not enough for the following -//KnownFailure( -NumericEqual( -RoundTo(N((Pi/2-ArcTan(N(Tan(N(Pi/2)-10^(-24)))))*10^24 ), 25) -, 1. -//) -, 25); - -/// special functions -BuiltinPrecisionSet(20); // let's be gentle - -TestMathPiper( -Gamma(10.5) -, (654729075*Sqrt(Pi))/1024 -); - -TestMathPiper( -Gamma(9/2) -, (105*Sqrt(Pi))/16 -); - -TestMathPiper( -Gamma(-10.5) -, (-2048*Sqrt(Pi))/13749310575 -); - -TestMathPiper( -Gamma(-7/2) -, (16*Sqrt(Pi))/105 -); - -NumericEqual(RoundTo(N( Internal'GammaNum(10.5) ), 13), 1133278.3889487855673, 13); -NumericEqual(RoundTo(N( Internal'GammaNum(-11.5) ), 20), 0.00000002295758104824, 20); -NumericEqual(RoundTo(N( Internal'GammaNum(-12.5) ), 20), -0.00000000183660648386, 20); - -// Check for one example that N(Gamma(x)) returns the same as Internal'GammaNum -NumericEqual(RoundTo(N( Gamma(10.5) ), 13), 1133278.3889487855673, 13); - - - -NumericEqual( // lost 2 digits b/c of imprecise arithmetic -RoundTo(N( Zeta(-11.5) ), 18) -, 0.020396978715942792 -,18); - -TestMathPiper( -Zeta(40) -, (261082718496449122051*Pi^40)/20080431172289638826798401128390556640625 -); - -TestMathPiper( -Zeta(-11) -, 691/32760 -); - -TestMathPiper( -Zeta(-12) -, 0 -); - -NumericEqual( -RoundTo(N(Zeta(40)), 19) -, 1.0000000000009094948 -,19); - -NumericEqual( -RoundTo(N(Zeta(1.5)), 19) -, 2.6123753486854883433 -,19); - -// test correctness of Zeta(3) -NumericEqual( -RoundTo(Internal'ZetaNum(3)-N(Zeta(3)), 20) -, 0 -,20); - -TestMathPiper( -Bernoulli(40) -, -261082718496449122051/13530 -); - -Verify( -ContFracList(355/113) -, {3,7,16} -); - -Verify( -ContFracList(-24, 4) -, {-24} -); - -Verify( -ContFracList(-355/113) -, {-4,1,6,16} -); - -BuiltinPrecisionSet(7); - -Verify( -GuessRational(N(Pi)) -, 355/113 -); - -/* - For the NearRational test, perhaps better would be a real test that - checks that the result is correct up to the required number of digits - accuracy. -*/ -BuiltinPrecisionSet(10); -Verify( -NearRational(N(Pi)) -, 355/113, -); - -// Lambert's W function -NumericEqual( -N(LambertW(-0.24),BuiltinPrecisionGet()) -, -0.3357611648 -, BuiltinPrecisionGet()); -NumericEqual( -N(LambertW(10),BuiltinPrecisionGet()) -, 1.7455280027 -, BuiltinPrecisionGet()); - -// Bessel Functions -// These results are from GNU bc, matlab seems to suck. -BuiltinPrecisionSet(50); -NumericEqual( N(BesselJ(0,.5)), RoundTo(.93846980724081290422840467359971262556892679709682,50),50 ); -NumericEqual( N(BesselJ(0,.9)), RoundTo(.80752379812254477730240904228745534863542363027564,50),50 ); -NumericEqual( N(BesselJ(0,.99999)), RoundTo(.76520208704756659155313775543958045290339472808482,50),50 ); -NumericEqual( N(BesselJ(10,.75)), RoundTo(.00000000001496217131175968146987124836216828348578,50),50 ); -NumericEqual( N(BesselJ(5,1)), RoundTo(.00024975773021123443137506554098804519815836777698,50),50 ); -NumericEqual( N(BesselJ(4,2)), RoundTo(.03399571980756843414575921128853104471483296834631,50),50 ); -NumericEqual( N(BesselJ(10,3)), RoundTo( .00001292835164571588377753453080258017074342083284,50),50 ); - -NumericEqual( N(BesselJ(11,11)), RoundTo( .20101400990926940339478738551009382430831534125484,50),50 ); -NumericEqual( N(BesselJ(-11,11)), RoundTo( -.20101400990926940339478738551009382430831534125484,50),50 ); -NumericEqual( RoundTo(N(BesselJ(1,10)),50), RoundTo( .04347274616886143666974876802585928830627286711859, 50),50 ); -NumericEqual( N(BesselJ(10,10)), RoundTo( .20748610663335885769727872351875342803274461128682, 50 ),50 ); -NumericEqual( RoundTo(N(BesselJ(1,3.6)),50), RoundTo( .09546554717787640384570674422606098601943275490885, 50 ),50) ; - -BuiltinPrecisionSet(20); -Verify( RoundTo(N(Erf(Sqrt(0.8)),20),19), // verified with Maple -RoundTo(.79409678926793169113034892342, 19) -); -Verify( RoundTo(N(Erf(50*I+20)/10^910,22),19), // verified with Maple -RoundTo(1.09317119002909585408+I*0.00475463306931818955275, 19) -); - -// testing GammaConstNum against Maple -Testing("Gamma constant"); -BuiltinPrecisionSet(40); -NumericEqual(Internal'gamma()+0, 0.5772156649015328606065120900824024310422,BuiltinPrecisionGet()); -BuiltinPrecisionSet(20); -Verify(gamma,Atom("gamma")); -NumericEqual(RoundTo(Internal'gamma()+0,19), 0.5772156649015328606,19); -NumericEqual(RoundTo(N(1/2+gamma+Pi), 19), 4.2188083184913260991,19); - -// From GSL 1.0 -//NumericEqual( N(PolyLog(2,-0.001),20), -0.00099975011104865108, 20 ); -// PolyLog I didn't write PolyLog, but it seems to not always calculate correctly up to the last digit. -Verify( RoundTo(N(PolyLog(2,-0.001)+0.00099975011104865108,20),20),0); - -// Round-off errors -N([ - Local(a,b); - a:= 77617; - b:= 33096; - // this expression gives a wrong answer on any hardware floating-point platform - NumericEqual( 333.75*b^6 + a^2*(11*a^2*b^2-b^6-121*b^4-2)+5.5*b^8 +a/(2*b), -0.827396,6); -],40); diff -Nru mathpiper-0.0.svn2556/tests/scripts/nummethods.mpt mathpiper-0.81f+dfsg1/tests/scripts/nummethods.mpt --- mathpiper-0.0.svn2556/tests/scripts/nummethods.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/nummethods.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -// test some numerical methods - -// these examples are taken from the refman - -Verify(IntPowerNum(3*10^100, 0, MultiplyN,1), 1); -Verify(IntPowerNum(3, 3, MultiplyN,1), 27); -Verify(IntPowerNum(HilbertMatrix(2), 4, *, Identity(2)), {{289/144,29/27},{29/27,745/1296}}); - -Verify(IntPowerNum(3,100,{{x,y},Mod(x*y,7)},1), 4); - -BuiltinPrecisionSet(21); -NumericEqual(RoundTo(SumTaylorNum(1, {{k},1/k!}, {{k},1/k}, 21),21), 2.718281828459045235359,21); -NumericEqual(RoundTo(SumTaylorNum(1, {{k},1/k!}, 21),21), 2.718281828459045235359,21); -BuiltinPrecisionSet(20); -NumericEqual(NewtonNum({{x}, x+Sin(x)}, 3, 5, 3), 3.14159265358979323846,20); diff -Nru mathpiper-0.0.svn2556/tests/scripts/ode.mpt mathpiper-0.81f+dfsg1/tests/scripts/ode.mpt --- mathpiper-0.0.svn2556/tests/scripts/ode.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/ode.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ - - -Verify( OdeTest(y''+y, OdeSolve(y''+y==0) ), 0 ); -Verify( OdeTest(y'/5-Sin(x), OdeSolve(y'/5==Sin(x)) ), 0 ); -Verify( OdeTest(x*y' - 1, OdeSolve(x*y'==1) ), 0 ); diff -Nru mathpiper-0.0.svn2556/tests/scripts/openmath.mpt mathpiper-0.81f+dfsg1/tests/scripts/openmath.mpt --- mathpiper-0.0.svn2556/tests/scripts/openmath.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/openmath.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -NextTest("Converting to and from OpenMath expressions"); - -Macro(OMTest1,{expr}) -[ - Local(string,result); - string:=ToString() OMForm(@expr); - result:=FromString(string)OMRead(); -// Echo(Hold(@expr),`Hold(@result)); - Verify(Hold(@expr),`Hold(@result)); -]; - -OMTest1(2+3); -OMTest1(2*a+3*Sin(Cos(a*x+b))); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/orthopoly.mpt mathpiper-0.81f+dfsg1/tests/scripts/orthopoly.mpt --- mathpiper-0.0.svn2556/tests/scripts/orthopoly.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/orthopoly.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -NextTest("Testing orthogonal polynomials"); -/* Symbolic calculations */ -TestMathPiper(OrthoG(3, 1/5, x), 88/125*x^3-12/25*x); -TestMathPiper(OrthoG(9, 1/2, x), 12155/128*x^9-6435/32*x^7+9009/64*x^5-1155/32*x^3+315/128*x); -TestMathPiper(OrthoH(4, x), 16*x^4-48*x^2+12); -TestMathPiper(OrthoH(10, x), 1024*x^10-23040*x^8+161280*x^6-403200*x^4+302400*x^2-30240); -TestMathPiper(OrthoL(4, 1/3, x), x^4/24-13/18*x^3+65/18*x^2-455/81*x+455/243); -TestMathPiper(OrthoP(3,1/2,5/2,x), 21/2*x^3-7*x^2-35/16*x+7/8); -TestMathPiper(OrthoP(7,x), (429*x^7-693*x^5+315*x^3-35*x)/16); -TestMathPiper(OrthoT(15, x), 16384*x^15-61440*x^13+92160*x^11-70400*x^9+28800*x^7-6048*x^5+560*x^3-15*x); -TestMathPiper(OrthoU(16, x), 65536*x^16-245760*x^14+372736*x^12-292864*x^10+126720*x^8-29568*x^6+3360*x^4-144*x^2+1); -/* Numerical calculations */ -TestMathPiper(OrthoP(100, 1), 1); -TestMathPiper(OrthoL(50,5/3,5/2), 956329424993407752478497541911420551314045339353541114044036291602395886513403153686689293955/143232645897909553890691033589829981069003266848814603996731044282564768594296559565258358784); -TestMathPiper(OrthoP(15,1/7,1/9,2/3), 3891107589471727673898835091294644097395/16032477875245178148605931130545427636128); diff -Nru mathpiper-0.0.svn2556/tests/scripts/outer.mpt mathpiper-0.81f+dfsg1/tests/scripts/outer.mpt --- mathpiper-0.0.svn2556/tests/scripts/outer.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/outer.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -////// -// $Id: outer.yts,v 1.2 2006/03/26 12:49:15 ayalpinkus Exp $ -// Tests for Outer -////// - -Testing("-- Outer"); - -Verify(Outer({},{}),{}); -Verify(Outer({{}},{}),Hold(Outer({{}},{}))); -Verify(Outer({},{{}}),Hold(Outer({},{{}}))); -Verify(Outer({{}},{{}}),Hold(Outer({{}},{{}}))); -Verify(Outer(a,b),Hold(Outer(a,b))); -Verify(Outer({a},{b}),{{a*b}}); -Verify(Outer({a,b},{c}),{{a*c},{b*c}}); -Verify(Outer({a},{b,c}),{{a*b,a*c}}); -Verify(Outer({a,b},{c,d,e}),{{a*c,a*d,a*e},{b*c,b*d,b*e}}); -Verify(Outer({a,b,c},{d,e}),{{a*d,a*e},{b*d,b*e},{c*d,c*e}}); - -////// diff -Nru mathpiper-0.0.svn2556/tests/scripts/piper_test.bat mathpiper-0.81f+dfsg1/tests/scripts/piper_test.bat --- mathpiper-0.0.svn2556/tests/scripts/piper_test.bat 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/piper_test.bat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -java org.mathpiper.tests.MathPiperTest diff -Nru mathpiper-0.0.svn2556/tests/scripts/plots.mpt mathpiper-0.81f+dfsg1/tests/scripts/plots.mpt --- mathpiper-0.0.svn2556/tests/scripts/plots.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/plots.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ - -// some tests to verify that plotting works - -/* I stringified the results for now, as that is what the tests used to mean. The correct way to deal with this - * would be to compare the resulting numbers to accepted precision. - */ -Verify(ToString()Write(Plot2D(a,-1:1,output->data,points->4,depth->0)), "{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}"); -Verify(ToString()Write(Plot2D(b,b-> -1:1,output->data,points->4)), "{{{-1,-1},{-0.5,-0.5},{0,0},{0.5,0.5},{1.,1.}}}"); - -[ - Local(result); - result:="{{{-1,-1,-1},{-1,0,-1},{-1,1.,-1},{0,-1,0},{0,0,0},{0,1.,0},{1.,-1,1.},{1.,0,1.},{1.,1.,1.}}}"; - Verify(ToString()Write(Plot3DS(a,-1:1,-1:1,output->data,points->2)), result); - Verify(ToString()Write(Plot3DS(x1,x1 -> -1:1,x2 -> -1:1,output->data,points->2)), result); -]; - - -// test NFunction -BuiltinPrecisionSet(10); -Retract("f",1); -Retract("f1",1); -f(x) := N(Abs(1/x-1)); -Verify(f(0), Infinity); -NumericEqual(RoundTo(f(3),BuiltinPrecisionGet()), 0.6666666667,BuiltinPrecisionGet()); -NFunction("f1", "f", {x}); -Verify(f1(0), Undefined); -NumericEqual(RoundTo(f1(3),BuiltinPrecisionGet()), 0.6666666667,BuiltinPrecisionGet()); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/poly.mpt mathpiper-0.81f+dfsg1/tests/scripts/poly.mpt --- mathpiper-0.0.svn2556/tests/scripts/poly.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/poly.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ - -NextTest("Polynomials"); -TestMathPiper(Expand((1+x)^2),1+2*x+x^2); - -// We need more polynomial tests - diff -Nru mathpiper-0.0.svn2556/tests/scripts/predicates.mpt mathpiper-0.81f+dfsg1/tests/scripts/predicates.mpt --- mathpiper-0.0.svn2556/tests/scripts/predicates.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/predicates.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +0,0 @@ - -Testing("Predicates"); -Verify(IsFunction(a(b)),True); -Verify(IsFunction(a),False); -Verify(IsList({a,b,c}),True); -Verify(IsList(a),False); -Verify(IsAtom({a,b,c}),False); -Verify(IsAtom(a),True); -Verify(IsAtom(123),True); - -Verify(IsNumber(123),True); -Verify(IsNumber(123.123),True); -Verify(IsNumber(a),False); -Verify(IsNumber({a}),False); - -Verify(IsInteger(123),True); -Verify(IsInteger(123.123),False); -Verify(IsInteger(a),False); -Verify(IsInteger({a}),False); - -Testing("Boolean Operations"); -Verify(False And False,False); -Verify(True And False,False); -Verify(False And True,False); -Verify(True And True,True); - -Verify(False Or False,False); -Verify(True Or False,True); -Verify(False Or True,True); -Verify(True Or True,True); - -Verify(Not(True),False); -Verify(Not(False),True); - -Verify(Equals(a,b),False); -Verify(Equals(a,a),True); -Verify(Equals({a,b},{a}),False); -Verify(Equals({a,b},{a,b}),True); - -Testing("NumberCompares"); -Verify(LessThan(2,3),True); -Verify(LessThan(3,2),False); -Verify(GreaterThan(2,3),False); -Verify(GreaterThan(3,2),True); - -Verify(.1<2,True); -Verify(0.1<2,True); -Verify(.3<2,True); -Verify(.1>2,False); -Verify(0.1>2,False); -Verify(.3>2,False); - -Verify(2<.1,False); -Verify(2<0.1,False); -Verify(2<.3,False); -Verify(2>.1,True); -Verify(2>0.1,True); -Verify(2>.3,True); - -Testing("comparisons in exponential notation"); -// some of these failed -Verify(1e-5 < 1, True); -Verify(1e-5 < 2e-5, True); -Verify(1e-1 < 2e-1, True); -Verify(1e-15 < 2e-15, True); -Verify(1e-5 < 1e-10, False); -Verify(1e-5 < 1e-2, True); -Verify(-1e-5 < 1e-5, True); -Verify(-1e-5 < 1e-6, True); -Verify(1e-5 = 2e-5, False); -Verify(1e-5 = 1e-6, False); -Verify(1e-15 > 0, True); -Verify(1e-5 > 0, True); -Verify(1e-4 > 0, True); -Verify(1e-3 > 0, True); -Verify(1e-2 > 0, True); -Verify(1e-1 > 0, True); -Verify(1e5 > 0, True); - -Verify(1.0000000000000000000000000000111 > 1, True); -Verify(0.999999999999999999999999999992 < 1, True); - -Verify(LessThan(-1e-115, 0), True); -Verify(LessThan(-1e-15, 0), True); -Verify(LessThan(-1e-10, 0), True); -Verify(LessThan(-1e-5, 0), True); -Verify(LessThan(-1e-1, 0), True); - -Testing("Matrix predicates"); -Verify(IsHermitian({{0,I},{-I,0}}),True); -Verify(IsHermitian({{0,I},{-I,1}}),True); -Verify(IsHermitian({{0,I},{-2*I,0}}),False); - -Verify(IsUnitary({{0,I},{-I,0}}),True); -Verify(IsUnitary({{0,I},{-I,1}}),False); -Verify(IsUnitary({{0,I},{-2*I,0}}),False); - -Verify(IsVariable(a),True); -Verify(IsVariable(Sin(a)),False); -Verify(IsVariable(2),False); -Verify(IsVariable(-2),False); -Verify(IsVariable(2.1),False); - - -Verify(HasExpr(a*b+1,1),True); -Verify(HasExpr(a+Sin(b*c),c),True); -Verify(HasExpr(a*b+1,2),False); -Verify(HasExpr(a*b+f({b,c}),f),False); -Verify(HasExprArith(a*b+1,Atom("+")),False); -Verify(HasExprArith(a*b+1,1),True); -Verify(HasExprArith(a+Sin(b*c),c),False); -Verify(HasExprArith(a+Sin(b*c),Sin(b*c)),True); -Verify(HasExprArith(a*b+f({b,c}),c),False); - -Verify(HasFunc(a*b+1,*),True); -Verify(HasFunc(a+Sin(b*c),*),True); -Verify(HasFunc(a*b+1,List),False); -Verify(HasFunc(a*b+f({b,c}),List),True); -Verify(HasFuncArith(a*b+1,Atom("+")),True); -Verify(HasFuncArith(a+Sin(b*c),*),False); -Verify(HasFuncArith(a+Sin(b*c),Sin),True); -Verify(HasFuncArith(a*b+f({b,c}),List),False); - -Verify(IsGaussianInteger(3+4*I),True ); -Verify(IsGaussianInteger(5),True); -Verify(IsGaussianInteger(1.1), False ); -Verify(IsGaussianPrime(5+2*I),True ); -Verify(IsGaussianPrime(13), False ); -Verify(IsGaussianPrime(0), False ); -Verify(IsGaussianPrime(3.5), False ); -Verify(IsGaussianPrime(2+3.1*I), False ); -Verify(IsPerfect(2305843008139952128), True ); -Verify(IsPerfect(137438691328),True ); -Verify(IsPerfect(234325),False ); - -Testing("IsConstant"); - -Verify(IsConstant(Pi), True); -Verify(IsConstant(Exp(1)+Sqrt(3)), True); -Verify(IsConstant(x), False); -Verify(IsConstant(Infinity), True); -Verify(IsConstant(-Infinity), True); -Verify(IsConstant(Undefined), True); - -Testing("-- IsScalar"); -Verify(IsScalar(a),True); -Verify(IsScalar({a}),False); - -Testing("-- IsVector"); -Verify(IsVector(1),False); -Verify(IsVector(a),False); -Verify(IsVector(Sin(a)+2),False); -Verify(IsVector({}),True); -Verify(IsVector({{}}),False); -Verify(IsVector({1,2,a,4}),True); -Verify(IsVector({1,{2,a},4}),False); -Verify(IsVector({{a,b,c}}),False); - -Testing("-- IsVector(IsNumber)"); -Verify(IsVector(IsNumber,1),False); -Verify(IsVector(IsNumber,{}),True); -Verify(IsVector(IsNumber,{a,b,c}),False); -Verify(IsVector(IsNumber,{a,2,c}),False); -Verify(IsVector(IsNumber,{2,2.5,4}),True); -Verify(IsVector(IsNumber,{Pi,2,3}),False); -Verify(IsVector(IsNumber,{{1},{2}}),False); - -Testing("-- Matrix Predicates"); - -Testing("---- IsMatrix"); -Verify(IsMatrix(1),False); -Verify(IsMatrix({}),False); -Verify(IsMatrix({a,b}),False); -Verify(IsMatrix({{}}),True); -Verify(IsMatrix({{a}}),True); -Verify(IsMatrix({{{a}}}),False); -Verify(IsMatrix({{},a}),False); -Verify(IsMatrix({{a},b}),False); -Verify(IsMatrix({{},{}}),True); -Verify(IsMatrix({{{}},{}}),False); -Verify(IsMatrix({{},{{}}}),False); -Verify(IsMatrix({{a,b},{c}}),False); -Verify(IsMatrix({{a,b},{c,d}}),True); -Verify(IsMatrix({{a,b},{c,{d}}}),False); -Verify(IsMatrix({{{}}}), False); -Verify(IsMatrix({{{a}}}), False); -Verify(IsMatrix({{{{a}}},{{{b}}}}),False); - -Testing("---- IsMatrix(IsInteger)"); -Verify(IsMatrix(IsInteger,{{a,1}}),False); -Verify(IsMatrix(IsInteger,{{1,2}}),True); -Verify(IsMatrix(IsInteger,{{1,2/3}}),False); -Verify(IsMatrix(IsInteger,{{1,2,3},{4,5,6}}),True); -Verify(IsMatrix(IsInteger,{{1,{2},3},{4,5,6}}),False); -Verify(IsMatrix(IsInteger,{{1,2,3},{4,5}}),False); -Verify(IsMatrix(IsInteger,{{Sin(1),2,3},{4,5,6}}),False); -Verify(IsMatrix(IsInteger,{{Sin(0),2,3},{4,5,6}}),True); - -Testing("---- IsSquareMatrix"); -Verify(IsSquareMatrix({{}}),False); -Verify(IsSquareMatrix({{a}}),True); -Verify(IsSquareMatrix({{},{}}),False); -Verify(IsSquareMatrix({{a,b}}),False); -Verify(IsSquareMatrix({{a,b},{c,d}}),True); -Verify(IsSquareMatrix({{a,b},{c,d},{e,f}}),False); -Verify(IsSquareMatrix({{a,b,c},{d,e,f},{g,h,i}}),True); -Verify(IsSquareMatrix({{a,b,c},{d,e,f}}),False); -Verify(IsSquareMatrix({{{a,b}},{{c,d}}}), False); diff -Nru mathpiper-0.0.svn2556/tests/scripts/programming.mpt mathpiper-0.81f+dfsg1/tests/scripts/programming.mpt --- mathpiper-0.0.svn2556/tests/scripts/programming.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/programming.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ - - -Testing("Apply"); -Verify(Apply("+",{2,3}),5); -[ - Local(x,y); - Verify(Apply({{x,y},x+y},{2,3}),5); - Verify(Apply(Lambda({x,y},x+y),{2,3}),5); - Verify(Lambda({x,y},x+y) @ {2,3},5); - - /* Basically the next line is to check that {{x},Length(x)} - * behaves in an undesirable way (Length being evaluated - * prematurely), so that the next test can then check that - * Lambda solves the problem. - */ - Verify(Apply({{x},Length(x)},{"aaa"}),Length); - Verify(Apply(Lambda({x},Length(x)),{"aaa"}),3); - - Verify(x,x); - Verify(y,y); - - Testing("ThreadingListables"); - x:={bb,cc,dd}; - Verify(Sin(aa*x),{Sin(aa*bb),Sin(aa*cc),Sin(aa*dd)}); -]; - - - -Testing("MapSingle"); -Verify(MapSingle("!",{1,2,3,4}),{1,2,6,24}); - -/* Example: using the for function. */ -Function("count",{from,to}) -[ - Local(i); - Local(sum); - Set(sum,0); - For(i:=from,i0 And A<=0),False); -LogicVerify(CanProve(A>0 Or A<=0),True); -Verify(A<0,A<0); -Verify(A>0,A>0); -TestMathPiper(Arg(Exp(2*I*Pi/3)),2*Pi/3); - -TestMathPiper(Content(1/2*x+1/2),1/2); -TestMathPiper(PrimitivePart(1/2*x+1/2),x+1); -TestMathPiper(Content(1/2*x+1/3),1/6); -TestMathPiper(PrimitivePart(1/2*x+1/3),3*x+2); - -// Mod generated a stack overflow on floats. -Verify(Mod(1.2,3.4),6/5); -//TODO I need to understand why we need to put Eval here. Mod(-1.2,3.4)-2.2 returns 0/5 where the 0 is not an integer according to the system. Round-off error? -NumericEqual(N(Eval(Mod(-1.2,3.4))),2.2,BuiltinPrecisionGet()); -Verify(Mod(-12/10,34/10),11/5); -// just a test to see if Verify still gives correct error Verify(N(Mod(-12/10,34/10)),11/5); - - -// some reports: - -LocalSymbols(f,p,a,b,x,n) -[ - f(_n) <-- Apply("D",{x,n, x^n}); - Verify(f(10)-(10!)); - - p := a+2-(a+1); - Verify(Simplify(x^p),x); -]; - -LocalSymbols(f,p,a,b,x,n,simple,u,v) -[ - simple := { - Exp(_a)*Exp(_b) <- Exp(a+b), - Exp(_a)*_u*Exp(_b) <- u*Exp(a+b), - _u*Exp(_a)*Exp(_b) <- u*Exp(a+b), - Exp(_a)*Exp(_b)*_u <- u*Exp(a+b), - _u*Exp(_a)*_v*Exp(_b) <- u*v*Exp(a+b), - Exp(_a)*_u*Exp(_b)*_v <- u*v*Exp(a+b), - _u*Exp(_a)*Exp(_b)*_v <- u*v*Exp(a+b), - _u*Exp(_a)*_v*Exp(_b)*_w <- u*v*w*Exp(a+b) - }; - - a := Simplify(Exp(x)*(D(x) x*Exp(-x))); - b := Exp(x)*Exp(-x)-Exp(x)*x*Exp(-x); - - a:= (a /: simple); - b:= (b /: simple); - - Verify(Simplify(a-(1-x)),0); - Verify(Simplify(b-(1-x)),0); - -]; - -// Verify that postfix operators can be applied one after the other -// without brackets -Verify((3!) !, 720); -Verify(3! !, 720); - -TestMathPiper(TrigSimpCombine(Exp(A*X)),Exp(A*X)); -TestMathPiper(TrigSimpCombine(x^Sin(a*x+b)),x^Sin(a*x+b)); -Verify(CanBeUni(x^(-1)),False); - - -f(x):=Eval(Factor(x))=x; -Verify(f(703), True); -Verify(f(485), True); -Verify(f(170410240), True); - - - - - -/* bug reported by Jonathan: - All functions that do not have Taylor Expansions about - the given point go into infinite loops. - */ - -Verify(Taylor(x,0,5) Ln(x),Undefined); -Verify(Taylor(x,0,5) 1/x,Undefined); -Verify(Taylor(x,0,5) 1/Sin(x),Undefined); - -// Yacas used to not simplify the following, due to Pi being -// considered constant. The expression was thus not expanded -// as a univariate polynomial in Pi -TestMathPiper(2*Pi/3,(Pi-Pi/3)); - -TestMathPiper(( a*(Sqrt(Pi))^2/2), (a*Pi)/2); -TestMathPiper(( 3*(Sqrt(Pi))^2/2), (3*Pi)/2); -TestMathPiper(( a*(Sqrt(b ))^2/2), (a*b)/2); - -// Bug was found: gcd sometimes returned 0! Very bad, since the -// value returned by gcd is usually used to divide out greatest -// common divisors, and dividing by zero is not a good idea. -Verify(Gcd(0,0),1); -Verify(Gcd({0}),1); - -// Product didn't check for correct input -Verify(Product(10), Product(10)); -Verify(Product(-1), Product(-1)); -Verify(Product(Infinity), Product(Infinity)); -Verify(Product(1 .. 10),3628800); - -// -TestMathPiper(Sin(Pi-22),-Sin(22-Pi)); -TestMathPiper(Cos(Pi-22), Cos(22-Pi)); - -// Verify that some matrix functions accept only positive -// integer arguments. Regression test for the fact that the functions -// in org/mathpiper/scripts/linalg.rep/ didn't check their arguments. - -// Note: Jonathan, perhaps some functions could return something -// useful if the argument passed in is just a number? I'd imagine -// Inverse(-2) <-- -1/2 would not be inconsistent? - -Verify(ZeroMatrix(-2,-2),ZeroMatrix(-2,-2)); -Verify(Identity(-2),Identity(-2)); -//Verify(LeviCivita(2),LeviCivita(2)); -//Verify(Permutations(2),Permutations(2)); -//Verify(InProduct(-2,-2),InProduct(-2,-2)); -//Verify(CrossProduct(-2,-2),CrossProduct(-2,-2)); -//Verify(BaseVector(-2,-2),BaseVector(-2,-2)); -//Verify(DiagonalMatrix(-2),DiagonalMatrix(-2)); -//Verify(Normalize(-2),Normalize(-2)); -//Verify(Transpose(-2),Transpose(-2)); -//Verify(Determinant(-2),Determinant(-2)); -//Verify(CoFactor(-2,-2,-2),CoFactor(-2,-2,-2)); -//Verify(Inverse(-2),Inverse(-2)); -//Verify(Trace(-2),Trace(-2)); -//Verify(SylvesterMatrix(-2,-2,-2),SylvesterMatrix(-2,-2,-2)); -Verify(ZeroVector(-2),ZeroVector(-2)); - -Verify(Sech(x),1/Cosh(x)); -Verify(Cot(x),1/Tan(x)); - -// Matrix operations failed: a^2 performed the squaring on each element -Verify({{1,2},{3,4}}^2,{{7,10},{15,22}}); -// And check that raising powers still works on lists/vectors (dotproduct?) correctly -Verify({2,3}^2,{4,9}); - -Verify( D(x,0) Sin(x), Sin(x) ); - -Verify( 2/3 >= 1/3, True); - -Verify( Infinity + I, Complex(Infinity,1) ); -Verify( Infinity - I, Complex(Infinity,-1) ); -Verify( I - Infinity,Complex(-Infinity,1) ); -Verify( I + Infinity, Complex(Infinity,1) ); -Verify( I*Infinity,Complex(0,Infinity)); //Changed Ayal: I didn't like the old definition -Verify(-I*Infinity,Complex(0,-Infinity)); //Changed Ayal: I didn't like the old definition -Verify( Infinity*I,Complex(0,Infinity)); //Changed Ayal: I didn't like the old definition -Verify( Infinity^I,Undefined);//Changed Ayal: I didn't like the old definition (it is undefined, right?) -Verify( (2*I)^Infinity, Infinity ); -Verify( Infinity/I,Infinity ); -Verify( Sign(Infinity), 1 ); -Verify( Sign(-Infinity), -1 ); - -Verify( Limit(n, Infinity) (n+1)/(2*n+3)*I, Complex(0,1/2) ); -Verify( Limit(x, Infinity) x*I, Complex(0,Infinity) ); //Changed Ayal: I didn't like the old definition - -Verify(Integrate(x) z^100, z^100*x ); -Verify(Integrate(x) x^(-1),Ln(x) ); - -NumericEqual( -RoundTo(N(ArcSin(0.0000000321232123),50),50) -, 0.00000003212321230000000552466124302049336784679316 -,50); - -Verify(Internal'LnNum(1), 0); - -Verify(BinomialCoefficient(0,0),1 ); - -Verify(0|1, 1); -Verify(0&1, 0); -Verify(0%1, 0); - -Verify(0.0/Sqrt(2),0); -Verify(0.0000000000/Sqrt(2),0); -Verify(0.0000^(24),0); - -Verify(Bernoulli(24), -236364091/2730); - -Verify(Gamma(1/2), Sqrt(Pi)); - -// Coef accepted non-integer arguments as second argument, and -// crashed on it. -Verify(Coef(3*Pi,Pi),Coef(3*Pi,Pi)); -Verify(Coef(3*Pi,x), Coef(3*Pi,x)); - -// Univariates in Pi did not get handled well, due to Pi being -// considered a constant, non-variable. -Verify(Degree(Pi,Pi),1); -Verify(Degree(2*Pi,Pi),1); - -Verify(Sin(2*Pi), 0); -Verify(Cos(2*Pi), 1); -Verify(Cos(4*Pi), 1); -Verify(Sin(3*Pi/2)+1, 0); -Verify(Sin(Pi/2), 1); - -// - and ! operators didn't get handled correctly in the -// parser/pretty printer (did you fix this, Serge?) -Verify(ToString()Write((-x)!),"(-x)!"); - -// some interesting interaction between the rules... -Verify(x*x*x,x^3,); -Verify(x+x+x,3*x); -Verify(x+x-x+x,2*x); - - -// bugs with complex numbers -Verify((1+I)^0, 1); -Verify((-I)^0, 1); -Verify((2*I)^(-10), -1/1024); -Verify((-I)^(-10), -1); -Verify((1-I)^(-10), Complex(0,1/32)); -Verify((1-I)^(+10), Complex(0,-32)); -Verify((1+2*I)^(-10), Complex(237/9765625,3116/9765625)); -Verify((1+2*I)^(+10), Complex(237,-3116)); - -// expansion of negative powers of fractions -Verify( (-1/2)^(-10), 1024); - -Verify( I^(Infinity), Undefined ); -Verify( I^(-Infinity), Undefined ); -Verify( Limit(n,Infinity) n*I^n, Undefined ); - -Verify(1 <= 1.0, True); -Verify(-1 <= -1.0, True); -Verify(0 <= 0.0, True); -Verify(0.0 <= 0, True); -Verify(1 >= 1.0, True); -Verify(-1 >= -1.0, True); -Verify(0 >= 0.0, True); -Verify(0.0 >= 0, True); - -Verify((1==1) != True, True); -Verify((a==a) != True, True); -Verify((1==2) != False, True); -Verify((a==2) != False, True); - -Verify( Integrate(x) x^5000, x^5001/5001 ); - -Verify( Integrate(x) Sin(x)/2, (-Cos(x))/2 ); - -Verify( 2^(-10), 1/1024 ); - -// The following line catches a bug reported where Simplify -// would go into an infinite loop. It doesn't check the correctness -// of the returned value as such, but merely the fact that this -// simplification terminates in the first place. -// -// The problem was caused by a gcd calculation (from the multivariate -// code) not terminating. -Verify( Simplify((a^2+b^2)/(2*a)), (a^2+b^2)/(2*a) ); - -// The following is a classical error: 0*x=0 is only true if -// x is a number! In this case, it is checked for that the -// multiplication of 0 with a vector returns a zero vector. -// This would automatically be caught with type checking. -// More tests of this ilk are possible: 0*matrix, etcetera. -Verify(0*{a,b,c},{0,0,0}); - -// the following broke evaluation (dr) -Verify(Conjugate({a}),{a}); - -// not yet fixed (dr) -Verify(Abs(Undefined),Undefined); - -// broke Plot2D() on singular functions with Abs() -Verify(Undefined<1, False); -Verify(Undefined>Undefined, False); -Verify(Undefined>1, False); -Verify(Undefined >= -4, False); -Verify(Undefined <= -4, False); - -// Jonathan's bug report -BuiltinPrecisionSet(10); -NumericEqual(N(Cos(Pi*.5)), 0,BuiltinPrecisionGet()); - -/* Jitse's bug report, extended with the changes that do not coerce integers to floats automatically - any more (just enter a dot and the number becomes float if that is what is intended). - */ -Verify(CForm(4), "4"); -Verify(CForm(4.), "4."); -Verify(CForm(0), "0"); -Verify(CForm(0.), "0."); - -// Discovered that Floor didn't handle new exponent notation -Verify(Floor(1001.1e-1),100); -Verify(Floor(10.01e1),100); -Verify(Floor(100.1),100); - -// Bugs discovered by Jonathan: -Verify(Undefined*0,Undefined); -// Actually, the following Groebner test is just to check that the program doesn't crash on this, -// more than on the exact result (which is hopefully correct also ;-) ) -Verify(Groebner({x*(y-1),y*(x-1)}),{x*y-x,x*y-y,y-x,y^2-y}); - -// Reported by Yannick Versley -Verify((Integrate(x,a,b)Cos(x)^2) - ((b-Sin((-2)*b)/2)/2-(a-Sin((-2)*a)/2)/2),0); -Verify(D(t) Integrate(x,a,b) f(x,t),Integrate(x,a,b)Deriv(t)f(x,t)); - -// This was returning FWatom(Sin(x)) -Verify( Factor(Sin(x)), Factor(Sin(x)) ); - -// should return unevaled -Verify( BesselJ(0,x), BesselJ(0,x) ); - - -// Listify and UnList coredumped when their arguments were invalid -Verify(Listify(Cos(x)),{Cos,x}); -Verify(UnList({Cos,x}),Cos(x)); -[ - Local(error); - error:=""; - TrapError(Listify(1.2),error:=GetCoreError()); - Verify(IsString(error) And error != ""); - - error:=""; - TrapError(UnList(1.2),error:=GetCoreError()); - Verify(IsString(error) And error != ""); -]; - -// Reported by Serge: xml tokenizer not general enough -Verify(XmlExplodeTag("

    "), XmlTag("P",{},"OpenClose")); -Verify(XmlExplodeTag("

    "), XmlTag("P",{},"OpenClose")); - -Verify(ToBase(16,30),"1e"); -Verify(FromBase(16,"1e"),30); - -// numbers are too small because of wrong precision handling -BuiltinPrecisionSet(30); -Verify(0.00000000000000000005421010862 = 0, False); // 2^(-64) -Verify(0.00000000000000000005421010862 / 1 = 0, False); -Verify(0.00000000000000000005421010862 / 2 = 0, False); -Verify(0.00000000000000000001 = 0, False); -Verify(0.00000000000000000001 / 2 = 0, False); -Verify(0.00000000000000000000000000001 = 0, False); -Verify(0.000000000000000000000000000001 = 0, False); -Verify((0.0000000000000000000000000000000000000001 = 0), False); -// I added another one, the code will currently say that 0.0000...00001=0 is True -// for a sufficient amount of zeroes, regardless of precision. Either that is good -// or that is bad, but the above tests didn't go far enough. This one makes it -// more explicit, unless we move over to a 128-bits system ;-) -Verify((0.0000000000000000000000000000000000000000000000001 = 0), False); - - -// Problem with FloatIsInt and gmp -Verify(FloatIsInt(3.1415926535e9), False); -Verify(FloatIsInt(3.1415926535e10), True); -Verify(FloatIsInt(3.1415926535e20), True); -Verify(FloatIsInt(0.3e20), True); - -/* Regression on bug reports from docs/bugs.txt */ - -/* Bug #1 */ -/* Can't test: 'Limit(x,0)D(x,2)Sin(x)/x' never terminates */ - -/* Bug #2 */ -KnownFailure((Limit(x,Infinity) x^n/Ln(x)) = Infinity); -KnownFailure((Limit(x,0,Right) x^(Ln(a)/(1+Ln(x)))) = a); -Verify((Limit(x,0) (x+1)^(Ln(a)/x)), a); -/* Note paren's around bodied operators like Limit, D, Integrate; - otherwise it's parsed as Limit (... = ...) */ - -/* Bug #3 */ -KnownFailure(Gcd(10,3.3) != 3.3 And Gcd(10,3.3) != 1); -/* I don't know what the answer should be, but buth 1 and 3.3 seem */ -/* certainly wrong. */ -Verify(Gcd(-10, 0), 10); -Verify(Gcd(0, -10), 10); - -/* Bug #4 */ -/* How can we test for this? */ -/* Bug says: at startup, 2^Infinity does not simplify to Infinity */ - -/* Bug #5 */ -/* How can we test for this? */ -/* Bug says: Limit(n,Infinity) Sqrt(n+1)-Sqrt(n) floods stack */ -/* but 'MaxEvalDepth reached' exits Yacas, even inside TrapError */ - -/* Bug #6 */ -KnownFailure((D(z) Conjugate(z)) = Undefined); - -/* Bug #7 */ -Verify(Im(3+I*Infinity), Infinity); /* resolved */ -Verify(Im(3+I*Undefined), Undefined); - -/* Bug #9 */ -Verify((Integrate(x,-1,1) 1/x), 0); /* or maybe Undefined? */ -Verify((Integrate(x,-1,1) 1/x^2), Infinity); - -/* Bug #10 */ -Verify(Simplify(x^(-2)/(1-x)^3) != 0); -/* I don't know what we want to return, but '0' is definitely wrong! */ - -/* Bug #11 */ -KnownFailure(ArcCos(Cos(beta)) != beta); - -/* Bug #12 */ -KnownFailure((Limit(n, Infinity) n^5/2^n) = 0); - -/* Bug #13 */ -/* Cannot test; TrigSimpCombine(x^500) floods stack */ - -/* Bug #14 */ -Verify((Limit(x,Infinity) Zeta(x)), 1); -// Actually, I changed the Factorial(x) to (x!) -Verify((Limit(x,Infinity) (x!)), Infinity); - -/* Bug #15 */ -Verify(PowerN(0,0.55), 0); -// LogN(-1) locks up in gmpnumbers.cpp, will be fixed in scripts -//FIXME this test should be uncommented eventually -// Verify(TrapError(PowerN(-1,-0.5), error), error); - -/* Bug #16 */ -/* Can't test, bug in build system */ - -/* Bug #17 */ -Verify(Assoc(x-1, Factors(x^6-1))[2], 1); - -/* Bug #18 */ -//Changed, see next line TestMathPiper(Integrate(x) x^(1/2), 2/3*x^(3/2)); -TestMathPiper(Integrate(x) x^(1/2), (2/3)*Sqrt(x)^(3)); - -Verify(a[2]*Sin(x)/:{Sin(_x) <- sin(x)},a[2]*sin(x)); - -// There was a bug, reported by Sebastian Ferraro, which caused the determinant -// to return "Undefined" when one of the elements of the diagonal of a matrix -// was zero. This was due to the numeric determinant algorithm applying -// Gaussian elimination, but taking the elements on the diagonal as pivot points. -Verify(IsZero(Determinant( {{1,-1,0,0},{0,0,-1,1},{1,0,0,1},{0,1,1,0}} )),True); - -// The following failed when numerics changed so that 0e-1 was not matched to 0 any more in -// a transformation rule defining the less than operator. -Verify(ExpNum(0),1); -NumericEqual(ExpNum(0e-1),1.,BuiltinPrecisionGet()); -Verify(500 < 0e-1,False); - -// version 1.0.56: Due to MathBitCount returning negative values sometimes, functions depending on -// proper functioning failed. MathSqrtFloat failed for instance on N(1/2). It did give the right -// result for 0.5. -NumericEqual(N(Sqrt(500000e-6),20),N(Sqrt(0.0000005e6),20),20); -NumericEqual(N(Sqrt(0.5),20),N(Sqrt(N(1/2)),20),20); - -// With the changes in numerics, RoundTo seems to have been broken. This line demonstrates the problem. -// The last digit is suddenly rounded down (it used to be 4, correctly, and then gets rounded down to 3). -KnownFailure(RoundTo(RoundTo(N(Cot(2),9),9),N(Cot(2),9),9)=0); - -// LogN used to hang on *all* input -Verify(LogN(2)!=0,True); - -// Bug that was introduced when going to the new numeric setup where -// numbers were not converted to strings any more. In the situation -// -n*10^-m where n and m positive integers, the number got truncated -// prematurely, resulting in a wrong rounding. -[ - Local(n,m,nkeep,lcl); - n:=7300 + 12*I; - m:=2700 + 100*I; - nkeep:=n; - n:=m; - m:=nkeep - m*Round(nkeep/m); - lcl:=Re(N(n/m))+0.5; - Verify(FloorN(lcl),-3); -]; - - -/* Here follow some tests for MathBitCount. These were written while creating - the Java version, fixing BitCount in the process. - */ -Verify(MathBitCount(3),2); -Verify(MathBitCount(3.0),2); - -Verify(MathBitCount(4),3); -Verify(MathBitCount(4.0),3); - -Verify(MathBitCount(0),0); -Verify(MathBitCount(0.0),0); - -Verify(MathBitCount(0.5),0); -Verify(MathBitCount(0.25),-1); -Verify(MathBitCount(0.125),-2); -Verify(MathBitCount(0.0125),-6); - -Verify(MathBitCount(-3),2); -Verify(MathBitCount(-3.0),2); - -Verify(MathBitCount(-4),3); -Verify(MathBitCount(-4.0),3); - -Verify(MathBitCount(-0),0); -Verify(MathBitCount(-0.0),0); - -Verify(MathBitCount(-0.5),0); -Verify(MathBitCount(-0.25),-1); -Verify(MathBitCount(-0.125),-2); -Verify(MathBitCount(-0.0125),-6); - -// This one ended in an infinite loop because 1 is an even function, and the indefinite integrator -// then kept on calling itself because the left and right boundaries were equal to zero. -Verify(Integrate(x,0,0)1,0); - -// This code verifies that if integrating over a zero domain, the result -// is zero. -Verify(Integrate(x,1,1)Sin(Exp(x^2)),0); - -/* Reverse and FlatCopy (and some friends) would segfault in the past if passed a string as argument. - * I am not opposed to overloading these functions to also work on strings per se, but for now just - * check that they return an error in stead of segfaulting. - */ -Verify(TrapError(Reverse("abc"),True),True); -Verify(TrapError(FlatCopy("abc"),True),True); - -// Make sure Mod works threaded -Verify(Mod(2,Infinity),2); -Verify(Mod({2,1},{2,2}),{0,1}); -Verify(Mod({5,1},4),{1,1}); - -/* In MatchLinear and MatchPureSquare, the matched coefficients were - * assigned to global variables that were not protected with LocalSymbols. - */ -[ - Local(a,b,A); - a:=mystr; - A:=mystr; - /* The real test here is that no error is generated due to the - * fact that variables a or A are set. - */ - Verify(Simplify((Integrate(x,a,b)Sin(x))-Cos(a)+Cos(b)),0); -]; - -// Factoring 2*x^2 used to generate an error -Verify(Factor(2*x^2),x^2); - -/* Bug report from Magnus Petursson regarding determinants of matrices that have symbolic entries */ -Verify(CanBeUni(Determinant({{a,b},{c,d}})),True); - -/* Bug report from Michael Borcherds. The brackets were missing. */ -Verify(TeXForm(Hold(2*x*(-2))), "$2 x \\left( - 2\\right) $"); - -/* Bug reported by Adrian Vontobel. */ -[ - Local(A1,A2); - A1:=Pi*20^2; // 400*Pi - A2:=Pi*18^2; // 324*Pi - Verify(Min(A1,A2), 324*Pi); - Verify(Max(A1,A2), 400*Pi); -]; - -/* One place where we forgot to change Sum to Add */ -TestMathPiper(Diverge({x*y,x*y,x*y},{x,y,z}),x+y); - -/* Bug reported by Adrian Vontobel: comparison operators should coerce - * to a real value as much as possible before trying the comparison. - */ -[ - Local(F); - F:=0.2*Pi; - Verify(F>0.5, True); - Verify(F>0.7, False); - Verify(F<0.7, True); - Verify(F<0.6, False); -]; - -/* Bug reported by Michael Borcherds: Simplify(((4*x)-2.25)/2) - returned some expression with three calls to Gcd, which was technically - correct, but not the intended simplification. - */ -Verify(IsZero(Simplify(Simplify(((4*x)-2.25)/2)-(2*x-2.25/2))),True); - -/* Bug reported by Adrian Vontobel: when assigning an expression to a variable, - * it did not get re-evaluated in the calling environment when passing it in to Newton. - * The resulting value was "Undefined", instead of the expected 1.5 . - */ -NumericEqual([ Local(expr); expr := 1800*x/1.5 - 1800; Newton(expr, x,2,0.001); ],1.5,3); - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/scopestack.mpt mathpiper-0.81f+dfsg1/tests/scripts/scopestack.mpt --- mathpiper-0.0.svn2556/tests/scripts/scopestack.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/scopestack.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ - - -LocalSymbols(st) -[ - st:=NewStack(); - Verify(IsOnStack(st,"c"),False); - PushStackFrame(st,fenced); - AddToStack(st,"a"); - AddToStack(st,"b"); - Verify(IsOnStack(st,"a"),True); - Verify(IsOnStack(st,"c"),False); - Verify(FindOnStack(st,"a"),{}); - FindOnStack(st,"b")["set"]:=True; - Verify(FindOnStack(st,"b"),{{"set",True}}); - PushStackFrame(st,unfenced); - AddToStack(st,"c"); - Verify(IsOnStack(st,"c"),True); - Verify(IsOnStack(st,"a"),True); - PopStackFrame(st); - - PushStackFrame(st,fenced); - AddToStack(st,"c"); - Verify(IsOnStack(st,"c"),True); - Verify(IsOnStack(st,"a"),False); - PopStackFrame(st); - - PopStackFrame(st); - Verify(StackDepth(st),0); -]; - - diff -Nru mathpiper-0.0.svn2556/tests/scripts/simplify.mpt mathpiper-0.81f+dfsg1/tests/scripts/simplify.mpt --- mathpiper-0.0.svn2556/tests/scripts/simplify.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/simplify.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ - -/* Test Simplify() */ -NextTest("Simplify"); - -TestMathPiper( Simplify((x+y)*(x-y)-(x+y)^2), -2*y^2-2*x*y ); -TestMathPiper( Simplify(1+x+x+3*y-4*(x+y+2)), -2*x-y-7 ); -TestMathPiper( Simplify((1+I)^4), -4 ); -TestMathPiper( Simplify((x-y)/(x*y)), 1/y-1/x ); -//See below, now handled with II KnownFailure(TestMathPiper( Simplify((x+I)^4), x^4+4*x^3*I-6*x^2-4*x*I+1 )); - -TestMathPiper( Simplify((xx+II)^4), xx^4+4*xx^3*II-6*xx^2-4*xx*II+1 ); - -TestMathPiper( Simplify(D(x,4)Exp(-x^2/2)), Exp(-x^2/2)*(x^4-6*x^2+3)); - -TestMathPiper( Simplify(1),1); -TestMathPiper( Simplify(1/x ), 1/x ); -TestMathPiper( Simplify( 1/(1/x+1) ),x/(x+1) ); -TestMathPiper( Simplify(1/(1/(1/x+1)+1) ),(x+1)/(2*x+1) ); -TestMathPiper( Simplify(1/(1/(1/(1/x+1)+1)+1) ),(2*x+1)/(3*x+2) ); -TestMathPiper( Simplify(1/(1/(1/(1/(1/x+1)+1)+1)+1) ),(3*x+2)/(5*x+3) ); -TestMathPiper( Simplify(1/(1/(1/(1/(1/(1/x+1)+1)+1)+1)+1) ),(5*x+3)/(8*x+5) ); - - - -/*Serge: these are not handled yet ;-) -TestMathPiper( Simplify((x^2-y^2)/(x+y)), x-y ); -*/ - -TestMathPiper(ExpandFrac(x+y/x+1/3),(x^2+y+x/3)/x); - -// this did not work until the latest fix to ExpandBrackets using MM() -Verify( -ExpandBrackets(x*(a+b)*y*z) -, x*a*y*z+x*b*y*z -); - -Verify( -ExpandBrackets(ExpandFrac((x+1)/(x-1)+1/x)) -, (x^2+2*x-1)/(x^2-x) -); - -// these used to fail. Added by Serge, resolved by Ayal -Verify([Local(a);a:=0.1;Simplify(a*b);], 0.1*b); -Verify([Local(a);a:=0.1;Simplify(a/b);], 0.1/b); - - -// Testing FactorialSimplify - -TestMathPiper(FactorialSimplify((n+1)! / n!),n+1); -TestMathPiper(FactorialSimplify((n-k+2)! / (n-k)!),(n-k+2)*(n-k+1)); -TestMathPiper(FactorialSimplify(2^(n+2)/2^n),4); -TestMathPiper(FactorialSimplify((-1)^(n+1)/(-1)^n),-1); -TestMathPiper(FactorialSimplify((n+1)! / n! + (n-k+2)! / (n-k)!),n+1 + (n-k+2)*(n-k+1)); - -TestMathPiper(FactorialSimplify((n+1)! / n! + (-1)^(n+1)/(-1)^n),n); - -/* And now for the piece de resistance: an example from - the book "A=B" - */ - -TestMathPiper(FactorialSimplify( - ( - (n+1)! / (2*k! *(n+1-k)!) - - n! / (k! * (n-k)!) + - n! / (2*k! * (n-k)!) - - n! / (2*(k-1)! * (n-k+1)!) - )*(k! *(n+1-k)!)/(n!) -),0); diff -Nru mathpiper-0.0.svn2556/tests/scripts/solve.mpt mathpiper-0.81f+dfsg1/tests/scripts/solve.mpt --- mathpiper-0.0.svn2556/tests/scripts/solve.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/solve.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,198 +0,0 @@ - -/* - * VerifySolve(e1, e2) tests whether 'e1' evaluates to something - * "equal" to 'e2', and complains if it doesn't. - * - * Here, "equal" means: - * o for lists: having the same entries, possibly in a different - * order; - * o for equations: having the same right-hand sides, possibly after - * 'Simplify'; - * o in all other cases: equality, possible after 'Simplify'. - * Hence, { a == 1, a == x+1 } is "equal" to { a == 1+x, a == 1 }. - */ - -VerifySolve(_e1, _e2) <-- -If (VerifySolve'Equal(Eval(e1), Eval(e2)), - True, - [ - WriteString("******************"); NewLine(); - ShowLine(); NewLine(); - Write(e1); NewLine(); - WriteString(" evaluates to "); NewLine(); - Write(Eval(e1)); NewLine(); - WriteString(" which differs from "); NewLine(); - Write(e2); NewLine(); - WriteString("******************"); NewLine(); - False; - ]); -HoldArgNr("VerifySolve", 2, 1); - -10 # VerifySolve'Equal({}, {}) <-- True; - -20 # VerifySolve'Equal({}, e2_IsList) <-- False; - -30 # VerifySolve'Equal(e1_IsList, e2_IsList) <-- -[ - Local(i, found); - found := False; - i := 0; - While(i < Length(e2) And Not found) [ - i++; - found := VerifySolve'Equal(First(e1), e2[i]); - ]; - If (found, VerifySolve'Equal(Rest(e1), Delete(e2, i)), False); -]; - -40 # VerifySolve'Equal(_l1 == _r1, _l2 == _r2) -<-- Equals(l1,l2) And Simplify(r1-r2)=0; - -50 # VerifySolve'Equal(_e1, _e2) <-- Simplify(e1-e2) = 0; - -/**********************************************************************/ - -Testing("Solve"); - -Verify(OldSolve(a+x*y==z,x),(z-a)/y); -Verify(OldSolve({a+x*y==z},{x}),{{x==(z-a)/y}}); - -// check that solving systems of equations works, at least at the -// level of simple back-substitutions -Verify(Solve({a+x*y==z},{x}),{{x==(z-a)/y}}); -[ - Local(eq,res); - eq:={a-b==c,b==c}; - res:=Solve(eq,{a,b}); - Verify(eq Where res,{{c==c,c==c}}); -]; - -VerifySolve(Solve(a+x*y == z, x), { x == (z-a)/y }); - -VerifySolve(Solve(x^2-3*x+2, x), { x == 1, x == 2 }); - -VerifySolve(Solve(2^n == 32, n), { n == Ln(32)/Ln(2) }); - /* Of course, Ln(32)/Ln(2) = 5 */ - -VerifySolve(Solve(ArcTan(x^4) == Pi/4, x), - { x == 1, x == -1, x == I, x == -I }); - -VerifySolve(Solve(Exp(x)/(1-Exp(x)) == a, x), {x == Ln(a/(a+1))}); -VerifySolve(Solve(Exp(x)/(1-Exp(x)) == a, a), {a == Exp(x)/(1-Exp(x))}); - -VerifySolve(Solve(x^5 == 1, x), - { x == 1, x == Exp(2/5*I*Pi), x == Exp(4/5*I*Pi), - x == Exp(-2/5*I*Pi), x == Exp(-4/5*I*Pi)}); - -VerifySolve(Solve(Sqrt(x) == 1, x), { x == 1 }); -VerifySolve(Solve(Sqrt(x) == -1, x), { }); -VerifySolve(Solve(Sqrt(x) == I, x), { x == -1 }); -VerifySolve(Solve(Sqrt(x) == -I, x), { }); -VerifySolve(Solve(Sqrt(x) == 0, x), { x == 0 }); - - -/* The following equations have in fact infinitely many solutions */ - -VerifySolve(Solve(Sin(x), x), { x == 0, x == Pi }); - -VerifySolve(Solve(x*Exp(x), x), { x == 0 }); - -VerifySolve(Solve(Cos(a)^2 == 1/2, a), - { a == Pi/4, a == 3/4*Pi, a == -3/4*Pi, a == -Pi/4 }); - -/* This goes into an infinite recursion: - * VerifySolve(Solve(Sin(a*Pi)^2-Sin(a*Pi)/2 == 1/2, a), - * { a == 1/2, a == 7/6 }); - */ - -Verify(IsError(), False); - -/* This equation can be solved (the solution is x>0), but the current - * code does not do this. The least we can expect is that no spurious - * solutions are returned. */ -VerifySolve(Solve(0^x == 0, x), {}); -Verify(ClearError("Solve'Fails"), True); -Verify(IsError(), False); - -/* This equation could be solved using the Lambert W function */ -VerifySolve(Solve(x^x == 1, x), {}); -Verify(ClearError("Solve'Fails"), True); -Verify(IsError(), False); - -/* Another equation which cannot be solved at the moment */ -VerifySolve(Solve(BesselJ(1,x), x), {}); -Verify(ClearError("Solve'Fails"), True); -Verify(IsError(), False); - -/* And another one */ -VerifySolve(Solve(Exp(x)+Cos(x) == 3, x), {}); -Verify(ClearError("Solve'Fails"), True); -Verify(IsError(), False); - -/* This equation could be solved if we knew that x >= 0 */ -VerifySolve(Solve(Sqrt(x) == a, x), { }); -Verify(ClearError("Solve'Fails"), True); -Verify(IsError(), False); - -/* Test the type-checking mechanism */ -VerifySolve(Solve(2*x == 1, 1), {}); -Verify(ClearError("Solve'TypeError"), True); -Verify(IsError(), False); - -/* This command is clearly nonsense, but it used to send Yacas in an - * infinite recursion, which should never happen. Note that 'D(y)x == 0' - * is parsed as 'D(y)(x==0)'. */ -VerifySolve(Solve(D(y)(x == 0), x), { }); -Verify(ClearError("Solve'Fails"), True); -Verify(IsError(), False); - -/**********************************************************************/ - -Testing("PSolve"); - -/* Linear equations */ - -VerifySolve(PSolve(x,x), 0); -VerifySolve(PSolve(x+3*Sin(b)-1,x), 1-3*Sin(b)); -VerifySolve(PSolve(2*x-a,x), a/2); -VerifySolve(PSolve(2*x-a,a), 2*x); - -/* Quadratic equations */ - -VerifySolve(PSolve(x^2,x), {0,0}); -VerifySolve(PSolve(4*x^2-1,x), {1/2,-1/2}); -VerifySolve(PSolve(x^2+1,x), {I,-I}); -VerifySolve(PSolve(x^2-3*x+2,x), {1,2}); - -/* Cubic equations */ - -VerifySolve(PSolve(x^3,x), {0,0,0}); -VerifySolve(PSolve(x^3-1,x), {1, Exp(2/3*Pi*I), Exp(-2/3*Pi*I)}); -VerifySolve(PSolve(x^3+1,x), {-1, Exp(1/3*Pi*I), Exp(-1/3*Pi*I)}); -[ - Local(roots); - roots := BubbleSort(N(PSolve(x^3-3*x^2+2*x,x)), "<"); - NumericEqual(roots[1], 0, 10); - NumericEqual(roots[2], 1, 10); - NumericEqual(roots[3], 2, 10); -]; -/* Ideally, we want yacas to simplify the result of - * PSolve(x^3-3*x^2+2*x,x) to {0,1,2}, but that does not seem feasible, - * so we just test for numerical equality. */ - -/* Quartic equations */ - -VerifySolve(PSolve(x^4,x), {0,0,0,0}); -VerifySolve(PSolve(16*x^4-1,x), {1/2, -1/2, 1/2*I, -1/2*I}); -VerifySolve(PSolve(x^4-x,x), {0, 1, Exp(2/3*Pi*I), Exp(-2/3*Pi*I)}); -VerifySolve(PSolve(x^4+x,x), {0, -1, Exp(1/3*Pi*I), Exp(-1/3*Pi*I)}); -/* Yacas has difficulties with more complicated equations, like the - * biquadratic x^4 - 3*x^2 + 2. */ - -/* Added the ability to Solve and Where to handle expressions more complex than just variables. - One can now Solve for say x[1], or Sin(x) (it only uses a simple comparison for now though). - The following test just assures that that will never break. - */ -Verify(Simplify(x[1]-4*x[2]+x[3] Where (Solve({x[1]-4*x[2]+x[3]==0},{x[2]}))),{0}); - - -/*TODO MatrixSolve */ diff -Nru mathpiper-0.0.svn2556/tests/scripts/sturm.mpt mathpiper-0.81f+dfsg1/tests/scripts/sturm.mpt --- mathpiper-0.0.svn2556/tests/scripts/sturm.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/sturm.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,137 +0,0 @@ -/* - TESTS: - - random-test code for roots, be generating random roots and - multiplicities. - - find an example where bisection is needed, or better, a group - of examples where bisection is needed, for tests - - GarbageCollect in TryRandomPoly causes some corruption, as is - visible when turning show file/line on. -*/ - -BuiltinPrecisionSet(5); - -VerifyZero(x) := (Abs(x)<10^ -BuiltinPrecisionGet()); - - -sl() := []; //Echo(CurrentFile(),CurrentLine()); -TryRandomPoly(deg,coefmin,coefmax):= -[ - //GarbageCollect(); - Local(coefs,p,roots,px); - coefs:=Table(FloorN(coefmin+Random()*(coefmax-coefmin)),i,1,deg+1,1); - p:=Add(coefs*x^(0 .. deg)); - p:=Rationalize(p); -//Echo("Test polynom ",p); - Verify(Max(Abs(coefs))<=MaximumBound(p)); - Verify(Min(Abs(coefs))>MinimumBound(p)); -//Echo("bounds ",BoundRealRoots(p)); - roots:=FindRealRoots(p); -//Echo("roots ",roots); - px := (p Where x==x); - Verify(px . px < 0.01); -]; -TryRandomRoots(deg,coefmin,coefmax):= -[ - //GarbageCollect(); - Local(coefs,p,roots,px,mult); - coefs:=RemoveDuplicates(Table(FloorN(coefmin+Random()*(coefmax-coefmin)),i,1,deg+1,1)); - deg:=Length(coefs)-1; - mult:=1+Abs(Table(FloorN(coefmin+Random()*(coefmax-coefmin)),i,1,deg+1,1)); - p:=Product((x-coefs)^mult); - p:=Rationalize(p); -Echo("Test polynom ",p); -Echo("minimum ",MinimumBound(p)); -Echo("maximum ",MaximumBound(p)); -Echo("bounds ",BoundRealRoots(p)); - roots:=FindRealRoots(p); -Echo("roots ",roots); - Verify(Length(roots) = Length(coefs)); - Verify(Length(RemoveDuplicates(roots)) = Length(coefs)); - px := (p Where x==x); - Verify(px . px < 0.01); -]; - -sl(); - -[ - Local(p); - p := FindRealRoots((x+2)^9*(x-4)^5*(x-1)^4)-{-2.,1.,4.}; - Verify(VerifyZero(p . p),True); -]; -sl(); - -/*TODO -TryRandomRoots(3,-10,10); sl(); -TryRandomRoots(3,-10,10); sl(); -TryRandomRoots(5,5,1000); sl(); -TryRandomRoots(5,5,1000); sl(); -*/ - -// Bounds on coefficients -Verify(MinimumBound(4),-Infinity); sl(); -Verify(MaximumBound(4),Infinity); sl(); - -// NumRealRoots -Verify(NumRealRoots(x^2-1),2); sl(); -Verify(NumRealRoots(x^2+1),0); sl(); - -[ - Local(p); - p:=FindRealRoots(Expand((x*(x-10)^3*(x+2)^2)))-{0,-2.,10.}; - Verify(VerifyZero(p . p),True); -]; -Verify(FindRealRoots((x^2+20)*(x^2+10)),{}); -Verify(NumRealRoots((x^2+20)*(x^2+10)),0); - -sl(); - -// Simple test on Squarefree -TestMathPiper(Monic(SquareFree((x-1)^2*(x-3)^3)),Monic((x-1)*(x-3))); - -sl(); - -// Check the rare case where the bounds finder lands on -// exactly a root -[ - Local(p); - p:=FindRealRoots((x+4)*(x-6),1,7)-{-4.,6.}; - Verify(VerifyZero(p . p),True); -]; - - - -sl(); -[ - Local(p); - - p:=Expand((x-3.1)*(x+6.23)); - p:=FindRealRoots(p)-{-6.23,3.1}; - Verify(VerifyZero(p . p),True); -]; - -sl(); -Verify(BuiltinPrecisionGet(),5); -[ - Local(res); - res:=FindRealRoots(Expand((x-3.1)*(x+6.23)))-{-6.23,3.1}; - Verify(VerifyZero(res . res) , True); -]; -sl(); - -TryRandomPoly(5,5,1000); sl(); -sl(); -TryRandomPoly(5,5,1000); sl(); -sl(); -TryRandomPoly(5,5,1000); sl(); -sl(); -TryRandomPoly(5,5,1000); sl(); -sl(); -TryRandomPoly(5,5,1000); sl(); -sl(); -TryRandomPoly(5,5,1000); sl(); -sl(); - - -//RandomPoly(_var,_degree,_coefmin,_coefmax) -//RandomIntegerVector(_count,_coefmin,_coefmax) - diff -Nru mathpiper-0.0.svn2556/tests/scripts/sums.mpt mathpiper-0.81f+dfsg1/tests/scripts/sums.mpt --- mathpiper-0.0.svn2556/tests/scripts/sums.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/sums.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,341 +0,0 @@ - -Verify(Product(i,1,3,i),6); - -Verify( Sum(k,1,n,k), n*(n+1)/2 ); -Verify( Simplify(Sum(k,1,n,k^3)), Simplify( (n*(n+1))^2 / 4 ) ); -Verify( Sum(k,1,Infinity,1/k^2), Zeta(2) ); -Verify( Sum(k,1,Infinity,1/k), Infinity ); -Verify( Sum(k,1,Infinity,Sqrt(k)), Infinity ); -Verify( Sum(k,2,Infinity,x^k/k!), Exp(x)-(x+1) ); -Verify( Sum(k,1,n,Sin(a)+Sin(b)+p),(Sin(a)+Sin(b)+p)*n ); - -Verify(Add({1,2,3,4}), 10); -Verify(Add({1}), 1); -Verify(Add({}), 0); -Verify(Add(1,2,3,4), 10); -Verify(Add(1), 1); -Verify(Add(), Add()); -[ - Local(list); - list:={1,2,3,4,5}; - Verify(Add(list)/Length(list), 3); - list:={0}; - Verify(Add(list)/Length(list), 0); - list:={}; - Verify(Add(list)/Length(list), Undefined); -]; - -Verify(Min(0,1),0); -Verify(Min({}), Undefined); -Verify(Min({x}), x); -Verify(Min(x), x); -Verify(Min(Exp(x)), Exp(x)); -Verify(Min({1,2,3}), 1); -// since Min(multiple args) is disabled, comment this out -Verify(Min(1,2,3), 1); -Verify(Min(1,2,0), 0); -Verify(Min(5,2,3,4), 2); -Verify(Min(5,2,0,4), 0); - -// ------------------------------------------------------------ - -Testing("Taylor"); - -// Black-box testing - -Verify(Taylor2(x,0,9) Sin(x), x - x^3/6 + x^5/120 - x^7/5040 + x^9/362880); -Verify(Taylor2(x,0,6) Cos(x), 1 - x^2/2 + x^4/24 - x^6/720); -Verify(Taylor2(x,0,6) Exp(x), - 1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120 + x^6/720); -Verify(Taylor2(x,1,6) 1/x, - 1 - (x-1) + (x-1)^2 - (x-1)^3 + (x-1)^4 - (x-1)^5 + (x-1)^6); -Verify(Taylor2(x,1,6) Ln(x), - (x-1) - (x-1)^2/2 + (x-1)^3/3 - (x-1)^4/4 + (x-1)^5/5 - (x-1)^6/6); -Verify(Taylor2(x,0,6) x/(Exp(x)-1), - 1 - x/2 + x^2/12 - x^4/720 + x^6/30240); -Verify(Taylor2(x,0,6) Sin(x)^2+Cos(x)^2, 1); -TestMathPiper(Taylor2(x,0,14) Sin(Tan(x)) - Tan(Sin(x)), - -1/30*x^7 - 29/756*x^9 - 1913/75600*x^11 - 95/7392*x^13); -TestMathPiper((Taylor2(t,a+1,2) Exp(c*t)), - Exp(c*(a+1)) + c*Exp(c*(a+1))*(t-a-1) - + c^2*Exp(c*(a+1))*(t-a-1)^2/2); - -// Consistency checks - -TestMathPiper(Taylor2(x,0,7) (Sin(x)+Cos(x)), - (Taylor2(x,0,7) Sin(x)) + (Taylor2(x,0,7) Cos(x))); -TestMathPiper(Taylor2(x,0,7) (a*Sin(x)), - a * (Taylor2(x,0,7) Sin(x))); -TestMathPiper(Taylor2(x,0,7) (Sin(x)-Cos(x)), - (Taylor2(x,0,7) Sin(x)) - (Taylor2(x,0,7) Cos(x))); -TestMathPiper(Taylor2(x,0,7) (Sin(x)*Cos(x)), - Taylor2(x,0,7) ((Taylor2(x,0,7) Sin(x)) * (Taylor2(x,0,7) Cos(x)))); -TestMathPiper(Taylor2(x,0,7) (Sin(x)/Ln(1+x)), - Taylor2(x,0,7) ((Taylor2(x,0,8) Sin(x)) / Taylor2(x,0,8) Ln(1+x))); -TestMathPiper(Taylor2(t,0,7) (Sin(t)^2), - Taylor2(t,0,7) ((Taylor2(t,0,7) Sin(t))^2)); -TestMathPiper(Taylor2(x,0,7) Cos(Ln(x+1)), - Taylor2(x,0,7) (Subst(y,Taylor2(x,0,7)Ln(x+1)) Cos(y))); - -100 # Taylor'LPS'CompOrder(_x, jn(_x)) <-- 5; -100 # Taylor'LPS'CompCoeff(_x, jn(_x), _k) <-- Atom("jn":String(k)); - -Verify(Taylor2(t,0,8) jn(t), jn5*t^5 + jn6*t^6 + jn7*t^7 + jn8*t^8); -Verify((Taylor2(x,0,10) Exp(jn(x))), - 1 + jn5*x^5 + jn6*x^6 + jn7*x^7 + jn8*x^8 - + jn9*x^9 + (jn10+jn5^2/2)*x^10); - -// Some examples of power series -LocalSymbols(p1,p2,p3,p4,p0,pj,pp,pju0,pj40,pj50,pj51,pj52,pj53,pj54,pc24,pc35,pc46,pc57,pc68) [ -p1 := Taylor'LPS(0, {1,1,1/2,1/6}, x, Exp(x)); -p2 := Taylor'LPS(1, {1,0,-1/6,0,1/120,0}, t, Sin(t)); -p3 := Taylor'LPS(0, {a0,a1,a2,a3}, x, foo(x)); -p4 := Taylor'LPS(-2, {1,0,-1/2,0,1/24}, x, Cos(x)/x^2); -p0 := Taylor'LPS(Infinity, {}, x, 0); // special case: zero - -// Taylor'LPS should not evaluate - -Verify(p1, Hold(Taylor'LPS(0, {1,1,1/2,1/6}, x, Exp(x)))); - -// Taylor'LPS'Coeffs can get pre-computed coefficients - -Verify(Taylor'LPS'Coeffs(p1, 0, 3), {1,1,1/2,1/6}); -Verify(Taylor'LPS'Coeffs(p1, -3, -1), {0,0,0}); -Verify(Taylor'LPS'Coeffs(p2, -1, 3), {0,0,1,0,-1/6}); -Verify(Taylor'LPS'Coeffs(p3, 0, 3), {a0,a1,a2,a3}); -Verify(Taylor'LPS'Coeffs(p4, -1, 1), {0,-1/2,0}); -Verify(Taylor'LPS'Coeffs(p0, 1, 5), {0,0,0,0,0}); - -// Conversion to power series - -Verify(Taylor'LPS'PowerSeries(p1, 3, x), 1+x+x^2/2+x^3/6); -Verify(Taylor'LPS'PowerSeries(p2, 4, t), t-t^3/6); -Verify(Taylor'LPS'PowerSeries(p3, 3, s), a0+a1*s+a2*s^2+a3*s^3); -Verify({Taylor'LPS'PowerSeries(p4, 2, x), ClearError("singularity")}, - {Undefined, True}); -Verify(Taylor'LPS'PowerSeries(p0, 3, x), 0); - -// Construction of new LPS - -Verify(Taylor'LPS'Construct(x, 1), Taylor'LPS(Undefined, {}, x, 1)); - -// Taylor'LPS'Coeffs can compute new coefficients in-place - -Verify(Taylor'LPS'Coeffs(p1, 0, 4), {1,1,1/2,1/6,1/24}); -Verify(p1, Taylor'LPS(0, {1,1,1/2,1/6,1/24}, x, Exp(x))); -p1 := Taylor'LPS(0, {1,1,1/2,1/6}, x, Exp(x)); - -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, 1), 0, 7), - {1, 0, 0, 0, 0, 0, 0, 0}); -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, 0), 0, 7), - {0, 0, 0, 0, 0, 0, 0, 0}); -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, 1/x), 0, 7), - {0, 0, 0, 0, 0, 0, 0, 0}); -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, x^2), 0, 7), - {0, 0, 1, 0, 0, 0, 0, 0}); -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, Exp(x)), 0, 7), - {1, 1, 1/2, 1/6, 1/24, 1/120, 1/720, 1/5040}); -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, Ln(1+x)), 0, 7), - {0, 1, -1/2, 1/3, -1/4, 1/5, -1/6, 1/7}); -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, Sin(x)), 0, 7), - {0, 1, 0, -1/6, 0, 1/120, 0, -1/5040}); -Verify(Taylor'LPS'Coeffs(Taylor'LPS'Construct(x, Cos(x)), 0, 7), - {1, 0, -1/2, 0, 1/24, 0, -1/720, 0}); - -// Check order of power series - -Verify(Taylor'LPS'GetOrder(p1), {0,True}); -Verify(Taylor'LPS'GetOrder(Taylor'LPS'Construct(x, Cos(x))), {0,True}); -Verify(Taylor'LPS'GetOrder(Taylor'LPS'Construct(x, Sin(x))), {1,True}); -Verify(Taylor'LPS'GetOrder(Taylor'LPS'Construct(x, x-Sin(x))), {1,False}); -Verify(Taylor'LPS'GetOrder(Taylor'LPS'Construct(x, 1/x)), {-1,True}); - -// User-defined power series - -pju0 := Taylor'LPS(Undefined, {}, x, jn(x)); -pj40 := Taylor'LPS(5, {}, x, jn(x)); -pj50 := Taylor'LPS(5, {}, x, jn(x)); -pj51 := Taylor'LPS(5, {jn5}, x, jn(x)); -pj52 := Taylor'LPS(5, {jn5,jn6}, x, jn(x)); -pj53 := Taylor'LPS(5, {jn5,jn6,jn7}, x, jn(x)); -pj54 := Taylor'LPS(5, {jn5,jn6,jn7,jn8}, x, jn(x)); - -pc24 := {0,0,0}; -pc35 := {0,0,jn5}; -pc46 := {0,jn5,jn6}; -pc57 := {jn5,jn6,jn7}; -pc68 := {jn6,jn7,jn8}; - -tlc(_a,_b,_c) <-- Taylor'LPS'Coeffs(a,b,c); // abbreviation - -pj := FlatCopy(pju0); Verify(tlc(pj,2,4), pc24); Verify(pj, pj50); -pj := FlatCopy(pju0); Verify(tlc(pj,3,5), pc35); Verify(pj, pj51); -pj := FlatCopy(pju0); Verify(tlc(pj,4,6), pc46); Verify(pj, pj52); -pj := FlatCopy(pju0); Verify(tlc(pj,5,7), pc57); Verify(pj, pj53); -pj := FlatCopy(pju0); Verify(tlc(pj,6,8), pc68); Verify(pj, pj54); - -pj := FlatCopy(pj40); Verify(tlc(pj,2,4), pc24); Verify(pj, pj50); -pj := FlatCopy(pj40); Verify(tlc(pj,3,5), pc35); Verify(pj, pj51); -pj := FlatCopy(pj40); Verify(tlc(pj,4,6), pc46); Verify(pj, pj52); -pj := FlatCopy(pj40); Verify(tlc(pj,5,7), pc57); Verify(pj, pj53); -pj := FlatCopy(pj40); Verify(tlc(pj,6,8), pc68); Verify(pj, pj54); - -pj := FlatCopy(pj50); Verify(tlc(pj,2,4), pc24); Verify(pj, pj50); -pj := FlatCopy(pj50); Verify(tlc(pj,3,5), pc35); Verify(pj, pj51); -pj := FlatCopy(pj50); Verify(tlc(pj,4,6), pc46); Verify(pj, pj52); -pj := FlatCopy(pj50); Verify(tlc(pj,5,7), pc57); Verify(pj, pj53); -pj := FlatCopy(pj50); Verify(tlc(pj,6,8), pc68); Verify(pj, pj54); - -pj := FlatCopy(pj51); Verify(tlc(pj,2,4), pc24); Verify(pj, pj51); -pj := FlatCopy(pj51); Verify(tlc(pj,3,5), pc35); Verify(pj, pj51); -pj := FlatCopy(pj51); Verify(tlc(pj,4,6), pc46); Verify(pj, pj52); -pj := FlatCopy(pj51); Verify(tlc(pj,5,7), pc57); Verify(pj, pj53); -pj := FlatCopy(pj51); Verify(tlc(pj,6,8), pc68); Verify(pj, pj54); - -pj := FlatCopy(pj52); Verify(tlc(pj,2,4), pc24); Verify(pj, pj52); -pj := FlatCopy(pj52); Verify(tlc(pj,3,5), pc35); Verify(pj, pj52); -pj := FlatCopy(pj52); Verify(tlc(pj,4,6), pc46); Verify(pj, pj52); -pj := FlatCopy(pj52); Verify(tlc(pj,5,7), pc57); Verify(pj, pj53); -pj := FlatCopy(pj52); Verify(tlc(pj,6,8), pc68); Verify(pj, pj54); - -pj := FlatCopy(pj53); Verify(tlc(pj,2,4), pc24); Verify(pj, pj53); -pj := FlatCopy(pj53); Verify(tlc(pj,3,5), pc35); Verify(pj, pj53); -pj := FlatCopy(pj53); Verify(tlc(pj,4,6), pc46); Verify(pj, pj53); -pj := FlatCopy(pj53); Verify(tlc(pj,5,7), pc57); Verify(pj, pj53); -pj := FlatCopy(pj53); Verify(tlc(pj,6,8), pc68); Verify(pj, pj54); - -pj := FlatCopy(pj54); Verify(tlc(pj,2,4), pc24); Verify(pj, pj54); -pj := FlatCopy(pj54); Verify(tlc(pj,3,5), pc35); Verify(pj, pj54); -pj := FlatCopy(pj54); Verify(tlc(pj,4,6), pc46); Verify(pj, pj54); -pj := FlatCopy(pj54); Verify(tlc(pj,5,7), pc57); Verify(pj, pj54); -pj := FlatCopy(pj54); Verify(tlc(pj,6,8), pc68); Verify(pj, pj54); - -// Addition - -pp := Taylor'LPS(Undefined, {}, x, - Taylor'LPS'Add(FlatCopy(p1), FlatCopy(p3))); -Verify(Taylor'LPS'Coeffs(pp, 0, 3), {1+a0,1+a1,1/2+a2,1/6+a3}); -Verify(pp, Taylor'LPS(0, {1+a0,1+a1,1/2+a2,1/6+a3}, x, - Taylor'LPS'Add(p1,p3))); - -pp := Taylor'LPS(0, {1+a0}, x, - Taylor'LPS'Add(FlatCopy(p1), FlatCopy(p3))); -Verify(Taylor'LPS'Coeffs(pp, 0, 3), {1+a0,1+a1,1/2+a2,1/6+a3}); -Verify(pp, Taylor'LPS(0, {1+a0,1+a1,1/2+a2,1/6+a3}, x, - Taylor'LPS'Add(p1,p3))); - -pp := Taylor'LPS'Construct(x, 1+Ln(x+1)); -Verify(Taylor'LPS'Coeffs(pp, 0, 4), {1, 1, -1/2, 1/3, -1/4}); -Verify(pp, Taylor'LPS(0, {1,1,-1/2,1/3,-1/4}, x, Taylor'LPS'Add(pp2,pp1)) - Where {pp1 == Taylor'LPS(0, {1,0,0,0,0}, x, 1), - pp2 == Taylor'LPS(1, {1,-1/2,1/3,-1/4}, x, Ln(x+1))}); - -pp := Taylor'LPS'Construct(a, Exp(a)+jn(a)); -Verify(Taylor'LPS'Coeffs(pp, -1, 5), {0, 1, 1, 1/2, 1/6, 1/24, 1/120+jn5}); -Verify(pp, Taylor'LPS(0, {1, 1, 1/2, 1/6, 1/24, 1/120+jn5}, - a, Taylor'LPS'Add(pp1,pp2)) - Where {pp1 == Taylor'LPS(0, {1,1,1/2,1/6,1/24,1/120}, a, Exp(a)), - pp2 == Taylor'LPS(5, {jn5}, a, jn(a))}); - -// Scalar multiplication - -pp := Taylor'LPS(Undefined, {}, x, Taylor'LPS'ScalarMult(5, FlatCopy(p1))); -Verify(Taylor'LPS'Coeffs(pp, 0, 3), {5,5,5/2,5/6}); -Verify(pp, Taylor'LPS(0, {5,5,5/2,5/6}, x, Taylor'LPS'ScalarMult(5,p1))); - -pp := Taylor'LPS(0, {5,5}, x, Taylor'LPS'ScalarMult(5, FlatCopy(p1))); -Verify(Taylor'LPS'Coeffs(pp, 0, 3), {5,5,5/2,5/6}); -Verify(pp, Taylor'LPS(0, {5,5,5/2,5/6}, x, Taylor'LPS'ScalarMult(5,p1))); - -pp := Taylor'LPS'Construct(t, (-2)*Sin(t)); -Verify(Taylor'LPS'Coeffs(pp, -1, 4), {0, 0, -2, 0, 1/3, 0}); -Verify(pp, Taylor'LPS(1, {-2,0,1/3,0}, t, Taylor'LPS'ScalarMult(-2, pp1)) - Where pp1 == Taylor'LPS(1, {1,0,-1/6,0}, t, Sin(t))); - -// Subtraction - -pp := Taylor'LPS'Construct(x, Exp(x)-Cos(x)); - // zero order term cancels! -Verify(Taylor'LPS'Coeffs(pp, 0, 4), {0, 1, 1, 1/6, 0}); -Verify(pp, Taylor'LPS(1, {1,1,1/6,0}, x, Taylor'LPS'Add(pp1, pp2)) - Where pp1 == Taylor'LPS(0, {1,1,1/2,1/6,1/24}, x, Exp(x)) - Where pp2 == Taylor'LPS(0, {-1,0,1/2,0,-1/24}, x, - Taylor'LPS'ScalarMult(-1, pp3)) - Where pp3 == Taylor'LPS(0, {1,0,-1/2,0,1/24}, x, Cos(x))); - -// Multiplication - -pp := Taylor'LPS(Undefined, {}, x, - Taylor'LPS'Multiply(FlatCopy(p1), FlatCopy(p3))); -Verify(Taylor'LPS'Coeffs(pp, 0, 2), {a0, a1+a0, a2+a1+1/2*a0}); -Verify(pp, Taylor'LPS(0, {a0, a1+a0, a2+a1+1/2*a0}, x, - Taylor'LPS'Multiply(p1,p3))); - -pp := Taylor'LPS(0, {a0}, x, - Taylor'LPS'Multiply(FlatCopy(p1), FlatCopy(p3))); -Verify(Taylor'LPS'Coeffs(pp, 0, 2), {a0, a1+a0, a2+a1+1/2*a0}); -Verify(pp, Taylor'LPS(0, {a0, a1+a0, a2+a1+1/2*a0}, x, - Taylor'LPS'Multiply(p1,p3))); - -pp := Taylor'LPS'Construct(x, x^2*Ln(x+1)); -Verify(Taylor'LPS'Coeffs(pp, 0, 4), {0, 0, 0, 1, -1/2}); -Verify(pp, Taylor'LPS(3, {1,-1/2}, x, Taylor'LPS'Multiply(pp1,pp2)) - Where {pp1 == Taylor'LPS(2, {1,0}, x, x^2), - pp2 == Taylor'LPS(1, {1,-1/2}, x, Ln(x+1))}); - -// Inversion - -pp := Taylor'LPS(Undefined, {}, x, Taylor'LPS'Inverse(FlatCopy(p1))); -Verify(Taylor'LPS'Coeffs(pp, 0, 3), {1,-1,1/2,-1/6}); -Verify(pp, Taylor'LPS(0, {1,-1,1/2,-1/6}, x, Taylor'LPS'Inverse(p1))); - -pp := Taylor'LPS(Undefined, {}, t, Taylor'LPS'Inverse(FlatCopy(p2))); -Verify(Taylor'LPS'Coeffs(pp, 0, 2), {0,1/6,-0}); -Verify(pp, Taylor'LPS(-1, {1,0,1/6,0}, t, Taylor'LPS'Inverse(p2))); - -pp := Taylor'LPS(Undefined, {}, x, Taylor'LPS'Inverse(FlatCopy(p0))); -Verify([Taylor'LPS'Coeffs(pp, 0, 0); ClearError("div-by-zero");], True); - -pp := Taylor'LPS'Construct(x, 1/jn(x)); -Verify(Taylor'LPS'Coeffs(pp, -7, -4), {0,0,1/jn5,-jn6/jn5^2}); -Verify(pp, Taylor'LPS(-5, {1/jn5,-jn6/jn5^2}, x, Taylor'LPS'Inverse(pp1)) - Where pp1 == Taylor'LPS(5, {jn5,jn6}, x, jn(x))); - -pp := Taylor'LPS'Construct(x, 1/(Cos(x)^2+Sin(x)^2-1)); -Verify([Taylor'LPS'Coeffs(pp, 0, 5); ClearError("maybe-div-by-zero");], True); - -// Division - -pp := Taylor'LPS'Construct(x, Exp(x)/Cos(x)); -Verify(Taylor'LPS'Coeffs(pp, 0, 4), {1, 1, 1, 2/3, 1/2}); -Verify(pp, Taylor'LPS(0, {1,1,1,2/3,1/2}, x, Taylor'LPS'Multiply(pp1, pp2)) - Where pp1 == Taylor'LPS(0, {1,1,1/2,1/6,1/24}, x, Exp(x)) - Where pp2 == Taylor'LPS(0, {1,0,1/2,0,5/24}, x, - Taylor'LPS'Inverse(pp3)) - Where pp3 == Taylor'LPS(0, {1,0,-1/2,0,1/24}, x, Cos(x))); - -// Raising to a natural power - -// No tests (Taylor'LPS'Power is not implemented yet) - -// Composition - -Verify(Taylor'LPS'Construct(x, Ln(Sin(x))), - Taylor'LPS(Undefined, {}, x, Taylor'LPS'Compose(pp1,pp2)) - Where {pp1 == Taylor'LPS(Undefined, {}, x, Ln(x)), - pp2 == Taylor'LPS(1, {}, x, Sin(x))}); - -Verify(Taylor'LPS'Construct(x, Ln(Cos(x))), - Taylor'LPS(Undefined, {}, x, Taylor'LPS'Compose(pp1,pp2)) - Where {pp1 == Taylor'LPS(Undefined, {}, x, Ln(1+x)), - pp2 == Taylor'LPS(Undefined, {}, x, Taylor'LPS'Add(pp3,pp4)), - pp3 == Taylor'LPS(0, {1}, x, Cos(x)), - pp4 == Taylor'LPS(Undefined, {}, x, -1)}); - -pp := Taylor'LPS(Undefined, {}, x, - Taylor'LPS'Compose(FlatCopy(p1), FlatCopy(p2))); -Verify(Taylor'LPS'Coeffs(pp, 0, 3), {1, 1, 1/2, 0}); -Verify(pp, Taylor'LPS(0, {1,1,1/2,0}, x, Taylor'LPS'Compose(p1,p2))); - -]; // LocalSymbols(p*) - diff -Nru mathpiper-0.0.svn2556/tests/scripts/tensors.mpt mathpiper-0.81f+dfsg1/tests/scripts/tensors.mpt --- mathpiper-0.0.svn2556/tests/scripts/tensors.mpt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/tensors.mpt 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ - - -NextTest("Tensors"); - -TestMathPiper(TSimplify( TSum({j}) Delta(i,j)*v(j) ),v(i)); -TestMathPiper(TSimplify( TSum({j,i}) Delta(i,j)*Delta(i,j) ), Ndim); -TestMathPiper(TSimplify( TSum({j,i}) Delta(i,j)*Delta(j,i) ), Ndim); -TestMathPiper(TSimplify( TSum({j}) Delta(i,j)*Delta(j,k) ), Delta(i,k)); -TestMathPiper(TSimplify( TSum({i}) v(i)*v(i) ), TSum({i})(v(i)^2)); -Retract("v",1); -RuleBase("v",{ii}); -f(i,j):=v(i)*v(j); -TestMathPiper(f(i,i),v(i)^2); -TestMathPiper(TSimplify( TSum({i}) f(i,i) ),TSum({i})(v(i)^2)); -TestMathPiper(TSimplify( TSum({j}) Delta(i,j)*f(j,k) ),v(i)*v(k)); - -TestMathPiper(TSimplify(TSum({i,j}) Delta(i,j)*f(i,j) ), TSum({j})v(j)^2); -TestMathPiper(TSimplify(TSum({i})X(j)*TD(i)X(i)), Ndim*X(j)); -TestMathPiper(TSimplify(TSum({i}) TD(i)(X(i)*X(j)) ), Ndim*X(j)+X(j)); -TestMathPiper(TSimplify(TSum({i}) X(i)*TD(i)X(j) ), X(j)); -TestMathPiper(TSimplify(TSum({i})TD(i)v(i)), TSum({i})TD(i)v(i)); - -TestMathPiper(TSimplify(TSum({i,j})TD(i)TD(j)(X(i)*X(j))), Ndim+Ndim^2); -TestMathPiper(TSimplify(TSum({i})TD(i)(X(i)*X(j)*X(j))), Ndim*X(j)^2+2*X(j)^2); -TestMathPiper(TSimplify(TSum({i,j,k})TD(i)TD(j)TD(k)(X(i)*X(j)*X(k))), 3*Ndim^2+2*Ndim+Ndim^3); - diff -Nru mathpiper-0.0.svn2556/tests/scripts/test_index.txt mathpiper-0.81f+dfsg1/tests/scripts/test_index.txt --- mathpiper-0.0.svn2556/tests/scripts/test_index.txt 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/test_index.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -arithmetic.mpt -binaryfactors.mpt -calculus.mpt -canprove.mpt -comments.mpt -complex.mpt -c_tex_form.mpt -cyclotomic.mpt -deriv.mpt -dimensions.mpt -dot.mpt -GaussianIntegers.mpt -includetestfiles -integrate.mpt -io.mpt -journal.mpt -linalg.mpt -lists.mpt -logic_simplify_test.mpt -macro.mpt -mathpiper_tests.log -matrixpower.mpt -multivar.mpt -nthroot.mpt -numbers.mpt -numerics.mpt -nummethods.mpt -ode.mpt -openmath.mpt -orthopoly.mpt -outer.mpt -piper_test.bat -plots.mpt -poly.mpt -predicates.mpt -programming.mpt -radsimp.mpt -regress.mpt -scopestack.mpt -simplify.mpt -solve.mpt -sturm.mpt -sums.mpt -tensors.mpt -test-yacas-c-version -trace.mpt -transforms.mpt -tr.mpt - diff -Nru mathpiper-0.0.svn2556/tests/scripts/test-yacas-c-version mathpiper-0.81f+dfsg1/tests/scripts/test-yacas-c-version --- mathpiper-0.0.svn2556/tests/scripts/test-yacas-c-version 2009-10-06 15:12:53.000000000 +0000 +++ mathpiper-0.81f+dfsg1/tests/scripts/test-yacas-c-version 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -#! /bin/sh -# -# test-yacas -- Script for testing Yacas - -# Give help, if requested - -if [ $# -eq 0 ] || [ "x$1" = "x-h" ] || [ "x$1" = "x--help" ]; then - echo "Usage: $0