packages icon
Genius Calculator
=================

------------------------------------------------------------------
NOTE: if you are using the vi mode of readline and the gui version
of genius (gnome-genius), you need to patch readline since there
is a bug in readline that makes it lock up. I've sent a patch to
the maintainers. In the meantime apply the readline-4.0.patch.
------------------------------------------------------------------

Although it's under heavy development, it's actually very usable.
I use it myself as my desktop calculator.

To make myself look important, I also made up an official looking name for
the programming language of Genius, it's called GEL, (Genius Extention
Language) :)

Here's what doesn't work or isn't done yet: (somewhat of a TODO list)

- need to make more built-in functions!
- complete matrix support, right it is not complete
- CORBA interface
- do a code clean-up (such as split up eval.[ch]) and make the names of
  types, functions and variables more consistent
- clean up calc.[ch] to be a better "interface to the calculator"
- profile and make the code leaner and meaner
- optimize the engine a bit more

Features of Genius:

 * language is very close to real mathematical notation
 * arbitrary precision integers (2-36), multiple precision floats
 * uses rationals when possible
 * will calculate and show half calculated expressions if the calculation
   could not be completed
 * variables
 * user functions
 * variable and function references with C like syntax
 * anonymous functions
 * matrix support
 * complex numbers
 * modular arithmetic
 * more ...

How to use this thing: (this is just a quick description)

Just type in the expression and press enter to get a result.  The
expression is written in GEL (Genius Extention Language).  A simple
GEL expression looks just like a math expression. So you don't need
to learn GEL to use the calculator. GEL is used when you want to
define and use functions, and variables and do other cool things.

GEL is designed so that you can quickly get your result with the minimal
typing.

****************************************************************************
What follows is a simple description of GEL:

A program in GEL is basically an expression which evaluates to a number,
since there exist only numbers.

Previous result:

The "Ans" variable can be used to get the result of the last expression

so if you did some calculation and just wanted to add 389 to the result,
you'd do "Ans+389"

(you can also use the lowercase "ans" as well)

Functions:

For variables use the = operator, that operator sets the variable and
returns the number you set, so you can do something like "a=b=5", just
like in C. Variables are really functions with no argument

There are a number of built in functions (currently "e" "pi" "sin" "cos"
"tan", and more)

To type functions in:

function_name(argument1, argument2, argument3)
function_name()

to type in variables:

variable_name

(of course the number of arguments is different for each function)

NOTE: if you don't type the () in, the function will not be evaluated
but it will be returned as a "function node", unless of course if it's a
normal variable in which case it returns the value of the variable, so this
fact is used 
1) for variables
2) for passing functions to functions (explained below)

NOTE2: built in functions with 0 usually act like variables

Current built in functions:

name:		# of arguments:		description:

warranty	0			prints warranty and license info
exit		0			exits genius
quit		0			exits genius
help		0			displays a list of functions with
					short descriptions
sethelp		2 (string,string)	set a description for the above list,
					(to be used inside library files)
set_float_prec	1 (integer)		set the floating point precision
get_float_prec	0			get the current float_prec
set_max_digits	1 (integer)		set the maximum digits in a result
get_max_digits	0 			get the current max_digits
set_results_as_floats 1 (bool)		sets if the results should be always
					printed as floats
get_results_as_floats 0			returns if the results should be always
					printed as floats
set_scientific_notation 1 (bool)	sets if floats should be in scientific
					notation
get_scientific_notation 0		return if floats should be in scientific
					notation
set_full_expressions	1 (bool)	sets if we should print out full
					expressions for non-numeric return
					values (longer then a line)
get_full_expressions	0		return the full_expressions value
set_max_errors	1 (integer)		sets the maximum number of errors
					to return on one evaluation
get_max_errors	0			gets the maximum number of errors
					to return on one evaluation
error		1 (string)		prints an error to the error channel
print		1 (string)		prints a string onto the standard
					output
printn		1 (string)		prints a string onto the standard
					output without trailing carrige
					return
display		2 (string,value)	prints a string, a colon and then the
					value

