[genius] Tue Jul 12 23:16:59 2011 Jiri (George) Lebl <jirka 5z com>



commit e37bfda806efe87038f388a925acc12f91497162
Author: Jiri (George) Lebl <jirka 5z com>
Date:   Tue Jul 12 23:36:48 2011 -0700

    Tue Jul 12 23:16:59 2011  Jiri (George) Lebl <jirka 5z com>
    
    	* src/eval.c, src/structs.h, src/parse.y, src/lexer.l, src/calc.c,
    	  src/matrixw.[ch]: add increment and swapwith operators which
    	  are quicker ways to do these common operations.  swapwith does
    	  not yet work with ranges, something that should be remedied.
    
    	* src/funclib.c: improve inline docs for rand and randint
    
    	* src/geniustests.txt, src/testscope.gel: add tests
    
    	* lib/linear_algebra/misc.gel: add ShuffleVector, fix some other
    	  functions to accept null
    
    	* lib/*/*.gel: use increment and swapwith, remove some unneeded
    	  trailing semicolons
    
    	* help/Makefile.am, help/genius.txt: add the genius.txt back into
    	  the distribution
    
    	* help/C/gel-function-list.xml help/C/genius.xml: document new
    	  features and functions

 ChangeLog                             |   23 +
 help/C/gel-function-list.xml          |   72 +-
 help/C/genius.xml                     |   47 +-
 help/Makefile.am                      |    8 +-
 help/genius.txt                       | 6440 +++++++++++++++++++++++++++++++++
 lib/calculus/fourier.gel              |   16 +-
 lib/calculus/limits.gel               |    4 +-
 lib/calculus/sums_products.gel        |    8 +-
 lib/equation_solving/diffeqs.gel      |   18 +-
 lib/equation_solving/find_root.gel    |   12 +-
 lib/functions/elementary.gel          |    4 +-
 lib/library-strings.c                 |    1 +
 lib/linear_algebra/linear_algebra.gel |    4 +-
 lib/linear_algebra/misc.gel           |   50 +-
 lib/number_theory/factoring.gel       |   14 +-
 lib/number_theory/misc.gel            |    6 +-
 lib/number_theory/modulus.gel         |   18 +-
 lib/number_theory/primes.gel          |    8 +-
 src/calc.c                            |   14 +-
 src/compil.c                          |    2 +-
 src/eval.c                            |  596 +++-
 src/funclib.c                         |    4 +-
 src/geniustests.txt                   |   36 +
 src/lexer.l                           |    5 +-
 src/matrixw.c                         |  132 +-
 src/matrixw.h                         |   30 +-
 src/parse.y                           |   14 +-
 src/structs.h                         |    3 +
 src/testscope.gel                     |   34 +
 29 files changed, 7491 insertions(+), 132 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9a0e2b5..f1ceb8b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+Tue Jul 12 23:16:59 2011  Jiri (George) Lebl <jirka 5z com>
+
+	* src/eval.c, src/structs.h, src/parse.y, src/lexer.l, src/calc.c,
+	  src/matrixw.[ch]: add increment and swapwith operators which
+	  are quicker ways to do these common operations.  swapwith does
+	  not yet work with ranges, something that should be remedied.
+
+	* src/funclib.c: improve inline docs for rand and randint
+
+	* src/geniustests.txt, src/testscope.gel: add tests
+
+	* lib/linear_algebra/misc.gel: add ShuffleVector, fix some other
+	  functions to accept null
+
+	* lib/*/*.gel: use increment and swapwith, remove some unneeded
+	  trailing semicolons
+
+	* help/Makefile.am, help/genius.txt: add the genius.txt back into
+	  the distribution
+
+	* help/C/gel-function-list.xml help/C/genius.xml: document new
+	  features and functions
+
 Tue Jun 28 15:53:40 2011  Jiri (George) Lebl <jirka 5z com>
 
 	* src/compil.c: use basic ascii for encoding simple strings
diff --git a/help/C/gel-function-list.xml b/help/C/gel-function-list.xml
index a6d512b..6dffa38 100644
--- a/help/C/gel-function-list.xml
+++ b/help/C/gel-function-list.xml
@@ -215,7 +215,7 @@ not consider <constant>null</constant> a matrix.</para>
          <term>IsNull</term>
          <listitem>
           <synopsis>IsNull (arg)</synopsis>
-          <para>Check if argument is a null.</para>
+	  <para>Check if argument is a <constant>null</constant>.</para>
          </listitem>
         </varlistentry>
 
@@ -310,7 +310,7 @@ is called inside a block that was evaluated using modular arithmetic (using <lit
          <listitem>
           <synopsis>false</synopsis>
           <para>Aliases: <function>False</function> <function>FALSE</function></para>
-          <para>The false boolean value.</para>
+	  <para>The <constant>false</constant> boolean value.</para>
          </listitem>
         </varlistentry>
 
@@ -387,7 +387,7 @@ unprotected variables as user defined.</para>
          <listitem>
           <synopsis>true</synopsis>
           <para>Aliases: <function>True</function> <function>TRUE</function></para>
-          <para>The true boolean value.</para>
+	  <para>The <constant>true</constant> boolean value.</para>
          </listitem>
         </varlistentry>
 
@@ -1209,7 +1209,7 @@ number is specified) of the given size returned.</para>
           <para>Generate random integer in the range
 <literal>[0,max)</literal>.
 If size is given then a matrix (if two numbers are specified) or vector (if one
-number is specified) of the given size returned.  For example
+number is specified) of the given size returned.  For example,
           <screen><prompt>genius></prompt> <userinput>randint(4)</userinput>
 = 3
 <prompt>genius></prompt> <userinput>randint(4,2)</userinput>
@@ -1732,7 +1732,7 @@ number is specified) of the given size returned.  For example
           <para>
 	    Attempt fermat factorization of <varname>n</varname> into
 	    <userinput>(t-s)*(t+s)</userinput>, returns <varname>t</varname>
-	    and <varname>s</varname> as a vector if possible, null otherwise.
+	    and <varname>s</varname> as a vector if possible, <constant>null</constant> otherwise.
 	    <varname>tries</varname> specifies the number of tries before
 	    giving up.
 	  </para>
@@ -1882,7 +1882,7 @@ precalculated and returned in the second column.</para>
 	    value of 22 yields a probability of about 5.7e-14.
 	  </para>
           <para>
-	    If <literal>false</literal> is returned, you can be sure that
+	    If <constant>false</constant> is returned, you can be sure that
 	    the number is a composite.  If you want to be absolutely sure
 	    that you have a prime you can use 
 	    <link linkend='gel-function-MillerRabinTestSure'>
@@ -2191,7 +2191,7 @@ that is if <userinput>b^(n-1) == 1 mod n</userinput>.  This calles the <function
          <term>PseudoprimeTest</term>
          <listitem>
           <synopsis>PseudoprimeTest (n,b)</synopsis>
-          <para>Pseudoprime test, returns true if and only if
+	  <para>Pseudoprime test, returns <constant>true</constant> if and only if
 		<userinput>b^(n-1) == 1  mod n</userinput></para>
           <para>
 	    See
@@ -2417,7 +2417,7 @@ same size.  No conjugates are taken so this is a bilinear form even if working o
          <listitem>
           <synopsis>I (n)</synopsis>
           <para>Aliases: <function>eye</function></para>
-          <para>Return an identity matrix of a given size, that is <varname>n</varname> by <varname>n</varname>.  If <varname>n</varname> is zero, returns null.</para>
+	  <para>Return an identity matrix of a given size, that is <varname>n</varname> by <varname>n</varname>.  If <varname>n</varname> is zero, returns <constant>null</constant>.</para>
           <para>
 	    See
 	    <ulink url="http://planetmath.org/encyclopedia/IdentityMatrix.html";>Planetmath</ulink> for more information.
@@ -2431,7 +2431,7 @@ same size.  No conjugates are taken so this is a bilinear form even if working o
           <synopsis>IndexComplement (vec,msize)</synopsis>
           <para>Return the index complement of a vector of indexes.  Everything is one based.  For example for vector <userinput>[2,3]</userinput> and size
 <userinput>5</userinput>, we return <userinput>[1,4,5]</userinput>.  If
-<varname>msize</varname> is 0, we always return null.</para>
+<varname>msize</varname> is 0, we always return <constant>null</constant>.</para>
          </listitem>
         </varlistentry>
 
@@ -2452,11 +2452,11 @@ same size.  No conjugates are taken so this is a bilinear form even if working o
          <term>IsIdentity</term>
          <listitem>
           <synopsis>IsIdentity (x)</synopsis>
-          <para>Check if a matrix is the identity matrix.  Automatically returns <varname>false</varname>
+          <para>Check if a matrix is the identity matrix.  Automatically returns <constant>false</constant>
 	    if the matrix is not square.  Also works on numbers, in which
 	    case it is equivalent to <userinput>x==1</userinput>.  When <varname>x</varname> is
-	    <literal>null</literal> (we could think of that as a 0 by 0 matrix),
-	    no error is generated and <varname>false</varname> is returned.</para>
+	    <constant>null</constant> (we could think of that as a 0 by 0 matrix),
+	    no error is generated and <constant>false</constant> is returned.</para>
          </listitem>
         </varlistentry>
 
@@ -2566,8 +2566,8 @@ functions make this check.  Values can be any number including complex numbers.<
           <synopsis>IsZero (x)</synopsis>
           <para>Check if a matrix is composed of all zeros.  Also works on numbers, in which
 	    case it is equivalent to <userinput>x==0</userinput>.  When <varname>x</varname> is
-	    <literal>null</literal> (we could think of that as a 0 by 0 matrix),
-	    no error is generated and <varname>true</varname> is returned as the condition is
+	    <constant>null</constant> (we could think of that as a 0 by 0 matrix),
+	    no error is generated and <constant>true</constant> is returned as the condition is
 	    vacuous.
 	    </para>
          </listitem>
@@ -2600,7 +2600,7 @@ functions make this check.  Values can be any number including complex numbers.<
          <listitem>
           <synopsis>MakeVector (A)</synopsis>
           <para>Make column vector out of matrix by putting columns above
-	    each other.  Returns null when given null.</para>
+		  each other.  Returns <constant>null</constant> when given <constant>null</constant>.</para>
          </listitem>
         </varlistentry>
 
@@ -2651,7 +2651,7 @@ the outer product is <userinput>v * u.'</userinput>.</para>
          <term>ReverseVector</term>
          <listitem>
           <synopsis>ReverseVector (v)</synopsis>
-          <para>Reverse elements in a vector.</para>
+	  <para>Reverse elements in a vector.  Return <constant>null</constant> if given <constant>null</constant></para>
          </listitem>
         </varlistentry>
 
@@ -2692,11 +2692,19 @@ something(r)</userinput>.</para>
 	  matrix will be returned to which the old one is copied.  Entries that
 	  don't fit are clipped and extra space is filled with zeros.
 	  if <varname>rows</varname> or <varname>columns</varname> are zero
-	  then null is returned.
+	  then <constant>null</constant> is returned.
 	  </para>
          </listitem>
         </varlistentry>
 
+        <varlistentry id="gel-function-ShuffleVector">
+         <term>ShuffleVector</term>
+         <listitem>
+          <synopsis>ShuffleVector (v)</synopsis>
+	  <para>Shuffle elements in a vector.  Return <constant>null</constant> if given <constant>null</constant></para>
+         </listitem>
+        </varlistentry>
+
         <varlistentry id="gel-function-SortVector">
          <term>SortVector</term>
          <listitem>
@@ -2768,7 +2776,7 @@ number of columns times the number of rows.</para>
          <term>ones</term>
          <listitem>
           <synopsis>ones (rows,columns...)</synopsis>
-          <para>Make an matrix of all ones (or a row vector if only one argument is given).  Returns null if either rows or columns are zero.</para>
+	  <para>Make an matrix of all ones (or a row vector if only one argument is given).  Returns <constant>null</constant> if either rows or columns are zero.</para>
          </listitem>
         </varlistentry>
 
@@ -2784,7 +2792,7 @@ number of columns times the number of rows.</para>
          <term>zeros</term>
          <listitem>
           <synopsis>zeros (rows,columns...)</synopsis>
-          <para>Make a matrix of all zeros (or a row vector if only one argument is given).  Returns null if either rows or columns are zero.</para>
+	  <para>Make a matrix of all zeros (or a row vector if only one argument is given).  Returns <constant>null</constant> if either rows or columns are zero.</para>
          </listitem>
         </varlistentry>
 
@@ -3227,7 +3235,7 @@ determinant.
           <para>
 	    Get the LU decomposition of <varname>A</varname>
 	    and store the result in the <varname>L</varname> and
-	    <varname>U</varname> which should be references.  It returns true
+	    <varname>U</varname> which should be references.  It returns <constant>true</constant>
 	    if successful.
 	    For example suppose that A is a square matrix, then after running:
 	    <screen><prompt>genius></prompt> <userinput>LUDecomposition(A,&amp;L,&amp;U)</userinput>
@@ -3247,8 +3255,8 @@ determinant.
 	  <para>
 	    Not all matrices have LU decompositions, for example
 	    <userinput>[0,1;1,0]</userinput> does not and this function returns
-	    <literal>false</literal> in this case and sets <varname>L</varname>
-	    and <varname>U</varname> to null.
+	    <constant>false</constant> in this case and sets <varname>L</varname>
+	    and <varname>U</varname> to <constant>null</constant>.
 	  </para>
           <para>
 	    See
@@ -3353,7 +3361,7 @@ function of two arguments or it can be a matrix giving a sesquilinear form.
 	    Get the QR decomposition of a square matrix <varname>A</varname>,
 	    returns the upper triangular matrix <varname>R</varname>
 	    and sets <varname>Q</varname> to the orthogonal (unitary) matrix.
-	    <varname>Q</varname> should be a reference or null if you don't
+	    <varname>Q</varname> should be a reference or <constant>null</constant> if you don't
 	    want any return.
 	    For example:
 	    <screen><prompt>genius></prompt> <userinput>R = QRDecomposition(A,&amp;Q)</userinput>
@@ -3392,9 +3400,9 @@ function of two arguments or it can be a matrix giving a sesquilinear form.
 		at a eigenvector and could be random.  It should have 
 	        nonzero imaginary part if it will have any chance at finding
 	        complex eigenvalues.  The code will run at most
-	        <varname>maxiter</varname> iterations and return null
+		<varname>maxiter</varname> iterations and return <constant>null</constant>
 		if we cannot get within an error of <varname>epsilon</varname>.
-		<varname>vecref</varname> should either be null or a reference
+		<varname>vecref</varname> should either be <constant>null</constant> or a reference
 		to a variable where the eigenvector should be stored.
 		</para>
           <para>
@@ -3502,7 +3510,7 @@ function of two arguments or it can be a matrix giving a sesquilinear form.
          <term>SolveLinearSystem</term>
          <listitem>
           <synopsis>SolveLinearSystem (M,V,args...)</synopsis>
-          <para>Solve linear system Mx=V, return solution V if there is a unique solution, null otherwise.  Extra two reference parameters can optionally be used to get the reduced M and V.</para>
+	  <para>Solve linear system Mx=V, return solution V if there is a unique solution, <constant>null</constant> otherwise.  Extra two reference parameters can optionally be used to get the reduced M and V.</para>
          </listitem>
         </varlistentry>
 
@@ -3772,7 +3780,7 @@ divided to make all pivots 1.</para>
           <para>
 	    Find the vector <varname>c</varname> of non-negative integers
 	    such that taking the dot product with <varname>v</varname> is
-	    equal to n.  If not possible returns null.  <varname>v</varname>
+	    equal to n.  If not possible returns <constant>null</constant>.  <varname>v</varname>
 	    should be given sorted in increasing order and should consist
 	    of non-negative integers.
 	  </para>
@@ -4993,7 +5001,7 @@ and has period <userinput>b-a</userinput>.</para>
          <term>NewtonsMethodPoly</term>
          <listitem>
           <synopsis>NewtonsMethodPoly (poly,guess,epsilon,maxn)</synopsis>
-          <para>Run newton's method on a polynomial to attempt to find a root, returns after two successive values are within epsilon or after maxn tries (then returns null).</para>
+	  <para>Run newton's method on a polynomial to attempt to find a root, returns after two successive values are within epsilon or after maxn tries (then returns <constant>null</constant>).</para>
          </listitem>
         </varlistentry>
 
@@ -5063,7 +5071,7 @@ and has period <userinput>b-a</userinput>.</para>
          <term>IsIn</term>
          <listitem>
           <synopsis>IsIn (x,X)</synopsis>
-          <para>Returns true if the element x is in the set X (where X is a vector pretending to be a set).</para>
+	  <para>Returns <constant>true</constant> if the element x is in the set X (where X is a vector pretending to be a set).</para>
          </listitem>
         </varlistentry>
 
@@ -5071,7 +5079,7 @@ and has period <userinput>b-a</userinput>.</para>
          <term>IsSubset</term>
          <listitem>
           <synopsis>IsSubset (X, Y)</synopsis>
-          <para>Returns true if X is a subset of Y (X and Y are vectors pretending to be sets).</para>
+	  <para>Returns <constant>true</constant> if X is a subset of Y (X and Y are vectors pretending to be sets).</para>
          </listitem>
         </varlistentry>
 
@@ -5163,7 +5171,7 @@ and has period <userinput>b-a</userinput>.</para>
          <term>SymbolicDerivativeTry</term>
          <listitem>
           <synopsis>SymbolicDerivativeTry (f)</synopsis>
-          <para>Attempt to symbolically differentiate the function f, where f is a function of one variable, returns null if unsuccessful but is silent.
+	  <para>Attempt to symbolically differentiate the function f, where f is a function of one variable, returns <constant>null</constant> if unsuccessful but is silent.
 	  (See <link linkend="gel-function-SymbolicDerivative"><function>SymbolicDerivative</function></link>)
           </para>
          </listitem>
@@ -5183,7 +5191,7 @@ and has period <userinput>b-a</userinput>.</para>
          <term>SymbolicNthDerivativeTry</term>
          <listitem>
           <synopsis>SymbolicNthDerivativeTry (f,n)</synopsis>
-	  <para>Attempt to symbolically differentiate a function n times quietly and return null on failure
+	  <para>Attempt to symbolically differentiate a function n times quietly and return <constant>null</constant> on failure
 	  (See <link linkend="gel-function-SymbolicNthDerivative"><function>SymbolicNthDerivative</function></link>)
           </para>
          </listitem>
diff --git a/help/C/genius.xml b/help/C/genius.xml
index 16d0cc6..c11a889 100644
--- a/help/C/genius.xml
+++ b/help/C/genius.xml
@@ -3,8 +3,8 @@
 "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
   <!ENTITY app "<application>Genius Mathematics Tool</application>">
   <!ENTITY appname "Genius">
-  <!ENTITY appversion "1.0.11">
-  <!ENTITY date "September 2010">
+  <!ENTITY appversion "1.0.13">
+  <!ENTITY date "July 2011">
 
   <!ENTITY legal SYSTEM "legal.xml">
 
@@ -33,11 +33,11 @@
 <!-- please do not change the id; for translations, change lang to -->
 <!-- appropriate code -->
   <bookinfo>
-    <abstract role="description">Manual for the Genius Math Tool.</abstract>
+	  <!--<abstract role="description">Manual for the Genius Math Tool.</abstract>-->
     <title>&appname; Manual</title>       
 
     <copyright>
-      <year>1997-2010</year>
+      <year>1997-2011</year>
       <holder>Ji&#345;&#237; (George) Lebl</holder>
     </copyright>
     <copyright>
@@ -1670,6 +1670,45 @@ different from <literal>=</literal> because it never gets translated to a
          </listitem>
         </varlistentry>
 
+        <varlistentry>
+         <term><synopsis>a swapwith b</synopsis></term>
+         <listitem>
+           <para>
+		   Swap value of <varname>a</varname> with the value
+		   of <varname>b</varname>.  Currently does not operate
+		   on ranges of matrix elements.
+		   It returns <constant>null</constant>.
+		   Available from version 1.0.13.
+           </para>
+         </listitem>
+        </varlistentry>
+
+        <varlistentry>
+         <term><synopsis>increment a</synopsis></term>
+         <listitem>
+           <para>
+		   Increment the variable <varname>a</varname> by 1.  If
+		   <varname>a</varname> is a matrix, then increment each element.
+		   This is equivalent to <userinput>a=a+1</userinput>, but 
+		   it is somewhat faster.  It returns <constant>null</constant>.
+		   Available from version 1.0.13.
+           </para>
+         </listitem>
+        </varlistentry>
+
+        <varlistentry>
+         <term><synopsis>increment a by b</synopsis></term>
+         <listitem>
+           <para>
+		   Increment the variable <varname>a</varname> by <varname>b</varname>.  If
+		   <varname>a</varname> is a matrix, then increment each element.
+		   This is equivalent to <userinput>a=a+b</userinput>, but 
+		   it is somewhat faster.  It returns <constant>null</constant>.
+		   Available from version 1.0.13.
+           </para>
+         </listitem>
+        </varlistentry>
+
 
       </variablelist>
 
diff --git a/help/Makefile.am b/help/Makefile.am
index 4a0da53..66211b4 100644
--- a/help/Makefile.am
+++ b/help/Makefile.am
@@ -27,11 +27,11 @@ DOC_LINGUAS = de es
 
 # Run this by hand for now
 #genius.txt: genius.xml $(entities)
-#	docbook2txt genius.xml
-#	dos2unix -a genius.txt # for svn
+#	docbook2txt C/genius.xml
+#	dos2unix genius.txt
 
 manualdir = $(datadir)/genius
 
-#manual_DATA = genius.txt
+manual_DATA = genius.txt
 
