/*----------------------------------------------------- GBnums language ------------------------------------------------------*/ 0.- General =========== It's ANSI C, with some restrictions and modifications 1. - Types =========== mpz : large integers (Z-numbers) mpf : large real numbers (F-numbers) mpq : large rationals (Q-numbers) uint : small 32-bits unsigned integers (vectors only) string : string of characters (length < 256) Exemples of declarations : mpz a,b; mpf PI; mpq q,r,s; mpz mm[100][100] ; uint vect[10000]; mpz *zz; // same as mpz zz[] ; string s; mpf complex zz; mpz polynomial pp = {1,2,3} ; Hint to port an existing C-program : #define int mpz #define double mpf 2. - Constants =============== a = 111111111111111111199999; b = 0xFEDAAAAAAAAAAAAAddddddddd; // hexa X = 2344444.55e+30; q = 1/3 ; // NO SPACES q= -17777777777777777/77 ; s = 'Hello world' ; // ' or " delimiter s = "Hello world" ; mpz v1[] = {1,5,77777777777777777777} ; mpq q1[2][2] = {1/3 , 1/4} {2/3 5/6} ; string uu[] = {'foo', 'gee'} 3. - Conversions ================= - conversions are automatically performed (implicit type casting) - when a conversion is not possible or not implemented, the following message is issued : -> mpf f -> mpz z -> f @=z // trying to exact divide mpf by mpz. * no conversion rule: @= * compilation aborted 3.1 type casting ----------------- mpf x ; x = 10 / 3 --> 3 x = (mpf)10 /3 ---> 3.333333333333 4.- Special operators ====================== 4.0 "%%" is_divisible operator ------------------------------ a %% b -> 1 iff a is divisible by b ; else 0 4.1 "@" , "@=": exact division ------------------------------ If it is known that b divides a, a@b is quicker than a / b; Ex : f = factor(n); n @= f ; 4.2 "=#" and "!#" ----------------- F-comparison using the global EPSILON (default 1.e-10) mpf f1,f2 ; f1 =# f2 is true (i.e == 1) iff |f1 - f2| < EPSILON f1 !# f2 is true (i.e == 1) iff |f1 - f2| >= EPSILON Ex : assert (x =# sin(asin(x)) ) To set EPSILON: use precision(n-digits) 4.3 "**" -------- As "^" is the standard C for exclusive-or, "**" is the exponentiation operator. -> 666**42 $2 := 38540524895511613165266748863173814985473295063157418576769816295283207864908351682948692085553606681763707358759878656 -> 4.4 push(),pop() ---------------- -> mpf u,a -> a=1.23456 $11 := 1.23456 -> push(a) // by value -> ++a $12 := 2.23456 -> pop(u) // pop into u (same type) -> u $13 := 1.23456 -> a $14 := 2.23456 -> -> push(&a) // by address -> ++a $15 := 3.23456 -> pop(u) -> u $16 := 3.23456 -> a $17 := 3.23456 -> 5. - Functions =============== mpz foo(a, b, mpf c) ; // default type for a,b is mpz // the following takes a function as 1rst argument // DEFAULT values are provided for two last arguments void plotf(mpf fun(mpf), mpf xfrom = 0, mpf xto = 1000.) {....} ; // the mother of all recursives mpz nfact(n) {if(n==0) return 1; return n * nfact(n-1);} // the following takes a vector as argument // vectors are passed by NAME (ADDRESS) mpz mysum(mpz v[]) {mpz i,sum; sum=0; for(i=0;i mpq mq[4][2] // 4 rows, 2 columns -> vrand(mq,100) // random vector initialization { 3/10, 4/13} { 27/13, 13} { 63/19, 49/96} { 55/23, 1/61} -> Vectors and matrixes can be dynamically dimensionned explicitally vdim(v,100); vdim(v,0); mxdim(md,10,4); or implicitally by some operations (vdelete, ...) 7. - Variables and namepaces ============================ 7.1 Packages ------------- package mypack; // introduces a new package mpz myvar; myvar may be referenced as 'myvar' inside mypack or 'mypack.myvar' elsewhere. package otherpack; mpz myvar; // otherpack.myvar TOPLEVEL HINT: You may access (read) a static variable 'myvar' declared inside the function 'foo' : foo.myvar 7.2 Functions ------------- mpz fun(n) {mpz mylocal; mpz static mystatic; ....} Arguments and local may be referenced as fun.n , fun.mylocal and fun.mystatic; This is useful after BREAK (CTRL-PAUSE) to inspect the current local bindings. 8. - Special toplevel ====================== - Declarations are allowed at toplevel. - No need to delare Z-variables - mpz is the default type. - If a variable is unknown at toplevel, GBnums tries to creates one with the right type : -> f = 1.3 ; // creates an mpf global variable f (if f unknown) -> vdim(v,12) // creates the vector v. (default type mpz)