sin		1 (value)		calculates the sin function
cos		1 (value)		calculates the cos function
sinh		1 (value)		calculates the hyperbolic sin function
cosh		1 (value)		calculates the hyperbolic cos function
tan		1 (value)		calculates the tan function
atan		1 (value)		calculates the inverse tan function
pi		0 			the number pi
e		0 			the number e (same as exp(1), but
					answer is cached)
sqrt		1 (value)		calculates the sqare root
exp		1 (value)		calculates the e^value (exponential
					function)
ln		1 (value)		calculates the natural logarithm
gcd		2 (integer,integer)	the greatest common divisor function
lcm		2 (integer,integer)	the least common multiple function
jacobi		2 (integer,integer)	obtain the jacobi symbol
legendre	2 (integer,integer)	obtain the legendre symbol
perfect_square	1 (integer)		return 1 if argument is a perfect
					square
max		2 (value,value)		returns the larger of the two values
min		2 (value,value)		returns the smaller of the two values
prime		1 (integer)		returns the n'th prime for primes up
					to n==100000
round		1 (value)		rounds the value
floor		1 (value)		greatest integer <= value
ceil		1 (value)		least integer >= value
trunc		1 (value)		truncate the number to an integer
float		1 (value)		make the number into a floating
					point number, no matter what type it
					was
Re		1 (value)		get the real part of a complex number
Im		1 (value)		get the imaginary part of a
					complex number
I		1 (integer)		make an identity matrix of the size n
rows		1 (matrix)		get the number of rows in a matrix
columns		1 (matrix)		get the number of columns in a matrix
det		1 (matrix)		calculate the determinant of a matrix
ref		1 (matrix)		reduce the matrix to row-echelon form
					using the gaussian elimination method
rref		1 (matrix)		reduce the matrix to reduced
					row-echelon form, this is usefull for
					solving systems of linear equations
set_size	3 (matrix,integer,integer)
					return a matrix which is truncated or
					extended according to the size given
					as rows, columns
is_value_only	1 (matrix)		are all the nodes in the matrix values

is_null		1 (anything)		returns true if the argument is a
					null (empty result not a 0)
is_value	1 (anything)		returns true if the argument is a
					scalar value
is_string	1 (anything)		returns true if the argument is a
					string
is_matrix	1 (anything)		returns true if the argument is a
					matrix
is_function	1 (anything)		returns true if the argument is a
					function (anonymous)
is_function_ref	1 (anything)		returns true if the argument is a
					reference variable to a function
is_complex	1 (anything)		returns true if the argument is a
					value and a complex number
is_real		1 (anything)		returns true if the argument is a
					value and a real number (note that
					this is not exactly the opposite of
					is_complex)
is_integer	1 (anything)		returns true if the argument is a
					non complex integer value
is_rational	1 (anything)		returns true if the argument is a
					non complex rational value, note that
					it returns false for integers!
is_float	1 (anything)		returns true if the argument is a
					non complex floating point value

is_poly		1 (vector)		does this vector look like a
					polynomial (horizontal with value
					nodes only)
trimpoly	1 (vector)		trim the 0's off of the polynomial
					high powers
addpoly		2 (vector,vector)	add two polynomials
subpoly		2 (vector,vector)	subtract two polynomials
mulpoly		2 (vector,vector)	multiply two polynomials
derpoly		1 (vector)		returns the first derivative of
					a polynomial
der2poly	1 (vector)		returns the second derivative of
					a polynomial
polytostring	2 (vector,string)	convert the polynomial to a string
					which is a humal (and GEL) readable
					expression, the string argument is
					what is to be used for the variable
					name (such as "x")
polytofunc	1 (vector)		convert the polynomial into a function 
					which you can then assign to an
					identifier for use


Functions in the standard library (lib.gel):

name:		# of arguments:		description:

abs		1 (value or matrix)	absolute value (see also |x| operator)
sum		3 (from,to,function)	calculates the sum of the function
					which should take one argument
					which is an integer stepped from
					"from" to "to
prod		3 (from,to,function)	calculates the product of the
					function which should take one
					argument which is an integer
					stepped from "from" to "to