-#EXTRA_DIST = += genius.txt
+EXTRA_DIST = genius.txt
diff --git a/help/genius.txt b/help/genius.txt
new file mode 100644
index 0000000..d16611c
--- /dev/null
+++ b/help/genius.txt
@@ -0,0 +1,6440 @@
+Genius Manual
+
+JiÅÃ Lebl
+
+   University of Illinois, Urbana-Champaign
+
+    <jirka 5z com>
+
+Kai Willadsen
+
+   University of Queensland, Australia
+
+    <kaiw itee uq edu au>
+
+   Copyright  1997-2011 JiÅà (George) Lebl
+
+   Copyright  2004 Kai Willadsen
+
+   Permission is granted to copy, distribute and/or modify this
+   document under the terms of the GNU Free Documentation License
+   (GFDL), Version 1.1 or any later version published by the Free
+   Software Foundation with no Invariant Sections, no Front-Cover
+   Texts, and no Back-Cover Texts. You can find a copy of the GFDL
+   at this link or in the file COPYING-DOCS distributed with this
+   manual.
+
+   This manual is part of a collection of GNOME manuals
+   distributed under the GFDL. If you want to distribute this
+   manual separately from the collection, you can do so by adding
+   a copy of the license to the manual, as described in section 6
+   of the license.
+
+   Many of the names used by companies to distinguish their
+   products and services are claimed as trademarks. Where those
+   names appear in any GNOME documentation, and the members of the
+   GNOME Documentation Project are made aware of those trademarks,
+   then the names are in capital letters or initial capital
+   letters.
+
+   DOCUMENT AND MODIFIED VERSIONS OF THE DOCUMENT ARE PROVIDED
+   UNDER THE TERMS OF THE GNU FREE DOCUMENTATION LICENSE WITH THE
+   FURTHER UNDERSTANDING THAT:
+
+    1. DOCUMENT IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTY
+       OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+       WITHOUT LIMITATION, WARRANTIES THAT THE DOCUMENT OR
+       MODIFIED VERSION OF THE DOCUMENT IS FREE OF DEFECTS
+       MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+       NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY,
+       ACCURACY, AND PERFORMANCE OF THE DOCUMENT OR MODIFIED
+       VERSION OF THE DOCUMENT IS WITH YOU. SHOULD ANY DOCUMENT OR
+       MODIFIED VERSION PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+       THE INITIAL WRITER, AUTHOR OR ANY CONTRIBUTOR) ASSUME THE
+       COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS
+       DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF
+       THIS LICENSE. NO USE OF ANY DOCUMENT OR MODIFIED VERSION OF
+       THE DOCUMENT IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
+       DISCLAIMER; AND
+    2. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER
+       IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE,
+       SHALL THE AUTHOR, INITIAL WRITER, ANY CONTRIBUTOR, OR ANY
+       DISTRIBUTOR OF THE DOCUMENT OR MODIFIED VERSION OF THE
+       DOCUMENT, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE
+       TO ANY PERSON FOR ANY DIRECT, INDIRECT, SPECIAL,
+       INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER
+       INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+       GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION,
+       OR ANY AND ALL OTHER DAMAGES OR LOSSES ARISING OUT OF OR
+       RELATING TO USE OF THE DOCUMENT AND MODIFIED VERSIONS OF
+       THE DOCUMENT, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED
+       OF THE POSSIBILITY OF SUCH DAMAGES.
+
+   Feedback
+
+   To report a bug or make a suggestion regarding the Genius
+   Mathematics Tool application or this manual, follow the
+   directions in the GNOME Feedback Page.
+   This manual describes version 1.0.13 of Genius.
+     __________________________________________________________
+
+   Table of Contents
+   Introduction
+   Getting Started
+
+        To Start Genius Mathematics Tool
+        When You Start Genius
+
+   Basic Usage
+
+        Using the Work Area
+        To Create a New Program
+        To Open and Run a Program
+
+   Plotting
+
+        Line Plots
+        Parametric Plots
+        Slopefield Plots
+        Vectorfield Plots
+        Surface Plots
+
+   GEL Basics
+
+        Values
+
+              Numbers
+              Booleans
+              Strings
+              Null
+
+        Using Variables
+
+              Setting Variables
+              Built-in Variables
+              Previous Result Variable
+
+        Using Functions
+
+              Defining Functions
+              Variable Argument Lists
+              Passing Functions to Functions
+              Operations on Functions
+
+        Absolute Value / Modulus
+        Separator
+        Modular Evaluation
+        List of GEL Operators
+
+   Programming with GEL
+
+        Conditionals
+        Loops
+
+              While Loops
+              For Loops
+              Foreach Loops
+              Break and Continue
+
+        Sums and Products
+        Comparison Operators
+        Global Variables and Scope of Variables
+        Parameter variables
+        Returning
+        References
+        Lvalues
+
+   Advanced Programming with GEL
+
+        Error Handling
+        Toplevel Syntax
+        Returning Functions
+        True Local Variables
+        GEL Startup Procedure
+        Loading Programs
+
+   Matrices in GEL
+
+        Entering Matrices
+        Conjugate Transpose and Transpose Operator
+        Linear Algebra
+
+   Polynomials in GEL
+
+        Using Polynomials
+
+   Set Theory in GEL
+
+        Using Sets
+
+   List of GEL functions
+
+        Commands
+        Basic
+        Parameters
+        Constants
+        Numeric
+        Trigonometry
+        Number Theory
+        Matrix Manipulation
+        Linear Algebra
+        Combinatorics
+        Calculus
+        Functions
+        Equation Solving
+        Statistics
+        Polynomials
+        Set Theory
+        Miscellaneous
+        Symbolic Operations
+        Plotting
+
+   Example Programs in GEL
+   Settings
+
+        Output
+        Precision
+        Terminal
+        Memory
+
+   About Genius Mathematics Tool
+     __________________________________________________________
+
+Introduction
+
+   The Genius Mathematics Tool application is a general calculator
+   for use as a desktop calculator, an educational tool in
+   mathematics, and is useful even for research. The language used
+   in Genius Mathematics Tool is designed to be âmathematicalâ in
+   the sense that it should be âwhat you mean is what you getâ. Of
+   course that is not an entirely attainable goal. Genius
+   Mathematics Tool features rationals, arbitrary precision
+   integers and multiple precision floats using the GMP library.
+   It handles complex numbers using cartesian notation. It has
+   good vector and matrix manipulation and can handle basic linear
+   algebra. The programming language allows user defined
+   functions, variables and modification of parameters.
+
+   Genius Mathematics Tool comes in two versions. One version is
+   the graphical GNOME version, which features an IDE style
+   interface and the ability to plot functions of one or two
+   variables. The command line version does not require GNOME, but
+   of course does not implement any feature that requires the
+   graphical interface.
+
+   This manual describes mostly the graphical version of the
+   calculator, but the language is of course the same. The command
+   line only version lacks the graphing capabilities and all other
+   capabilities that require the graphical user interface.
+     __________________________________________________________
+
+Getting Started
+
+To Start Genius Mathematics Tool
+
+   You can start Genius Mathematics Tool in the following ways:
+
+   Applications menu
+          Depending on your operating system and version, the menu
+          item for Genius Mathematics Tool could appear in a
+          number of different places. It can be in the Education,
+          Accessories, Office, Science, or similar submenu,
+          depending on your particular setup. The menu item name
+          you are looking for is Genius Math Tool. Once you locate
+          this menu item click on it to start Genius Mathematics
+          Tool.
+
+   Run dialog
+          Depending on your system installation the menu item may
+          not be available. If it is not, you can open the Run
+          dialog and execute gnome-genius.
+
+   Command line
+          To start the GNOME version of Genius Mathematics Tool
+          execute gnome-genius from the command line.
+
+          To start the command line only version, execute the
+          following command: genius. This version does not include
+          the graphical environment and some functionality such as
+          plotting will not be available.
+     __________________________________________________________
+
+When You Start Genius
+
+   When you start the GNOME edition of Genius Mathematics Tool,
+   the window pictured in Figure 1 is displayed.
+
+   [genius_window.png]
+
+   Figure 1. Genius Mathematics Tool Window
+
+   The Genius Mathematics Tool window contains the following
+   elements:
+
+   Menubar.
+          The menus on the menubar contain all of the commands
+          that you need to work with files in Genius Mathematics
+          Tool. The File menu contains items for loading and
+          saving items and creating new programs. The Load and
+          Run... command does not open a new window for the
+          program, but just executes the program directly. It is
+          equivalent to the load command.
+
+          The Calculator menu controls the calculator engine. It
+          allows you to run the currently selected program or to
+          interrupt the current calculation. You can also look at
+          the full expression of the last answer (useful if the
+          last answer was too large to fit onto the console), or
+          you can view a listing of the values of all user defined
+          variables. Finally it allows plotting functions using a
+          user friendly dialog box.
+
+          The other menus have same familiar functions as in other
+          applications.
+
+   Toolbar.
+          The toolbar contains a subset of the commands that you
+          can access from the menubar.
+
+   Working area
+          The working area is the primary method of interacting
+          with the application.
+
+          The working area initially has just the Console tab
+          which is the main way of interacting with the
+          calculator. Here you type expressions and the results
+          are immediately returned after you hit the Enter key.
+
+          Alternatively you can write longer programs and those
+          can appear in separate tabs and can be stored in files
+          for later retrieval.
+     __________________________________________________________
+
+Basic Usage
+
+Using the Work Area
+
+   Normally you interact with the calculator in the Console tab of
+   the work area. If you are running the text only version then
+   the console will be the only thing that is available to you. If
+   you want to use Genius Mathematics Tool as a calculator only,
+   just type in your expression here and it will be evaluated.
+
+   Type your expression into the Console work area and press enter
+   and the expression will be evaluated. Expressions are written
+   in a language called GEL. The most simple GEL expression just
+   looks like mathematics. For example
+genius> 30*70 + 67^3.0 + ln(7) * (88.8/100)
+
+   or
+genius> 62734 + 812634 + 77^4 mod 5
+
+   or
+genius> | sin(37) - e^7 |
+
+   or
+genius> sum n=1 to 70 do 1/n
+
+   (Last is the harmonic sum from 1 to 70)
+
+   To get a list of functions and commands, type:
+genius> help
+
+   If you wish to get more help on a specific function, type:
+genius> help FunctionName
+
+   To view this manual, type:
+genius> manual
+
+   Suppose you have previously saved some GEL commands as a
+   program to a file and you now want to execute them. To load
+   this program from the file path/to/program.gel, type
+genius> load path/to/program.gel
+
+   Genius Mathematics Tool keeps track of the current directory.
+   To list files in the current directory type ls, to change
+   directory do cd directory as in the unix command shell.
+     __________________________________________________________
+
+To Create a New Program
+
+   To start writing a new program, choose File->New Program. A new
+   tab will appear in the work area. You can write a GEL program
+   in this work area. Once you have written your program you can
+   run it by Calculator->Run. This will execute your program and
+   will display any output on the Console tab. Executing a program
+   is equivalent of taking the text of the program and typing it
+   into the console. The only difference is that this input is
+   done independent of the console and just the output goes onto
+   the console. Calculator->Run will always run the currently
+   selected program even if you are on the Console tab. The
+   currently selected program has its tab in bold type. To select
+   a program, just click on its tab.
+
+   To save the program you've just written, choose File->Save
+   As...
+     __________________________________________________________
+
+To Open and Run a Program
+
+   To open a file, choose File->Open. A new tab containing the
+   file will appear in the work area. You can use this to edit the
+   file.
+
+   To run a program from a file, choose File->Load and Run....
+   This will run the program without opening it in a separate tab.
+   This is equivalent to the load command.
+     __________________________________________________________
+
+Plotting
+
+   Plotting support is only available in the graphical GNOME
+   version. All plotting accessible from the graphical interface
+   is available from the Create Plot window. You can access this
+   window by either clicking on the Plot button on the toolbar or
+   selecting Plot from the Calculator menu. You can also access
+   the plotting functionality by using the plotting functions of
+   the GEL language. See the Chapter called GEL Basics to find out
+   how to enter expressions that Genius understands.
+     __________________________________________________________
+
+Line Plots
+
+   To graph real valued functions of one variable open the Create
+   Plot window. You can also use the LinePlot function on the
+   command line (see its documentation).
+
+   Once you click the Plot button, a window opens up with some
+   notebooks in it. You want to be in the Function line plot
+   notebook tab, and inside you want to be on the Functions /
+   Expressions notebook tab. See Figure 1.
+
+   [line_plot.png]
+
+   Figure 1. Create Plot Window
+
+   Into the text boxes just type in expressions where x is the
+   independent variable. You can also just give names of functions
+   such as cos rather then having to type cos(x). You can graph up
+   to ten functions. If you make a mistake and Genius cannot parse
+   the input it will signify this with a warning icon on the right
+   of the text input box where the error occurred, as well as
+   giving you an error dialog. You can change the ranges of the
+   dependent and independent variables in the bottom part of the
+   dialog. Pressing the Plot button produces the graph shown in
+   Figure 2.
+
+   [line_plot_graph.png]
+
+   Figure 2. Plot Window
+
+   From here you can print out the plot, create encapsulated
+   postscript or a PNG version of the plot or change the zoom. If
+   the dependent axis was not set correctly you can have Genius
+   fit it by finding out the extrema of the graphed functions.
+
+   For plotting using the command line see the documentation of
+   the LinePlot function.
+     __________________________________________________________
+
+Parametric Plots
+
+   In the create plot window, you can also choose the Parametric
+   notebook tab to create two dimensional parametric plots. This
+   way you can plot a single parametric function. You can either
+   specify the points as x and y, or giving a single complex
+   number. See Figure 3.
+
+   [parametric.png]
+
+   Figure 3. Parametric Plot Tab
+
+   An example of a parametric plot is given in Figure 3. Similar
+   operations can be done on such graphs as can be done on the
+   other line plots. For plotting using the command line see the
+   documentation of the LinePlotParametric or LinePlotCParametric
+   function.
+
+   [parametric_graph.png]
+
+   Figure 4. Parametric Plot
+     __________________________________________________________
+
+Slopefield Plots
+
+   In the create plot window, you can also choose the Slope field
+   notebook tab to create a two dimensional slope field plot.
+   Similar operations can be done on such graphs as can be done on
+   the other line plots. For plotting using the command line see
+   the documentation of the SlopefieldPlot function.
+
+   When a slope field is active, there is an extra Solver menu
+   available, through which you can bring up the solver dialog.
+   Here you can have Genius plot specific solutions for the given
+   initial conditions. You can either specify initial conditions
+   in the dialog, or you can click on the plot directly to specify
+   the initial point. While the solver dialog is active, the
+   zooming by clicking and dragging does not work. You have to
+   close the dialog first if you want to zoom using the mouse.
+
+   The solver uses the standard Runge-Kutta method. The plots will
+   stay on the screen until cleared. The solver will stop whenever
+   it reaches the boundary of the plot window. Zooming does not
+   change the limits or parameters of the solutions, you will have
+   to clear and redraw them with appropriate parameters. You can
+   also use the SlopefieldDrawSolution function to draw solutions
+   from the command line or programs.
+     __________________________________________________________
+
+Vectorfield Plots
+
+   In the create plot window, you can also choose the Vector field
+   notebook tab to create a two dimensional vector field plot.
+   Similar operations can be done on such graphs as can be done on
+   the other line plots. For plotting using the command line see
+   the documentation of the VectorfieldPlot function.
+
+   By default the direction and magnitude of the vector field is
+   shown. To only show direction and not the magnitude, check the
+   appropriate checkbox to normalize the arrow lengths.
+
+   When a vector field is active, there is an extra Solver menu
+   available, through which you can bring up the solver dialog.
+   Here you can have Genius plot specific solutions for the given
+   initial conditions. You can either specify initial conditions
+   in the dialog, or you can click on the plot directly to specify
+   the initial point. While the solver dialog is active, the
+   zooming by clicking and dragging does not work. You have to
+   close the dialog first if you want to zoom using the mouse.
+
+   The solver uses the standard Runge-Kutta method. The plots will
+   stay on the screen until cleared. Zooming does not change the
+   limits or parameters of the solutions, you will have to clear
+   and redraw them with appropriate parameters. You can also use
+   the VectorfieldDrawSolution function to draw solutions from the
+   command line or programs.
+     __________________________________________________________
+
+Surface Plots
+
+   Genius can also plot surfaces. Select the Surface plot tab in
+   the main notebook of the Create Plot window. Here you can
+   specify a single expression which should use either x and y as
+   real independent variables or z as a complex variable (where x
+   is the real part of z and y is the imaginary part). For example
+   to plot the modulus of the cosine function for complex
+   parameters, you could enter |cos(z)|. This would be equivalent
+   to |cos(x+1i*y)|. See Figure 5. For plotting using the command
+   line see the documentation of the SurfacePlot function.
+
+   [surface_graph.png]
+
+   Figure 5. Surface Plot
+     __________________________________________________________
+
+GEL Basics
+
+   GEL stands for Genius Extension Language. It is the language
+   you use to write programs in Genius. A program in GEL is simply
+   an expression that evaluates to a number. Genius Mathematics
+   Tool can therefore be used as a simple calculator, or as a
+   powerful theoretical research tool. The syntax is meant to have
+   as shallow of a learning curve as possible, especially for use
+   as a calculator.
+     __________________________________________________________
+
+Values
+
+   Values in GEL can be numbers, Booleans or strings. Values can
+   be used in calculations, assigned to variables and returned
+   from functions, among other uses.
+     __________________________________________________________
+
+Numbers
+
+   Integers are the first type of number in GEL. Integers are
+   written in the normal way.
+1234
+
+   Hexadecimal and octal numbers can be written using C notation.
+   For example:
+0x123ABC
+01234
+
+   Or you can type numbers in an arbitrary base using
+   <base>\<number>. Digits higher than 10 use letters in a similar
+   way to hexadecimal. For example, a number in base 23 could be
+   written:
+23\1234ABCD
+
+   The second type of GEL number is rationals. Rationals are
+   simply achieved by dividing two integers. So one could write:
+3/4
+
+   to get three quarters. Rationals also accept mixed fraction
+   notation. So in order to get one and three tenths you could
+   write:
+1 3/10
+
+   The next type if number is floating point. These are entered in
+   a similar fashion to C notation. You can use E, e or @ as the
+   exponent delimiter. Note that using the exponent delimiter
+   gives a float even if there is no decimal point in the number.
+   Examples:
+1.315
+7.887e77
+7.887e-77
+.3
+0.3
+77e5
+
+   When Genius prints a floating point number it will always
+   append a .0 even if the number is whole. This is to indicate
+   that floating point numbers are taken as imprecise quantities.
+   When a number is written in the scientific notation, it is
+   always a floating point number and thus Genius does not print
+   the .0.
+
+   The final type of number in gel is the complex numbers. You can
+   enter a complex number as a sum of real and imaginary parts.
+   The imaginary part ends with an i. Here are examples of
+   entering complex numbers:
+1+2i
+8.01i
+77*e^(1.3i)
+
+   Important
+
+   When entering imaginary numbers, a number must be in front of
+   the i. If you use i by itself, Genius will interpret this as
+   referring to the variable i. If you need to refer to i by
+   itself, use 1i instead.
+
+   In order to use mixed fraction notation with imaginary numbers
+   you must have the mixed fraction in parentheses. (i.e., (1
+   2/5)i)
+     __________________________________________________________
+
+Booleans
+
+   Genius also supports native Boolean values. The two Boolean
+   constants are defined as true and false; these identifiers can
+   be used like any other variable. You can also use the
+   identifiers True, TRUE, False and FALSE as aliases for the
+   above.
+
+   At any place where a Boolean expression is expected, you can
+   use a Boolean value or any expression that produces either a
+   number or a Boolean. If Genius needs to evaluate a number as a
+   Boolean it will interpret 0 as false and any other number as
+   true.
+
+   In addition, you can do arithmetic with Boolean values. For
+   example:
+( (1 + true) - false ) * true
+
+   is the same as:
+( (true or true) or not false ) and true
+
+   Only addition, subtraction and multiplication are supported. If
+   you mix numbers with Booleans in an expression then the numbers
+   are converted to Booleans as described above. This means that,
+   for example:
+1 == true
+
+   always evaluates to true since 1 will be converted to true
+   before being compared to true.
+     __________________________________________________________
+
+Strings
+
+   Like numbers and Booleans, strings in GEL can be stored as
+   values inside variables and passed to functions. You can also
+   concatenate a string with another value using the plus
+   operator. For example:
+a=2+3;"The result is: "+a
+
+   will create the string:
+The result is: 5
+
+   You can also use C-like escape sequences such as \n,\t,\b,\a
+   and \r. To get a \ or " into the string you can quote it with a
+   \. For example:
+"Slash: \\ Quotes: \" Tabs: \t1\t2\t3"
+
+   will make a string:
+Slash: \ Quotes: " Tabs:        1       2       3
+
+   In addition, you can use the library function string to convert
+   anything to a string. For example:
+string(22)
+
+   will return
+"22"
+
+   Strings can also be compared with == (equal), != (not equal)
+   and <=> (comparison) operators
+     __________________________________________________________
+
+Null
+
+   There is a special value called null. No operations can be
+   performed on it, and nothing is printed when it is returned.
+   Therefore, null is useful when you do not want output from an
+   expression. The value null can be obtained as an expression
+   when you type ., the contant null or nothing. By nothing we
+   mean that if you end an expression with a separator ;, it is
+   equivalent to ending it with a separator followed by a null.
+
+   Example:
+x=5;.
+x=5;
+
+   Some functions return null when no value can be returned or an
+   error happened. Also null is used as an empty vector or matrix,
+   or an empty reference.
+     __________________________________________________________
+
+Using Variables
+
+   Syntax:
+VariableName
+
+   Example:
+genius> e
+= 2.71828182846
+
+   To evaluate a variable by itself, just enter the name of the
+   variable. This will return the value of the variable. You can
+   use a variable anywhere you would normally use a number or
+   string. In addition, variables are necessary when defining
+   functions that take arguments (see the Section called Defining
+   Functions).
+
+   Tip Using Tab completion
+
+
+   You can use Tab completion to get Genius to complete variable
+   names for you. Try typing the first few letters of the name and
+   pressing Tab.
+
+   Important Variable names are case sensitive
+
+
+   The names of variables are case sensitive. That means that
+   variables named hello, HELLO and Hello are all different
+   variables.
+     __________________________________________________________
+
+Setting Variables
+
+   Syntax:
+<identifier> = <value>
+<identifier> := <value>
+
+   Example:
+x = 3
+x := 3
+
+   To assign to a variable, use the = or := operators. These
+   operators set the value of the variable and return the number
+   you set, so you can do things like
+a = b = 5
+
+   The = and := operators can both be used to set variables. The
+   difference between them is that the := operator always acts as
+   an assignment operator, whereas the = operator may be
+   interpreted as testing for equality when used in a context
+   where a Boolean expression is expected.
+
+   For issues regarding the scope of variables, see the Section
+   called Global Variables and Scope of Variables in the Chapter
+   called Programming with GEL.
+     __________________________________________________________
+
+Built-in Variables
+
+   GEL has a number of built-in âvariablesâ, such as e, pi or
+   GoldenRatio. These are widely used constants with a preset
+   value, and they cannot be assigned new values. There are a
+   number of other built-in variables. See the Section called
+   Constants in the Chapter called List of GEL functions for a
+   full list.
+     __________________________________________________________
+
+Previous Result Variable
+
+   The Ans and ans variables can be used to get the result of the
+   last expression. For example, if you had performed some
+   calculation, to add 389 to the result you could do:
+Ans+389
+     __________________________________________________________
+
+Using Functions
+
+   Syntax:
+FunctionName(argument1, argument2, ...)
+
+   Example:
+Factorial(5)
+cos(2*pi)
+gcd(921,317)
+
+   To evaluate a function, enter the name of the function,
+   followed by the arguments (if any) to the function in
+   parentheses. This will return the result of applying the
+   function to its arguments. The number of arguments to the
+   function is, of course, different for each function.
+
+   There are many built-in functions, such as sin, cos and tan.
+   You can use the help built-in function to get a list of
+   available functions, or see the Chapter called List of GEL
+   functions for a full listing.
+
+   Tip Using Tab completion
+
+
+   You can use Tab completion to get Genius to complete function
+   names for you. Try typing the first few letters of the name and
+   pressing Tab.
+
+   Important Function names are case sensitive
+
+
+   The names of functions are case sensitive. That means that
+   functions named dosomething, DOSOMETHING and DoSomething are
+   all different functions.
+     __________________________________________________________
+
+Defining Functions
+
+   Syntax:
+function <identifier>(<comma separated arguments>) = <function body>
+<identifier> = (`() = <function body>)
+
+   The ` is the backquote character, and signifies an anonymous
+   function. By setting it to a variable name you effectively
+   define a function.
+
+   A function takes zero or more comma separated arguments, and
+   returns the result of the function body. Defining your own
+   functions is primarily a matter of convenience; one possible
+   use is to have sets of functions defined in GEL files which
+   Genius can load in order to make available. Example:
+function addup(a,b,c) = a+b+c
+
+   then addup(1,4,9) yields 14
+     __________________________________________________________
+
+Variable Argument Lists
+
+   If you include ... after the last argument name in the function
+   declaration, then Genius will allow any number of arguments to
+   be passed in place of that argument. If no arguments were
+   passed then that argument will be set to null. Otherwise, it
+   will be a horizontal vector containing all the arguments. For
+   example:
+function f(a,b...) = b
+
+   Then f(1,2,3) yields [2,3], while f(1) yields a null.
+     __________________________________________________________
+
+Passing Functions to Functions
+
+   In Genius, it is possible to pass a function as an argument to
+   another function. This can be done using either âfunction
+   nodesâ or anonymous functions.
+
+   If you do not enter the parentheses after a function name,
+   instead of being evaluated, the function will instead be
+   returned as a âfunction nodeâ. The function node can then be
+   passed to another function. Example:
+function f(a,b) = a(b)+1;
+function b(x) = x*x;
+f(b,2)
+
+   To pass functions which are not defined, you can use an
+   anonymous function (see the Section called Defining Functions).
+   That is, you want to pass a function without giving it a name.
+   Syntax:
+function(<comma separated arguments>) = <function body>
+`(<comma separated arguments>) = <function body>
+
+   Example:
+function f(a,b) = a(b)+1;
+f(`(x) = x*x,2)
+
+   This will return 5.
+     __________________________________________________________
+
+Operations on Functions
+
+   Some functions allow arithmetic operations, and some single
+   argument functions such as exp or ln, to operate on the
+   function. For example,
+exp(sin*cos+4)
+
+   will return a function that takes x and returns
+   exp(sin(x)*cos(x)+4). It is functionally equivalent to typing
+`(x) = exp(sin(x)*cos(x)+4)
+
+   This operation can be useful when quickly defining functions.
+   For example to create a function called f to perform the above
+   operation, you can just type:
+f = exp(sin*cos+4)
+
+   It can also be used in plotting. For example, to plot sin
+   squared you can enter:
+LinePlot(sin^2)
+
+   Warning
+
+   Not all functions can be used in this way. For example, when
+   you use a binary operation the functions must take the same
+   number of arguments.
+     __________________________________________________________
+
+Absolute Value / Modulus
+
+   You can make an absolute value of something by putting the |'s
+   around it. For example:
+   |a-b|
+
+   In case the expression is a complex number the result will be
+   the modulus (distance from the origin). For example: |3 *
+   e^(1i*pi)| returns 3.
+     __________________________________________________________
+
+Separator
+
+   In GEL if you want to type more than one command you have to
+   use the ; operator, which is a way to separate expressions,
+   such a combined expression will return whatever is the result
+   of the last one, so suppose you type the following:
+3 ; 5
+
+   This expression will yield 5.
+
+   This will require some parenthesizing to make it unambiguous
+   sometimes, especially if the ; is not the top most primitive.
+   This slightly differs from other programming languages where
+   the ; is a terminator of statements, whereas in GEL itâs
+   actually a binary operator. If you are familiar with pascal
+   this should be second nature. However genius can let you
+   pretend it is a terminator somewhat, if a ; is found at the end
+   of a parenthesis or a block, genius will itself append a null
+   node to it as if you would have written ;null. This is useful
+   in case you do not want to return a value from say a loop, or
+   if you handle the return differently. Note that it will
+   slightly slow down the code if it is executed too often as
+   there is one more operator involved.
+     __________________________________________________________
+
+Modular Evaluation
+
+   Genius implements modular arithmetic. To use it you just add
+   "mod <integer>" after the expression. Example:
+   2^(5!) * 3^(6!) mod 5
+
+   It could be possible to do modular arithmetic by computing with
+   integers and then modding in the end with the % operator, but
+   that may be time consuming if not impossible when working with
+   larger numbers. For example 10^(10^10) % 6 will simply not work
+   (the exponent will be too large), while 10^(10^10) mod 6 is
+   instanteneous.
+
+   You can calculate the inverses of numbers mod some integer by
+   just using rational numbers (of course the inverse has to
+   exist). Examples:
+10^-1 mod 101
+1/10 mod 101
+
+   You can also do modular evaluation with matrices including
+   taking inverses, powers and dividing. Example:
+A = [1,2;3,4]
+B = A^-1 mod 5
+A*B mod 5
+
+   This should yield the identity matrix as B will be the inverse
+   of A mod 5.
+
+   Some functions such as sqrt or log work in a different way when
+   in modulo mode. These will then work like their discrete
+   versions working within the ring of integers you selected. For
+   example:
+genius> sqrt(4) mod 7
+=
+[2, 5]
+genius> 2*2 mod 7
+= 4
+
+   sqrt will actually return all the possible square roots.
+     __________________________________________________________
+
+List of GEL Operators
+
+   Everything in gel is really just an expression. Expressions are
+   stringed together with different operators. As we have seen,
+   even the separator is simply a binary operator in GEL. Here is
+   a list of the operators in GEL.
+
+a;b
+
+          The separator, just evaluates both a and b, but returns
+          only the result of b.
+
+a=b
+
+          The assignment operator. This assigns b to a (a must be
+          a valid lvalue) (note however that this operator may be
+          translated to == if used in a place where boolean
+          expression is expected)
+
+a:=b
+
+          The assignment operator. Assigns b to a (a must be a
+          valid lvalue). This is different from = because it never
+          gets translated to a ==.
+
+|a|
+
+          Absolute value or modulus (if a is a complex number).
+
+          See Mathworld for more information.
+
+a^b
+
+          Exponentiation, raises a to the bth power.
+
+a.^b
+
+          Element by element exponentiation. Raise each element of
+          a matrix a to the bth power. Or if b is a matrix of the
+          same size as a, then do the operation element by
+          element. If a is a number and b is a matrix then it
+          creates matrix of the same size as b with a raised to
+          all the different powers in b.
+
+a+b
+
+          Addition. Adds two numbers, matrices, functions or
+          strings. If you add a string to anything the result will
+          just be a string.
+
+a-b
+
+          Subtraction. Subtract two numbers, matrices or
+          functions.
+
+a*b
+
+          Multiplication. This is the normal matrix
+          multiplication.
+
+a.*b
+
+          Element by element multiplication if a and b are
+          matrices.
+
+a/b
+
+          Division.
+
+a./b
+
+          Element by element division.
+
+a\b
+
+          Back division. That is this is the same as b/a.
+
+a.\b
+
+          Element by element back division.
+
+a%b
+
+          The mod operator. This does not turn on the modular
+          mode, but just returns the remainder of a/b.
+
+a.%b
+
+          Element by element the mod operator. Returns the
+          remainder after element by element integer a./b.
+
+a mod b
+
+          Modular evaluation operator. The expression a is
+          evaluated modulo b. See the Section called Modular
+          Evaluation. Some functions and operators behave
+          differently modulo an integer.
+
+a!
+
+          Factorial operator. This is like 1*...*(n-2)*(n-1)*n.
+
+a!!
+
+          Double factorial operator. This is like
+          1*...*(n-4)*(n-2)*n.
+
+a==b
+
+          Equality operator (returns true or false).
+
+a!=b
+
+          Inequality operator, returns true if a does not equal b
+          else returns false.
+
+a<>b
+
+          Alternative inequality operator, returns true if a does
+          not equal b else returns false.
+
+a<=b
+
+          Less than or equal operator, returns true if a is less
+          than or equal to b else returns false.
+
+a>=b
+
+          Greater than or equal operator, returns true if a is
+          greater than or equal to b else returns false.
+
+a<=>b
+
+          Comparison operator. If a is equal to b it returns 0, if
+          a is less than b it returns -1 and if a is greater than
+          b it returns 1.
+
+a and b
+
+          Logical and.
+
+a or b
+
+          Logical or.
+
+a xor b
+
+          Logical xor.
+
+not a
+
+          Logical not.
+
+-a
+
+          Negation operator.
+
+&a
+
+          Variable referencing (to pass a reference to something).
+          See the Section called References in the Chapter called
+          Programming with GEL.
+
+*a
+
+          Variable dereferencing (to access a referenced varible).
+          See the Section called References in the Chapter called
+          Programming with GEL.
+
+a'
+
+          Matrix conjugate transpose.
+
+a.'
+
+          Matrix transpose, does not conjugate the entries.
+
+a@(b,c)
+
+          Get element of a matrix in row b and column c. If b, c
+          are vectors, then this gets the corresponding rows
+          columns or submatrices.
+
+a@(b,)
+
+          Get row of a matrix (or rows if b is a vector).
+
+a@(b,:)
+
+          Same as above.
+
+a@(,c)
+
+          Get column of a matrix (or columns if c is a vector).
+
+a@(:,c)
+
+          Same as above.
+
+a@(b)
+
+          Get an element from a matrix treating it as a vector.
+          This will traverse the matrix row-wise.
+
+a:b
+
+          Build a vector from a to b (or specify a row, column
+          region for the @ operator). For example to get rows 2 to
+          4 of matrix A we could do
+
+A@(2:4,)
+
+          as 2:4 will return a vector [2,3,4].
+
+a:b:c
+
+          Build a vector from a to c with b as a step. That is for
+          example
+
+genius> 1:2:9
+=
+`[1, 3, 5, 7, 9]
+
+(a)i
+
+          Make a imaginary number (multiply a by the imaginary).
+          Note that normally the number i is written as 1i. So the
+          above is equal to
+
+(a)*1i
+
+`a
+
+          Quote an identifier so that it doesn't get evaluated. Or
+          quote a matrix so that it doesn't get expanded.
+
+a swapwith b
+
+          Swap value of a with the value of b. Currently does not
+          operate on ranges of matrix elements. It returns null.
+          Available from version 1.0.13.
+
+increment a
+
+          Increment the variable a by 1. If a is a matrix, then
+          increment each element. This is equivalent to a=a+1, but
+          it is somewhat faster. It returns null. Available from
+          version 1.0.13.
+
+increment a by b
+
+          Increment the variable a by b. If a is a matrix, then
+          increment each element. This is equivalent to a=a+b, but
+          it is somewhat faster. It returns null. Available from
+          version 1.0.13.
+
+   Note
+
+   The @() operator makes the : operator most useful. With this
+   you can specify regions of a matrix. So that a@(2:4,6) is the
+   rows 2,3,4 of the column 6. Or a@(,1:2) will get you the first
+   two columns of a matrix. You can also assign to the @()
+   operator, as long as the right value is a matrix that matches
+   the region in size, or if it is any other type of value.
+
+   Note
+
+   The comparison operators (except for the <=> operator which
+   behaves normally), are not strictly binary operators, they can
+   in fact be grouped in the normal mathematical way, e.g.:
+   (1<x<=y<5) is a legal boolean expression and means just what it
+   should, that is (1<x and xây and y<5)
+
+   Note
+
+   The unitary minus operates in a different fashion depending on
+   where it appears. If it appears before a number it binds very
+   closely, if it appears in front of an expression it binds less
+   than the power and factorial operators. So for example -1^k is
+   really (-1)^k, but -foo(1)^k is really -(foo(1)^k). So be
+   careful how you use it and if in doubt, add parentheses.
+     __________________________________________________________
+
+Programming with GEL
+
+Conditionals
+
+   Syntax:
+if <expression1> then <expression2> [else <expression3>]
+
+   If else is omitted, then if the expression1 yields false or 0,
+   NULL is returned.
+
+   Examples:
+if(a==5)then(a=a-1)
+if b<a then b=a
+if c>0 then c=c-1 else c=0
+a = ( if b>0 then b else 1 )
+
+   Note that = will be translated to == if used inside the
+   expression for if, so
+if a=5 then a=a-1
+
+   will be interpreted as:
+if a==5 then a:=a-1
+     __________________________________________________________
+
+Loops
+
+While Loops
+
+   Syntax:
+while <expression1> do <expression2>
+until <expression1> do <expression2>
+do <expression2> while <expression1>
+do <expression2> until <expression1>
+
+   These are similar to other languages. However, as in gel it is
+   simply an expression that must have some return value, these
+   constructs will simply return the result of the last iteration
+   or NULL if no iteration was done. In the boolean expression, =
+   is translated into == just as for the if statement.
+     __________________________________________________________
+
+For Loops
+
+   Syntax:
+for <identifier> = <from> to <to> do <body>
+for <identifier> = <from> to <to> by <increment> do <body>
+
+   Loop with identifier being set to all values from <from> to
+   <to>, optionally using an increment other than 1. These are
+   faster, nicer and more compact than the normal loops such as
+   above, but less flexible. The identifier must be an identifier
+   and can't be a dereference. The value of identifier is the last
+   value of identifier, or <from> if body was never evaluated. The
+   variable is guaranteed to be initialized after a loop, so you
+   can safely use it. Also the <from>, <to> and <increment> must
+   be non complex values. The <to> is not guaranteed to be hit,
+   but will never be overshot, for example the following prints
+   out odd numbers from 1 to 19:
+for i = 1 to 20 by 2 do print(i)
+     __________________________________________________________
+
+Foreach Loops
+
+   Syntax:
+   for <identifier> in <matrix> do <body>
+
+   For each element in the matrix, going row by row from left to
+   right we execute the body with the identifier set to the
+   current element. To print numbers 1,2,3 and 4 in this order you
+   could do:
+for n in [1,2:3,4] do print(n)
+
+   If you wish to run through the rows and columns of a matrix,
+   you can use the RowsOf and ColumnsOf functions which return a
+   vector of the rows or columns of the matrix. So,
+for n in RowsOf ([1,2:3,4]) do print(n)
+
+   will print out [1,2] and then [3,4].
+     __________________________________________________________
+
+Break and Continue
+
+   You can also use the break and continue commands in loops. The
+   continue continue command will restart the current loop at its
+   next iteration, while the break command exits the current loop.
+while(<expression1>) do (
+  if(<expression2>) break
+  else if(<expression3>) continue;
+  <expression4>
+)
+     __________________________________________________________
+
+Sums and Products
+
+   Syntax:
+sum <identifier> = <from> to <to> do <body>
+sum <identifier> = <from> to <to> by <increment> do <body>
+sum <identifier> in <matrix> do <body>
+prod <identifier> = <from> to <to> do <body>
+prod <identifier> = <from> to <to> by <increment> do <body>
+prod <identifier> in <matrix> do <body>
+
+   If you substitute for with sum or prod, then you will get a sum
+   or a product instead of a for loop. Instead of returning the
+   last value, these will return the sum or the product of the
+   values respectively.
+
+   If no body is executed (for example sum i=1 to 0 do ...) then
+   sum returns 0 and prod returns 1 as is the standard convention.
+     __________________________________________________________
+
+Comparison Operators
+
+   The following standard comparison operators are supported in
+   GEL and have the obvious meaning: ==, >=, <=, !=, <>, <, >.
+   They return true or false. The operators != and <> are the same
+   thing and mean "is not equal to". GEL also supports the
+   operator <=>, which returns -1 if left side is smaller, 0 if
+   both sides are equal, 1 if left side is larger.
+
+   Normally = is translated to == if it happens to be somewhere
+   where GEL is expecting a condition such as in the if condition.
+   For example
+if a=b then c
+if a==b then c
+
+   are the same thing in GEL. However you should really use == or
+   := when you want to compare or assign respectively if you want
+   your code to be easy to read and to avoid mistakes.
+
+   All the comparison operators (except for the <=> operator which
+   behaves normally), are not strictly binary operators, they can
+   in fact be grouped in the normal mathematical way, e.g.:
+   (1<x<=y<5) is a legal boolean expression and means just what it
+   should, that is (1<x and xây and y<5)
+
+   To build up logical expressions use the words not, and, or,
+   xor. The operators or and and are special beasts as they
+   evaluate their arguments one by one, so the usual trick for
+   conditional evaluation works here as well. For example, 1 or
+   a=1 will not set a=1 since the first argument was true.
+     __________________________________________________________
+
+Global Variables and Scope of Variables
+
+   GEL is a dynamically scoped language. We will explain what this
+   means below. That is, normal variables and functions are
+   dynamically scoped. The exception are parameter variables,
+   which are always global.
+
+   Like most programming languages, GEL has different types of
+   variables. Normally when a variable is defined in a function,
+   it is visible from that function and from all functions that
+   are called (all higher contexts). For example, suppose a
+   function f defines a variable a and then calls function g. Then
+   function g can reference a. But once f returns, the variable a
+   goes out of scope. For example, the following code will print
+   out 5. The function g cannot be called on the top level
+   (outside f as a will not be defined).
+function f() = (a:=5; g());
+function g() = print(a);
+f();
+
+   If you define a variable inside a function it will override any
+   variables defined in calling functions. For example, we modify
+   the above code and write:
+function f() = (a:=5; g());
+function g() = print(a);
+a:=10;
+f();
+
+   This code will still print out 5. But if you call g outside of
+   f then you will get a printout of 10. Note that setting a to 5
+   inside f does not change the value of a at the top (global)
+   level, so if you now check the value of a it will still be 10.
+
+   Function arguments are exactly like variables defined inside
+   the function, except that they are initialized with the value
+   that was passed to the function. Other than this point, they
+   are treated just like all other variables defined inside the
+   function.
+
+   Functions are treated exactly like variables. Hence you can
+   locally redefine functions. Normally (on the top level) you
+   cannot redefine protected variables and functions. But locally
+   you can do this. Consider the following session:
+genius> function f(x) = sin(x)^2
+= (`(x)=(sin(x)^2))
+genius> function f(x) = sin(x)^2
+= (`(x)=(sin(x)^2))
+genius> function g(x) = ((function sin(x)=x^10);f(x))
+= (`(x)=((sin:=(`(x)=(x^10)));f(x)))
+genius> g(10)
+= 1e20
+
+   Functions and variables defined at the top level are considered
+   global. They are visible from anywhere. As we said the
+   following function f will not change the value of a to 5.
+a=6;
+function f() = (a:=5);
+f();
+
+   Sometimes, however, it is necessary to set a global variable
+   from inside a function. When this behaviour is needed, use the
+   set function. Passing a string or a quoted identifier to this
+   function sets the variable globally (on the top level). For
+   example, to set a to the value 3 you could call:
+set(`a,3)
+
+   or:
+set("a",3)
+
+   The set function always sets the toplevel global. There is no
+   way to set a local variable in some function from a subroutine.
+   If this is required, must use passing by reference.
+
+   So to recap in a more technical language: Genius operates with
+   different numbered contexts. The top level is the context 0
+   (zero). Whenever a function is entered, the context is raised,
+   and when the function returns the context is lowered. A
+   function or a variable is always visible from all higher
+   numbered contexts. When a variable was defined in a lower
+   numbered context, then setting this variable has the effect of
+   creating a new local variable in the current context number and
+   this variable will now be visible from all higher numbered
+   contexts.
+
+   There are also true local variables, which are not seen from
+   anywhere but the current context. Also when returning functions
+   by value it may reference variables not visible from higher
+   context and this may be a problem. See the sections True Local
+   Variables and Returning Functions.
+     __________________________________________________________
+
+Parameter variables
+
+   As we said before, there exist special variables called
+   parameters that exist in all scopes. To declare a parameter
+   called foo with the initial value 1, we write
+parameter foo = 1
+
+   From then on, foo is a strictly global variable. Setting foo
+   inside any function will modify the variable in all contexts,
+   that is, functions do not have a private copy of parameters.
+
+   When you undefine a parameter using the undefine function, it
+   stops being a parameter.
+
+   Some parameters are built-in and modify the behaviour of
+   genius.
+     __________________________________________________________
+
+Returning
+
+   Normally a function is one or several expressions separated by
+   a semicolon, and the value of the last expression is returned.
+   This is fine for simple functions, but sometimes you do not
+   want a function to return the last thing calculated. You may,
+   for example, want to return from a middle of a function. In
+   this case, you can use the return keyword. return takes one
+   argument, which is the value to be returned.
+
+   Example:
+function f(x) = (
+  y=1;
+  while true do (
+    if x>50 then return y;
+    y=y+1;
+    x=x+1
+  )
+)
+     __________________________________________________________
+
+References
+
+   It may be necessary for some functions to return more than one
+   value. This may be accomplished by returning a vector of
+   values, but many times it is convenient to use passing a
+   reference to a variable. You pass a reference to a variable to
+   a function, and the function will set the variable for you
+   using a dereference. You do not have to use references only for
+   this purpose, but this is their main use.
+
+   When using functions that return values through references in
+   the argument list, just pass the variable name with an
+   ampersand. For example the following code will compute an
+   eigenvalue of a matrix A with initial eigenvector guess x, and
+   store the computed eigenvector into the variable named v:
+RayleighQuotientIteration (A,x,0.001,100,&v)
+
+   The details of how references work and the syntax is similar to
+   the C language. The operator & references a variable and *
+   dereferences a variable. Both can only be applied to an
+   identifier, so **a is not a legal expression in GEL.
+
+   References are best explained by an example:
+a=1;
+b=&a;
+*b=2;
+
+   now a contains 2. You can also reference functions:
+function f(x) = x+1;
+t=&f;
+*t(3)
+
+   gives us 4.
+     __________________________________________________________
+
+Lvalues
+
+   An lvalue is the left hand side of an assignment. In other
+   words, an lvalue is what you assign something to. Valid lvalues
+   are:
+
+   a
+          Identifier. Here we would be setting the variable of
+          name a.
+
+   *a
+          Dereference of an identifier. This will set whatever
+          variable a points to.
+
+   a@(<region>)
+          A region of a matrix. Here the region is specified
+          normally as with the regular @() operator, and can be a
+          single entry, or an entire region of the matrix.
+
+   Examples:
+a:=4
+*tmp := 89
+a@(1,1) := 5
+a@(4:8,3) := [1,2,3,4,5]'
+
+   Note that both := and = can be used interchangably. Except if
+   the assignment appears in a condition. It is thus always safer
+   to just use := when you mean assignment, and == when you mean
+   comparison.
+     __________________________________________________________
+
+Advanced Programming with GEL
+
+Error Handling
+
+   If you detect an error in your function, you can bail out of
+   it. For normal errors, such as wrong types of arguments, you
+   can fail to compute the function by adding the statement
+   bailout. If something went really wrong and you want to
+   completely kill the current computation, you can use exception.
+
+   For example if you want to check for arguments in your
+   function. You could use the following code.
+function f(M) = (
+  if not IsMatrix (M) then (
+    error ("M not a matrix!");
+    bailout
+  );
+  ...
+)
+     __________________________________________________________
+
+Toplevel Syntax
+
+   The synatax is slightly different if you enter statements on
+   the top level versus when they are inside parentheses or inside
+   functions. On the top level, enter acts the same as if you
+   press return on the command line. Therefore think of programs
+   as just sequence of lines as if were entered on the command
+   line. In particular, you do not need to enter the separator at
+   the end of the line (unless it is of course part of several
+   statements inside parentheses).
+
+   The following code will produce an error when entered on the
+   top level of a program, while it will work just fine in a
+   function.
+if Something() then
+  DoSomething()
+else
+  DoSomethingElse()
+
+   The problem is that after Genius Mathematics Tool sees the end
+   of line after the second line, it will decide that we have
+   whole statement and it will execute it. After the execution is
+   done, Genius Mathematics Tool will go on to the next line, it
+   will see else, and it will produce a parsing error. To fix
+   this, use parentheses. Genius Mathematics Tool will not be
+   satisfied until it has found that all parentheses are closed.
+if Something() then (
+  DoSomething()
+) else (
+  DoSomethingElse()
+)
+     __________________________________________________________
+
+Returning Functions
+
+   It is possible to return functions as value. This way you can
+   build functions that construct special purpose functions
+   according to some parameters. The tricky bit is what variables
+   does the function see. The way this works in GEL is that when a
+   function returns another function, all identifiers referenced
+   in the function body that went out of scope are prepended a
+   private dictionary of the returned function. So the function
+   will see all variables that were in scope when it was defined.
+   For example, we define a function that returns a function that
+   adds 5 to its argument.
+function f() = (
+  k = 5;
+  `(x) = (x+k)
+)
+
+   Notice that the function adds k to x. You could use this as
+   follows.
+g = f();
+g(5)
+
+   And g(5) should return 10.
+
+   One thing to note is that the value of k that is used is the
+   one that's in effect when the f returns. For example:
+function f() = (
+  k := 5;
+  function r(x) = (x+k);
+  k := 10;
+  r
+)
+
+   will return a function that adds 10 to its argument rather than
+   5. This is because the extra dictionary is created only when
+   the context in which the function was defined ends, which is
+   when the function f returns. This is consistent with how you
+   would expect the function r to work inside the function f
+   according to the rules of scope of variables in GEL. Only those
+   variables are added to the extra dictionary that are in the
+   context that just ended and no longer exists. Variables used in
+   the function that are in still valid contexts will work as
+   usual, using the current value of the variable. The only
+   difference is with global variables and functions. All
+   identifiers that referenced global variables at time of the
+   function definition are not added to the private dictionary.
+   This is to avoid much unnecessary work when returning functions
+   and would rarely be a problem. For example, suppose that you
+   delete the "k=5" from the function f, and at the top level you
+   define k to be say 5. Then when you run f, the function r will
+   not put k into the private dictionary because it was global
+   (toplevel) at the time of definition of r.
+
+   Sometimes it is better to have more control over how variables
+   are copied into the private dictionary. Since version 1.0.7,
+   you can specify which variables are copied into the private
+   dictionary by putting extra square brackets after the arguments
+   with the list of variables to be copied separated by commas. If
+   you do this, then variables are copied into the private
+   dictionary at time of the function definition, and the private
+   dictionary is not touched afterwards. For example
+function f() = (
+  k := 5;
+  function r(x) [k] = (x+k);
+  k := 10;
+  r
+)
+
+   will return a function that when called will add 5 to its
+   argument. The local copy of k was created when the function was
+   defined.
+
+   When you want the function to not have any private dictionary
+   when put empty square brackets after the argument list. Then no
+   private dictionary will be created at all. Doing this is good
+   to increase efficiency when a private dictionary is not needed
+   or when you want the function to lookup all variables as it
+   sees them when called. For example suppose you want the
+   function returned from f to see the value of k from the
+   toplevel despite there being a local variable of the same name
+   during definition. So the code
+function f() = (
+  k := 5;
+  function r(x) [] = (x+k);
+  r
+);
+k := 10;
+g = f();
+g(10)
+
+   will return 20 and not 15, which would happen if k with a value
+   of 5 was added to the private dictionary.
+     __________________________________________________________
+
+True Local Variables
+
+   When passing functions into other functions, the normal scoping
+   of variables might be undesired. For example:
+k := 10;
+function r(x) = (x+k);
+function f(g,x) = (
+  k := 5;
+  g(x)
+);
+f(r,1)
+
+   you probably want the function r when passed as g into f to see
+   k as 10 rather than 5, so that the code returns 11 and not 6.
+   However, as written, the function when executed will see the k
+   that is equal to 5. There are two ways to solve this. One would
+   be to have r get k in a private dictionary using the square
+   bracket notation section Returning Functions.
+
+   But there is another solution. Since version 1.0.7 there are
+   true local variables. These are variables that are visible only
+   from the current context and not from any called functions. We
+   could define k as a local variable in the function f. To do
+   this add a local statement as the first statement in the
+   function (it must always be the first statement in the
+   function). You can also make any arguments be local variables
+   as well. That is,
+function f(g,x) = (
+  local g,x,k;
+  k := 5;
+  g(x)
+);
+
+   Then the code will work as expected and prints out 11. Note
+   that the local statement initializes all the refereced
+   variables (except for function arguments) to a null.
+
+   If all variables are to be created as locals you can just pass
+   an asterix instead of a list of variables. In this case the
+   variables will not be initialized until they are actually set
+   of course. So the following definition of f will also work:
+function f(g,x) = (
+  local *;
+  k := 5;
+  g(x)
+);
+
+   It is good practice that all functions that take other
+   functions as arguments use local variables. This way the passed
+   function does not see implementation details and get confused.
+     __________________________________________________________
+
+GEL Startup Procedure
+
+   First the program looks for the installed library file (the
+   compiled version lib.cgel) in the installed directory, then it
+   looks into the current directory, and then it tries to load an
+   uncompiled file called ~/.geniusinit.
+
+   If you ever change the the library its installed place, youâll
+   have to first compile it with genius --compile loader.gel >
+   lib.cgel
+     __________________________________________________________
+
+Loading Programs
+
+   Sometimes you have a larger program that you wrote into a file
+   and want to read in that file. In these situations, you have
+   two options. You can keep the functions you use most inside the
+   ~/.geniusinit file. Or if you want to load up a file in a
+   middle of a session (or from within another file), you can type
+   load <list of filenames> at the prompt. This has to be done on
+   the top level and not inside any function or whatnot, and it
+   cannot be part of any expression. It also has a slightly
+   different syntax than the rest of genius, more similiar to a
+   shell. You can enter the file in quotes. If you use the ''
+   quotes, you will get exactly the string that you typed, if you
+   use the "" quotes, special characters will be unescaped as they
+   are for strings. Example:
+load program1.gel program2.gel
+load "Weird File Name With SPACES.gel"
+
+   There are also cd, pwd and ls commands built in. cd will take
+   one argument, ls will take an argument that is like the glob in
+   the unix shell (i.e., you can use wildcards). pwd takes no
+   arguments. For example:
+cd directory_with_gel_programs
+ls *.gel
+     __________________________________________________________
+
+Matrices in GEL
+
+   Genius has support for vectors and matrices and a sizable
+   library of matrix manipulation and linear algebra functions.
+     __________________________________________________________
+
+Entering Matrices
+
+   To enter matrixes, you can use one of the following two
+   syntaxes. You can either enter the matrix on one line,
+   separating values by commas and rows by semicolons. Or you can
+   enter each row on one line, separating values by commas. You
+   can also just combine the two methods. So to enter a 3x3 matrix
+   of numbers 1-9 you could do
+[1,2,3;4,5,6;7,8,9]
+
+   or
+[1, 2, 3
+ 4, 5, 6
+ 7, 8, 9]
+
+   Do not use both ';' and return at once on the same line though.
+
+   You can also use the matrix expansion functionality to enter
+   matricies. For example you can do:
+a = [ 1, 2, 3
+      4, 5, 6
+      7, 8, 9]
+b = [ a,  10
+      11, 12]
+
+   and you should get
+[1,   2,  3, 10
+ 4,   5,  6, 10
+ 7,   8,  9, 10
+ 11, 11, 11, 12]
+
+   similiarly you can build matricies out of vectors and other
+   stuff like that.
+
+   Another thing is that non-specified spots are initialized to 0,
+   so
+[1, 2, 3
+ 4, 5
+ 6]
+
+   will end up being
+[1, 2, 3
+ 4, 5, 0
+ 6, 0, 0]
+
+   When matrices are evaluated, they are evaluated and traversed
+   row-wise. This is just like the M@(j) operator which traverses
+   the matrix row-wise.
+
+   Note
+
+   Be careful about using returns for expressions inside the [ ]
+   brackets, as they have a slightly different meaning there. You
+   will start a new row.
+     __________________________________________________________
+
+Conjugate Transpose and Transpose Operator
+
+   You can conjugate transpose a matrix by using the ' operator.
+   That is the entry in the ith column and the jth row will be the
+   complex conjugate of the entry in the jth column and the ith
+   row of the original matrix. For example:
+[1,2,3]*[4,5,6]'
+
+   We transpose the second vector to make matrix multiplication
+   possible. If you just want to transpose a matrix without
+   conjugating it, you would use the .' operator. For example:
+[1,2,3]*[4,5,6i].'
+
+   Note that normal transpose, that is the .' operator, is much
+   faster and will not create a new copy of the matrix in memory.
+   The conjugate transpose does create a new copy unfortunately.
+   It is recommended to always use the .' operator when working
+   with real matrices and vectors.
+     __________________________________________________________
+
+Linear Algebra
+
+   Genius implements many useful linear algebra and matrix
+   manipulation routines. See the Linear Algebra and Matrix
+   Manipulation sections of the GEL function listing.
+
+   The linear algebra routines implemented in GEL do not currently
+   come from a well tested numerical package, and thus should not
+   be used for critical numerical computation. On the other hand,
+   Genius implements very well many linear algebra operations with
+   rational and integer coefficients. These are inherently exact
+   and in fact will give you much better results than common
+   double precision routines for linear algebra.
+
+   For example, it is pointless to compute the rank and nullspace
+   of a floating point matrix since for all practical purposes, we
+   need to consider the matrix as having some slight errors. You
+   are likely to get a different result than you expect. The
+   problem is that under a small perturbation every matrix is of
+   full rank and invertible. If the matrix however is of rational
+   numbers, then the rank and nullspace are always exact.
+
+   In general when Genius computes the basis of a certain
+   vectorspace (for example with the NullSpace) it will give the
+   basis as a matrix, in which the columns are the vectors of the
+   basis. That is, when Genius talks of a linear subspace it means
+   a matrix whose column space is the given linear subspace.
+
+   It should be noted that Genius can remember certain properties
+   of a matrix. For example, it will remember that a matrix is in
+   row reduced form. If many calls are made to functions that
+   internally use row reduced form of the matrix, we can just row
+   reduce the matrix beforehand once. Successive calls to rref
+   will be very fast.
+     __________________________________________________________
+
+Polynomials in GEL
+
+   Currently Genius can handle polynomials of one variable written
+   out as vectors, and do some basic operations with these. It is
+   planned to expand this support further.
+     __________________________________________________________
+
+Using Polynomials
+
+   Currently polynomials in one variable are just horizontal
+   vectors with value only nodes. The power of the term is the
+   position in the vector, with the first position being 0. So,
+[1,2,3]
+
+   translates to a polynomial of
+1 + 2*x + 3*x^2
+
+   You can add, subtract and multiply polynomials using the
+   AddPoly, SubtractPoly, and MultiplyPoly functions respectively.
+   You can print a polynomial using the PolyToString function. For
+   example,
+PolyToString([1,2,3],"y")
+
+   gives
+3*y^2 + 2*y + 1
+
+   You can also get a function representation of the polynomial so
+   that you can evaluate it. This is done by using PolyToFunction,
+   which returns an anonymous function.
+f = PolyToFunction([0,1,1])
+f(2)
+
+   It is also possible to find roots of polynomials of degrees 1
+   through 4 by using the function PolynomialRoots, which calls
+   the appropriate formula function. Higher degree polynomials
+   must be converted to functions and solved numerically using a
+   function such as FindRootBisection, FindRootFalsePosition,
+   FindRootMullersMethod, or FindRootSecant.
+
+   See the Section called Polynomials in the Chapter called List
+   of GEL functions in the function list for the rest of functions
+   acting on polynomials.
+     __________________________________________________________
+
+Set Theory in GEL
+
+   Genius has some basic set theoretic functionality built in.
+   Currently a set is just a vector (or a matrix). Every distinct
+   object is treated as a different element.
+     __________________________________________________________
+
+Using Sets
+
+   Just like vectors, objects in sets can include numbers,
+   strings, null, matrices and vectors. It is planned in the
+   future to have a dedicated type for sets, rather than using
+   vectors. Note that floating point numbers are distinct from
+   integers, even if they appear the same. That is, Genius will
+   treat 0 and 0.0 as two distinct elements. The null is treated
+   as an empty set.
+
+   To build a set out of a vector, use the MakeSet function.
+   Currently, it will just return a new vector where every element
+   is unique.
+genius> MakeSet([1,2,2,3])
+= [1, 2, 3]
+
+   Similarly there are functions Union, Intersection, SetMinus,
+   which are rather self explanatory. For example:
+genius> Union([1,2,3], [1,2,4])
+= [1, 2, 4, 3]
+
+   Note that no order is guaranteed for the return values. If you
+   wish to sort the vector you should use the SortVector function.
+
+   For testing membership, there are functions IsIn and IsSubset,
+   which return a boolean value. For example:
+genius> IsIn (1, [0,1,2])
+= true
+
+   The input IsIn(x,X) is of course equivalent to IsSubset([x],X).
+   Note that since the empty set is a subset of every set,
+   IsSubset(null,X) is always true.
+     __________________________________________________________
+
+List of GEL functions
+
+   To get help on a specific function from the console type:
+help FunctionName
+     __________________________________________________________
+
+Commands
+
+   help
+
+help
+
+help FunctionName
+
+          Print help (or help on a function/command).
+
+   load
+
+load "file.gel"
+
+          Load a file into the interpretor. The file will execute
+          as if it were typed onto the command line.
+
+   cd
+
+cd /directory/name
+
+          Change working directory to /directory/name.
+
+   pwd
+
+pwd
+
+          Print the current working directory.
+
+   ls
+
+ls
+
+          List files in the current directory.
+
+   plugin
+
+plugin plugin_name
+
+          Load a plugin. Plugin of that name must be installed on
+          the system in the proper directory.
+     __________________________________________________________
+
+Basic
+
+   AskButtons
+
+AskButtons (query)
+
+AskButtons (query, button1, ...)
+
+          Asks a question and presents a list of buttons to the
+          user (or a menu of options in text mode). Returns the
+          1-based index of the button pressed. That is, returns 1
+          if the first button was pressed, 2 if the second button
+          was pressed, and so on. If the user closes the window
+          (or simply hits enter in text mode), then null is
+          returned. The execution of the program is blocked until
+          the user responds.
+
+   AskString
+
+AskString (query)
+
+AskString (query, default)
+
+          Asks a question and lets the user enter a string which
+          it then returns. If the user cancels or closes the
+          window, then null is returned. The execution of the
+          program is blocked until the user responds. If default
+          is given, then it is pre-typed in for the user to just
+          press enter on.
+
+   Compose
+
+Compose (f,g)
+
+          Compose two functions and return a function that is the
+          composition of f and g.
+
+   ComposePower
+
+ComposePower (f,n,x)
+
+          Compose and execute a function with itself n times,
+          passing x as argument. Returning x if n equals 0.
+          Example:
+
+genius> function f(x) = x^2 ;
+genius> ComposePower (f,3,7)
+= 5764801
+genius> f(f(f(7)))
+= 5764801
+
+   Evaluate
+
+Evaluate (str)
+
+          Parses and evaluates a string.
+
+   GetCurrentModulo
+
+GetCurrentModulo
+
+          Get current modulo from the context outside the
+          function. That is, if outside of the function was
+          executed in modulo (using mod) then this returns what
+          this modulo was. Normally the body of the function
+          called is not executed in modular arithmetic, and this
+          builtin function makes it possible to make GEL functions
+          aware of modular arithmetic.
+
+   Identity
+
+Identity (x)
+
+          Identity function, returns its argument.
+
+   IntegerFromBoolean
+
+IntegerFromBoolean (bval)
+
+          Make integer (0 for false or 1 for true) from a boolean
+          value. bval can also be a number in which case a
+          non-zero value will be interpreted as true and zero will
+          be interpreted as false.
+
+   IsBoolean
+
+IsBoolean (arg)
+
+          Check if argument is a boolean (and not a number).
+
+   IsDefined
+
+IsDefined (id)
+
+          Check if an id is defined. You should pass a string or
+          and identifier. If you pass a matrix, each entry will be
+          evaluated separately and the matrix should contain
+          strings or identifiers.
+
+   IsFunction
+
+IsFunction (arg)
+
+          Check if argument is a function.
+
+   IsFunctionOrIdentifier
+
+IsFunctionOrIdentifier (arg)
+
+          Check if argument is a function or an identifier.
+
+   IsFunctionRef
+
+IsFunctionRef (arg)
+
+          Check if argument is a function reference. This includes
+          variable references.
+
+   IsMatrix
+
+IsMatrix (arg)
+
+          Check if argument is a matrix. Even though null is
+          sometimes considered an empty matrix, the function
+          IsMatrix does not consider null a matrix.
+
+   IsNull
+
+IsNull (arg)
+
+          Check if argument is a null.
+
+   IsString
+
+IsString (arg)
+
+          Check if argument is a text string.
+
+   IsValue
+
+IsValue (arg)
+
+          Check if argument is a number.
+
+   Parse
+
+Parse (str)
+
+          Parses but does not evaluate a string. Note that certain
+          pre-computation is done during the parsing stage.
+
+   SetFunctionFlags
+
+SetFunctionFlags (id,flags...)
+
+          Set flags for a function, currently "PropagateMod" and
+          "NoModuloArguments". If "PropagateMod" is set, then the
+          body of the function is evaluated in modular arithmetic
+          when the function is called inside a block that was
+          evaluated using modular arithmetic (using mod). If
+          "NoModuloArguments", then the arguments of the function
+          are never evaluated using modular arithmetic.
+
+   SetHelp
+
+SetHelp (id,category,desc)
+
+          Set the category and help description line for a
+          function.
+
+   SetHelpAlias
+
+SetHelpAlias (id,alias)
+
+          Sets up a help alias.
+
+   chdir
+
+chdir (dir)
+
+          Changes current directory, same as the cd.
+
+   display
+
+display (str,expr)
+
+          Display a string and an expression with a colon to
+          separate them.
+
+   error
+
+error (str)
+
+          Prints a string to the error stream (onto the console).
+
+   exit
+
+exit
+
+          Aliases: quit
+
+          Exits the program.
+
+   false
+
+false
+
+          Aliases: False FALSE
+
+          The false boolean value.
+
+   manual
+
+manual
+
+          Displays the user manual.
+
+   print
+
+print (str)
+
+          Prints an expression and then print a newline. The
+          argument str can be any expression. It is made into a
+          string before being printed.
+
+   printn
+
+printn (str)
+
+          Prints an expression without a trailing newline. The
+          argument str can be any expression. It is made into a
+          string before being printed.
+
+   protect
+
+protect (id)
+
+          Protect a variable from being modified. This is used on
+          the internal GEL functions to avoid them being
+          accidentally overridden.
+
+   ProtectAll
+
+ProtectAll ()
+
+          Protect all currently defined variables, parameters and
+          functions from being modified. This is used on the
+          internal GEL functions to avoid them being accidentally
+          overridden. Normally Genius Mathematics Tool considers
+          unprotected variables as user defined.
+
+   set
+
+set (id,val)
+
+          Set a global variable. The id can be either a string or
+          a quoted identifier as follows. For example:
+
+set(`x,1)
+
+          will set the global variable x to the value 1.
+
+   string
+
+string (s)
+
+          Make a string. This will make a string out of any
+          argument.
+
+   true
+
+true
+
+          Aliases: True TRUE
+
+          The true boolean value.
+
+   undefine
+
+undefine (id)
+
+          Alias: Undefine
+
+          Undefine a variable. This includes locals and globals,
+          every value on all context levels is wiped. This
+          function should really not be used on local variables. A
+          vector of identifiers can also be passed to undefine
+          several variables.
+
+   UndefineAll
+
+UndefineAll ()
+
+          Undefine all unprotected global variables (including
+          functions and parameters). Normally Genius Mathematics
+          Tool considers protected variables as system defined
+          functions and variables. Note that UndefineAll only
+          removes the global definition of symbols not local ones,
+          so that it may be run from inside other functions
+          safely.
+
+   unprotect
+
+unprotect (id)
+
+          Unprotect a variable from being modified.
+
+   UserVariables
+
+UserVariables ()
+
+          Return a vector of identifiers of user defined
+          (unprotected) global variables.
+
+   wait
+
+wait (secs)
+
+          Waits a specified number of seconds. secs must be
+          non-negative. Zero is accepted and nothing happens in
+          this case, except possibly user interface events are
+          processed.
+
+   version
+
+version
+
+          Returns the version of Genius as a horizontal 3-vector
+          with major version first, then minor version and finally
+          the patch level.
+
+   warranty
+
+warranty
+
+          Gives the warranty information.
+     __________________________________________________________
+
+Parameters
+
+   ChopTolerance
+
+ChopTolerance = number
+
+          Tolerance of the Chop function.
+
+   ContinuousNumberOfTries
+
+ContinuousNumberOfTries = number
+
+          How many iterations to try to find the limit for
+          continuity and limits.
+
+   ContinuousSFS
+
+ContinuousSFS = number
+
+          How many successive steps to be within tolerance for
+          calculation of continuity.
+
+   ContinuousTolerance
+
+ContinuousTolerance = number
+
+          Tolerance for continuity of functions and for
+          calculating the limit.
+
+   DerivativeNumberOfTries
+
+DerivativeNumberOfTries = number
+
+          How many iterations to try to find the limit for
+          derivative.
+
+   DerivativeSFS
+
+DerivativeSFS = number
+
+          How many successive steps to be within tolerance for
+          calculation of derivative.
+
+   DerivativeTolerance
+
+DerivativeTolerance = number
+
+          Tolerance for calculating the derivatives of functions.
+
+   ErrorFunctionTolerance
+
+ErrorFunctionTolerance = number
+
+          Tolerance of the ErrorFunction.
+
+   FloatPrecision
+
+FloatPrecision = number
+
+          Floating point precision.
+
+   FullExpressions
+
+FullExpressions = boolean
+
+          Print full expressions, even if more than a line.
+
+   GaussDistributionTolerance
+
+GaussDistributionTolerance = number
+
+          Tolerance of the GaussDistribution function.
+
+   IntegerOutputBase
+
+IntegerOutputBase = number
+
+          Integer output base.
+
+   IsPrimeMillerRabinReps
+
+IsPrimeMillerRabinReps = number
+
+          Number of extra Miller-Rabin tests to run on a number
+          before declaring it a prime in IsPrime.
+
+   LinePlotDrawLegends
+
+LinePlotDrawLegends = true
+
+          Tells genius to draw the legends for line plotting
+          functions such as LinePlot.
+
+   LinePlotVariableNames
+
+LinePlotVariableNames = ["x","y","z","t"]
+
+          Tells genius which variable names are used as default
+          names for line plotting functions such as LinePlot and
+          friends.
+
+   LinePlotWindow
+
+LinePlotWindow = [x1,x2,y1,y2]
+
+          Sets the limits for line plotting functions such as
+          LinePlot.
+
+   MaxDigits
+
+MaxDigits = number
+
+          Maximum digits to display.
+
+   MaxErrors
+
+MaxErrors = number
+
+          Maximum errors to display.
+
+   MixedFractions
+
+MixedFractions = boolean
+
+          If true, mixed fractions are printed.
+
+   NumericalIntegralFunction
+
+NumericalIntegralFunction = function
+
+          The function used for numerical integration in
+          NumericalIntegral.
+
+   NumericalIntegralSteps
+
+NumericalIntegralSteps = number
+
+          Steps to perform in NumericalIntegral.
+
+   OutputChopExponent
+
+OutputChopExponent = number
+
+          When another number in the object being printed (a
+          matrix or a value) is greater than
+          10^-OutputChopWhenExponent, and the number being printed
+          is less than 10^-OutputChopExponent, then display 0.0
+          instead of the number.
+
+          Output is never chopped if OutputChopExponent is zero.
+          It must be a non-negative integer.
+
+          If you want output always chopped according to
+          OutputChopExponent, then set OutputChopWhenExponent, to
+          something greater than or equal to OutputChopExponent.
+
+   OutputChopWhenExponent
+
+OutputChopWhenExponent = number
+
+          When to chop output. See OutputChopExponent.
+
+   OutputStyle
+
+OutputStyle = string
+
+          Output style, this can be normal, latex, mathml or
+          troff.
+
+          This affects mostly how matrices and fractions are
+          printed out and is useful for pasting into documents.
+          For example you can set this to the latex by:
+
+OutputStyle = "latex"
+
+   ResultsAsFloats
+
+ResultsAsFloats = boolean
+
+          Convert all results to floats before printing.
+
+   ScientificNotation
+
+ScientificNotation = boolean
+
+          Use scientific notation.
+
+   SlopefieldTicks
+
+SlopefieldTicks = [vertical,horizontal]
+
+          Sets the number of vertical and horizontal ticks in a
+          slopefield plot. (See SlopefieldPlot).
+
+   SumProductNumberOfTries
+
+SumProductNumberOfTries = number
+
+          How many iterations to try for InfiniteSum and
+          InfiniteProduct.
+
+   SumProductSFS
+
+SumProductSFS = number
+
+          How many successive steps to be within tolerance for
+          InfiniteSum and InfiniteProduct.
+
+   SumProductTolerance
+
+SumProductTolerance = number
+
+          Tolerance for InfiniteSum and InfiniteProduct.
+
+   SurfacePlotVariableNames
+
+SurfacePlotVariableNames = ["x","y","z"]
+
+          Tells genius which variable names are used as default
+          names for surface plotting functions using SurfacePlot.
+          Note that the z does not refer to the dependent
+          (vertical) axis, but to the indepent complex variable
+          z=x+iy.
+
+   SurfacePlotWindow
+
+SurfacePlotWindow = [x1,x2,y1,y2,z1,z2]
+
+          Sets the limits for surface plotting (See SurfacePlot).
+
+   VectorfieldNormalized
+
+VectorfieldNormalized = true
+
+          Should the vectorfield plotting have normalized arrow
+          length. If true, vector fields will only show direction
+          and not magnitude. (See VectorfieldPlot).
+
+   VectorfieldTicks
+
+VectorfieldTicks = [vertical,horizontal]
+
+          Sets the number of vertical and horizontal ticks in a
+          vectorfield plot. (See VectorfieldPlot).
+     __________________________________________________________
+
+Constants
+
+   CatalanConstant
+
+CatalanConstant
+
+          Catalan's Constant, approximately 0.915... It is defined
+          to be the series where terms are (-1^k)/((2*k+1)^2),
+          where k ranges from 0 to infinity.
+
+          See Mathworld for more information.
+
+   EulerConstant
+
+EulerConstant
+
+          Aliases: gamma
+
+          Euler's Constant gamma. Sometimes called the
+          Euler-Mascheroni constant.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   GoldenRatio
+
+GoldenRatio
+
+          The Golden Ratio.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   Gravity
+
+Gravity
+
+          Free fall acceleration at sea level.
+
+          See Wikipedia for more information.
+
+   e
+
+e
+
+          The base of the natural logarithm. e^x is the
+          exponential function exp. This is the number
+          approximately 2.71828182846...
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   pi
+
+pi
+
+          The number pi, that is the ratio of a circle's
+          circumference to its diameter. This is approximately
+          3.14159265359...
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+     __________________________________________________________
+
+Numeric
+
+   AbsoluteValue
+
+AbsoluteValue (x)
+
+          Aliases: abs
+
+          Absolute value of a number and if x is a complex value
+          the modulus of x. I.e. this the distance of x to the
+          origin.
+
+          See Wikipedia, Planetmath (absolute value), Planetmath
+          (modulus), Mathworld (absolute value) or Mathworld
+          (complex modulus) for more information.
+
+   Chop
+
+Chop (x)
+
+          Replace very small number with zero.
+
+   ComplexConjugate
+
+ComplexConjugate (z)
+
+          Aliases: conj Conj
+
+          Calculates the complex conjugate of the complex number
+          z. If z is a vector or matrix, all its elements are
+          conjugated.
+
+          See Wikipedia for more information.
+
+   Denominator
+
+Denominator (x)
+
+          Get the denominator of a rational number.
+
+          See Wikipedia for more information.
+
+   FractionalPart
+
+FractionalPart (x)
+
+          Return the fractional part of a number.
+
+          See Wikipedia for more information.
+
+   Im
+
+Im (z)
+
+          Aliases: ImaginaryPart
+
+          Get the imaginary part of a complex number.
+
+          See Wikipedia for more information.
+
+   IntegerQuotient
+
+IntegerQuotient (m,n)
+
+          Division without remainder.
+
+   IsComplex
+
+IsComplex (num)
+
+          Check if argument is a complex (non-real) number.
+
+   IsComplexRational
+
+IsComplexRational (num)
+
+          Check if argument is a possibly complex rational number.
+          That is, if both real and imaginary parts are given as
+          rational numbers. Of course rational simply means "not
+          stored as a floating point number."
+
+   IsFloat
+
+IsFloat (num)
+
+          Check if argument is a floating point number
+          (non-complex).
+
+   IsGaussInteger
+
+IsGaussInteger (num)
+
+          Aliases: IsComplexInteger
+
+          Check if argument is a possibly complex integer.
+
+   IsInteger
+
+IsInteger (num)
+
+          Check if argument is an integer (non-complex).
+
+   IsNonNegativeInteger
+
+IsNonNegativeInteger (num)
+
+          Check if argument is a non-negative real integer.
+
+   IsPositiveInteger
+
+IsPositiveInteger (num)
+
+          Aliases: IsNaturalNumber
+
+          Check if argument is a positive real integer. Note that
+          we accept the convention that 0 is not a natural number.
+
+   IsRational
+
+IsRational (num)
+
+          Check if argument is a rational number (non-complex). Of
+          course rational simply means "not stored as a floating
+          point number."
+
+   IsReal
+
+IsReal (num)
+
+          Check if argument is a real number.
+
+   Numerator
+
+Numerator (x)
+
+          Get the numerator of a rational number.
+
+          See Wikipedia for more information.
+
+   Re
+
+Re (z)
+
+          Aliases: RealPart
+
+          Get the real part of a complex number.
+
+          See Wikipedia for more information.
+
+   Sign
+
+Sign (x)
+
+          Aliases: sign
+
+          Return the sign of a number. That is returns -1 if value
+          is negative, 0 if value is zero and 1 if value is
+          positive. If x is a complex value then Sign returns the
+          direction or 0.
+
+   ceil
+
+ceil (x)
+
+          Aliases: Ceiling
+
+          Get the lowest integer more than or equal to n.
+
+   exp
+
+exp (x)
+
+          The exponential function. This is the function e^x where
+          e is the base of the natural logarithm.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   float
+
+float (x)
+
+          Make number a floating point value. That is returns the
+          floating point representation of the number x.
+
+   floor
+
+floor (x)
+
+          Aliases: Floor
+
+          Get the highest integer less than or equal to n.
+
+   ln
+
+ln (x)
+
+          The natural logarithm, the logarithm to base e.
+
+   log
+
+log (x)
+
+log (x,b)
+
+          Logarithm of x base b (calls DiscreteLog if in modulo
+          mode), if base is not given, e is used.
+
+   log10
+
+log10 (x)
+
+          Logarithm of x base 10.
+
+   log2
+
+log2 (x)
+
+          Aliases: lg
+
+          Logarithm of x base 2.
+
+   max
+
+max (a,args...)
+
+          Aliases: Max Maximum
+
+          Returns the maximum of arguments or matrix.
+
+   min
+
+min (a,args...)
+
+          Aliases: Min Minimum
+
+          Returns the minimum of arguments or matrix.
+
+   rand
+
+rand (size...)
+
+          Generate random float in the range [0,1). If size is
+          given then a matrix (if two numbers are specified) or
+          vector (if one number is specified) of the given size
+          returned.
+
+   randint
+
+randint (max,size...)
+
+          Generate random integer in the range [0,max). If size is
+          given then a matrix (if two numbers are specified) or
+          vector (if one number is specified) of the given size
+          returned. For example,
+
+genius> randint(4)
+= 3
+genius> randint(4,2)
+=
+[0      1]
+genius> randint(4,2,3)
+=
+[2      2       1
+ 0      0       3]
+
+   round
+
+round (x)
+
+          Aliases: Round
+
+          Round a number.
+
+   sqrt
+
+sqrt (x)
+
+          Aliases: SquareRoot
+
+          The square root. When operating modulo some integer will
+          return either a null or a vector of the square roots.
+          Examples:
+
+genius> sqrt(2)
+= 1.41421356237
+genius> sqrt(-1)
+= 1i
+genius> sqrt(4) mod 7
+=
+[2      5]
+genius> 2*2 mod 7
+= 4
+
+          See Planetmath for more information.
+
+   trunc
+
+trunc (x)
+
+          Aliases: Truncate IntegerPart
+
+          Truncate number to an integer (return the integer part).
+     __________________________________________________________
+
+Trigonometry
+
+   acos
+
+acos (x)
+
+          Aliases: arccos
+
+          The arccos (inverse cos) function.
+
+   acosh
+
+acosh (x)
+
+          Aliases: arccosh
+
+          The arccosh (inverse cosh) function.
+
+   acot
+
+acot (x)
+
+          Aliases: arccot
+
+          The arccot (inverse cot) function.
+
+   acoth
+
+acoth (x)
+
+          Aliases: arccoth
+
+          The arccoth (inverse coth) function.
+
+   acsc
+
+acsc (x)
+
+          Aliases: arccsc
+
+          The inverse cosecant function.
+
+   acsch
+
+acsch (x)
+
+          Aliases: arccsch
+
+          The inverse hyperbolic cosecant function.
+
+   asec
+
+asec (x)
+
+          Aliases: arcsec
+
+          The inverse secant function.
+
+   asech
+
+asech (x)
+
+          Aliases: arcsech
+
+          The inverse hyperbolic secant function.
+
+   asin
+
+asin (x)
+
+          Aliases: arcsin
+
+          The arcsin (inverse sin) function.
+
+   asinh
+
+asinh (x)
+
+          Aliases: arcsinh
+
+          The arcsinh (inverse sinh) function.
+
+   atan
+
+atan (x)
+
+          Aliases: arctan
+
+          Calculates the arctan (inverse tan) function.
+
+          See Wikipedia or Mathworld for more information.
+
+   atanh
+
+atanh (x)
+
+          Aliases: arctanh
+
+          The arctanh (inverse tanh) function.
+
+   atan2
+
+atan2 (y, x)
+
+          Aliases: arctan2
+
+          Calculates the arctan2 function. If x>0 then it returns
+          atan(y/x). If x<0 then it returns sign(y) * (pi -
+          atan(|y/x|). When x=0 it returns sign(y) * pi/2.
+          atan2(0,0) returns 0 rather then failing.
+
+          See Wikipedia or Mathworld for more information.
+
+   cos
+
+cos (x)
+
+          Calculates the cosine function.
+
+          See Planetmath for more information.
+
+   cosh
+
+cosh (x)
+
+          Calculates the hyperbolic cosine function.
+
+          See Planetmath for more information.
+
+   cot
+
+cot (x)
+
+          The cotangent function.
+
+          See Planetmath for more information.
+
+   coth
+
+coth (x)
+
+          The hyperbolic cotangent function.
+
+          See Planetmath for more information.
+
+   csc
+
+csc (x)
+
+          The cosecant function.
+
+          See Planetmath for more information.
+
+   csch
+
+csch (x)
+
+          The hyperbolic cosecant function.
+
+          See Planetmath for more information.
+
+   sec
+
+sec (x)
+
+          The secant function.
+
+          See Planetmath for more information.
+
+   sech
+
+sech (x)
+
+          The hyperbolic secant function.
+
+          See Planetmath for more information.
+
+   sin
+
+sin (x)
+
+          Calculates the sine function.
+
+          See Planetmath for more information.
+
+   sinh
+
+sinh (x)
+
+          Calculates the hyperbolic sine function.
+
+          See Planetmath for more information.
+
+   tan
+
+tan (x)
+
+          Calculates the tan function.
+
+          See Planetmath for more information.
+
+   tanh
+
+tanh (x)
+
+          The hyperbolic tangent function.
+
+          See Planetmath for more information.
+     __________________________________________________________
+
+Number Theory
+
+   AreRelativelyPrime
+
+AreRelativelyPrime (a,b)
+
+          Are the real integers a and b relatively prime? Returns
+          true or false.
+
+          See Planetmath or Mathworld for more information.
+
+   BernoulliNumber
+
+BernoulliNumber (n)
+
+          Return the nth Bernoulli number.
+
+          See Wikipedia or Mathworld for more information.
+
+   ChineseRemainder
+
+ChineseRemainder (a,m)
+
+          Aliases: CRT
+
+          Find the x that solves the system given by the vector a
+          and modulo the elements of m, using the Chinese
+          Remainder Theorem.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   CombineFactorizations
+
+CombineFactorizations (a,b)
+
+          Given two factorizations, give the factorization of the
+          product.
+
+          See Factorize.
+
+   ConvertFromBase
+
+ConvertFromBase (v,b)
+
+          Convert a vector of values indicating powers of b to a
+          number.
+
+   ConvertToBase
+
+ConvertToBase (n,b)
+
+          Convert a number to a vector of powers for elements in
+          base b.
+
+   DiscreteLog
+
+DiscreteLog (n,b,q)
+
+          Find discrete log of n base b in F[q], the finite field
+          of order q, where q is a prime, using the
+          Silver-Pohlig-Hellman algorithm.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   Divides
+
+Divides (m,n)
+
+          Checks divisibility (if m divides n).
+
+   EulerPhi
+
+EulerPhi (n)
+
+          Compute the Euler phi function for n, that is the number
+          of integers between 1 and n relatively prime to n.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   ExactDivision
+
+ExactDivision (n,d)
+
+          Return n/d but only if d divides n. If d does not divide
+          n then this function returns garbage. This is a lot
+          faster for very large numbers than the operation n/d,
+          but of course only useful if you know that the division
+          is exact.
+
+   Factorize
+
+Factorize (n)
+
+          Return factorization of a number as a matrix. The first
+          row is the primes in the factorization (including 1) and
+          the second row are the powers. So for example:
+
+genius> Factorize(11*11*13)
+=
+[1      11      13
+ 1      2       1]
+
+          See Wikipedia for more information.
+
+   Factors
+
+Factors (n)
+
+          Return all factors of n in a vector. This includes all
+          the non-prime factors as well. It includes 1 and the
+          number itself. So for example to print all the perfect
+          numbers (those that are sums of their factors) up to the
+          number 1000 you could do (this is of course very
+          inefficient)
+
+for n=1 to 1000 do (
+    if MatrixSum (Factors(n)) == 2*n then
+        print(n)
+)
+
+   FermatFactorization
+
+FermatFactorization (n,tries)
+
+          Attempt fermat factorization of n into (t-s)*(t+s),
+          returns t and s as a vector if possible, null otherwise.
+          tries specifies the number of tries before giving up.
+
+          This is a fairly good factorization if your number is
+          the product of two factors that are very close to each
+          other.
+
+          See Wikipedia for more information.
+
+   FindPrimitiveElementMod
+
+FindPrimitiveElementMod (q)
+
+          Find the first primitive element in F[q], the finite
+          group of order q. Of course q must be a prime.
+
+   FindRandomPrimitiveElementMod
+
+FindRandomPrimitiveElementMod (q)
+
+          Find a random primitive element in F[q], the finite
+          group of order q (q must be a prime).
+
+   IndexCalculus
+
+IndexCalculus (n,b,q,S)
+
+          Compute discrete log base b of n in F[q], the finite
+          group of order q (q a prime), using the factor base S. S
+          should be a column of primes possibly with second column
+          precalculated by IndexCalculusPrecalculation.
+
+   IndexCalculusPrecalculation
+
+IndexCalculusPrecalculation (b,q,S)
+
+          Run the precalculation step of IndexCalculus for
+          logarithms base b in F[q], the finite group of order q
+          (q a prime), for the factor base S (where S is a column
+          vector of primes). The logs will be precalculated and
+          returned in the second column.
+
+   IsEven
+
+IsEven (n)
+
+          Tests if an integer is even.
+
+   IsMersennePrimeExponent
+
+IsMersennePrimeExponent (p)
+
+          Tests if a positive integer p is a Mersenne prime
+          exponent. That is if 2^p-1 is a prime. It does this by
+          looking it up in a table of known values which is
+          relatively short. See also MersennePrimeExponents and
+          LucasLehmer.
+
+          See Wikipedia, Planetmath, Mathworld or GIMPS for more
+          information.
+
+   IsNthPower
+
+IsNthPower (m,n)
+
+          Tests if a rational number m is a perfect nth power. See
+          also IsPerfectPower and IsPerfectSquare.
+
+   IsOdd
+
+IsOdd (n)
+
+          Tests if an integer is odd.
+
+   IsPerfectPower
+
+IsPerfectPower (n)
+
+          Check an integer is any perfect power, a^b.
+
+   IsPerfectSquare
+
+IsPerfectSquare (n)
+
+          Check an integer for being a perfect square of an
+          integer. The number must be a real integer. Negative
+          integers are of course never perfect squares of real
+          integers.
+
+   IsPrime
+
+IsPrime (n)
+
+          Tests primality of integers, for numbers less than
+          2.5e10 the answer is deterministic (if Riemann
+          hypothesis is true). For numbers larger, the probability
+          of a false positive depends on IsPrimeMillerRabinReps.
+          That is the probability of false positive is 1/4 to the
+          power IsPrimeMillerRabinReps. The default value of 22
+          yields a probability of about 5.7e-14.
+
+          If false is returned, you can be sure that the number is
+          a composite. If you want to be absolutely sure that you
+          have a prime you can use MillerRabinTestSure but it may
+          take a lot longer.
+
+          See Planetmath or Mathworld for more information.
+
+   IsPrimitiveMod
+
+IsPrimitiveMod (g,q)
+
+          Check if g is primitive in F[q], the finite group of
+          order q, where q is a prime. If q is not prime results
+          are bogus.
+
+   IsPrimitiveModWithPrimeFactors
+
+IsPrimitiveModWithPrimeFactors (g,q,f)
+
+          Check if g is primitive in F[q], the finite group of
+          order q, where q is a prime and f is a vector of prime
+          factors of q-1. If q is not prime results are bogus.
+
+   IsPseudoprime
+
+IsPseudoprime (n,b)
+
+          If n is a pseudoprime base b but not a prime, that is if
+          b^(n-1) == 1 mod n. This calles the PseudoprimeTest
+
+   IsStrongPseudoprime
+
+IsStrongPseudoprime (n,b)
+
+          Test if n is a strong pseudoprime to base b but not a
+          prime.
+
+   Jacobi
+
+Jacobi (a,b)
+
+          Aliases: JacobiSymbol
+
+          Calculate the Jacobi symbol (a/b) (b should be odd).
+
+   JacobiKronecker
+
+JacobiKronecker (a,b)
+
+          Aliases: JacobiKroneckerSymbol
+
+          Calculate the Jacobi symbol (a/b) with the Kronecker
+          extension (a/2)=(2/a) when a odd, or (a/2)=0 when a
+          even.
+
+   LeastAbsoluteResidue
+
+LeastAbsoluteResidue (a,n)
+
+          Return the residue of a mod n with the least absolute
+          value (in the interval -n/2 to n/2).
+
+   Legendre
+
+Legendre (a,p)
+
+          Aliases: LegendreSymbol
+
+          Calculate the Legendre symbol (a/p).
+
+          See Planetmath or Mathworld for more information.
+
+   LucasLehmer
+
+LucasLehmer (p)
+
+          Test if 2^p-1 is a Mersenne prime using the Lucas-Lehmer
+          test. See also MersennePrimeExponents and
+          IsMersennePrimeExponent.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   LucasNumber
+
+LucasNumber (n)
+
+          Returns the nth Lucas number.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   MaximalPrimePowerFactors
+
+MaximalPrimePowerFactors (n)
+
+          Return all maximal prime power factors of a number.
+
+   MersennePrimeExponents
+
+MersennePrimeExponents
+
+          A vector of known Mersenne prime exponents, that is a
+          list of positive integers p such that 2^p-1 is a prime.
+          See also IsMersennePrimeExponent and LucasLehmer.
+
+          See Wikipedia, Planetmath, Mathworld or GIMPS for more
+          information.
+
+   MillerRabinTest
+
+MillerRabinTest (n,reps)
+
+          Use the Miller-Rabin primality test on n, reps number of
+          times. The probability of false positive is (1/4)^reps.
+          It is probably usually better to use IsPrime since that
+          is faster and better on smaller integers.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   MillerRabinTestSure
+
+MillerRabinTestSure (n)
+
+          Use the Miller-Rabin primality test on n with enough
+          bases that assuming the Generalized Reimann Hypothesis
+          the result is deterministic.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   ModInvert
+
+ModInvert (n,m)
+
+          Returns inverse of n mod m.
+
+          See Mathworld for more information.
+
+   MoebiusMu
+
+MoebiusMu (n)
+
+          Return the Moebius mu function evaluated in n. That is,
+          it returns 0 if n is not a product of distinct primes
+          and (-1)^k if it is a product of k distinct primes.
+
+          See Planetmath or Mathworld for more information.
+
+   NextPrime
+
+NextPrime (n)
+
+          Returns the least prime greater than n. Negatives of
+          primes are considered prime and so to get the previous
+          prime you can use -NextPrime(-n).
+
+          This function uses the GMP's mpz_nextprime which in turn
+          uses the probabilistic Miller-Rabin test (See also
+          MillerRabinTest). The probability of false positive is
+          not tunable, but is low enough for all practical
+          purposes.
+
+          See Planetmath or Mathworld for more information.
+
+   PadicValuation
+
+PadicValuation (n,p)
+
+          Returns the p-adic valuation (number of trailing zeros
+          in base p).
+
+          See Planetmath for more information.
+
+   PowerMod
+
+PowerMod (a,b,m)
+
+          Compute a^b mod m. The b's power of a modulo m. It is
+          not neccessary to use this function as it is
+          automatically used in modulo mode. Hence a^b mod m is
+          just as fast.
+
+   Prime
+
+Prime (n)
+
+          Aliases: prime
+
+          Return the nth prime (up to a limit).
+
+          See Planetmath or Mathworld for more information.
+
+   PrimeFactors
+
+PrimeFactors (n)
+
+          Return all prime factors of a number as a vector.
+
+          See Mathworld for more information.
+
+   PseudoprimeTest
+
+PseudoprimeTest (n,b)
+
+          Pseudoprime test, returns true if and only if b^(n-1) ==
+          1 mod n
+
+          See Planetmath or Mathworld for more information.
+
+   RemoveFactor
+
+RemoveFactor (n,m)
+
+          Removes all instances of the factor m from the number n.
+          That is divides by the largest power of m, that divides
+          n.
+
+          See Planetmath or Mathworld for more information.
+
+   SilverPohligHellmanWithFactorization
+
+SilverPohligHellmanWithFactorization (n,b,q,f)
+
+          Find discrete log of n base b in F[q], the finite group
+          of order q, where q is a prime using the
+          Silver-Pohlig-Hellman algorithm, given f being the
+          factorization of q-1.
+
+   SqrtModPrime
+
+SqrtModPrime (n,p)
+
+          Find square root of n modulo p (where p is a prime).
+          Null is returned if not a quadratic residue.
+
+          See Planetmath or Mathworld for more information.
+
+   StrongPseudoprimeTest
+
+StrongPseudoprimeTest (n,b)
+
+          Run the strong pseudoprime test base b on n.
+
+          See Planetmath or Mathworld for more information.
+
+   gcd
+
+gcd (a,args...)
+
+          Aliases: GCD
+
+          Greatest common divisor of integers. You can enter as
+          many integers in the argument list, or you can give a
+          vector or a matrix of integers. If you give more than
+          one matrix of the same size then GCD is done element by
+          element.
+
+          See Planetmath or Mathworld for more information.
+
+   lcm
+
+lcm (a,args...)
+
+          Aliases: LCM
+
+          Least common multiplier of integers. You can enter as
+          many integers in the argument list, or you can give a
+          vector or a matrix of integers. If you give more than
+          one matrix of the same size then LCM is done element by
+          element.
+
+          See Planetmath or Mathworld for more information.
+     __________________________________________________________
+
+Matrix Manipulation
+
+   ApplyOverMatrix
+
+ApplyOverMatrix (a,func)
+
+          Apply a function over all entries of a matrix and return
+          a matrix of the results.
+
+   ApplyOverMatrix2
+
+ApplyOverMatrix2 (a,b,func)
+
+          Apply a function over all entries of 2 matrices (or 1
+          value and 1 matrix) and return a matrix of the results.
+
+   ColumnsOf
+
+ColumnsOf (M)
+
+          Gets the columns of a matrix as a horizontal vector.
+
+   ComplementSubmatrix
+
+ComplementSubmatrix (m,r,c)
+
+          Remove column(s) and row(s) from a matrix.
+
+   CompoundMatrix
+
+CompoundMatrix (k,A)
+
+          Calculate the kth compound matrix of A.
+
+   CountZeroColumns
+
+CountZeroColumns (M)
+
+          Count the number of zero columns in a matrix. For
+          example Once you column reduce a matrix you can use this
+          to find the nullity. See cref and Nullity.
+
+   DeleteColumn
+
+DeleteColumn (M,col)
+
+          Delete a column of a matrix.
+
+   DeleteRow
+
+DeleteRow (M,row)
+
+          Delete a row of a matrix.
+
+   DiagonalOf
+
+DiagonalOf (M)
+
+          Gets the diagonal entries of a matrix as a column
+          vector.
+
+          See Wikipedia for more information.
+
+   DotProduct
+
+DotProduct (u,v)
+
+          Get the dot product of two vectors. The vectors must be
+          of the same size. No conjugates are taken so this is a
+          bilinear form even if working over the complex numbers.
+
+          See Planetmath for more information.
+
+   ExpandMatrix
+
+ExpandMatrix (M)
+
+          Expands a matrix just like we do on unquoted matrix
+          input. That is we expand any internal matrices as
+          blocks. This is a way to construct matrices out of
+          smaller ones and this is normally done automatically on
+          input unless the matrix is quoted.
+
+   HermitianProduct
+
+HermitianProduct (u,v)
+
+          Aliases: InnerProduct
+
+          Get the Hermitian product of two vectors. The vectors
+          must be of the same size. This is a sesquilinear form
+          using the identity matrix.
+
+          See Mathworld for more information.
+
+   I
+
+I (n)
+
+          Aliases: eye
+
+          Return an identity matrix of a given size, that is n by
+          n. If n is zero, returns null.
+
+          See Planetmath for more information.
+
+   IndexComplement
+
+IndexComplement (vec,msize)
+
+          Return the index complement of a vector of indexes.
+          Everything is one based. For example for vector [2,3]
+          and size 5, we return [1,4,5]. If msize is 0, we always
+          return null.
+
+   IsDiagonal
+
+IsDiagonal (M)
+
+          Is a matrix diagonal.
+
+          See Wikipedia or Planetmath for more information.
+
+   IsIdentity
+
+IsIdentity (x)
+
+          Check if a matrix is the identity matrix. Automatically
+          returns false if the matrix is not square. Also works on
+          numbers, in which case it is equivalent to x==1. When x
+          is null (we could think of that as a 0 by 0 matrix), no
+          error is generated and false is returned.
+
+   IsLowerTriangular
+
+IsLowerTriangular (M)
+
+          Is a matrix lower triangular. That is, are all the
+          entries above the diagonal zero.
+
+   IsMatrixInteger
+
+IsMatrixInteger (M)
+
+          Check if a matrix is a matrix of an integers
+          (non-complex).
+
+   IsMatrixNonnegative
+
+IsMatrixNonnegative (M)
+
+          Check if a matrix is non-negative, that is if each
+          element is non-negative. Do not confuse positive
+          matrices with positive semi-definite matrices.
+
+          See Wikipedia for more information.
+
+   IsMatrixPositive
+
+IsMatrixPositive (M)
+
+          Check if a matrix is positive, that is if each element
+          is positive (and hence real). In particular, no element
+          is 0. Do not confuse positive matrices with positive
+          definite matrices.
+
+          See Wikipedia for more information.
+
+   IsMatrixRational
+
+IsMatrixRational (M)
+
+          Check if a matrix is a matrix of rational (non-complex)
+          numbers.
+
+   IsMatrixReal
+
+IsMatrixReal (M)
+
+          Check if a matrix is a matrix of real (non-complex)
+          numbers.
+
+   IsMatrixSquare
+
+IsMatrixSquare (M)
+
+          Check if a matrix is square, that is its width is equal
+          to its height.
+
+   IsUpperTriangular
+
+IsUpperTriangular (M)
+
+          Is a matrix upper triangular? That is, a matrix is upper
+          triangular if all all the entries below the diagonal are
+          zero.
+
+   IsValueOnly
+
+IsValueOnly (M)
+
+          Check if a matrix is a matrix of numbers only. Many
+          internal functions make this check. Values can be any
+          number including complex numbers.
+
+   IsVector
+
+IsVector (v)
+
+          Is argument a horizontal or a vertical vector. Genius
+          does not distinguish between a matrix and a vector and a
+          vector is just a 1 by n or n by 1 matrix.
+
+   IsZero
+
+IsZero (x)
+
+          Check if a matrix is composed of all zeros. Also works
+          on numbers, in which case it is equivalent to x==0. When
+          x is null (we could think of that as a 0 by 0 matrix),
+          no error is generated and true is returned as the
+          condition is vacuous.
+
+   LowerTriangular
+
+LowerTriangular (M)
+
+          Returns a copy of the matrix M with all the entries
+          above the diagonal set to zero.
+
+   MakeDiagonal
+
+MakeDiagonal (v,arg...)
+
+          Aliases: diag
+
+          Make diagonal matrix from a vector.
+
+          See Wikipedia or Planetmath for more information.
+
+   MakeVector
+
+MakeVector (A)
+
+          Make column vector out of matrix by putting columns
+          above each other. Returns null when given null.
+
+   MatrixProduct
+
+MatrixProduct (A)
+
+          Calculate the product of all elements in a matrix or
+          vector. That is we multiply all the elements and return
+          a number that is the product of all the elements.
+
+   MatrixSum
+
+MatrixSum (A)
+
+          Calculate the sum of all elements in a matrix or vector.
+          That is we add all the elements and return a number that
+          is the sum of all the elements.
+
+   MatrixSumSquares
+
+MatrixSumSquares (A)
+
+          Calculate the sum of squares of all elements in a matrix
+          or vector.
+
+   OuterProduct
+
+OuterProduct (u,v)
+
+          Get the outer product of two vectors. That is, suppose
+          that u and v are vertical vectors, then the outer
+          product is v * u.'.
+
+   ReverseVector
+
+ReverseVector (v)
+
+          Reverse elements in a vector. Return null if given null
+
+   RowSum
+
+RowSum (m)
+
+          Calculate sum of each row in a matrix and return a
+          vertical vector with the result.
+
+   RowSumSquares
+
+RowSumSquares (m)
+
+          Calculate sum of squares of each row in a matrix.
+
+   RowsOf
+
+RowsOf (M)
+
+          Gets the rows of a matrix as a vertical vector. Each
+          element of the vector is a horizontal vector which is
+          the corresponding row of M. This function is useful if
+          you wish to loop over the rows of a matrix. For example,
+          as for r in RowsOf(M) do something(r).
+
+   SetMatrixSize
+
+SetMatrixSize (M,rows,columns)
+
+          Make new matrix of given size from old one. That is, a
+          new matrix will be returned to which the old one is
+          copied. Entries that don't fit are clipped and extra
+          space is filled with zeros. if rows or columns are zero
+          then null is returned.
+
+   ShuffleVector
+
+ShuffleVector (v)
+
+          Shuffle elements in a vector. Return null if given null
+
+   SortVector
+
+SortVector (v)
+
+          Sort vector elements in an increasing order.
+
+   StripZeroColumns
+
+StripZeroColumns (M)
+
+          Removes any all-zero columns of M.
+
+   StripZeroRows
+
+StripZeroRows (M)
+
+          Removes any all-zero rows of M.
+
+   Submatrix
+
+Submatrix (m,r,c)
+
+          Return column(s) and row(s) from a matrix. This is just
+          equivalent to m@(r,c). r and c should be vectors of rows
+          and columns (or single numbers if only one row or column
+          is needed).
+
+   SwapRows
+
+SwapRows (m,row1,row2)
+
+          Swap two rows in a matrix.
+
+   UpperTriangular
+
+UpperTriangular (M)
+
+          Returns a copy of the matrix M with all the entries
+          below the diagonal set to zero.
+
+   columns
+
+columns (M)
+
+          Get the number of columns of a matrix.
+
+   elements
+
+elements (M)
+
+          Get the total number of elements of a matrix. This is
+          the number of columns times the number of rows.
+
+   ones
+
+ones (rows,columns...)
+
+          Make an matrix of all ones (or a row vector if only one
+          argument is given). Returns null if either rows or
+          columns are zero.
+
+   rows
+
+rows (M)
+
+          Get the number of rows of a matrix.
+
+   zeros
+
+zeros (rows,columns...)
+
+          Make a matrix of all zeros (or a row vector if only one
+          argument is given). Returns null if either rows or
+          columns are zero.
+     __________________________________________________________
+
+Linear Algebra
+
+   AuxiliaryUnitMatrix
+
+AuxiliaryUnitMatrix (n)
+
+          Get the auxiliary unit matrix of size n. This is a
+          square matrix matrix with that is all zero except the
+          superdiagonal being all ones. It is the Jordan block
+          matrix of one zero eigenvalue.
+
+          See Planetmath or Mathworld for more information on
+          Jordan Cannonical Form.
+
+   BilinearForm
+
+BilinearForm (v,A,w)
+
+          Evaluate (v,w) with respect to the bilinear form given
+          by the matrix A.
+
+   BilinearFormFunction
+
+BilinearFormFunction (A)
+
+          Return a function that evaluates two vectors with
+          respect to the bilinear form given by A.
+
+   CharacteristicPolynomial
+
+CharacteristicPolynomial (M)
+
+          Aliases: CharPoly
+
+          Get the characteristic polynomial as a vector. That is,
+          return the coefficients of the polynomial starting with
+          the constant term. This is the polynomial defined by
+          det(M-xI). The roots of this polynomial are the
+          eigenvalues of M. See also
+          CharacteristicPolynomialFunction.
+
+          See Planetmath for more information.
+
+   CharacteristicPolynomialFunction
+
+CharacteristicPolynomialFunction (M)
+
+          Get the characteristic polynomial as a function. This is
+          the polynomial defined by det(M-xI). The roots of this
+          polynomial are the eigenvalues of M. See also
+          CharacteristicPolynomial.
+
+          See Planetmath for more information.
+
+   ColumnSpace
+
+ColumnSpace (M)
+
+          Get a basis matrix for the columnspace of a matrix. That
+          is, return a matrix whose columns are the basis for the
+          column space of M. That is the space spanned by the
+          columns of M.
+
+   CommutationMatrix
+
+CommutationMatrix (m, n)
+
+          Return the commutation matrix K(m,n) which is the unique
+          m*n by m*n matrix such that K(m,n) * MakeVector(A) =
+          MakeVector(A.') for all m by n matrices A.
+
+   CompanionMatrix
+
+CompanionMatrix (p)
+
+          Companion matrix of a polynomial (as vector).
+
+   ConjugateTranspose
+
+ConjugateTranspose (M)
+
+          Conjugate transpose of a matrix (adjoint). This is the
+          same as the ' operator.
+
+          See Planetmath for more information.
+
+   Convolution
+
+Convolution (a,b)
+
+          Aliases: convol
+
+          Calculate convolution of two horizontal vectors.
+
+   ConvolutionVector
+
+ConvolutionVector (a,b)
+
+          Calculate convolution of two horizontal vectors. Return
+          result as a vector and not added together.
+
+   CrossProduct
+
+CrossProduct (v,w)
+
+          CrossProduct of two vectors in R^3 as a column vector.
+
+   DeterminantalDivisorsInteger
+
+DeterminantalDivisorsInteger (M)
+
+          Get the determinantal divisors of an integer matrix (not
+          its characteristic).
+
+   DirectSum
+
+DirectSum (M,N...)
+
+          Direct sum of matrices.
+
+   DirectSumMatrixVector
+
+DirectSumMatrixVector (v)
+
+          Direct sum of a vector of matrices.
+
+   Eigenvalues
+
+Eigenvalues (M)
+
+          Aliases: eig
+
+          Get the eigenvalues of a square matrix. Currently only
+          works for matrices of size up to 4 by 4, or for
+          triangular matrices (for which the eigenvalues are on
+          the diagonal).
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   Eigenvectors
+
+Eigenvectors (M)
+
+Eigenvectors (M, &eigenvalues)
+
+Eigenvectors (M, &eigenvalues, &multiplicities)
+
+          Get the eigenvectors of a square matrix. Optionally get
+          also the eigenvalues and their algebraic multiplicities.
+          Currently only works for matrices of size up to 2 by 2.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   GramSchmidt
+
+GramSchmidt (v,B...)
+
+          Apply the Gram-Schmidt process (to the columns) with
+          respect to inner product given by B. If B is not given
+          then the standard Hermitian product is used. B can
+          either be a sesquilinear function of two arguments or it
+          can be a matrix giving a sesquilinear form. The vectors
+          will be made orthonormal with respect to B.
+
+          See Planetmath for more information.
+
+   HankelMatrix
+
+HankelMatrix (c,r)
+
+          Hankel matrix.
+
+   HilbertMatrix
+
+HilbertMatrix (n)
+
+          Hilbert matrix of order n.
+
+          See Planetmath for more information.
+
+   Image
+
+Image (T)
+
+          Get the image (columnspace) of a linear transform.
+
+   InfNorm
+
+InfNorm (v)
+
+          Get the Inf Norm of a vector, sometimes called the sup
+          norm or the max norm.
+
+   InvariantFactorsInteger
+
+InvariantFactorsInteger (M)
+
+          Get the invariant factors of a square integer matrix
+          (not its characteristic).
+
+   InverseHilbertMatrix
+
+InverseHilbertMatrix (n)
+
+          Inverse Hilbert matrix of order n.
+
+          See Planetmath for more information.
+
+   IsHermitian
+
+IsHermitian (M)
+
+          Is a matrix Hermitian. That is, is it equal to its
+          conjugate transpose.
+
+          See Planetmath for more information.
+
+   IsInSubspace
+
+IsInSubspace (v,W)
+
+          Test if a vector is in a subspace.
+
+   IsInvertible
+
+IsInvertible (n)
+
+          Is a matrix (or number) invertible (Integer matrix is
+          invertible iff it's invertible over the integers).
+
+   IsInvertibleField
+
+IsInvertibleField (n)
+
+          Is a matrix (or number) invertible over a field.
+
+   IsNormal
+
+IsNormal (M)
+
+          Is M a normal matrix. That is, does M*M' == M'*M.
+
+          See Planetmath or Mathworld for more information.
+
+   IsPositiveDefinite
+
+IsPositiveDefinite (M)
+
+          Is M a Hermitian positive definite matrix. That is if
+          HermitianProduct(M*v,v) is always strictly positive for
+          any vector v. M must be square and Hermitian to be
+          positive definite. The check that is performed is that
+          every principal submatrix has a non-negative
+          determinant. (See HermitianProduct)
+
+          Note that some authors (for example Mathworld) do not
+          require that M be Hermitian, and then the condition is
+          on the real part of the inner product, but we do not
+          take this view. If you wish to perform this check, just
+          check the Hermitian part of the matrix M as follows:
+          IsPositiveDefinite(M+M').
+
+          See Planetmath or Mathworld for more information.
+
+   IsPositiveSemidefinite
+
+IsPositiveSemidefinite (M)
+
+          Is M a Hermitian positive semidefinite matrix. That is
+          if HermitianProduct(M*v,v) is always non-negative for
+          any vector v. M must be square and Hermitian to be
+          positive semidefinite. The check that is performed is
+          that every principal submatrix has a non-negative
+          determinant. (See HermitianProduct)
+
+          Note that some authors do not require that M be
+          Hermitian, and then the condition is on the real part of
+          the inner product, but we do not take this view. If you
+          wish to perform this check, just check the Hermitian
+          part of the matrix M as follows:
+          IsPositiveSemidefinite(M+M').
+
+          See Planetmath or Mathworld for more information.
+
+   IsSkewHermitian
+
+IsSkewHermitian (M)
+
+          Is a matrix skew-Hermitian. That is, is the conjugate
+          transpose equal to negative of the matrix.
+
+          See Planetmath for more information.
+
+   IsUnitary
+
+IsUnitary (M)
+
+          Is a matrix unitary? That is, does M'*M and M*M' equal
+          the identity.
+
+          See Planetmath or Mathworld for more information.
+
+   JordanBlock
+
+JordanBlock (n,lambda)
+
+          Aliases: J
+
+          Get the Jordan block corresponding to the eigenvalue
+          lambda with multiplicity n.
+
+          See Planetmath or Mathworld for more information.
+
+   Kernel
+
+Kernel (T)
+
+          Get the kernel (nullspace) of a linear transform.
+
+          (See NullSpace)
+
+   LUDecomposition
+
+LUDecomposition (A, L, U)
+
+          Get the LU decomposition of A and store the result in
+          the L and U which should be references. It returns true
+          if successful. For example suppose that A is a square
+          matrix, then after running:
+
+genius> LUDecomposition(A,&L,&U)
+
+          You will have the lower matrix stored in a variable
+          called L and the upper matrix in a variable called U.
+
+          This is the LU decomposition of a matrix aka Crout
+          and/or Cholesky reduction. (ISBN 0-201-11577-8
+          pp.99-103) The upper triangular matrix features a
+          diagonal of values 1 (one). This is not Doolittle's
+          Method which features the 1's diagonal on the lower
+          matrix.
+
+          Not all matrices have LU decompositions, for example
+          [0,1;1,0] does not and this function returns false in
+          this case and sets L and U to null.
+
+          See Planetmath or Mathworld for more information.
+
+   Minor
+
+Minor (M,i,j)
+
+          Get the i-j minor of a matrix.
+
+          See Planetmath for more information.
+
+   NonPivotColumns
+
+NonPivotColumns (M)
+
+          Return the columns that are not the pivot columns of a
+          matrix.
+
+   Norm
+
+Norm (v,p...)
+
+          Aliases: norm
+
+          Get the p Norm (or 2 Norm if no p is supplied) of a
+          vector.
+
+   NullSpace
+
+NullSpace (T)
+
+          Get the nullspace of a matrix. That is the kernel of the
+          linear mapping that the matrix represents. This is
+          returned as a matrix whose column space is the nullspace
+          of T.
+
+          See Planetmath for more information.
+
+   Nullity
+
+Nullity (M)
+
+          Aliases: nullity
+
+          Get the nullity of a matrix. That is, return the
+          dimension of the nullspace; the dimension of the kernel
+          of M.
+
+          See Planetmath for more information.
+
+   OrthogonalComplement
+
+OrthogonalComplement (M)
+
+          Get the orthogonal complement of the columnspace.
+
+   PivotColumns
+
+PivotColumns (M)
+
+          Return pivot columns of a matrix, that is columns which
+          have a leading 1 in row reduced form. Also returns the
+          row where they occur.
+
+   Projection
+
+Projection (v,W,B...)
+
+          Projection of vector v onto subspace W with respect to
+          inner product given by B. If B is not given then the
+          standard Hermitian product is used. B can either be a
+          sesquilinear function of two arguments or it can be a
+          matrix giving a sesquilinear form.
+
+   QRDecomposition
+
+QRDecomposition (A, Q)
+
+          Get the QR decomposition of a square matrix A, returns
+          the upper triangular matrix R and sets Q to the
+          orthogonal (unitary) matrix. Q should be a reference or
+          null if you don't want any return. For example:
+
+genius> R = QRDecomposition(A,&Q)
+
+          You will have the upper triangular matrix stored in a
+          variable called R and the orthogonal (unitary) matrix
+          stored in Q.
+
+          See Planetmath or Mathworld for more information.
+
+   RayleighQuotient
+
+RayleighQuotient (A,x)
+
+          Return the Rayleigh quotient (also called the
+          Rayleigh-Ritz quotient or ratio) of a matrix and a
+          vector.
+
+          See Planetmath for more information.
+
+   RayleighQuotientIteration
+
+RayleighQuotientIteration (A,x,epsilon,maxiter,vecref)
+
+          Find eigenvalues of A using the Rayleigh quotient
+          iteration method. x is a guess at a eigenvector and
+          could be random. It should have nonzero imaginary part
+          if it will have any chance at finding complex
+          eigenvalues. The code will run at most maxiter
+          iterations and return null if we cannot get within an
+          error of epsilon. vecref should either be null or a
+          reference to a variable where the eigenvector should be
+          stored.
+
+          See Planetmath for more information on Rayleigh
+          quotient.
+
+   Rank
+
+Rank (M)
+
+          Aliases: rank
+
+          Get the rank of a matrix.
+
+          See Planetmath for more information.
+
+   RosserMatrix
+
+RosserMatrix ()
+
+          Rosser matrix, a classic symmetric eigenvalue test
+          problem.
+
+   Rotation2D
+
+Rotation2D (angle)
+
+          Aliases: RotationMatrix
+
+          Return the matrix corresponding to rotation around
+          origin in R^2.
+
+   Rotation3DX
+
+Rotation3DX (angle)
+
+          Return the matrix corresponding to rotation around
+          origin in R^3 about the x-axis.
+
+   Rotation3DY
+
+Rotation3DY (angle)
+
+          Return the matrix corresponding to rotation around
+          origin in R^3 about the y-axis.
+
+   Rotation3DZ
+
+Rotation3DZ (angle)
+
+          Return the matrix corresponding to rotation around
+          origin in R^3 about the z-axis.
+
+   RowSpace
+
+RowSpace (M)
+
+          Get a basis matrix for the rowspace of a matrix.
+
+   SesquilinearForm
+
+SesquilinearForm (v,A,w)
+
+          Evaluate (v,w) with respect to the sesquilinear form
+          given by the matrix A.
+
+   SesquilinearFormFunction
+
+SesquilinearFormFunction (A)
+
+          Return a function that evaluates two vectors with
+          respect to the sesquilinear form given by A.
+
+   SmithNormalFormField
+
+SmithNormalFormField (A)
+
+          Smith Normal Form for fields (will end up with 1's on
+          the diagonal).
+
+   SmithNormalFormInteger
+
+SmithNormalFormInteger (M)
+
+          Smith Normal Form for square integer matrices (not its
+          characteristic).
+
+   SolveLinearSystem
+
+SolveLinearSystem (M,V,args...)
+
+          Solve linear system Mx=V, return solution V if there is
+          a unique solution, null otherwise. Extra two reference
+          parameters can optionally be used to get the reduced M
+          and V.
+
+   ToeplitzMatrix
+
+ToeplitzMatrix (c, r...)
+
+          Return the Toeplitz matrix constructed given the first
+          column c and (optionally) the first row r. If only the
+          column c is given then it is conjugated and the
+          nonconjugated version is used for the first row to give
+          a Hermitian matrix (if the first element is real of
+          course).
+
+          See Planetmath for more information.
+
+   Trace
+
+Trace (M)
+
+          Aliases: trace
+
+          Calculate the trace of a matrix. That is the sum of the
+          diagonal elements.
+
+          See Planetmath for more information.
+
+   Transpose
+
+Transpose (M)
+
+          Transpose of a matrix. This is the same as the .'
+          operator.
+
+          See Planetmath for more information.
+
+   VandermondeMatrix
+
+VandermondeMatrix (v)
+
+          Aliases: vander
+
+          Return the Vandermonde matrix.
+
+   VectorAngle
+
+VectorAngle (v,w,B...)
+
+          The angle of two vectors with respect to inner product
+          given by B. If B is not given then the standard
+          Hermitian product is used. B can either be a
+          sesquilinear function of two arguments or it can be a
+          matrix giving a sesquilinear form.
+
+   VectorSpaceDirectSum
+
+VectorSpaceDirectSum (M,N)
+
+          The direct sum of the vector spaces M and N.
+
+   VectorSubspaceIntersection
+
+VectorSubspaceIntersection (M,N)
+
+          Intersection of the subspaces given by M and N.
+
+   VectorSubspaceSum
+
+VectorSubspaceSum (M,N)
+
+          The sum of the vector spaces M and N, that is {w |
+          w=m+n, m in M, n in N}.
+
+   adj
+
+adj (m)
+
+          Aliases: Adjugate
+
+          Get the classical adjoint (adjugate) of a matrix.
+
+   cref
+
+cref (M)
+
+          Aliases: CREF ColumnReducedEchelonForm
+
+          Compute the Column Reduced Echelon Form.
+
+   det
+
+det (M)
+
+          Aliases: Determinant
+
+          Get the determinant of a matrix.
+
+          See Wikipedia or Planetmath for more information.
+
+   ref
+
+ref (M)
+
+          Aliases: REF RowEchelonForm
+
+          Get the row echelon form of a matrix. That is, apply
+          gaussian elimination but not backaddition to M. The
+          pivot rows are divided to make all pivots 1.
+
+          See Wikipedia or Planetmath for more information.
+
+   rref
+
+rref (M)
+
+          Aliases: RREF ReducedRowEchelonForm
+
+          Get the reduced row echelon form of a matrix. That is,
+          apply gaussian elimination together with backaddition to
+          M.
+
+          See Wikipedia or Planetmath for more information.
+     __________________________________________________________
+
+Combinatorics
+
+   Catalan
+
+Catalan (n)
+
+          Get n'th catalan number.
+
+          See Planetmath for more information.
+
+   Combinations
+
+Combinations (k,n)
+
+          Get all combinations of k numbers from 1 to n as a
+          vector of vectors. (See also NextCombination)
+
+   DoubleFactorial
+
+DoubleFactorial (n)
+
+          Double factorial: n(n-2)(n-4)...
+
+          See Planetmath for more information.
+
+   Factorial
+
+Factorial (n)
+
+          Factorial: n(n-1)(n-2)...
+
+          See Planetmath for more information.
+
+   FallingFactorial
+
+FallingFactorial (n,k)
+
+          Falling factorial: (n)_k = n(n-1)...(n-(k-1))
+
+          See Planetmath for more information.
+
+   Fibonacci
+
+Fibonacci (x)
+
+          Aliases: fib
+
+          Calculate nth Fibonacci number. That is the number
+          defined recursively by Fibonacci(n) = Fibonacci(n-1) +
+          Fibonacci(n-2) and Fibonacci(1) = Fibonacci(2) = 1.
+
+          See Wikipedia or Planetmath or Mathworld for more
+          information.
+
+   FrobeniusNumber
+
+FrobeniusNumber (v,arg...)
+
+          Calculate the Frobenius number. That is calculate
+          smallest number that cannot be given as a non-negative
+          integer linear combination of a given vector of
+          non-negative integers. The vector can be given as
+          separate numbers or a single vector. All the numbers
+          given should have GCD of 1.
+
+          See Mathworld for more information.
+
+   GaloisMatrix
+
+GaloisMatrix (combining_rule)
+
+          Galois matrix given a linear combining rule
+          (a_1*x_+...+a_n*x_n=x_(n+1)).
+
+   GreedyAlgorithm
+
+FrobeniusNumber (n,v)
+
+          Find the vector c of non-negative integers such that
+          taking the dot product with v is equal to n. If not
+          possible returns null. v should be given sorted in
+          increasing order and should consist of non-negative
+          integers.
+
+          See Mathworld for more information.
+
+   HarmonicNumber
+
+HarmonicNumber (n,r)
+
+          Aliases: HarmonicH
+
+          Harmonic Number, the n'th harmonic number of order r.
+
+   Hofstadter
+
+Hofstadter (n)
+
+          Hofstadter's function q(n) defined by q(1)=1, q(2)=1,
+          q(n)=q(n-q(n-1))+q(n-q(n-2)).
+
+   LinearRecursiveSequence
+
+LinearRecursiveSequence (seed_values,combining_rule,n)
+
+          Compute linear recursive sequence using galois stepping.
+
+   Multinomial
+
+Multinomial (v,arg...)
+
+          Calculate multinomial coefficients. Takes a vector of k
+          non-negative integers and computes the multinomial
+          coefficient. This corresponds to the coefficient in the
+          homogeneous polynomial in k variables with the
+          corresponding powers.
+
+          The formula for Multinomial(a,b,c) can be written as:
+
+(a+b+c)! / (a!b!c!)
+
+          In other words, if we would have only two elements, then
+          Multinomial(a,b) is the same thing as Binomial(a+b,a) or
+          Binomial(a+b,b).
+
+          See Planetmath, Mathworld, or Wikipedia for more
+          information.
+
+   NextCombination
+
+NextCombination (v,n)
+
+          Get combination that would come after v in call to
+          combinations, first combination should be [1:k]. This
+          function is useful if you have many combinations to go
+          through and you don't want to waste memory to store them
+          all.
+
+          For example with Combination you would normally write a
+          loop like:
+
+for n in Combinations (4,6) do (
+  SomeFunction (n)
+);
+
+          But with NextCombination you would write something like:
+
+n:=[1:4];
+do (
+  SomeFunction (n)
+) while not IsNull(n:=NextCombination(n,6));
+
+          See also Combinations.
+
+   Pascal
+
+Pascal (i)
+
+          Get the Pascal's triangle as a matrix. This will return
+          an i+1 by i+1 lower diagonal matrix which is the
+          Pascal's triangle after i iterations.
+
+          See Planetmath for more information.
+
+   Permutations
+
+Permutations (k,n)
+
+          Get all permutations of k numbers from 1 to n as a
+          vector of vectors.
+
+          See Mathworld or Wikipedia for more information.
+
+   RisingFactorial
+
+RisingFactorial (n,k)
+
+          Aliases: Pochhammer
+
+          (Pochhammer) Rising factorial: (n)_k =
+          n(n+1)...(n+(k-1)).
+
+          See Planetmath for more information.
+
+   StirlingNumberFirst
+
+StirlingNumberFirst (n,m)
+
+          Aliases: StirlingS1
+
+          Stirling number of the first kind.
+
+          See Planetmath or Mathworld for more information.
+
+   StirlingNumberSecond
+
+StirlingNumberSecond (n,m)
+
+          Aliases: StirlingS2
+
+          Stirling number of the second kind.
+
+          See Planetmath or Mathworld for more information.
+
+   Subfactorial
+
+Subfactorial (n)
+
+          Subfactorial: n! times sum_{k=1}^n (-1)^k/k!.
+
+   Triangular
+
+Triangular (nth)
+
+          Calculate the n'th triangular number.
+
+          See Planetmath for more information.
+
+   nCr
+
+nCr (n,r)
+
+          Aliases: Binomial
+
+          Calculate combinations, that is, the binomial
+          coefficient. n can be any real number.
+
+          See Planetmath for more information.
+
+   nPr
+
+nPr (n,r)
+
+          Calculate the number of permutations of size rof numbers
+          from 1 to n.
+
+          See Mathworld or Wikipedia for more information.
+     __________________________________________________________
+
+Calculus
+
+   CompositeSimpsonsRule
+
+CompositeSimpsonsRule (f,a,b,n)
+
+          Integration of f by Composite Simpson's Rule on the
+          interval [a,b] with n subintervals with error of
+          max(f'''')*h^4*(b-a)/180, note that n should be even.
+
+          See Planetmath for more information.
+
+   CompositeSimpsonsRuleTolerance
+
+CompositeSimpsonsRuleTolerance (f,a,b,FourthDerivativeBound,Tolerance)
+
+          Integration of f by Composite Simpson's Rule on the
+          interval [a,b] with the number of steps calculated by
+          the fourth derivative bound and the desired tolerance.
+
+          See Planetmath for more information.
+
+   Derivative
+
+Derivative (f,x0)
+
+          Attempt to calculate derivative by trying first
+          symbolically and then numerically.
+
+   EvenPeriodicExtension
+
+EvenPeriodicExtension (f,L)
+
+          Return a function which is even periodic extension of f
+          with half period L. That is a function defined on the
+          interval [0,L] extended to be even on [-L,L] and then
+          extended to be periodic with period 2*L.
+
+          See also OddPeriodicExtension and PeriodicExtension.
+
+   FourierSeriesFunction
+
+FourierSeriesFunction (a,b,L)
+
+          Return a function which is a Fourier series with the
+          coefficients given by the vectors a (sines) and b
+          (cosines). Note that a@(1) is the constant coefficient!
+          That is, a@(n) refers to the term cos(x*(n-1)*pi/L),
+          while b@(n) refers to the term sin(x*n*pi/L). Either a
+          or b can be null.
+
+          See Wikipedia or Mathworld for more information.
+
+   InfiniteProduct
+
+InfiniteProduct (func,start,inc)
+
+          Try to calculate an infinite product for a single
+          parameter function.
+
+   InfiniteProduct2
+
+InfiniteProduct2 (func,arg,start,inc)
+
+          Try to calculate an infinite product for a double
+          parameter function with func(arg,n).
+
+   InfiniteSum
+
+InfiniteSum (func,start,inc)
+
+          Try to calculate an infinite sum for a single parameter
+          function.
+
+   InfiniteSum2
+
+InfiniteSum2 (func,arg,start,inc)
+
+          Try to calculate an infinite sum for a double parameter
+          function with func(arg,n).
+
+   IsContinuous
+
+IsContinuous (f,x0)
+
+          Try and see if a real-valued function is continuous at
+          x0 by calculating the limit there.
+
+   IsDifferentiable
+
+IsDifferentiable (f,x0)
+
+          Test for differentiability by approximating the left and
+          right limits and comparing.
+
+   LeftLimit
+
+LeftLimit (f,x0)
+
+          Calculate the left limit of a real-valued function at
+          x0.
+
+   Limit
+
+Limit (f,x0)
+
+          Calculate the limit of a real-valued function at x0.
+          Tries to calculate both left and right limits.
+
+   MidpointRule
+
+MidpointRule (f,a,b,n)
+
+          Integration by midpoint rule.
+
+   NumericalDerivative
+
+NumericalDerivative (f,x0)
+
+          Aliases: NDerivative
+
+          Attempt to calculate numerical derivative.
+
+   NumericalFourierSeriesCoefficients
+
+NumericalFourierSeriesCoefficients (f,L,N)
+
+          Return a vector of vectors [a,b] where a are the cosine
+          coefficients and b are the sine coefficients of the
+          Fourier series of f with half-period L (that is defined
+          on [-L,L] and extended periodically) with coefficients
+          up to Nth harmonic computed numerically. The
+          coefficients are computed by numerical integration using
+          NumericalIntegral.
+
+          See Wikipedia or Mathworld for more information.
+
+   NumericalFourierSeriesFunction
+
+NumericalFourierSeriesFunction (f,L,N)
+
+          Return a function which is the Fourier series of f with
+          half-period L (that is defined on [-L,L] and extended
+          periodically) with coefficients up to Nth harmonic
+          computed numerically. This is the trigonometric real
+          series composed of sines and cosines. The coefficients
+          are computed by numerical integration using
+          NumericalIntegral.
+
+          See Wikipedia or Mathworld for more information.
+
+   NumericalFourierCosineSeriesCoefficients
+
+NumericalFourierCosineSeriesCoefficients (f,L,N)
+
+          Return a vector of coefficients of the the cosine
+          Fourier series of f with half-period L. That is, we take
+          f defined on [0,L] take the even periodic extension and
+          compute the Fourier series, which only has sine terms.
+          The series is computed up to the Nth harmonic. The
+          coefficients are computed by numerical integration using
+          NumericalIntegral. Note that a@(1) is the constant
+          coefficient! That is, a@(n) refers to the term
+          cos(x*(n-1)*pi/L).
+
+          See Wikipedia or Mathworld for more information.
+
+   NumericalFourierCosineSeriesFunction
+
+NumericalFourierCosineSeriesFunction (f,L,N)
+
+          Return a function which is the cosine Fourier series of
+          f with half-period L. That is, we take f defined on
+          [0,L] take the even periodic extension and compute the
+          Fourier series, which only has cosine terms. The series
+          is computed up to the Nth harmonic. The coefficients are
+          computed by numerical integration using
+          NumericalIntegral.
+
+          See Wikipedia or Mathworld for more information.
+
+   NumericalFourierSineSeriesCoefficients
+
+NumericalFourierSineSeriesCoefficients (f,L,N)
+
+          Return a vector of coefficients of the the sine Fourier
+          series of f with half-period L. That is, we take f
+          defined on [0,L] take the odd periodic extension and
+          compute the Fourier series, which only has sine terms.
+          The series is computed up to the Nth harmonic. The
+          coefficients are computed by numerical integration using
+          NumericalIntegral.
+
+          See Wikipedia or Mathworld for more information.
+
+   NumericalFourierSineSeriesFunction
+
+NumericalFourierSineSeriesFunction (f,L,N)
+
+          Return a function which is the sine Fourier series of f
+          with half-period L. That is, we take f defined on [0,L]
+          take the odd periodic extension and compute the Fourier
+          series, which only has sine terms. The series is
+          computed up to the Nth harmonic. The coefficients are
+          computed by numerical integration using
+          NumericalIntegral.
+
+          See Wikipedia or Mathworld for more information.
+
+   NumericalIntegral
+
+NumericalIntegral (f,a,b)
+
+          Integration by rule set in NumericalIntegralFunction of
+          f from a to b using NumericalIntegralSteps steps.
+
+   NumericalLeftDerivative
+
+NumericalLeftDerivative (f,x0)
+
+          Attempt to calculate numerical left derivative.
+
+   NumericalLimitAtInfinity
+
+NumericalLimitAtInfinity (_f,step_fun,tolerance,successive_for_success,N
+)
+
+          Attempt to calculate the limit of f(step_fun(i)) as i
+          goes from 1 to N.
+
+   NumericalRightDerivative
+
+NumericalRightDerivative (f,x0)
+
+          Attempt to calculate numerical right derivative.
+
+   OddPeriodicExtension
+
+OddPeriodicExtension (f,L)
+
+          Return a function which is odd periodic extension of f
+          with half period L. That is a function defined on the
+          interval [0,L] extended to be odd on [-L,L] and then
+          extended to be periodic with period 2*L.
+
+          See also EvenPeriodicExtension and PeriodicExtension.
+
+   OneSidedFivePointFormula
+
+OneSidedFivePointFormula (f,x0,h)
+
+          Compute one-sided derivative using five point formula.
+
+   OneSidedThreePointFormula
+
+OneSidedThreePointFormula (f,x0,h)
+
+          Compute one-sided derivative using three-point formula.
+
+   PeriodicExtension
+
+PeriodicExtension (f,a,b)
+
+          Return a function which is the periodic extension of f
+          defined on the interval [a,b] and has period b-a.
+
+          See also OddPeriodicExtension and EvenPeriodicExtension.
+
+   RightLimit
+
+RightLimit (f,x0)
+
+          Calculate the right limit of a real-valued function at
+          x0.
+
+   TwoSidedFivePointFormula
+
+TwoSidedFivePointFormula (f,x0,h)
+
+          Compute two-sided derivative using five-point formula.
+
+   TwoSidedThreePointFormula
+
+TwoSidedThreePointFormula (f,x0,h)
+
+          Compute two-sided derivative using three-point formula.
+     __________________________________________________________
+
+Functions
+
+   Argument
+
+Argument (z)
+
+          Aliases: Arg arg
+
+          argument (angle) of complex number.
+
+   DirichletKernel
+
+DirichletKernel (n,t)
+
+          Dirichlet kernel of order n.
+
+   DiscreteDelta
+
+DiscreteDelta (v)
+
+          Returns 1 iff all elements are zero.
+
+   ErrorFunction
+
+ErrorFunction (x)
+
+          Aliases: erf
+
+          The error function, 2/sqrt(pi) * int_0^x e^(-t^2) dt.
+
+          See Planetmath for more information.
+
+   FejerKernel
+
+FejerKernel (n,t)
+
+          Fejer kernel of order n evaluated at t
+
+          See Planetmath for more information.
+
+   GammaFunction
+
+GammaFunction (x)
+
+          Aliases: Gamma
+
+          The Gamma function. Currently only implemented for real
+          values.
+
+          See Planetmath for more information.
+
+   KroneckerDelta
+
+KroneckerDelta (v)
+
+          Returns 1 iff all elements are equal.
+
+   MinimizeFunction
+
+MinimizeFunction (func,x,incr)
+
+          Find the first value where f(x)=0.
+
+   MoebiusDiskMapping
+
+MoebiusDiskMapping (a,z)
+
+          Moebius mapping of the disk to itself mapping a to 0.
+
+          See Planetmath for more information.
+
+   MoebiusMapping
+
+MoebiusMapping (z,z2,z3,z4)
+
+          Moebius mapping using the cross ratio taking z2,z3,z4 to
+          1,0, and infinity respectively.
+
+          See Planetmath for more information.
+
+   MoebiusMappingInftyToInfty
+
+MoebiusMappingInftyToInfty (z,z2,z3)
+
+          Moebius mapping using the cross ratio taking infinity to
+          infinity and z2,z3 to 1 and 0 respectively.
+
+          See Planetmath for more information.
+
+   MoebiusMappingInftyToOne
+
+MoebiusMappingInftyToOne (z,z3,z4)
+
+          Moebius mapping using the cross ratio taking infinity to
+          1 and z3,z4 to 0 and infinity respectively.
+
+          See Planetmath for more information.
+
+   MoebiusMappingInftyToZero
+
+MoebiusMappingInftyToZero (z,z2,z4)
+
+          Moebius mapping using the cross ratio taking infinity to
+          0 and z2,z4 to 1 and infinity respectively.
+
+          See Planetmath for more information.
+
+   PoissonKernel
+
+PoissonKernel (r,sigma)
+
+          Poisson kernel on D(0,1) (not normalized to 1, that is
+          integral of this is 2pi).
+
+   PoissonKernelRadius
+
+PoissonKernelRadius (r,sigma)
+
+          Poisson kernel on D(0,R) (not normalized to 1).
+
+   RiemannZeta
+
+RiemannZeta (x)
+
+          Aliases: zeta
+
+          The Riemann zeta function. Currently only implemented
+          for real values.
+
+          See Planetmath for more information.
+
+   UnitStep
+
+UnitStep (x)
+
+          The unit step function is 0 for x<0, 1 otherwise. This
+          is the integral of the Dirac Delta function. Also called
+          the Heaviside function.
+
+          See Wikipedia for more information.
+
+   cis
+
+cis (x)
+
+          The cis function, that is the same as cos(x)+1i*sin(x)
+
+   deg2rad
+
+deg2rad (x)
+
+          Convert degrees to radians.
+
+   rad2deg
+
+rad2deg (x)
+
+          Convert radians to degrees.
+     __________________________________________________________
+
+Equation Solving
+
+   CubicFormula
+
+CubicFormula (p)
+
+          Compute roots of a cubic (degree 3) polynomial using the
+          cubic formula. The polynomial should be given as a
+          vector of coefficients. That is 4*x^3 + 2*x + 1
+          corresponds to the vector [1,2,0,4]. Returns a column
+          vector of the three solutions. The first solution is
+          always the real one as a cubic always has one real
+          solution.
+
+          See Planetmath, Mathworld, or Wikipedia for more
+          information.
+
+   EulersMethod
+
+EulersMethod (f,x0,y0,x1,n)
+
+          Use classical Euler's method to numerically solve
+          y'=f(x,y) for initial x0, y0 going to x1 with n
+          increments, returns y at x1.
+
+          Systems can be solved by just having y be a (column)
+          vector everywhere. That is, y0 can be a vector in which
+          case f should take a number x and a vector of the same
+          size for the second argument and should return a vector
+          of the same size.
+
+          See Mathworld, or Wikipedia for more information.
+
+   EulersMethodFull
+
+EulersMethodFull (f,x0,y0,x1,n)
+
+          Use classical Euler's method to numerically solve
+          y'=f(x,y) for initial x0, y0 going to x1 with n
+          increments, returns a 2 by n+1 matrix with the x and y
+          values. Suitable for plugging into LinePlotDrawLine.
+
+          Systems can be solved by just having y be a (column)
+          vector everywhere. That is, y0 can be a vector in which
+          case f should take a number x and a vector of the same
+          size for the second argument and should return a vector
+          of the same size.
+
+          See Mathworld, or Wikipedia for more information.
+
+   FindRootBisection
+
+FindRootBisection (f,a,b,TOL,N)
+
+          Find root of a function using the bisection method. TOL
+          is the desired tolerance and N is the limit on the
+          number of iterations to run, 0 means no limit. The
+          function returns a vector [success,value,iteration],
+          where success is a boolean indicating success, value is
+          the last value computed, and iteration is the number of
+          iterations done.
+
+   FindRootFalsePosition
+
+FindRootFalsePosition (f,a,b,TOL,N)
+
+          Find root of a function using the method of false
+          position. TOL is the desired tolerance and N is the
+          limit on the number of iterations to run, 0 means no
+          limit. The function returns a vector
+          [success,value,iteration], where success is a boolean
+          indicating success, value is the last value computed,
+          and iteration is the number of iterations done.
+
+   FindRootMullersMethod
+
+FindRootMullersMethod (f,x1,x2,x3,TOL,N)
+
+          Find root of a function using the Muller's method. TOL
+          is the desired tolerance and N is the limit on the
+          number of iterations to run, 0 means no limit. The
+          function returns a vector [success,value,iteration],
+          where success is a boolean indicating success, value is
+          the last value computed, and iteration is the number of
+          iterations done.
+
+   FindRootSecant
+
+FindRootSecant (f,a,b,TOL,N)
+
+          Find root of a function using the secant method. TOL is
+          the desired tolerance and N is the limit on the number
+          of iterations to run, 0 means no limit. The function
+          returns a vector [success,value,iteration], where
+          success is a boolean indicating success, value is the
+          last value computed, and iteration is the number of
+          iterations done.
+
+   PolynomialRoots
+
+PolynomialRoots (p)
+
+          Compute roots of a polynomial (degrees 1 through 4)
+          using one of the formulas for such polynomials. The
+          polynomial should be given as a vector of coefficients.
+          That is 4*x^3 + 2*x + 1 corresponds to the vector
+          [1,2,0,4]. Returns a column vector of the solutions.
+
+          The function calls QuadraticFormula, CubicFormula, and
+          QuarticFormula.
+
+   QuadraticFormula
+
+QuadraticFormula (p)
+
+          Compute roots of a quadratic (degree 2) polynomial using
+          the quadratic formula. The polynomial should be given as
+          a vector of coefficients. That is 3*x^2 + 2*x + 1
+          corresponds to the vector [1,2,3]. Returns a column
+          vector of the two solutions.
+
+          See Planetmath or Mathworld for more information.
+
+   QuarticFormula
+
+QuarticFormula (p)
+
+          Compute roots of a quartic (degree 4) polynomial using
+          the quartic formula. The polynomial should be given as a
+          vector of coefficients. That is 5*x^4 + 2*x + 1
+          corresponds to the vector [1,2,0,0,5]. Returns a column
+          vector of the four solutions.
+
+          See Planetmath, Mathworld, or Wikipedia for more
+          information.
+
+   RungeKutta
+
+RungeKutta (f,x0,y0,x1,n)
+
+          Use classical non-adaptive fourth order Runge-Kutta
+          method to numerically solve y'=f(x,y) for initial x0, y0
+          going to x1 with n increments, returns y at x1.
+
+          Systems can be solved by just having y be a (column)
+          vector everywhere. That is, y0 can be a vector in which
+          case f should take a number x and a vector of the same
+          size for the second argument and should return a vector
+          of the same size.
+
+          See Mathworld, or Wikipedia for more information.
+
+   RungeKuttaFull
+
+RungeKuttaFull (f,x0,y0,x1,n)
+
+          Use classical non-adaptive fourth order Runge-Kutta
+          method to numerically solve y'=f(x,y) for initial x0, y0
+          going to x1 with n increments, returns a 2 by n+1 matrix
+          with the x and y values. Suitable for plugging into
+          LinePlotDrawLine.
+
+          Systems can be solved by just having y be a (column)
+          vector everywhere. That is, y0 can be a vector in which
+          case f should take a number x and a vector of the same
+          size for the second argument and should return a vector
+          of the same size.
+
+          See Mathworld, or Wikipedia for more information.
+     __________________________________________________________
+
+Statistics
+
+   Average
+
+Average (m)
+
+          Aliases: average Mean mean
+
+          Calculate average of an entire matrix.
+
+          See Mathworld for more information.
+
+   GaussDistribution
+
+GaussDistribution (x,sigma)
+
+          Integral of the GaussFunction from 0 to x (area under
+          the normal curve).
+
+          See Mathworld for more information.
+
+   GaussFunction
+
+GaussFunction (x,sigma)
+
+          The normalized Gauss distribution function (the normal
+          curve).
+
+          See Mathworld for more information.
+
+   Median
+
+Median (m)
+
+          Aliases: median
+
+          Calculate median of an entire matrix.
+
+          See Mathworld for more information.
+
+   PopulationStandardDeviation
+
+PopulationStandardDeviation (m)
+
+          Aliases: stdevp
+
+          Calculate the population standard deviation of a whole
+          matrix.
+
+   RowAverage
+
+RowAverage (m)
+
+          Aliases: RowMean
+
+          Calculate average of each row in a matrix.
+
+          See Mathworld for more information.
+
+   RowMedian
+
+RowMedian (m)
+
+          Calculate median of each row in a matrix and return a
+          column vector of the medians.
+
+          See Mathworld for more information.
+
+   RowPopulationStandardDeviation
+
+RowPopulationStandardDeviation (m)
+
+          Aliases: rowstdevp
+
+          Calculate the population standard deviations of rows of
+          a matrix and return a vertical vector.
+
+   RowStandardDeviation
+
+RowStandardDeviation (m)
+
+          Aliases: rowstdev
+
+          Calculate the standard deviations of rows of a matrix
+          and return a vertical vector.
+
+   StandardDeviation
+
+StandardDeviation (m)
+
+          Aliases: stdev
+
+          Calculate the standard deviation of a whole matrix.
+     __________________________________________________________
+
+Polynomials
+
+   AddPoly
+
+AddPoly (p1,p2)
+
+          Add two polynomials (vectors).
+
+   DividePoly
+
+DividePoly (p,q,&r)
+
+          Divide two polynomials (as vectors) using long division.
+          Returns the quotient of the two polynomials. The
+          optional argument r is used to return the remainder. The
+          remainder will have lower degree than q.
+
+          See Planetmath for more information.
+
+   IsPoly
+
+IsPoly (p)
+
+          Check if a vector is usable as a polynomial.
+
+   MultiplyPoly
+
+MultiplyPoly (p1,p2)
+
+          Multiply two polynomials (as vectors).
+
+   NewtonsMethodPoly
+
+NewtonsMethodPoly (poly,guess,epsilon,maxn)
+
+          Run newton's method on a polynomial to attempt to find a
+          root, returns after two successive values are within
+          epsilon or after maxn tries (then returns null).
+
+   Poly2ndDerivative
+
+Poly2ndDerivative (p)
+
+          Take second polynomial (as vector) derivative.
+
+   PolyDerivative
+
+PolyDerivative (p)
+
+          Take polynomial (as vector) derivative.
+
+   PolyToFunction
+
+PolyToFunction (p)
+
+          Make function out of a polynomial (as vector).
+
+   PolyToString
+
+PolyToString (p,var...)
+
+          Make string out of a polynomial (as vector).
+
+   SubtractPoly
+
+SubtractPoly (p1,p2)
+
+          Subtract two polynomials (as vectors).
+
+   TrimPoly
+
+TrimPoly (p)
+
+          Trim zeros from a polynomial (as vector).
+     __________________________________________________________
+
+Set Theory
+
+   Intersection
+
+Intersection (X,Y)
+
+          Returns a set theoretic intersection of X and Y (X and Y
+          are vectors pretending to be sets).
+
+   IsIn
+
+IsIn (x,X)
+
+          Returns true if the element x is in the set X (where X
+          is a vector pretending to be a set).
+
+   IsSubset
+
+IsSubset (X, Y)
+
+          Returns true if X is a subset of Y (X and Y are vectors
+          pretending to be sets).
+
+   MakeSet
+
+MakeSet (X)
+
+          Returns a vector where every element of X appears only
+          once.
+
+   SetMinus
+
+SetMinus (X,Y)
+
+          Returns a set theoretic difference X-Y (X and Y are
+          vectors pretending to be sets).
+
+   Union
+
+Union (X,Y)
+
+          Returns a set theoretic union of X and Y (X and Y are
+          vectors pretending to be sets).
+     __________________________________________________________
+
+Miscellaneous
+
+   ASCIIToString
+
+ASCIIToString (vec)
+
+          Convert a vector of ASCII values to a string.
+
+   AlphabetToString
+
+AlphabetToString (vec,alphabet)
+
+          Convert a vector of 0-based alphabet values (positions
+          in the alphabet string) to a string.
+
+   StringToASCII
+
+StringToASCII (str)
+
+          Convert a string to a vector of ASCII values.
+
+   StringToAlphabet
+
+StringToAlphabet (str,alphabet)
+
+          Convert a string to a vector of 0-based alphabet values
+          (positions in the alphabet string), -1's for unknown
+          letters.
+     __________________________________________________________
+
+Symbolic Operations
+
+   SymbolicDerivative
+
+SymbolicDerivative (f)
+
+          Attempt to symbolically differentiate the function f,
+          where f is a function of one variable.
+
+          Examples:
+
+genius> SymbolicDerivative(sin)
+= (`(x)=cos(x))
+genius> SymbolicDerivative(`(x)=7*x^2)
+= (`(x)=(7*(2*x)))
+
+   SymbolicDerivativeTry
+
+SymbolicDerivativeTry (f)
+
+          Attempt to symbolically differentiate the function f,
+          where f is a function of one variable, returns null if
+          unsuccessful but is silent. (See SymbolicDerivative)
+
+   SymbolicNthDerivative
+
+SymbolicNthDerivative (f,n)
+
+          Attempt to symbolically differentiate a function n
+          times. (See SymbolicDerivative)
+
+   SymbolicNthDerivativeTry
+
+SymbolicNthDerivativeTry (f,n)
+
+          Attempt to symbolically differentiate a function n times
+          quietly and return null on failure (See
+          SymbolicNthDerivative)
+
+   SymbolicTaylorApproximationFunction
+
+SymbolicTaylorApproximationFunction (f,x0,n)
+
+          Attempt to construct the taylor approximation function
+          around x0 to the nth degree. (See SymbolicDerivative)
+     __________________________________________________________
+
+Plotting
+
+   LinePlot
+
+LinePlot (func1,func2,func3,...)
+
+LinePlot (func1,func2,func3,x1,x2,y1,y2)
+
+          Plot a function (or several functions) with a line.
+          First up to 10 arguments are functions, then optionally
+          you can specify the limits of the plotting window as x1,
+          x2, y1, y2. If limits are not specified, then the
+          currently set limits apply (See LinePlotWindow)
+
+          The parameter LinePlotDrawLegends controls the drawing
+          of the legend.
+
+          Examples:
+
+genius> LinePlot(sin,cos)
+genius> LinePlot(`(x)=x^2,-1,1,0,1)
+
+   LinePlotClear
+
+LinePlotClear ()
+
+          Show the line plot window and clear out functions and
+          any other lines that were drawn.
+
+   LinePlotDrawLine
+
+LinePlotDrawLine (x1,y1,x2,y2,...)
+
+LinePlotDrawLine (v,...)
+
+          Draw a line from x1,y1 to x2,y2. x1,y1, x2,y2 can be
+          replaced by an n by 2 matrix for a longer line.
+
+          Extra parameters can be added to specify line color,
+          thickness, arrows, and the plotting window. You can do
+          this by adding a string "color", "thickness", "window",
+          or "arrow", and after it either the color string, the
+          thicknes as an integer, the window as 4-vector, and for
+          arrow either "origin", "end", "both", or "none". For
+          "window" we can specify "fit" rather than a vector in
+          which case, the x range will be set precisely and the y
+          range will be set with five percent borders around the
+          line. Finally, the legend can be specified by adding
+          "legend" and the string with the legend.
+
+          Examples:
+
+genius> LinePlotDrawLine(0,0,1,1,"color","blue","thickness",3)
+genius> LinePlotDrawLine([0,0;1,-1;-1,-1])
+genius> LinePlotDrawLine([0,0;1,1],"arrow","end")
+genius> LinePlotDrawLine(EulersMethodFull(`(x,y)=y,0,3,100),"color","blu
+e","legend","The Solution")
+
+   LinePlotParametric
+
+LinePlotParametric (xfunc,yfunc,...)
+
+LinePlotParametric (xfunc,yfunc,t1,t2,tinc)
+
+LinePlotParametric (xfunc,yfunc,t1,t2,tinc,x1,x2,y1,y2)
+
+          Plot a parametric function with a line. First come the
+          functions for x and y then optionally the t limits as
+          t1,t2,tinc, then optionally the limits as x1,x2,y1,y2.
+
+          If limits are not specified, then the currently set
+          limits apply (See LinePlotWindow).
+
+          The parameter LinePlotDrawLegends controls the drawing
+          of the legend.
+
+   LinePlotCParametric
+
+LinePlotCParametric (func,...)
+
+LinePlotCParametric (func,t1,t2,tinc)
+
+LinePlotCParametric (func,t1,t2,tinc,x1,x2,y1,y2)
+
+          Plot a parametric complex valued function with a line.
+          First comes the function that returns x+iy, then
+          optionally the t limits as t1,t2,tinc, then optionally
+          the limits as x1,x2,y1,y2.
+
+          If limits are not specified, then the currently set
+          limits apply (See LinePlotWindow).
+
+          The parameter LinePlotDrawLegends controls the drawing
+          of the legend.
+
+   SlopefieldClearSolutions
+
+SlopefieldClearSolutions ()
+
+          Clears the solutions drawn by the SlopefieldDrawSolution
+          function.
+
+   SlopefieldDrawSolution
+
+SlopefieldDrawSolution (x, y, dx)
+
+          When a slope field plot is active, draw a solution with
+          the specified initial condition. The standard
+          Runge-Kutta method is used with increment dx. Solutions
+          stay on the graph until a different plot is shown or
+          until you call SlopefieldClearSolutions. You can also
+          use the graphical interface to draw solutions and
+          specify initial conditions with the mouse.
+
+   SlopefieldPlot
+
+SlopefieldPlot (func)
+
+SlopefieldPlot (func,x1,x2,y1,y2)
+
+          Plot a slope field. The function func should take two
+          real numbers x and y, or a single complex number.
+          Optionally you can specify the limits of the plotting
+          window as x1, x2, y1, y2. If limits are not specified,
+          then the currently set limits apply (See
+          LinePlotWindow).
+
+          The parameter LinePlotDrawLegends controls the drawing
+          of the legend.
+
+          Examples:
+
+genius> Slopefield(`(x,y)=sin(x-y),-5,5,-5,5)
+
+   SurfacePlot
+
+SurfacePlot (func)
+
+SurfacePlot (func,x1,x2,y1,y2,z1,z2)
+
+          Plot a surface function which takes either two arguments
+          or a complex number. First comes the function then
+          optionally limits as x1, x2, y1, y2, z1, z2. If limits
+          are not specified, then the currently set limits apply
+          (See SurfacePlotWindow). Genius can only plot a single
+          surface function at this time.
+
+          Examples:
+
+genius> SurfacePlot(|sin|,-1,1,-1,1,0,1.5)
+genius> SurfacePlot(`(x,y)=x^2+y,-1,1,-1,1,-2,2)
+genius> SurfacePlot(`(z)=|z|^2,-1,1,-1,1,0,2)
+
+   VectorfieldClearSolutions
+
+VectorfieldClearSolutions ()
+
+          Clears the solutions drawn by the
+          VectorfieldDrawSolution function.
+
+   VectorfieldDrawSolution
+
+VectorfieldDrawSolution (x, y, dt, tlen)
+
+          When a vector field plot is active, draw a solution with
+          the specified initial condition. The standard
+          Runge-Kutta method is used with increment dt for an
+          interval of length tlen. Solutions stay on the graph
+          until a different plot is shown or until you call
+          VectorfieldClearSolutions. You can also use the
+          graphical interface to draw solutions and specify
+          initial conditions with the mouse.
+
+   VectorfieldPlot
+
+VectorfieldPlot (funcx, funcy)
+
+VectorfieldPlot (funcx, funcy, x1, x2, y1, y2)
+
+          Plot a two dimensional vector field. The function funcx
+          should be the dx/dt of the vectorfield and the function
+          funcy should be the dy/dt of the vectorfield. The
+          functions should take two real numbers x and y, or a
+          single complex number. When the parameter
+          VectorfieldNormalized is true, then the magnitude of the
+          vectors is normalized. That is, only the direction and
+          not the magnitude is shown.
+
+          Optionally you can specify the limits of the plotting
+          window as x1, x2, y1, y2. If limits are not specified,
+          then the currently set limits apply (See
+          LinePlotWindow).
+
+          The parameter LinePlotDrawLegends controls the drawing
+          of the legend.
+
+          Examples:
+
+genius> VectorfieldPlot(`(x,y)=x^2-y, `(x,y)=y^2-x, -1, 1, -1, 1)
+     __________________________________________________________
+
+Example Programs in GEL
+
+   Here is a function that calculates factorials:
+function f(x) = if x <= 1 then 1 else (f(x-1)*x)
+
+   With indentation it becomes:
+function f(x) = (
+  if x <= 1 then
+    1
+  else
+    (f(x-1)*x)
+)
+
+   This is a direct port of the factorial function from the bc
+   manpage. The syntax seems similar to bc, but different in that
+   in GEL, the last expression is the one that is returned. Using
+   the return function instead, it would be:
+function f(x) = (
+  if (x <= 1) then return (1);
+  return (f(x-1) * x)
+)
+
+   By far the easiest way to define a factorial function would be
+   using the product loop as follows. This is not only the
+   shortest and fastest, but also probably the most readable
+   version.
+function f(x) = prod k=1 to x do k
+
+   Here is a larger example, this basically redefines the internal
+   ref function to calculate the row echelon form of a matrix. The
+   function ref is built in and much faster, but this example
+   demonstrates some of the more complex features of GEL.
+# Calculate the row-echelon form of a matrix
+function MyOwnREF(m) = (
+  if not IsMatrix(m) or not IsValueOnly(m) then
+    (error("ref: argument not a value only matrix");bailout);
+  s := min(rows(m), columns(m));
+  i := 1;
+  d := 1;
+  while d <= s and i <= columns(m) do (
+
+    # This just makes the anchor element non-zero if at
+    # all possible
+    if m@(d,i) == 0 then (
+      j := d+1;
+      while j <= rows(m) do (
+        if m@(j,i) == 0 then
+          (j=j+1;continue);
+        a := m@(j,);
+        m@(j,) := m@(d,);
+        m@(d,) := a;
+        j := j+1;
+        break
+      )
+    );
+    if m@(d,i) == 0 then
+      (i:=i+1;continue);
+
+    # Here comes the actual zeroing of all but the anchor
+    # element rows
+    j := d+1;
+    while j <= rows(m)) do (
+      if m@(j,i) != 0 then (
+        m@(j,) := m@(j,)-(m@(j,i)/m@(d,i))*m@(d,)
+      );
+      j := j+1
+    );
+    m@(d,) := m@(d,) * (1/m@(d,i));
+    d := d+1;
+    i := i+1
+  );
+  m
+)
+     __________________________________________________________
+
+Settings
+
+   To configure Genius Mathematics Tool, choose
+   Settings->Preferences. There are several basic parameters
+   provided by the calculator in addition to the ones provided by
+   the standard library. These control how the calculator behaves.
+
+   Note Changing Settings with GEL
+
+
+   Many of the settings in Genius are simply global variables, and
+   can be evaluated and assigned to in the same way as normal
+   variables. See the Section called Using Variables in the
+   Chapter called GEL Basics about evaluating and assigning to
+   variables, and the Section called Parameters in the Chapter
+   called List of GEL functions for a list of settings that can be
+   modified in this way.
+
+   As an example, you can set the maximum number of digits in a
+   result to 12 by typing:
+MaxDigits = 12
+     __________________________________________________________
+
+Output
+
+   Maximum digits to output
+          The maximum digits in a result (MaxDigits)
+
+   Results as floats
+          If the results should be always printed as floats
+          (ResultsAsFloats)
+
+   Floats in scientific notation
+          If floats should be in scientific notation
+          (ScientificNotation)
+
+   Always print full expressions
+          Should we print out full expressions for non-numeric
+          return values (longer than a line) (FullExpressions)
+
+   Use mixed fractions
+          If fractions should be printed as mixed fractions such
+          as "1 1/3" rather than "4/3". (MixedFractions)
+
+   Display 0.0 when floating point number is less than 10^-x
+          (0=never chop)
+          How to chop output. But only when other numbers nearby
+          are large. See the documentation of the paramter
+          OutputChopExponent.
+
+   Only chop numbers when another number is greater than 10^-x
+          When to chop output. This is set by the paramter
+          OutputChopWhenExponent. See the documentation of the
+          paramter OutputChopExponent.
+
+   Remember output settings across sessions
+          Should the output settings in the Number/Expression
+          output options frame be remembered for next session.
+          Does not apply to the Error/Info output options frame.
+
+          If unchecked, either the default or any previously saved
+          settings are used each time Genius starts up. Note that
+          settings are saved at the end of the session, so if you
+          wish to change the defaults check this box, restart
+          Genius Mathematics Tool and then uncheck it again.
+
+   Display errors in a dialog
+          If set the errors will be displayed in a seprate dialog,
+          if unset the errors will be printed on the console.
+
+   Display information messages in a dialog
+          If set the information messages will be displayed in a
+          seprate dialog, if unset the information messages will
+          be printed on the console.
+
+   Maximum errors to display
+          The maximum number of errors to return on one evaluation
+          (MaxErrors). If you set this to 0 then all errors are
+          always returned. Usually if some loop causes many
+          errors, then it is unlikely that you will be able to
+          make sense out of more than a few of these, so seeing a
+          long list of errors is usually not helpful.
+
+   In addition to these preferences, there are some preferences
+   that can only be changed by setting them in the workspace
+   console. For others that may affect the output see the Section
+   called Parameters in the Chapter called List of GEL functions.
+
+   IntegerOutputBase
+          The base that will be used to output integers
+
+   OutputStyle
+          A string, can be "normal", "latex", "mathml" or "troff"
+          and it will effect how matrices (and perhaps other
+          stuff) is printed, useful for pasting into documents.
+          Normal style is the default human readable printing
+          style of Genius Mathematics Tool. The other styles are
+          for typsetting in LaTeX, MathML (XML), or in Troff.
+     __________________________________________________________
+
+Precision
+
+   Floating point precision
+          The floating point precision in bits (FloatPrecision).
+          Note that changing this only affects newly computed
+          quantities. Old values stored in variables are obviously
+          still in the old precision and if you want to have them
+          more precise you will have to recompute them. Exceptions
+          to this are the system constants such as pi or e.
+
+   Remember precision setting across sessions
+          Should the precision setting be remembered for the next
+          session. If unchecked, either the default or any
+          previously saved setting is used each time Genius starts
+          up. Note that settings are saved at the end of the
+          session, so if you wish to change the default check this
+          box, restart genius and then uncheck it again.
+     __________________________________________________________
+
+Terminal
+
+   Terminal refers to the console in the work area.
+
+   Scrollback lines
+          Lines of scrollback in the terminal.
+
+   Font
+          The font to use on the terminal.
+
+   Black on white
+          If to use black on white on the terminal.
+
+   Blinking cursor
+          If the cursor in the terminal should blink when the
+          terminal is in focus. This can sometimes be annoying and
+          it generates idle traffic if you are using Genius
+          remotely.
+     __________________________________________________________
+
+Memory
+
+   Maximum number of nodes to allocate
+          Internally all data is put onto small nodes in memory.
+          This gives a limit on the maximum number of nodes to
+          allocate for computations. This avoids the problem of
+          running out of memory if you do something by mistake
+          which uses too much memory, such as a recursion without
+          end. This could slow your computer and make it hard to
+          even interrupt the program.
+
+          Once the limit is reached, Genius Mathematics Tool asks
+          if you wish to interrupt the computation or if you wish
+          to continue. If you continue, no limit is applied and it
+          will be possible to run your computer out of memory. The
+          limit will be applied again next time you execute a
+          program or an expression on the Console regardless of
+          how you answered the question.
+
+          Setting the limit to zero means there is no limit to the
+          amount of memory that genius uses.
+     __________________________________________________________
+
+About Genius Mathematics Tool
+
+   Genius Mathematics Tool was written by JiÅÃ (George) Lebl
+   (<jirka 5z com>). The history of Genius Mathematics Tool goes
+   back to late 1997. It was the first calculator program for
+   GNOME, but it then grew beyond being just a desktop calculator.
+   To find more information about Genius Mathematics Tool, please
+   visit the Genius Web page.
+
+   To report a bug or make a suggestion regarding this application
+   or this manual, follow the directions in this document.
+
+   This program is distributed 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. A copy of this license can be found at this link, or
+   in the file COPYING included with the source code of this
+   program.
+
+   JiÅÃ Lebl was during various parts of the development partially
+   supported for the work by NSF grant DMS 0900885 and the
+   University of Illinois at Urbana-Champaign. The software has
+   been used for both teaching and research.
diff --git a/lib/calculus/fourier.gel b/lib/calculus/fourier.gel
index 4c689a4..1d29b07 100644
--- a/lib/calculus/fourier.gel
+++ b/lib/calculus/fourier.gel
@@ -68,8 +68,8 @@ function FourierSeriesFunction(a,b,L) =
 		);
 	
 		if not IsNull(b) then (
-			val = val + sum n = 1 to elements(b) do
-				b@(n) * sin(x*n*pi/L)
+			increment val by (sum n = 1 to elements(b) do
+					    b@(n) * sin(x*n*pi/L))
 		);
 	
 		val
@@ -152,8 +152,8 @@ function PeriodicExtension(f,a,b) =
 	`(x)[f,a,b] = (
 		local *;
 		#This is pretty stupid, but simplest way to do this
-		while x > b do x = x-(b-a);
-		while x < a do x = x+(b-a);
+		while x > L do increment x by -(b-a);
+		while x < -L do increment x by (b-a);
 		(f call (x))
 	)
 )
@@ -170,8 +170,8 @@ function EvenPeriodicExtension(f,L) =
 	`(x)[f,L] = (
 		local *;
 		#This is pretty stupid, but simplest way to do this
-		while x > L do x = x-2*L;
-		while x < -L do x = x+2*L;
+		while x > L do increment x by -2*L;
+		while x < -L do increment x by 2*L;
 
 		if x >= 0 then (f call (x)) else (f call (-x))
 	)
@@ -189,8 +189,8 @@ function OddPeriodicExtension(f,L) =
 	`(x)[f,L] = (
 		local *;
 		#This is pretty stupid, but simplest way to do this
-		while x > L do x = x-2*L;
-		while x < -L do x = x+2*L;
+		while x > L do increment x by -2*L;
+		while x < -L do increment x by 2*L;
 
 		if x >= 0 then (f call (x)) else -(f call (-x))
 	)
diff --git a/lib/calculus/limits.gel b/lib/calculus/limits.gel
index fcb25b6..62bc73b 100644
--- a/lib/calculus/limits.gel
+++ b/lib/calculus/limits.gel
@@ -35,13 +35,13 @@ function NumericalLimitAtInfinity(f,step_fun,tolerance,successive_for_success,N)
     for i = 2 to N do (
         new_limit = f(step_fun(i));
         if (|new_limit-current_limit| < tolerance) then (
-            number_of_consecutive_differences_within_tolerance = number_of_consecutive_differences_within_tolerance+1
+            increment number_of_consecutive_differences_within_tolerance
         ) else (
             number_of_consecutive_differences_within_tolerance = 0
         );
         current_limit = new_limit;
         if (number_of_consecutive_differences_within_tolerance >= successive_for_success) then
-            return current_limit;
+            return current_limit
     );
     null
 )
diff --git a/lib/calculus/sums_products.gel b/lib/calculus/sums_products.gel
index 6fec783..89f778b 100644
--- a/lib/calculus/sums_products.gel
+++ b/lib/calculus/sums_products.gel
@@ -21,7 +21,7 @@ function InfiniteSum (func, start, inc) = (
 	for n = 1 to SumProductNumberOfTries do (
 		newsum = oldsum + func(start);
 		if |newsum-oldsum| < SumProductTolerance then (
-			wt = wt + 1;
+			increment wt;
 			if wt >= SumProductSFS then (
 				return newsum
 			)
@@ -47,7 +47,7 @@ function InfiniteSum2(func,arg,start,inc) = (
 	for n = 1 to SumProductNumberOfTries do (
 		newsum = oldsum + func(arg,start);
 		if |newsum-oldsum| < SumProductTolerance then (
-			wt = wt + 1;
+			increment wt;
 			if wt >= SumProductSFS then (
 				return newsum
 			)
@@ -73,7 +73,7 @@ function InfiniteProduct (func, start, inc) = (
 	for n = 1 to SumProductNumberOfTries do (
 		newprod = oldprod * func(start);
 		if |newprod-oldprod| < SumProductTolerance then (
-			wt = wt + 1;
+			increment wt;
 			if wt >= SumProductSFS then (
 				return newprod
 			)
@@ -99,7 +99,7 @@ function InfiniteProduct2(func,arg,start,inc) = (
 	for n = 1 to SumProductNumberOfTries do (
 		newprod = oldprod * func(arg,start);
 		if |newprod-oldprod| < SumProductTolerance then (
-			wt = wt + 1;
+			increment wt;
 			if wt >= SumProductSFS then (
 				return newprod
 			)
diff --git a/lib/equation_solving/diffeqs.gel b/lib/equation_solving/diffeqs.gel
index e90eaf9..6a25599 100644
--- a/lib/equation_solving/diffeqs.gel
+++ b/lib/equation_solving/diffeqs.gel
@@ -17,8 +17,9 @@ function EulersMethod(f,x0,y0,x1,n) = (
 	x := float(x0);
 	y := float(y0);
 	for k = 1 to n do (
-		y := y + h*f(x,y);
-		x := x + h
+		# y could be a vector, so do not use increment
+		y := y+h*f(x,y);
+		increment x by h
 	);
 	y
 )
@@ -39,8 +40,10 @@ function EulersMethodFull(f,x0,y0,x1,n) = (
 	out@(1,1) := x := float(x0);
 	out@(1,2) := y := float(y0);
 	for k = 2 to n+1 do (
+		# y could be a vector, so do not use increment
 		out@(k,2) := y := y + h*f(x,y);
-		out@(k,1) := x := x + h
+		increment x by h;
+		out@(k,1) := x
 	);
 	out
 )
@@ -66,8 +69,9 @@ function RungeKutta(f,x0,y0,x1,n) = (
 		k1 := f(x,y);
 		k2 := f(x + hover2,y + k1*hover2);
 		k3 := f(x + hover2,y + k2*hover2);
-		x := x + h;
+		increment x by h;
 		k4 := f(x,y + k3*h);
+		# y could be a vector, so do not use increment
 		y := y + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h
 	);
 	y
@@ -93,9 +97,11 @@ function RungeKuttaFull(f,x0,y0,x1,n) = (
 		k1 := f(x,y);
 		k2 := f(x + hover2,y + k1*hover2);
 		k3 := f(x + hover2,y + k2*hover2);
-		out@(k,1) := x := x + h;
+		increment x by h;
 		k4 := f(x,y + k3*h);
-		out@(k,2) := y := y + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h
+		# y could be a vector, so do not use increment
+		out@(k,2) := y := y + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h;
+		out@(k,1) := x;
 	);
 	out
 )
diff --git a/lib/equation_solving/find_root.gel b/lib/equation_solving/find_root.gel
index 79efd02..ec579ad 100644
--- a/lib/equation_solving/find_root.gel
+++ b/lib/equation_solving/find_root.gel
@@ -45,7 +45,7 @@ function FindRootBisection(f,a,b,TOL,N) =
 	 diff=(b-a)/2;
 	 p=a+diff;
 	 if(f(p)==0 or diff<TOL) then (return [true,p,iteration]);
-	 iteration=iteration+1;
+	 increment iteration;
 	 if(f(a)*f(b)>0) then (a=p) else (b=p)
 	);
 	[false,p,iteration]
@@ -82,11 +82,11 @@ function FindRootSecant(f,a,b,TOL,N) =
 	(
 	 p=b-qb*(b-a)/(qb-qa);
 	 if(|p-b|<TOL) then (return [true,p,iteration]);
-	 iteration=iteration+1;
+	 increment iteration;
 	 a=b;
 	 qa=qb;
          b=p;
-         qb=f(p);
+         qb=f(p)
 	);
 	[false,p,iteration]
 )
@@ -118,11 +118,11 @@ function FindRootFalsePosition(f,a,b,TOL,N) =
 	(
 	 p=b-qb*(b-a)/(qb-qa);
 	 if(|p-b|<TOL) then (return [true,p,iteration]);
-	 iteration=iteration+1;
+	 increment iteration;
 	 q=f(p);
 	 if(q*qb<0) then (a=b;qa=qb);
          b=p;
-         qb=q;
+         qb=q
 	);
 	[false,p,iteration]
 )
@@ -168,7 +168,7 @@ function FindRootMullersMethod(f,x1,x2,x3,TOL,N) =
 	d1=(f(x1)-f(x0))/h1;
 	d2=(f(x2)-f(x1))/h2;
 	d=(d2-d1)/(h2+h1);
-	i=i+1;
+	increment i
 	);
 	[false,p,iteration]
 )
diff --git a/lib/functions/elementary.gel b/lib/functions/elementary.gel
index 7282cc0..44d7cb0 100644
--- a/lib/functions/elementary.gel
+++ b/lib/functions/elementary.gel
@@ -252,10 +252,10 @@ function ErrorFunction (x) = (
 	do (
 		t = xx * a * twosqrtpi;
 		s = s + t;
-		n = n + 1;
+		increment n;
 		f = f * n;
 		a = ((-1)^n) / (((2*n)+1) * f);
-		xx = xx * xsq;
+		xx = xx * xsq
 	) while (|t| > ErrorFunctionTolerance);
 	s
 );
diff --git a/lib/library-strings.c b/lib/library-strings.c
index ca69db5..0bc9d97 100644
--- a/lib/library-strings.c
+++ b/lib/library-strings.c
@@ -88,6 +88,7 @@ char *fake = N_("Get the outer product of two vectors");
 char *fake = N_("Reverse elements in a vector");
 char *fake = N_("Calculate sum of each row in a matrix");
 char *fake = N_("Calculate sum of squares of each row in a matrix");
+char *fake = N_("Shuffle elements in a vector");
 char *fake = N_("Sort vector elements");
 char *fake = N_("Removes any all-zero rows of M");
 char *fake = N_("Return column(s) and row(s) from a matrix");
diff --git a/lib/linear_algebra/linear_algebra.gel b/lib/linear_algebra/linear_algebra.gel
index c7dae75..02edd65 100644
--- a/lib/linear_algebra/linear_algebra.gel
+++ b/lib/linear_algebra/linear_algebra.gel
@@ -458,7 +458,7 @@ function Eigenvectors(M, evsmults...) = (
 				) else (
 					out@(k) := [1;-row@(1)/row@(2)]
 				);
-				k = k+1;
+				increment k
 			);
 			out
 		)
@@ -555,7 +555,7 @@ function RayleighQuotientIteration(A,x,epsilon,maxiter,vecref) = (
 
 		nsq = HermitianProduct (y,y);
 
-		p = p + (y'*x)@(1) / nsq;
+		increment p by (y'*x)@(1) / nsq;
 
 		x = y/sqrt(nsq);
 
diff --git a/lib/linear_algebra/misc.gel b/lib/linear_algebra/misc.gel
index 2b310aa..6104ebf 100644
--- a/lib/linear_algebra/misc.gel
+++ b/lib/linear_algebra/misc.gel
@@ -99,14 +99,16 @@ function ConvolutionVector(a,b) = (
 #calculate the sum of all elements in a matrix
 SetHelp("MatrixSum", "matrix","Calculate the sum of all elements in a matrix");
 function MatrixSum(a) = (
-	if(not IsMatrix(a) or not IsValueOnly(a)) then
+	if IsNull(a) then return 0
+	else if(not IsMatrix(a) or not IsValueOnly(a)) then
 		(error("MatrixSum: argument not a value only matrix");bailout);
 	sum n in a do n
 );
 
 SetHelp("MatrixSumSquares", "matrix","Calculate the sum of squares of all elements in a matrix");
 function MatrixSumSquares(a) = (
-	if(not IsMatrix(a) or not IsValueOnly(a)) then
+	if IsNull(a) then return 0
+	else if(not IsMatrix(a) or not IsValueOnly(a)) then
 		(error("MatrixSumSquares: argument not a value only matrix");bailout);
 	sum n in a do n^2
 );
@@ -158,7 +160,7 @@ function MinimizeFunction(func,x,incr) = (
 		(error("MinimizeFunction: x,incr arguments not values");bailout)
 	else if(not IsFunction(func)) then
 		(error("MinimizeFunction: func argument not a function");bailout);
-	while(func(x)>0) do x=x+incr;
+	while(func(x)>0) do increment x by incr;
 	x
 );
 
@@ -198,24 +200,26 @@ function SwapRows(m,row1,row2) = (
 
 SetHelp("RowSum","matrix","Calculate sum of each row in a matrix");
 function RowSum(m) = (
-	if not IsMatrix(m) then
+	if IsNull(m) then return null
+	else if not IsMatrix(m) then
 		(error("RowSum: argument not matrix");bailout);
 	r = zeros (rows(m),1);
 	for i = 1 to rows(m) do (
 		for j = 1 to columns(m) do
-			r@(i,1) = r@(i,1) + m@(i,j)
+			increment r@(i,1) by + m@(i,j)
 	);
 	r
 );
 
 SetHelp("RowSumSquares","matrix","Calculate sum of squares of each row in a matrix");
 function RowSumSquares(m) = (
-	if not IsMatrix(m) then
+	if IsNull(m) then return null
+	else if not IsMatrix(m) then
 		(error("RowSumSquares: argument not matrix");bailout);
 	r = zeros (rows(m),1);
 	for i = 1 to rows(m) do (
 		for j = 1 to columns(m) do
-			r@(i,1) = r@(i,1) + m@(i,j)^2
+			increment r@(i,1) by m@(i,j)^2
 	);
 	r
 );
@@ -223,16 +227,16 @@ function RowSumSquares(m) = (
 #sort a horizontal vector
 SetHelp("SortVector","matrix","Sort vector elements");
 function SortVector(v) = (
-	if not IsVector(v) then
+	if IsNull(v) then return null
+	else if not IsVector(v) then
 		(error("SortVector: argument not a vector");bailout);
+	# FIXME: really bad bubble sort
 	j = 1;
 	do (
 		sorted = true;
 		for i = 1 to elements(v)-j do (
 			if v@(i)>v@(i+1) then (
-				t = v@(i);
-				v@(i) = v@(i+1);
-				v@(i+1) = t;
+				v@(i) swapwith v@(i+1);
 				sorted = false
 			)
 		);
@@ -243,13 +247,27 @@ function SortVector(v) = (
 
 SetHelp("ReverseVector","matrix","Reverse elements in a vector");
 function ReverseVector(v) = (
-	if not IsVector(v) then
+	if IsNull(v) then return null
+	else if not IsVector(v) then
 		(error("ReverseVector: argument not a vector");bailout);
-	r = zeros (rows(v),columns(v));
 	ev = elements(v);
-	for i = 1 to ev do
-		r@(i) = v@(ev-i+1);
-	r
+	for i=1 to ceil((ev-1)/2) do (
+		v@(ev-i+1) swapwith v@(i)
+	);
+	v
+);
+
+SetHelp("ShuffleVector","matrix","Shuffle elements in a vector");
+function ShuffleVector(v) = (
+	if IsNull(v) then return null
+	else if not IsVector(v) then
+		(error("ShuffleVector: argument not a vector");bailout);
+
+	ev = elements(v);
+	for i=ev to 2 by -1 do (
+		v@(i) swapwith v@(randint(i)+1)
+	);
+	v
 );
 
 SetHelp("UpperTriangular", "matrix", "Zero out entries below the diagonal")
diff --git a/lib/number_theory/factoring.gel b/lib/number_theory/factoring.gel
index 0eeffc5..a222e7a 100644
--- a/lib/number_theory/factoring.gel
+++ b/lib/number_theory/factoring.gel
@@ -50,18 +50,18 @@ function CombineFactorizations(a,b) = (
     if k > columns(a) or a@(1,k) > b@(1,l) then (
       combined@(1,n) = a@(1,l);
       combined@(2,n) = a@(2,l);
-      l = l+1
+      increment l
     ) else if l > columns(b) or a@(1,k) < b@(1,l) then (
       combined@(1,n) = a@(1,k);
       combined@(2,n) = a@(2,k);
-      k = k+1
+      increment k
     ) else if a@(1,k) == b@(1,l) then (
       combined@(1,n) = a@(1,k);
       combined@(2,n) = a@(2,k) + b@(2,k);
-      k = k+1;
-      l = l+1
+      increment k;
+      increment l
     );
-    n = n+1;
+    increment n
   );
   combined
 )
@@ -107,10 +107,10 @@ function FermatFactorization(n,tries) = (
   	(error("FermatFactorization: arguments not positive integers");bailout);
   t = floor(sqrt(n));
   for i=1 to tries do (
-    t = t+1;
+    increment t;
     m = t^2 - n;
     s = sqrt(m);
-    if IsInteger (s) then return [t,s];
+    if IsInteger (s) then return [t,s]
   );
   null
 )
diff --git a/lib/number_theory/misc.gel b/lib/number_theory/misc.gel
index 57fd2fc..d2cb6e7 100644
--- a/lib/number_theory/misc.gel
+++ b/lib/number_theory/misc.gel
@@ -40,7 +40,7 @@ function PadicValuation(n,p) =
   valuation=0;
   while Divides(p,n) do
    (
-    valuation=valuation+1;
+    increment valuation;
     n=ExactDivision(n,p);
    );
   valuation
@@ -58,7 +58,7 @@ function RemoveFactor(n,m) =
 
   while Divides(m,n) do
    (
-    n = ExactDivision(n,m);
+    n = ExactDivision(n,m)
    );
   n
  )
@@ -111,7 +111,7 @@ function ConvertToBase(n,b) = (
   while n != 0 do (
     r = n % b;
     n = (n-r)/b;
-    ret = [ret;r];
+    ret = [ret;r]
   );
   ret
 )
diff --git a/lib/number_theory/modulus.gel b/lib/number_theory/modulus.gel
index 268be23..6323ee1 100644
--- a/lib/number_theory/modulus.gel
+++ b/lib/number_theory/modulus.gel
@@ -28,14 +28,14 @@ function SilverPohligHellmanWithFactorization(n,b,q,f) = (
   for i = 2 to columns(f) do (
     p = f@(1,i);
     for j = 0 to p-1 do
-      r@(i-1,j+1) = b^(j*(q-1)/p) mod q;
+      r@(i-1,j+1) = b^(j*(q-1)/p) mod q
   );
 
   # utility function to find the root in the table
   function FindRoot(rt,p,i) = (
     for j = 1 to p do
       if r@(i-1,j) == rt then return j-1;
-    (error("DiscreteLog: Error finding log, probably bogus arguments");bailout);
+    (error("DiscreteLog: Error finding log, probably bogus arguments");bailout)
   );
 
   # This will be our vector of moduli for the ChineseRemainder
@@ -52,9 +52,9 @@ function SilverPohligHellmanWithFactorization(n,b,q,f) = (
     for l = 0 to alpha-1 do (
       y = n/(b^xx);
       rt = y^((q-1)/p^(l+1)) mod q;
-      xx = xx + FindRoot(rt,p,i) * p^l;
+      xx = xx + FindRoot(rt,p,i) * p^l
     );
-    x@(i-1) = xx;
+    x@(i-1) = xx
   );
 
   # Now return the chinese remainder of the system
@@ -99,7 +99,7 @@ function IndexCalculusPrecalculation (b, q, S) = (
         divn = n / S@(i,1);
         if IsInteger (divn) then (
           fact@(i) = fact@(i) + 1;
-          n = divn;
+          n = divn
         )
       ) while n > 1 and IsInteger(divn);
     );
@@ -125,7 +125,7 @@ function IndexCalculusPrecalculation (b, q, S) = (
         # matrix we throw it away
         gcd(det(mat),q-1) != 1 then (
         mat = null;
-        v = null;
+        v = null
       )
     )
   ) while IsNull(mat) or rows (mat) < rows(S);
@@ -169,9 +169,9 @@ function IndexCalculus (n, b, q, S) = (
         divf = f / S@(i,1);
         if IsInteger (divf) then (
           l = l + S@(i,2);
-          f = divf;
+          f = divf
         )
-      ) while f > 1 and IsInteger(divf);
+      ) while f > 1 and IsInteger(divf)
     )
   ) while f > 1;
   l mod q-1
@@ -262,7 +262,7 @@ function SqrtModPrime(n,p) = (
     s=1; t=(p-1)/2;
     while IsEven(t) do (
       t = t/2;
-      s = s+1
+      increment s
     );
 
     nn = n^-1 mod p;
diff --git a/lib/number_theory/primes.gel b/lib/number_theory/primes.gel
index 97d41cd..27f92b2 100644
--- a/lib/number_theory/primes.gel
+++ b/lib/number_theory/primes.gel
@@ -51,7 +51,7 @@ function LucasLehmer(p) = (
 	Mp = (2^p) - 1;
 	while n<p-1 do (
 		S = ((S^2) - 2) % Mp;
-		n = n+1
+		increment n
 	);
 	S == 0
 );
@@ -120,10 +120,10 @@ function IsMersennePrimeExponent(p) = (
 		return true;
 
 	# http://www.mersenne.org / GIMPS doublechecked everything up
-	# to 18,297,089 (on Jul. 22, 2009)
-	if p <= 18297089 then
+	# to 22,338,397 (on Jul. 12, 2011)
+	if p <= 22338397 then
 		return false;
 
-	error("IsMersennePrimeExponent: Number too large (known values up to: " + 18297089 + ")");
+	error("IsMersennePrimeExponent: Number too large (known values up to: " + 22338397 + ")");
 	bailout
 );
diff --git a/src/calc.c b/src/calc.c
index 9033321..89501e4 100644
--- a/src/calc.c
+++ b/src/calc.c
@@ -572,7 +572,7 @@ append_anal_binaryoper(GelOutput *gelo, char *p, GelETree *n)
 }
 
 static void
-append_binaryoper(GelOutput *gelo, char *p, GelETree *n)
+append_binaryoper(GelOutput *gelo, const char *p, GelETree *n)
 {
 	GelETree *l,*r;
 	GEL_GET_LR(n,l,r);
@@ -1011,6 +1011,18 @@ appendoper(GelOutput *gelo, GelETree *n)
 			append_binaryoper(gelo," mod ",n); break;
 		case GEL_E_DEFEQUALS:
 			append_binaryoper (gelo, ":=", n); break;
+		case GEL_E_SWAPWITH:
+			append_binaryoper (gelo, " swapwith ", n); break;
+		case GEL_E_INCREMENT:
+			append_unaryoper (gelo, "increment ", n); break;
+		case GEL_E_INCREMENT_BY:
+			GEL_GET_LR(n,l,r);
+			gel_output_string(gelo,"(increment ");
+			gel_print_etree (gelo, l, FALSE);
+			gel_output_string(gelo," by ");
+			gel_print_etree (gelo, r, FALSE);
+			gel_output_string(gelo,")");
+			break;
 
 		default:
 			gel_errorout (_("Unexpected operator!"));
diff --git a/src/compil.c b/src/compil.c
index 3d2445f..785e306 100644
--- a/src/compil.c
+++ b/src/compil.c
@@ -47,7 +47,7 @@ gel_decode_string (const char *s)
 	if (s[0] == 'A') {
 		return g_strdup (&(s[1]));
 	} else if (s[0] == 'B') {
-		int len;
+		gsize len;
 		char *p = g_base64_decode (&(s[1]), &len);
 		if (p == NULL || len < 0) /* error was probably logged by now */
 			return NULL;
diff --git a/src/eval.c b/src/eval.c
index 45d3a05..c404213 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2010 Jiri (George) Lebl
+ * Copyright (C) 1997-2011 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -247,6 +247,9 @@ branches (int op)
 		case GEL_E_BREAK: return 0;
 		case GEL_E_MOD_CALC: return 2;
 		case GEL_E_DEFEQUALS: return 2;
+		case GEL_E_SWAPWITH: return 2;
+		case GEL_E_INCREMENT: return 1;
+		case GEL_E_INCREMENT_BY: return 2;
 	}
 	return 0;
 }
@@ -3138,6 +3141,9 @@ static const GelOper prim_table[GEL_E_OPER_LAST] = {
 	/*GEL_E_BREAK*/ EMPTY_PRIM,
 	/*GEL_E_MOD_CALC*/ EMPTY_PRIM,
 	/*GEL_E_DEFEQUALS*/ EMPTY_PRIM,
+	/*GEL_E_SWAPWITH*/ EMPTY_PRIM,
+	/*GEL_E_INCREMENT*/ EMPTY_PRIM,
+	/*GEL_E_INCREMENT_BY*/ EMPTY_PRIM,
 	/*GEL_E_OPER_LAST*/
 };
 
@@ -5327,17 +5333,25 @@ iter_get_matrix_p(GelETree *m, gboolean *new_matrix)
 			return NULL;
 		}
 		f = d_lookup_local(m->id.id);
-		if(!f) {
-			GelETree *t;
-			GEL_GET_NEW_NODE(t);
-			t->type = GEL_MATRIX_NODE;
-			t->mat.matrix = gel_matrixw_new();
-			t->mat.quoted = FALSE;
-			gel_matrixw_set_size(t->mat.matrix,1,1);
+		if (f == NULL) {
+			GelEFunc *fg = d_lookup_global (m->id.id);
 
-			f = d_makevfunc(m->id.id,t);
-			d_addfunc(f);
-			if(new_matrix) *new_matrix = TRUE;
+			if (fg != NULL) {
+				f = d_addfunc (d_makerealfunc (fg,
+							       m->id.id,
+							       FALSE));
+			} else {
+				GelETree *t;
+				GEL_GET_NEW_NODE(t);
+				t->type = GEL_MATRIX_NODE;
+				t->mat.matrix = gel_matrixw_new();
+				t->mat.quoted = FALSE;
+				gel_matrixw_set_size(t->mat.matrix,1,1);
+
+				f = d_makevfunc(m->id.id,t);
+				d_addfunc(f);
+				if(new_matrix) *new_matrix = TRUE;
+			}
 		} else if G_UNLIKELY (f->type != GEL_USER_FUNC &&
 				      f->type != GEL_VARIABLE_FUNC) {
 			gel_errorout (_("Indexed Lvalue not user function"));
@@ -5367,7 +5381,7 @@ iter_get_matrix_p(GelETree *m, gboolean *new_matrix)
 			return NULL;
 		}
 
-		f = d_lookup_local(l->id.id);
+		f = d_lookup_global(l->id.id);
 		if G_UNLIKELY (f == NULL) {
 			gel_errorout (_("Dereference of undefined variable!"));
 			return NULL;
@@ -5481,7 +5495,7 @@ iter_equalsop(GelETree *n)
 			return;
 		}
 		
-		f = d_lookup_local(ll->id.id);
+		f = d_lookup_global(ll->id.id);
 		if G_UNLIKELY (f == NULL) {
 			gel_errorout (_("Dereference of undefined variable!"));
 			return;
@@ -5684,6 +5698,476 @@ iter_equalsop(GelETree *n)
 	replacenode(n,r);
 }
 
+static GelEFunc *
+get_functoset (GelETree *l)
+{
+	if(l->type == GEL_IDENTIFIER_NODE) {
+		if G_UNLIKELY (l->id.id->parameter) {
+			gel_errorout (_("Increment/Swapwith does not work on parameters (trying to increment '%s')"),
+				      l->id.id->token);
+			return NULL;
+		} else if G_UNLIKELY (d_curcontext() == 0 &&
+			       l->id.id->protected_) {
+			gel_errorout (_("Trying to set a protected id '%s'"),
+				      l->id.id->token);
+			return NULL;
+		} else {
+			GelEFunc *f;
+
+			f = d_lookup_local (l->id.id);
+			if (f == NULL) {
+				GelEFunc *fg = d_lookup_global (l->id.id);
+				if (fg != NULL)
+					f = d_addfunc (d_makerealfunc (fg,
+								       l->id.id,
+								       FALSE));
+				else
+					f = d_addfunc (d_makevfunc (l->id.id, gel_makenum_ui (0)));
+			}
+			return f;
+		}
+	} else if(l->op.oper == GEL_E_DEREFERENCE) {
+		GelEFunc *f;
+		GelETree *ll;
+		GEL_GET_L(l,ll);
+
+		if G_UNLIKELY (ll->type != GEL_IDENTIFIER_NODE) {
+			gel_errorout (_("Dereference of non-identifier!"));
+			return NULL;
+		}
+		
+		f = d_lookup_global (ll->id.id);
+		if G_UNLIKELY (f == NULL) {
+			gel_errorout (_("Dereference of undefined variable!"));
+			return NULL;
+		}
+		if G_UNLIKELY (f->type!=GEL_REFERENCE_FUNC) {
+			gel_errorout (_("Dereference of non-reference!"));
+			return NULL;
+		}
+
+		if G_UNLIKELY (f->data.ref->context == 0 &&
+			       f->data.ref->id->protected_) {
+			gel_errorout (_("Trying to set a protected id '%s'"),
+				      f->data.ref->id->token);
+			return NULL;
+		}
+
+		return f->data.ref;
+	}
+
+	return NULL;
+}
+
+static void
+iter_incrementop (GelETree *n)
+{
+	GelETree *l;
+	mpw_ptr by;
+
+	if (n->op.args->any.next == NULL) {
+		GEL_GET_L(n,l);
+		by = NULL;
+	} else {
+		GelETree *r;
+		GEL_GET_LR(n,l,r);
+		if (r->type != GEL_VALUE_NODE) {
+			gel_errorout (_("Increment not a value!"));
+			return;
+		}
+		by = r->val.value;
+	}
+
+	if G_UNLIKELY (l->type != GEL_IDENTIFIER_NODE &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_GET_VELEMENT) &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_GET_ELEMENT) &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_GET_COL_REGION) &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_GET_ROW_REGION) &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_DEREFERENCE)) {
+		gel_errorout (_("Lvalue not an identifier/dereference/matrix location!"));
+		return;
+	}
+
+	if (l->type == GEL_IDENTIFIER_NODE ||
+	    l->op.oper == GEL_E_DEREFERENCE) {
+		GelEFunc *f = get_functoset (l);
+		if G_UNLIKELY (f == NULL) {
+			return;
+		} else if G_UNLIKELY (f->type != GEL_VARIABLE_FUNC ||
+				      ! (f->data.user->type == GEL_VALUE_NODE ||
+					 f->data.user->type == GEL_MATRIX_NODE)) {
+			gel_errorout (_("Trying to increment non-value id '%s'"),
+				      l->id.id->token);
+			return;
+		}
+
+		if (f->data.user->type == GEL_VALUE_NODE) {
+			if (by == NULL)
+				mpw_add_ui (f->data.user->val.value, f->data.user->val.value, 1);
+			else
+				mpw_add (f->data.user->val.value, f->data.user->val.value, by);
+		} else if (f->data.user->type == GEL_MATRIX_NODE) {
+			gel_matrixw_incr (f->data.user->mat.matrix, by);
+		}
+	} else if(l->op.oper == GEL_E_GET_ELEMENT) {
+		GelMatrixW *mat;
+		GelETree *m, *index1, *index2;
+		GEL_GET_LRR (l, m, index1, index2);
+
+		if (index1->type == GEL_VALUE_NODE &&
+		    index2->type == GEL_VALUE_NODE) {
+			int x, y;
+
+			x = iter_get_matrix_index_num (index2, INT_MAX);
+			if (x < 0)
+				return;
+			y = iter_get_matrix_index_num (index1, INT_MAX);
+			if (y < 0)
+				return;
+
+			mat = iter_get_matrix_p (l->op.args, NULL);
+			if (mat == NULL)
+				return;
+
+			gel_matrixw_incr_element (mat, x, y, by);
+		} else if ((index1->type == GEL_VALUE_NODE ||
+			    index1->type == GEL_MATRIX_NODE) &&
+			   (index2->type == GEL_VALUE_NODE ||
+			    index2->type == GEL_MATRIX_NODE)) {
+			int *regx, *regy;
+			int lx, ly;
+
+			if ( ! iter_get_index_regions (index1, index2,
+						       INT_MAX, INT_MAX,
+						       &regy, &regx,
+						       &ly, &lx))
+				return;
+
+			mat = iter_get_matrix_p (l->op.args, NULL);
+			if (mat == NULL) {
+				g_free (regx);
+				g_free (regy);
+				return;
+			}
+
+			gel_matrixw_incr_region (mat, regx, regy, lx, ly, by);
+			g_free (regx);
+			g_free (regy);
+		} else {
+			gel_errorout (_("Matrix index not an integer or a vector"));
+			return;
+		}
+	} else if(l->op.oper == GEL_E_GET_VELEMENT) {
+		GelMatrixW *mat;
+		GelETree *m, *index;
+		GEL_GET_LR (l, m, index);
+
+		if (index->type == GEL_VALUE_NODE) {
+			int i;
+
+			i = iter_get_matrix_index_num (index, INT_MAX);
+			if (i < 0)
+				return;
+
+			mat = iter_get_matrix_p (l->op.args, NULL);
+			if (mat == NULL)
+				return;
+
+			gel_matrixw_incr_velement (mat, i, by);
+		} else if (index->type == GEL_MATRIX_NODE) {
+			int *reg;
+			int len;
+
+			if ( ! iter_get_index_region (index, INT_MAX,
+						      &reg, &len))
+				return;
+
+			mat = iter_get_matrix_p (l->op.args, NULL);
+			if (mat == NULL) {
+				g_free (reg);
+				return;
+			}
+
+			gel_matrixw_incr_vregion (mat, reg, len, by);
+			g_free (reg);
+		} else {
+			gel_errorout (_("Matrix index not an integer or a vector"));
+			return;
+		}
+	} else /*l->data.oper == GEL_E_GET_COL_REGION GEL_E_GET_ROW_REGION*/ {
+		GelMatrixW *mat;
+		GelETree *m, *index;
+		GEL_GET_LR (l, m, index);
+
+		if (index->type == GEL_VALUE_NODE ||
+		    index->type == GEL_MATRIX_NODE) {
+			int *regx, *regy;
+			int lx, ly;
+			int i;
+
+			if (l->op.oper == GEL_E_GET_COL_REGION) {
+				if ( ! iter_get_index_region (index, INT_MAX, &regx, &lx))
+					return;
+			} else {
+				if ( ! iter_get_index_region (index, INT_MAX, &regy, &ly))
+					return;
+			}
+
+			mat = iter_get_matrix_p (l->op.args, NULL);
+			if (mat == NULL) {
+				g_free (regx);
+				g_free (regy);
+				return;
+			}
+
+			if (l->op.oper == GEL_E_GET_COL_REGION) {
+				ly = gel_matrixw_height (mat);
+				regy = g_new (int, ly);
+				for (i = 0; i < ly; i++)
+					regy[i] = i;
+			} else {
+				lx = gel_matrixw_width (mat);
+				regx = g_new (int, lx);
+				for (i = 0; i < lx; i++)
+					regx[i] = i;
+			}
+
+			gel_matrixw_incr_region (mat, regx, regy, lx, ly, by);
+			g_free (regx);
+			g_free (regy);
+		} else {
+			gel_errorout (_("Matrix index not an integer or a vector"));
+			return;
+		}
+	}
+	replacenode(n,gel_makenum_null ());
+}
+
+static void
+do_swapwithop (GelETree *l, GelETree *r)
+{
+	int lx, ly;
+	int rx, ry;
+	GelMatrixW *matr, *matl;
+	GelETree *tmp;
+
+	if (l->type == GEL_IDENTIFIER_NODE ||
+	    l->op.oper == GEL_E_DEREFERENCE) {
+		GelEFunc *lf = get_functoset (l);
+		if (lf == NULL)
+			return;
+		if (lf->type != GEL_VARIABLE_FUNC) {
+			gel_errorout (_("Can only swap user variables"));
+			return;
+		}
+		if (r->type == GEL_IDENTIFIER_NODE ||
+		    r->op.oper == GEL_E_DEREFERENCE) {
+			GelEFunc *rf = get_functoset (r);
+			GelETree *tmp;
+
+			if (rf->type != GEL_VARIABLE_FUNC) {
+				gel_errorout (_("Can only swap user variables"));
+				return;
+			}
+
+			tmp = lf->data.user;
+			lf->data.user = rf->data.user;
+			rf->data.user = tmp;
+		} else if(r->op.oper == GEL_E_GET_ELEMENT) {
+			GelMatrixW *mat;
+			GelETree *m, *index1, *index2;
+			GEL_GET_LRR (r, m, index1, index2);
+
+			if (index1->type == GEL_VALUE_NODE &&
+			    index2->type == GEL_VALUE_NODE) {
+				int x, y;
+				GelETree *t, *tmp;
+
+				x = iter_get_matrix_index_num (index2, INT_MAX);
+				if (x < 0)
+					return;
+				y = iter_get_matrix_index_num (index1, INT_MAX);
+				if (y < 0)
+					return;
+
+				mat = iter_get_matrix_p (r->op.args, NULL);
+				if (mat == NULL)
+					return;
+
+				gel_matrixw_set_at_least_size (mat, x+1, y+1);
+				gel_matrixw_make_private (mat, TRUE /* kill_type_caches */);
+				t = gel_matrixw_get_index (mat, x, y);
+				if (t != NULL) {
+					tmp = lf->data.user;
+					lf->data.user = t;
+					gel_matrixw_set_index (mat, x, y) = tmp;
+				} else {
+					gel_matrixw_set_index (mat, x, y) = lf->data.user;
+					lf->data.user = gel_makenum_ui (0);
+				}
+			} else {
+				gel_errorout (_("Cannot swap matrix regions"));
+			}
+		} else if(r->op.oper == GEL_E_GET_VELEMENT) {
+			GelMatrixW *mat;
+			GelETree *m, *index;
+			GEL_GET_LR (r, m, index);
+
+			if (index->type == GEL_VALUE_NODE) {
+				int i, x, y;
+				GelETree *t, *tmp;
+
+				i = iter_get_matrix_index_num (index, INT_MAX);
+				if (i < 0)
+					return;
+
+				mat = iter_get_matrix_p (r->op.args, NULL);
+				if (mat == NULL)
+					return;
+
+
+				GEL_MATRIXW_VINDEX_TO_INDEX (matl, i, x, y);
+
+				gel_matrixw_set_at_least_size (mat, x+1, y+1);
+				gel_matrixw_make_private (mat, TRUE /* kill_type_caches */);
+
+				t = gel_matrixw_get_vindex (mat, i);
+				if (t != NULL) {
+					tmp = lf->data.user;
+					lf->data.user = t;
+					gel_matrixw_set_index (mat, x, y) = tmp;
+				} else {
+					gel_matrixw_set_index (mat, x, y) = lf->data.user;
+					lf->data.user = gel_makenum_ui (0);
+				}
+			} else {
+				gel_errorout (_("Cannot swap matrix regions"));
+			}
+		}
+		return;
+	} else if (r->type == GEL_IDENTIFIER_NODE ||
+		   r->op.oper == GEL_E_DEREFERENCE) {
+		do_swapwithop (r, l);
+		return;
+	}
+
+	matl = iter_get_matrix_p (l->op.args, NULL);
+	if (matl == NULL)
+		return;
+
+	matr = iter_get_matrix_p (r->op.args, NULL);
+	if (matr == NULL)
+		return;
+
+	if (l->op.oper == GEL_E_GET_ELEMENT) {
+		GelETree *m, *index1, *index2;
+		GEL_GET_LRR (l, m, index1, index2);
+
+		if (index1->type == GEL_VALUE_NODE &&
+		    index2->type == GEL_VALUE_NODE) {
+			lx = iter_get_matrix_index_num (index2, INT_MAX);
+			if (lx < 0)
+				return;
+			ly = iter_get_matrix_index_num (index1, INT_MAX);
+			if (ly < 0)
+				return;
+		} else {
+			gel_errorout (_("Cannot swap matrix regions"));
+			return;
+		}
+	} else if (l->op.oper == GEL_E_GET_VELEMENT) {
+		GelETree *m, *index;
+		GEL_GET_LR (l, m, index);
+
+		if (index->type == GEL_VALUE_NODE) {
+			int i;
+
+			i = iter_get_matrix_index_num (index, INT_MAX);
+			if (i < 0)
+				return;
+
+			GEL_MATRIXW_VINDEX_TO_INDEX (matl, i, lx, ly);
+		} else {
+			gel_errorout (_("Cannot swap matrix regions"));
+			return;
+		}
+	}
+
+	if (r->op.oper == GEL_E_GET_ELEMENT) {
+		GelETree *m, *index1, *index2;
+		GEL_GET_LRR (r, m, index1, index2);
+
+		if (index1->type == GEL_VALUE_NODE &&
+		    index2->type == GEL_VALUE_NODE) {
+			rx = iter_get_matrix_index_num (index2, INT_MAX);
+			if (rx < 0)
+				return;
+			ry = iter_get_matrix_index_num (index1, INT_MAX);
+			if (ry < 0)
+				return;
+		} else {
+			gel_errorout (_("Cannot swap matrix regions"));
+			return;
+		}
+	} else if(r->op.oper == GEL_E_GET_VELEMENT) {
+		GelETree *m, *index;
+		GEL_GET_LR (r, m, index);
+
+		if (index->type == GEL_VALUE_NODE) {
+			int i;
+
+			i = iter_get_matrix_index_num (index, INT_MAX);
+			if (i < 0)
+				return;
+
+			GEL_MATRIXW_VINDEX_TO_INDEX (matl, i, rx, ry);
+		} else {
+			gel_errorout (_("Cannot swap matrix regions"));
+			return;
+		}
+	}
+
+	gel_matrixw_set_at_least_size (matl, lx+1, ly+1);
+	gel_matrixw_set_at_least_size (matr, rx+1, ry+1);
+
+	if (matl == matr && lx == rx && ly == ry)
+		return;
+
+	gel_matrixw_make_private (matl, TRUE /* kill_type_caches */);
+	gel_matrixw_make_private (matr, TRUE /* kill_type_caches */);
+
+	tmp = gel_matrixw_set_index (matr, rx, ry);
+	gel_matrixw_set_index (matr, rx, ry) = gel_matrixw_set_index (matl, lx, ly);
+	gel_matrixw_set_index (matl, lx, ly) = tmp;
+}
+
+static void
+iter_swapwithop(GelETree *n)
+{
+	GelETree *l, *r;
+
+	GEL_GET_LR(n,l,r);
+
+	if G_UNLIKELY (l->type != GEL_IDENTIFIER_NODE &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_GET_VELEMENT) &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_GET_ELEMENT) &&
+		       !(l->type == GEL_OPERATOR_NODE && l->op.oper == GEL_E_DEREFERENCE)) {
+		gel_errorout (_("Lvalue not an identifier/dereference/matrix location!"));
+		return;
+	}
+	if G_UNLIKELY (r->type != GEL_IDENTIFIER_NODE &&
+		       !(r->type == GEL_OPERATOR_NODE && r->op.oper == GEL_E_GET_VELEMENT) &&
+		       !(r->type == GEL_OPERATOR_NODE && r->op.oper == GEL_E_GET_ELEMENT) &&
+		       !(r->type == GEL_OPERATOR_NODE && r->op.oper == GEL_E_DEREFERENCE)) {
+		gel_errorout (_("Lvalue not an identifier/dereference/matrix location!"));
+		return;
+	}
+
+	do_swapwithop (l, r);
+
+	replacenode (n, gel_makenum_null ());
+}
+
 static void
 iter_parameterop (GelETree *n)
 {
@@ -5749,6 +6233,52 @@ iter_push_indexes_and_arg(GelCtx *ctx, GelETree *n)
 	}
 }
 
+static inline void
+iter_do_push_index (GelCtx *ctx, GelETree *l)
+{
+	GelETree *ident;
+
+	if (l->op.oper == GEL_E_GET_ELEMENT) {
+		GelETree *ll,*rr;
+		
+		GEL_GET_LRR(l,ident,ll,rr);
+
+		GE_PUSH_STACK(ctx,rr,GE_PRE);
+		GE_PUSH_STACK(ctx,ll,GE_PRE);
+	} else if(l->op.oper == GEL_E_GET_VELEMENT ||
+		  l->op.oper == GEL_E_GET_COL_REGION ||
+		  l->op.oper == GEL_E_GET_ROW_REGION) {
+		GelETree *ll;
+		
+		GEL_GET_LR(l,ident,ll);
+		GE_PUSH_STACK(ctx,ll,GE_PRE);
+	}
+}
+
+static inline void
+iter_push_left_indexes_only(GelCtx *ctx, GelETree *n)
+{
+	GelETree *l;
+
+	GEL_GET_L(n,l);
+
+	iter_do_push_index (ctx, l);
+	iter_pop_stack (ctx);
+}
+
+static inline void
+iter_push_indexes_both (GelCtx *ctx, GelETree *n)
+{
+	GelETree *l,*r,*ident;
+
+	GEL_GET_LR(n,l,r);
+
+	iter_do_push_index (ctx, l);
+	iter_do_push_index (ctx, r);
+
+	iter_pop_stack (ctx);
+}
+
 static void
 iter_get_velement (GelETree *n)
 {
@@ -5983,6 +6513,9 @@ iter_get_op_name(int oper)
 	case GEL_E_SEPAR:
 	case GEL_E_EQUALS:
 	case GEL_E_DEFEQUALS:
+	case GEL_E_SWAPWITH:
+	case GEL_E_INCREMENT:
+	case GEL_E_INCREMENT_BY:
 	case GEL_E_PARAMETER: break;
 	case GEL_E_ABS: name = g_strdup(_("Absolute value")); break;
 	case GEL_E_PLUS: name = g_strdup(_("Addition")); break;
@@ -6171,6 +6704,30 @@ iter_operator_pre(GelCtx *ctx)
 		iter_push_indexes_and_arg(ctx,n);
 		break;
 
+	case GEL_E_INCREMENT:
+		EDEBUG("  INCREMENT PRE");
+		GE_PUSH_STACK (ctx, n,
+			       GE_ADDWHACKARG (GE_POST,
+					       ctx->whackarg));
+		iter_push_left_indexes_only(ctx,n);
+		break;
+
+	case GEL_E_INCREMENT_BY:
+		EDEBUG("  EQUALS PRE");
+		GE_PUSH_STACK (ctx, n,
+			       GE_ADDWHACKARG (GE_POST,
+					       ctx->whackarg));
+		iter_push_indexes_and_arg(ctx,n);
+		break;
+
+	case GEL_E_SWAPWITH:
+		EDEBUG("  SWAPWITH PRE");
+		GE_PUSH_STACK (ctx, n,
+			       GE_ADDWHACKARG (GE_POST,
+					       ctx->whackarg));
+		iter_push_indexes_both(ctx,n);
+		break;
+
 	case GEL_E_PARAMETER:
 		EDEBUG("  PARAMETER PRE");
 		GE_PUSH_STACK (ctx, n,
@@ -6470,6 +7027,19 @@ iter_operator_post (GelCtx *ctx, gboolean *repushed)
 		iter_pop_stack(ctx);
 		break;
 
+	case GEL_E_INCREMENT:
+	case GEL_E_INCREMENT_BY:
+		EDEBUG("  INCREMENT POST");
+		iter_incrementop(n);
+		iter_pop_stack(ctx);
+		break;
+
+	case GEL_E_SWAPWITH:
+		EDEBUG("  SWAPWITH POST");
+		iter_swapwithop(n);
+		iter_pop_stack(ctx);
+		break;
+
 	case GEL_E_PARAMETER:
 		EDEBUG("  PARAMETER POST");
 		iter_parameterop (n);
diff --git a/src/funclib.c b/src/funclib.c
index dd372ef..2ea347c 100644
--- a/src/funclib.c
+++ b/src/funclib.c
@@ -6285,9 +6285,9 @@ gel_funclib_addall(void)
 
 	FUNC (Identity, 1, "x", "basic", N_("Identity function, returns its argument"));
 
-	VFUNC (rand, 1, "size", "numeric", N_("Generate random float"));
+	VFUNC (rand, 1, "size", "numeric", N_("Generate random float between 0 and 1, or if size given generate vector or matrix of random floats"));
 	f->no_mod_all_args = 1;
-	VFUNC (randint, 2, "max,size", "numeric", N_("Generate random integer"));
+	VFUNC (randint, 2, "max,size", "numeric", N_("Generate random integer between 0 and max-1 inclusive, or if size given generate vector or matrix of random integers"));
 	f->no_mod_all_args = 1;
 
 	PARAMETER (FloatPrecision, N_("Floating point precision"));
diff --git a/src/geniustests.txt b/src/geniustests.txt
index 9df2500..3e5558f 100644
--- a/src/geniustests.txt
+++ b/src/geniustests.txt
@@ -389,6 +389,8 @@ RowMedian([1,2,2,3;1,2,3,4;2,2,2,2;2,2,3,2])			[2;2 1/2;2;2]
 Median([1,2,3])							2
 Median([1,4,2,3])						2 1/2
 SortVector([1,2,2,3,1,2,3,4,2,2,2,2,2,2,3,2])			[1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,4]
+SortVector([3,2,1])						[1,2,3]
+SortVector(null)+1						((null)+1)
 [1,2,3;4,5,6;7,8,8]^-2						[17,-20 2/3,9;-25 1/3,31 2/3,-14;10 1/3,-13 1/3,6]
 [1,2,3;4,5,6;7,8,8]^4						[6981,8598,9597;15876,19557,21834;23273,28672,32014]
 [1,2;3,4]^5							[1069,1558;2337,3406]
@@ -1028,6 +1030,40 @@ Combinations(3,2)						Combinations(3,2)
 Permutations(3,2)						Permutations(3,2)
 Combinations(-1,2)						Combinations(-1,2)
 Permutations(-1,2)						Permutations(-1,2)
+increment i;i							1
+i=1;increment i;i						2
+i=1.1;increment i;i						2.1
+increment i by 1.1;i						1.1
+i=1;increment i by 1.1;i					2.1
+i=1.1;increment i by 1.1;i					2.2
+v=[0,1,2];increment v;v						[1,2,3]
+v=[0,1,2];increment v by 2;v					[2,3,4]
+v=[0,1,2];increment v@([2,3]);v					[0,2,3]
+v=[0,1,2];increment v@(2);v					[0,2,2]
+v=[0,1;2,3];increment v;v					[1,2;3,4]
+v=[0,1;2,3];increment v@(1,2);v					[0,2;2,3]
+v=[0,1;2,3];increment v@(1,:);v					[1,2;2,3]
+v=[0,1;2,3];increment v@(:,2);v					[0,2;2,4]
+v=[0,1;2,3];increment v@([1,2],[1,2]);v				[1,2;3,4]
+v=[0,1;2,3];increment v@([1,2],[1]);v				[1,1;3,3]
+v=[0,1;2,3];increment v@([1,2],[3]);v				[0,1,1;2,3,1]
+increment v@(3);v						[0,0,1]
+increment v@(3) by -1;v						[0,0,-1]
+v=[1,2];increment v@(3);v					[1,2,1]
+i=1;j=2;i swapwith j;[i,j]					[2,1]
+v=[1,2,3];w=[4,5,6];v@(2) swapwith w@(3);[v;w]			[1,6,3;4,5,2]
+v=[1,2,3];v@(2) swapwith v@(3);v				[1,3,2]
+v=[1,2,3];v@(2) swapwith v@(4);v				[1,0,3,2]
+v=[1;2;3];v@(2) swapwith v@(4);v				[1;0;3;2]
+m=[1,2;3,4];m@(1,1) swapwith m@(1,2);m				[2,1;3,4]
+m=[1,2;3,4];m@(3,1) swapwith m@(1,2);m				[1,0;3,4;2,0]
+k=99;m=[1,2;3,4];k swapwith m@(1,2);m				[1,99;3,4]
+k=99;m=[1,2;3,4];m@(1,2) swapwith k;m				[1,99;3,4]
+ReverseVector([1:5])						`[5,4,3,2,1]
+ReverseVector(null)+1						((null)+1)
+ShuffleVector([1])						[1]
+SortVector(ShuffleVector([6,5,4,3,2,1]))			[1,2,3,4,5,6]
+ShuffleVector(null)+1						((null)+1)
 load "nullspacetest.gel"					true
 load "longtest.gel"						true
 load "testprec.gel"						true
diff --git a/src/lexer.l b/src/lexer.l
index b36fbf0..cbef505 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2009 Jiri (George) Lebl
+ * Copyright (C) 1997-2011 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -262,6 +262,9 @@ gel_lexer_close(FILE *fp)
 =		{ NO_RET; return EQUALS; }
 :=		{ NO_RET; return DEFEQUALS; }
 
+swapwith	{ NO_RET; return SWAPWITH; }
+increment	{ NO_RET; return INCREMENT; }
+
 not		{ NO_RET; return LOGICAL_NOT; }
 and		{ NO_RET; return LOGICAL_AND; }
 xor		{ NO_RET; return LOGICAL_XOR; }
diff --git a/src/matrixw.c b/src/matrixw.c
index aecb501..749b58d 100644
--- a/src/matrixw.c
+++ b/src/matrixw.c
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2009 Jiri (George) Lebl
+ * Copyright (C) 1997-2011 Jiri (George) Lebl
  *
  * Author: George Lebl
  *
@@ -25,6 +25,7 @@
 #include <string.h>
 #include "structs.h"
 #include "eval.h"
+#include "calc.h"
 #include "matrix.h"
 
 /*implement the inline functions*/
@@ -586,6 +587,44 @@ gel_matrixw_set_element (GelMatrixW *m, int x, int y, gpointer data)
 	gel_matrixw_set_index (m, x, y) = data;
 }
 
+/*increment element*/
+int
+gel_matrixw_incr_element (GelMatrixW *m, int x, int y, mpw_ptr by)
+{
+	GelETree *t;
+
+	g_return_if_fail (m != NULL);
+	g_return_if_fail (x >= 0);
+	g_return_if_fail (y >= 0);
+#ifdef MATRIX_DEBUG
+	/*debug*/printf ("%s\n", G_GNUC_PRETTY_FUNCTION);
+#endif
+
+	if (m->tr)
+		internal_make_private (m, MAX(m->regh, y+1), MAX(m->regw, x+1),
+				       TRUE /* kill_type_caches */);
+	else
+		internal_make_private (m, MAX(m->regw, x+1), MAX(m->regh, y+1),
+				       TRUE /* kill_type_caches */);
+	gel_matrixw_set_at_least_size (m, x+1, y+1);
+	t = gel_matrixw_get_index (m, x, y);
+	if (t == NULL) {
+		if (by == NULL)
+			gel_matrixw_set_index (m, x, y) = gel_makenum_ui (1);
+		else
+			gel_matrixw_set_index (m, x, y) = gel_makenum (by);
+	} else if (t->type == GEL_VALUE_NODE) {
+		if (by == NULL)
+			mpw_add_ui (t->val.value, t->val.value, 1);
+		else
+			mpw_add (t->val.value, t->val.value, by);
+	} else {
+		gel_errorout (_("Trying to increment a nonvalue"));
+		return FALSE;
+	}
+	return TRUE;
+}
+
 /*set vector element*/
 void
 gel_matrixw_set_velement (GelMatrixW *m, int i, gpointer data)
@@ -624,6 +663,97 @@ gel_matrixw_set_velement (GelMatrixW *m, int i, gpointer data)
 	gel_matrixw_set_index (m, x, y) = data;
 }
 
+/*increment vector element*/
+int
+gel_matrixw_incr_velement (GelMatrixW *m, int i, mpw_ptr by)
+{
+	GelETree *t;
+	int x, y;
+
+	g_return_if_fail (m != NULL);
+	g_return_if_fail (i >= 0);
+
+	if (m->tr) {
+		if (m->regw == 1) {
+			x = 0;
+			y = i;
+		} else {
+			x = i % m->regh;
+			y = i / m->regh;
+		}
+		internal_make_private (m, MAX(m->regh, y+1), MAX(m->regw, x+1),
+				       TRUE /* kill_type_caches */);
+	} else {
+		if (m->regh == 1) {
+			x = i;
+			y = 0;
+		} else {
+			x = i % m->regw;
+			y = i / m->regw;
+		}
+		internal_make_private (m, MAX(m->regw, x+1), MAX(m->regh, y+1),
+				       TRUE /* kill_type_caches */);
+	}
+	gel_matrixw_set_at_least_size (m, x+1, y+1);
+	t = gel_matrixw_get_index (m, x, y);
+	if (t == NULL) {
+		if (by == NULL)
+			gel_matrixw_set_index (m, x, y) = gel_makenum_ui (1);
+		else
+			gel_matrixw_set_index (m, x, y) = gel_makenum (by);
+	} else if (t->type == GEL_VALUE_NODE) {
+		if (by == NULL)
+			mpw_add_ui (t->val.value, t->val.value, 1);
+		else
+			mpw_add (t->val.value, t->val.value, by);
+	} else {
+		gel_errorout (_("Trying to increment a nonvalue"));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int
+gel_matrixw_incr_region (GelMatrixW *m,
+			 int *destx, int *desty,
+			 int w, int h,
+			 mpw_ptr by)
+{
+	int i, j;
+
+	for (j = 0; j < h; j++) {
+		for (i = 0; i < w; i++) {
+			gel_matrixw_incr_element (m, destx[i], desty[j], by);
+		}
+	}
+}
+
+int
+gel_matrixw_incr (GelMatrixW *m, mpw_ptr by)
+{
+	int i, j, w, h;
+
+	w = gel_matrixw_width (m);
+	h = gel_matrixw_height (m);
+
+	for (j = 0; j < h; j++) {
+		for (i = 0; i < w; i++) {
+			gel_matrixw_incr_element (m, i, j, by);
+		}
+	}
+}
+
+int
+gel_matrixw_incr_vregion (GelMatrixW *m,
+			  int *desti, int len, mpw_ptr by)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		gel_matrixw_incr_velement (m, desti[i], by);
+	}
+}
+
 /*make sure it's in range first!*/
 GelMatrixW *
 gel_matrixw_get_region (GelMatrixW *m, int *regx, int *regy, int w, int h)
diff --git a/src/matrixw.h b/src/matrixw.h
index bf5e690..84954e1 100644
--- a/src/matrixw.h
+++ b/src/matrixw.h
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2008 Jiri (George) Lebl
+ * Copyright (C) 1997-2011 Jiri (George) Lebl
  *
  * Author: George Lebl
  *
@@ -67,6 +67,19 @@ void gel_matrixw_set_at_least_size(GelMatrixW *m, int width, int height);
 void gel_matrixw_set_element(GelMatrixW *m, int x, int y, gpointer data);
 void gel_matrixw_set_velement(GelMatrixW *m, int i, gpointer data);
 
+/*increment element (returns true on success) */
+/* NULL by means increment by 1 */
+int gel_matrixw_incr_element(GelMatrixW *m, int x, int y, mpw_ptr by);
+int gel_matrixw_incr_velement(GelMatrixW *m, int i, mpw_ptr by);
+int gel_matrixw_incr_region (GelMatrixW *m,
+			     int *destx, int *desty,
+			     int w, int h, mpw_ptr by);
+int gel_matrixw_incr_vregion (GelMatrixW *m,
+			     int *desti, int len,
+			     mpw_ptr by);
+int gel_matrixw_incr (GelMatrixW *m, mpw_ptr by);
+
+
 /*copy a matrix*/
 GelMatrixW * gel_matrixw_copy(GelMatrixW *source);
 
@@ -167,6 +180,21 @@ gel_matrixw_get_vindex(GelMatrixW *m, int i) {
 }
 #endif
 
+#define GEL_MATRIXW_VINDEX_TO_INDEX(m,i,x,y) \
+	{ \
+		int w = gel_matrixw_width(m); \
+		if (w == 1) { \
+			x = 0; \
+			y = i; \
+		} else if (gel_matrixw_height(m) == 1) { \
+			x = i; \
+			y = 0; \
+		} else { \
+			x = i % w; \
+			y = i / w; \
+		} \
+	}
+
 /* This should be usable as an lvalue */
 #define gel_matrixw_set_vindex(m,i) gel_matrixw_set_index((m),(i)%gel_matrixw_width(m),(i)/gel_matrixw_width(m))
 
diff --git a/src/parse.y b/src/parse.y
index 5f54e8d..60e1a26 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -1,5 +1,5 @@
 /* GENIUS Calculator
- * Copyright (C) 1997-2009 Jiri (George) Lebl
+ * Copyright (C) 1997-2011 Jiri (George) Lebl
  *
  * Author: Jiri (George) Lebl
  *
@@ -65,7 +65,7 @@ void yyerror(char *);
 
 %token AT MAKEIMAGPARENTH
 
-%token SEPAR NEXTROW EQUALS DEFEQUALS
+%token SEPAR NEXTROW EQUALS DEFEQUALS SWAPWITH
 
 %token TRANSPOSE
 
@@ -75,6 +75,8 @@ void yyerror(char *);
 
 %token LOGICAL_XOR LOGICAL_OR LOGICAL_AND LOGICAL_NOT
 
+%token INCREMENT
+
 %left NEXTROW
 
 %left SEPAR
@@ -83,6 +85,8 @@ void yyerror(char *);
 %nonassoc FUNCTION PARAMETER
 
 %nonassoc LOWER_THAN_ELSE
+%nonassoc LOWER_THAN_INCREMENT
+%nonassoc INCREMENT
 %nonassoc WHILE UNTIL DO IF FOR SUM PROD TO BY IN THEN ELSE RETURNTOK LOCAL
 
 %left LOGICAL_XOR LOGICAL_OR
@@ -91,7 +95,8 @@ void yyerror(char *);
 
 %left MOD
 
-%right EQUALS DEFEQUALS
+%right EQUALS DEFEQUALS 
+%nonassoc SWAPWITH
 
 %nonassoc CMP_CMP
 %right EQ_CMP NE_CMP LT_CMP GT_CMP LE_CMP GE_CMP
@@ -151,6 +156,9 @@ expr:		expr SEPAR expr		{ PUSH_ACT(GEL_E_SEPAR); }
 					  PUSH_ACT(GEL_E_MUL); }
 	|	expr EQUALS expr	{ PUSH_ACT(GEL_E_EQUALS); }
 	|	expr DEFEQUALS expr	{ PUSH_ACT(GEL_E_DEFEQUALS); }
+	|	INCREMENT expr %prec LOWER_THAN_INCREMENT { PUSH_ACT(GEL_E_INCREMENT); }
+	|	INCREMENT expr BY expr %prec INCREMENT { PUSH_ACT(GEL_E_INCREMENT_BY); }
+	|	expr SWAPWITH expr	{ PUSH_ACT(GEL_E_SWAPWITH); }
 	|	'|' expr '|'		{ PUSH_ACT(GEL_E_ABS); }
 	|	expr '+' expr		{ PUSH_ACT(GEL_E_PLUS); }
 	|	expr ELTELTPLUS expr	{ PUSH_ACT(GEL_E_ELTPLUS); }
diff --git a/src/structs.h b/src/structs.h
index a41dbde..ccf892d 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -405,6 +405,9 @@ enum {
 	GEL_E_BREAK,
 	GEL_E_MOD_CALC,
 	GEL_E_DEFEQUALS,
+	GEL_E_SWAPWITH,
+	GEL_E_INCREMENT,
+	GEL_E_INCREMENT_BY,
 	GEL_E_OPER_LAST
 };
 
diff --git a/src/testscope.gel b/src/testscope.gel
index 8c29e8c..1deca63 100644
--- a/src/testscope.gel
+++ b/src/testscope.gel
@@ -157,4 +157,38 @@ function f(x) = (
 h = f(0);
 if h(0) != 1+5 then (error("single explicit non-subst lookup failed");exit());
 
+v = [1,2,3];
+function f() = (
+	v@(3) = 99;
+	v
+);
+w = f();
+if [v;w] != [1,2,3;1,2,99] then (error("set vector element in function failed");exit());
+
+v = [1,2,3];
+function f() = (
+	v@(1) swapwith v@(3);
+	v
+);
+w = f();
+if [v;w] != [1,2,3;3,2,1] then (error("swapwith on vectors in function failed");exit());
+
+A = 1;
+B = 2;
+function f() = (
+	A swapwith B;
+	B
+);
+C=f();
+if [A,B,C] != [1,2,1] then (error("swapwith on variables in function failed");exit());
+
+A = 1;
+function f() = (
+	increment A;
+	A
+);
+B = f();
+if [A,B] != [1,2] then (error("increment on variable in function failed");exit());
+
+
 print("true");



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]