infsum		3 (function,start,inc)	try to calculate an infinite sum, to
					the point where the new terms
					calculated by function, don't make
					any difference on the sum, the index
					is passed as a single argument to the
					function
infsum2		4 (function,arg,start,inc)
					like the above, but pass arg as the
					first argument to function and the
					index as the second
nPr		2 (integer,integer)	calculate permutations
nCr		2 (integer,integer)	calculate combinations
pascal		1 (integer)		get the pascal's triangle as a matrix
					up to the n'th row (one more row then
					the argument)
fib		1 (integer)		returns n'th fibbonachi number
catalan		1 (integer)		returns the n'th catalan number
minimize	1 (func,x,incr)		"minimize" the function: start
					evaluating at x, by increments of
					incr and return the first x where
					func is 0
trace		1 (matrix)		calculate the trace of the matrix
adj		1 (matrix)		return the adjoint matrix
delrowcol	1 (matrix,row,col)	delete the row and column indicated
					from a matrix and return the rest
convol		2 (vector,vector)	takes two horizontal vectors and
					calculates convolution
convol_vec	2 (vector,vector)	as above, but returns a vector of
					the individual terms
matsum		1 (matrix)		sums up all the terms of the matrix
matsum_sq	1 (matrix)		sums up all the squares of terms of
					the matrix
matprod		1 (matrix)		multiplies all the terms of the matrix
diagonal	1 (vector)		make a diagonal matrix from a
					horizontal vector
swaprow		3 (matrix,row1,row2)	swap two rows of a matrix
sortv		1 (vector)		sort the elements in a horizontal vector
reversev	1 (vector)		reverse the elements in a horizontal vector
rad2deg		1 (value)		convert radians to degrees
deg2rad		1 (value)		convert degrees to radians
asinh		1 (value)		hyperbolic inverse sin function
acosh		1 (value)		hyperbolic inverse cos function
cot		1 (value)		cotangent function
coth		1 (value)		hyperbolic cotangent function
acot		1 (value)		inverse cotangent function
acoth		1 (value)		hyperbolic inverse cotangent function
tanh		1 (value)		hyperbolic tangent function
atanh		1 (value)		hyperbolic inverse tangent function
csc		1 (value)		cosecant function
csch		1 (value)		hyperbolic cosecant function
acsc		1 (value)		inverse cosecant function
acsch		1 (value)		hyperbolic inverse cosecant function
sec		1 (value)		secant function
sech		1 (value)		hyperbolic secant function
asec		1 (value)		inverse secant function
asech		1 (value)		hyperbolic inverse secant function
sign		1 (value)		return the sign of the value (-1,0,1)
log		2 (value,base)		log of the value to the base b
log10		1 (value)		log of the value to the base 10
log2		1 (value)		log of the value to the base 2
conj		1 (value)		conjugate of a complex value

string		1 (anything)		convert to a string

rowsum		1 (matrix)		sum up the elements in rows and return
					a vertical vector with the results
rowsum_sq	1 (matrix)		sum up the squares of elements in rows
					and return a vertical vector with the
					results
rowmedian	1 (matrix)		calculate the median of each row and
					return a vertical vector with results
rowaverage	1 (matrix)		calculate the average of each row and
					return a vertical vector with results
rowstdev	1 (matrix)		calculate the standard deviateion of
					each row and return a vertical vector
					with results
rowstdevp	1 (matrix)		calculate the population standard
					deviation of each row and return a
					vertical vector with results
median		1 (matrix)		calculate the median of the entire
					matrix
average		1 (matrix)		calculate the average of the entire
					matrix
stdev		1 (matrix)		calculate the standard deviation of
					the entire matrix
stdevp		1 (matrix)		calculate the population standard
					deviation of the entire matrix

apply_over_matrix1
		1 (matrix,function)	apply function to every element in
					the matrix, mostly used inside the
					library functions
apply_over_matrix2
		1 (matrix or value,matrix or value,function)
					apply function to two matrixes or
					a matrix and a scalar value


To define a function do:


function <identifier>(<comma separated argument names>) = <function body>

(you could also assign the anonymous function syntax to an identifier as in:
 <identifier> = (`() = <function body>)

NOTE: that's a backquote and signifies an anonymous function, by setting
it to a variable name you effectively define a function

for example:

function sum(a,b,c) = a+b+c

then "sum(1,1,1)" yields 3

Absoulte value:

You can make an absolute value of something by putting the |'s around it.
Example:

|a-b|

Separator:

Finally there is the ';' operator, which is a way to separate expressions,
such a combined expression will return whatever is the result of the last
one, so

3 ; 5

yeilds 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's 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 ";.". This is usefull in case you don't want to return a
value from say a loop, or if you handle the return differently. Note that
it will slow down the code if it's executed too often as there is one
more operator involved.

The GEL operators:

a;b		separator, just evaluates both but returns only b
a=b		assignment operator asigns b to a (a must be a valid lvalue)
|a|		absolute value
a^b		exponentiation
a+b		addition
a-b		subtraction
a*b		multiplication
a/b		division
a%b		the mod operator
a mod b		mod evaluation operator (a evaluated mod b)
a!		factorial operator
a==b		equality operator (returns 1 or 0)
a!=b		inequality operator (returns 1 or 0)
a<>b		alternative inequality operator (returns 1 or 0)
a<=b		inequality operator (returns 1 or 0)
a>=b		inequality operator (returns 1 or 0)
a<=>b		comparison operator (returns -1, 0 or 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)
*a		variable dereferencing (to access a referenced varible)
a'		matrix transpose
a@(b,c)		get element of a matrix
a@(b,)		get row of a matrix
a@(,c)		get column of a matrix
a..b		specify a row, column region
a@(b)		get an element from a matrix treating it as a vector

NOTE: the @() operator for matrixes is the only place you can use the ..
operator. With it you can specify a range of values instead of just
one. 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. The exception to the
above rule is the a@(b) operator which will only take a single value,
it tries to treat the matrix as a vector, if the matrix is not a vector,
it will traverse the matrix row-wise.

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)

Lvalues:

Valid lvalues are

a		identifier
*a		dereference of an identifier
a@(<region>)	a region of a matrix (where the region is specified normally
		as with the regular @() operator)

Examples:

a=4
*tmp = 89
a@(4..8,3)=[1,2,3,4,5]'

There are also a number of constructs:

Conditionals:

if <expression1> then <expression2> [else <expression3>]

If else is omitted, then if the expression1 yeilds 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 )

Loops:

while <expression1> do <expression2>
until <expression1> do <expression2>
do <expression2> while <expression1>
do <expression2> until <expression1>

These are similiar to other languages, they return the result of
the last iteration or NULL if no iteration was done

For loops:

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 then 1. These are faster, nicer and more compact
then 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:

for <identifier> in <matrix> do <body>

For each element, going row by row from left to right do the body. To
print numbers 1,2,3 and 4 in this order you could do:

for n in [1,2:3,4] do print(n)


And now the comparison operators:

==,>=,<=,!=,<>,<,> return 1 for TRUE, 0 for FALSE

!= and <> are the same thing and mean "is not equal to". Make sure
you use == for equality however, as = will have the same outcomes as
it does in C.

<=> returns -1 if left side is smaller, 0 if both sides are equal, 1
    if left side is larger

To build up logical expressions use the words "not","and","or","xor"

"not" and "and" are special beasts as they evaluate their arguemnts one by
one, so the usual trick for conditional evaluation works here as well.
(E.g. "1 or a=1" will not set a=1 since the first argument was true)

You can also use break and continue, in the same manner as they are used
in C. Such as in (bn are booleans s is just some statement):

while(b1) do (
	if(b2) break
	else if(b3) continue;
	s1
)

Null:

Null is a special value, if it is returned, nothing is printed on
screen, no operations can be done on it. It is also usefull if you want
no output from a command. Null can be achieved as an expression when you
type . or nothing

Example:

    x=5;.
    x=5;

Returning:

Sometimes it's not good to return the last thing calculated, you may for
example want to return from a middle of a function. This is what the return
keyword is for, it takes one argument which is the return value

Example:

    function f(x) = (
	    y=1;
	    while(1) do (
		    if(x>50) then return y;
		    y=y+1;
		    x=x+1
	    )
    )

References: 

GEL contains references with a C like syntax. & references a variable
and * dereferences a variable, both can only be applied to an identifier
so **a is not legal in GEL

Example:

    a=1;
    b=&a;
    *b=2;

    now a contains 2

    function f(x) = x+1;
    t=&f;
    *t(3)

    gives us 4

Anonymous functions:

It is possible to say use a function in another function yet you don't know
what the function will be, you use an anonymous function. Anonymous function
is declared as:

function(<comma separated argument names>) = <function body>

or shorthand:

`(<comma separated argument names>) = <function body>

Example:

    function f(a,b) = a(b)+1;
    f(`(x) = x*x,2)

    will return 5 (2*2+1)

You can also just pass the function name as well:

    function f(a,b) = a(b)+1;
    function b(x) = x*x;
    f(b,2)


Matrix support:

To enter matrixes use one of the following two syntaxes. You can either
enter the matrix separating values by commas and rows by semicolons, or
separating values by tabs and rows by returns, or any combination of the
two. 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]

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
however use tabs and commas together, as long as you use at most 1 comma
to separate values. To enter tabs inside the command line version, you have
to do M-Tab (usually Alt-Tab), or however else you have your .inputrc set
up (since it uses readline)

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]

NOTE: be careful about using whitespace and returns for expressions inside
the '[',']' brackets, they have a slightly different meaning and could mess
you up.

Transpose operator:

You can transpose a matrix by using the ' operator, example:

[1,2,3]*[4,5,6]'

We transpose the second vector to make matrix multiplication possible.


Modular evaluation:

Sometimes when working with large numbers, it might be faster if results
are modded after each calculation. So there is a modular evaluation operator
ever since 0.4.5. To use it you just add "mod <integer>" after the
expression.

Example:

    2^(5!) * 3^(6!) mod 5


Strings:

You can enter strings into gel and store them as values inside variables
and pass them to functions. (And do just about anything that values can
do). You can also concatenate the strings with something else (anything),
with the plus operator. So say:

a=2+3;"The result is: "+a

Will create a string "The result is: 5". You can also use C-like escape
sequences \n,\t,\b,\a,\r, to get a \ or " into the string you can qoute it
with a \. Example:

"Slash: \\ Quotes: \" Tabs: \t1\t2\t3"

will make a string:
Slash: \ Quotes: " Tabs: 	1	2	3

You can use the library function string to convert anything to a string.
Example:

string(22)

will return "22".

Strings can also be compared with ==, != and <=> operators


Error handeling:

If you detect an error in your function, you can bail out of it. You can
either fail to compute the function which is for normal errors, such as
wrong types of arguments, just add the empty statement "bailout". If something
went really wrong and you want to completely kill the current computation,
you can use "exception".

Look at lib.gel for some examples.

Polynomials:

Genius can do some things on polynomials. Polynomials in genius 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,
subpoly and mulpoly functions and you can print out a human readable
string using the polytostring function. This function takes the polynomial
vector as the first argument and a string to use as the variable as the
second argument and returns a string. You can also get a funcion
representation of the polynomial so that you can evaluate it. This is
done by the polytofunc function, which returns an anonymous function which
you can assign to something.

f = polytofunc([0,1,1])
f(2)

Look at the function table for the rest of polynomial functions.

Loading external programs:

Sometimes you have a larger program that you wrote into a file and want
to read in that file, you have two options, you can keep the functions
you use most inside a ~/.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 then 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"


Calculator parameters:

There are several parameters that one can set that control the behaviour
of the calculator. You can either use functions with the prefixes get_ or
set_. The available parameters are:

float_prec		the floating point precision
max_digits		the maximum digits in a result
results_as_floats	if the results should be always printed as floats
scientific_notation	if floats should be in scientific notation
full_expressions	boolean, should we print out full expressions
			for non-numeric return values (longer then a line)
max_errors		the maximum number of errors to return on one
			evaluation

You can use the parameters just like a variable, and you can put the name
on the left side of an equals sign. However, the parameters are not treated
as variables. They are translated into the get_ and set_ functions just
before execution. So you have to only use it to get the current value or
on the left side of the equals sign.


Standard 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 lib.gel in it's installed place, you'll have to
first compile it with "genius --compile lib.gel > lib.cgel"


EXAMPLE PROGRAM in GEL:
    a user factorial function (there already is one built in so
    this function is useless)

    function f(x) = if x<=1 then 1 else (f(x-1)*x)

    or 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 :)
    it seems similiar to bc syntax, but different in that in gel, the
    last expression is the one that is returned. It can be done with with
    returns as:

    function f(x) = (
	    if (x <= 1) then return (1);
	    return (f(x-1) * x)
    )

    which is almost verbatim bc code, except for then and the function
    definition (although there is a compatibility bc like define keyword
    which will likely disappear in the forseeable future)

    here's an iterative version:

    function f(x) = (
	    r=x;
	    while (x>1) do
		    (x=x-1;r=r*x);
	    r
    )

    Here's a larger example, this basically redefines the internal ref
    function to calculate the same thing, but written in GEL:

    #calculate the row-echelon form of a matrix
    function ref(m) = (
	    if(not is_matrix(m) or not is_value_only(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
    )




****************************************************************************

NOTE: GMP sefaults on some very large numbers so factorials of large numbers
will do this ... I'll try to catch those before they happen, but I don't
see this as a high priority ... the listbox will segfault anyway on such
numbers :)

Requirements:
	- lex (tested under flex)
	- yacc (tested under bison -y)
	- gmp (tested with 2.0.2)
	- glib
	- gtk+ (only for the GUI version)
	- gnome libs (only for the GUI version)
All except gmp seem to be pretty much standard or Linux systems, and even
on most other platforms. (except gtk and gnome libs, but since this is
distributed with gnome ...)

It's under GPL so read COPYING

George <jirka@5z.com>

-----------------------------------------------------------------------------
OLD history, read ChangeLog for new changes:

what's new since pre-alpha-1:
	- support for all the primitives
	- some scientific functions
	- uses gnomeapp
	- variables
	- user defined functions
	- and a lot more ... read the ChangeLog!

what's new since unusable-3:
	- version change :)
	- can read arbitrary ints (base#number#, e.g. 7#442#)
	- again some very slight tinkering with the gui
	- exponentials using rationals are now calculated via Newton's
	  method (e.g. 3^(33/12) )

what's new since unusable-2:
	- integer exponantiation, meaning you can do <whatever>^<integer>
	- the display box now stretches out to make use of free space in
	  the window
	- characters from the numpad now properly insert themselves
	- a bit of code cleanup
	- automaic conversion of floats to integers can be turned off since
	  it can make less precise numbers look precise
	- you can also turn off exact answers and get answers to a certain
	  precision (10 digits), or get the whole enchilada (sometimes
	  the listbox will crash for very large integers)

what's new since unusable-1:
	- floats are now formatted and output ok.
	- options frame for swiching between notations
	- negative numbers are handled by lexer so that they work in
	  postfix and prefix, this broke parser for infix, so turn off
	  negative functions for infix and use the unary minus operator
	  instead (same result)
	- factorial added (only for ints :)
	- it will now convert to int whenever possible even inside
	  calculations
	- parser.c renamed to calc.c since it didn't makes sense
	- GUI changed a bit
	- negation function is now functional it is ~ now ... but -
	  can also be used in infix, but not in postfix or prefix
	  since that would be ambiguous though you can still write
	  a negative number in any notation
	- division now works, it will make a rational number from integers
	  but will do a division for floats or rationals (rationals make
	  precise divisions)
	- it can now display unevaluated parts of equation when an error
	  occurs or a part just can't be evaluated (such as division by
	  zero)
	- results are now put on the display list in the GUI.