# basics

t := time();
print("\nChecking basic functions:\n");

# INC

printf("inc/++")

c := 0;
for i to 10k do
   inc c
od;
if c <> 10k then print('inc failed') fi;

c := 0;
for i to 10k do
   inc c, 2
od;
if c <> 20k then print('inc failed') fi;

a := [2, 'j'~100];
c := 0;
for i to 10k do
   inc c, a[1]
od;
if c <> 20k then print('inc failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   inc c, a[1]
od;
if c <> 0 then print('inc failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   inc c, a.j
od;
if c <> -20k then print('inc failed') fi;

a := [0, 'j'~(-2)];
c := 2;
for i to 10k do
   inc a[1], c
od;
if a[1] <> 20k then print('inc failed') fi;

a := [0, 'j'~(-2)];
for i to 10k do
   inc a[1], a.j
od;
if a[1] <> -20k then print('inc failed') fi;

a := [-2, 'j'~0];
for i to 10k do
   inc a.j, a[1]
od;
if a[1] <> -2 then print('inc failed') fi;
if a.j <> -20k then print('inc failed') fi;

f := proc() is
   local c, a;
   c := 0;
   for i to 10k do
      inc c
   od;
   if c <> 10k then print('inc failed') fi;

   c := 0;
   for i to 10k do
      inc c, 2
   od;
   if c <> 20k then print('inc failed') fi;

   a := [2, 'j'~100];
   c := 0;
   for i to 10k do
      inc c, a[1]
   od;
   if c <> 20k then print('inc failed') fi;

   a := [0, 'j'~(-2)];
   c := 0;
   for i to 10k do
      inc c, a[1]
   od;
   if c <> 0 then print('inc failed') fi;

   a := [0, 'j'~(-2)];
   c := 0;
   for i to 10k do
      inc c, a.j
   od;
   if c <> -20k then print('inc failed') fi;

   a := [0, 'j'~(-2)];
   c := 2;
   for i to 10k do
      inc a[1], c
   od;
   if a[1] <> 20k then print('inc failed') fi;

   a := [0, 'j'~(-2)];
   for i to 10k do
      inc a[1], a.j
   od;
   if a[1] <> -20k then print('inc failed') fi;

   a := [-2, 'j'~0];
   for i to 10k do
      inc a.j, a[1]
   od;
   if a[1] <> -2 then print('inc failed') fi;
   if a.j <> -20k then print('inc failed') fi;
end;

f();

f := proc() is
   local a;
   local c := 0;
   for i to 1k do
      a := 2 * c++
   od;
   return a
end;

if f() <> 1998 then
   print('++ failed, 1')
fi;

f := proc() is
   local c := 0;
   for i to 1k do
      c := 2 * c++
   od;
   return c
end;

if f() <> 0 then
   print('++ failed, 2')
fi;

clear f;

c := 0;

a, b := identity(c++);  # -- compound operator uses same code, no need to test separately

if a <> 0 or assigned b or c <> 1 then
   print('++ failed, 3')
fi

clear a, b, c;

# DEC

printf(", dec/--")

c := 0;
for i to 10k do
   dec c
od;
if c <> -10k then print('dec failed') fi;

c := 0;
for i to 10k do
   dec c, 2
od;
if c <> -20k then print('dec failed') fi;

a := [2, 'j'~100];
c := 0;
for i to 10k do
   dec c, a[1]
od;
if c <> -20k then print('dec failed') fi;


a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   dec c, a[1]
od;
if c <> 0 then print('dec failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   dec c, a.j
od;
if c <> 20k then print('dec failed') fi;

a := [0, 'j'~(-2)];
c := 2;
for i to 10k do
   dec a[1], c
od;
if a[1] <> -20k then print('dec failed') fi;

a := [0, 'j'~(-2)];
for i to 10k do
   dec a[1], a.j
od;
if a[1] <> 20k then print('dec failed') fi;

a := [-2, 'j'~0];
for i to 10k do
   dec a.j, a[1]
od;
if a[1] <> -2 then print('dec failed') fi;
if a.j <> 20k then print('dec failed') fi;

f := proc() is
   local a;
   local c := 0;
   for i to 1k do
      a := 2 * c--
   od;
   return a
end;

if f() <> -1998 then
   print('-- failed, 1')
fi;

f := proc() is
   local c := 0;
   for i to 1k do
      c := 2 * c--
   od;
   return c
end;

if f() <> 0 then
   print('-- failed, 2')
fi;

clear f;

printf(", mul")

a := 1;

for i to 10 do
   mul a, i!2
od;

if a <> -2475200-19448000*I then
   print('mul failed')
fi;

printf(", div")

a := 1;

for i to 5 do
   div a, i!2
od;

if not(a ~= -0.001790450928382+0.0003315649867374*I) then
   print('div failed')
fi

c := 0  # test case

printf(", +:=")

c := 0;
for i to 10k do
   c +:= 1
od;
if c <> 10k then print('+:= failed') fi;

c := 0;
for i to 10k do
   c +:= 2
od;
if c <> 20k then print('+:= failed') fi;

a := [2, 'j'~100];
c := 0;
for i to 10k do
   c +:= a[1]
od;
if c <> 20k then print('+:= failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   c +:= a[1]
od;
if c <> 0 then print('+:= failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   c +:= a.j
od;
if c <> -20k then print('+:= failed') fi;

a := [0, 'j'~(-2)];
c := 2;
for i to 10k do
   a[1] +:= c
od;
if a[1] <> 20k then print('+:= failed') fi;

a := [0, 'j'~(-2)];
for i to 10k do
   a[1] +:= a.j
od;
if a[1] <> -20k then print('+:= failed') fi;

a := [-2, 'j'~0];
for i to 10k do
   a.j +:= a[1]
od;
if a[1] <> -2 then print('+:= failed') fi;
if a.j <> -20k then print('+:= failed') fi;

f := proc() is
   local c, a;
c := 0;
for i to 10k do
   c +:= 1
od;
if c <> 10k then print('+:= failed') fi;

c := 0;
for i to 10k do
   c +:= 2
od;
if c <> 20k then print('+:= failed') fi;

a := [2, 'j'~100];
c := 0;
for i to 10k do
   c +:= a[1]
od;
if c <> 20k then print('+:= failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   c +:= a[1]
od;
if c <> 0 then print('+:= failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   c +:= a.j
od;
if c <> -20k then print('+:= failed') fi;

a := [0, 'j'~(-2)];
c := 2;
for i to 10k do
   a[1] +:= c
od;
if a[1] <> 20k then print('+:= failed') fi;

a := [0, 'j'~(-2)];
for i to 10k do
   a[1] +:= a.j
od;
if a[1] <> -20k then print('+:= failed') fi;

a := [-2, 'j'~0];
for i to 10k do
   a.j +:= a[1]
od;
if a[1] <> -2 then print('+:= failed') fi;
if a.j <> -20k then print('+:= failed') fi;
end;

f();

# DEC

printf(", -:=")

c := 0;
for i to 10k do
   c -:= 1
od;
if c <> -10k then print('-:= failed') fi;

c := 0;
for i to 10k do
   c -:= 2
od;
if c <> -20k then print('-:= failed') fi;

a := [2, 'j'~100];
c := 0;
for i to 10k do
   c -:= a[1]
od;
if c <> -20k then print('-:= failed') fi;


a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   c -:= a[1]
od;
if c <> 0 then print('-:= failed') fi;

a := [0, 'j'~(-2)];
c := 0;
for i to 10k do
   c -:= a.j
od;
if c <> 20k then print('-:= failed') fi;

a := [0, 'j'~(-2)];
c := 2;
for i to 10k do
   a[1] -:= c
od;
if a[1] <> -20k then print('-:= failed') fi;

a := [0, 'j'~(-2)];
for i to 10k do
   a[1] -:= a.j
od;
if a[1] <> 20k then print('-:= failed') fi;

a := [-2, 'j'~0];
for i to 10k do
   a.j -:= a[1]
od;
if a[1] <> -2 then print('-:= failed') fi;
if a.j <> 20k then print('-:= failed') fi;

printf(", *:=")

a := 1;

for i to 10 do
   a *:= i!2
od;

if a <> -2475200-19448000*I then
   print('*:= failed')
fi;

printf(", /:=")

a := 1;

for i to 5 do
   a /:= i!2
od;

if not(a ~= -0.001790450928382+0.0003315649867374*I) then
   print('/:= failed')
fi

c := 0  # test case


printf(", &:=")

a := 'In';
a &:= 'Sight'

if a <> 'InSight' then
   print('Error in &:=, 1')
fi;

b := ' JPL'
a &:= b;

if a <> 'InSight JPL' then
   print('Error in &:=, 2')
fi;

a := 'In';
a &:= 'Sight' & ' JPL'

if a <> 'InSight JPL' then
   print('Error in &:=, 3')
fi;

a := 'In';
a &:= b & ' JPL' & ' NASA'

if a <> 'In JPL JPL NASA' then
   print('Error in &:=, 4')
fi;

a := 'InSight'
a &:= tostring('123') & '456'

if a <> 'InSight123456' then
   print('Error in &:=, 5')
fi;

a := ['JPL' , 'NASA']
a[1] &:= a[2];

if a[1] <> 'JPLNASA' and a[2] <> 'NASA' then
   print('Error in &:=, 6')
fi;

f := proc(a, n) is
   a[n] &:= a[n] & '|'
   return a[n]
end;

if f(a, 1) <> 'JPLNASAJPLNASA|' then
   print('Error in &:=, 7')
fi;

clear a, b, f;

# insert stat

printf(", insert")

a := []
for i to 10k do
   insert i into a
   if a[i] <> i then error('insert stat #' & c) fi
od

inc c;
if size(a) <> 10k then
   error('insert stat #' & c)
fi;

inc c
a := [100~[]]
for i to 10k do
   insert i into a[100]
   if a[100][i] <> i then error('insert stat #' & c) fi
od

inc c;
if size(a[100]) <> 10k then
   error('insert stat #' & c)
fi;

inc c
a := ['a'~[]]
for i to 10k do
   insert i into a['a']
   if a['a'][i] <> i then error('insert stat #' & c) fi
od

inc c;
if size(a['a']) <> 10k then
   error('insert stat #' & c)
fi;

inc c
a := ['a'~[]]
for i to 10k do
   insert i into a.a
   if a.a[i] <> i then error('insert stat #' & c) fi
od

inc c;
if size(a.a) <> 10k then
   error('insert stat #' & c)
fi;


# insert and delete stat
inc c;
a := []
for i to 10k do
   insert i into a
   if a[1] <> i then error('insert stat #' & c) fi
   delete i from a
od;

printf(", delete")

inc c;
if size(a) <> 0 then
   error('insert/delete stat #' & c)
fi;

inc c;
a := [[[], []], []]
insert 2 into a[1, 1];
insert 3 into a[2];
if a <> [[[2], []], [3]] then
   error('insert stat #' & c, a)
fi;

inc c;
delete 3, 4, 5 from a[1, 1]
delete 2 from a[1, 1]
delete 3 from a[2]
if a <> [[[], []], []] then
   error('delete stat #' & c)
fi;

inc c;
a := seq(seq(seq(), seq()), seq())
insert 2 into a[1, 1];
insert 3 into a[2];
if a <> seq(seq(seq(2), seq()), seq(3)) then
   error('insert stat #' & c, a)
fi;


inc c;
delete 3, 4, 5 from a[1, 1]
delete 2 from a[1, 1]
delete 3 from a[2]
if a <> seq(seq(seq(), seq()), seq()) then
   error('delete stat #' & c)
fi;


inc c;
a := reg(reg(reg(), reg()), reg())
insert 2 into a[1, 1];
insert 3 into a[2];
if a <> reg(reg(reg(2, null, null, null, null, null, null, null, null, null, null, null,
   null, null, null, null), reg(null, null, null, null, null, null, null, null, null, null,
   null, null, null, null, null, null)), reg(3, null, null, null, null, null, null, null,
   null, null, null, null, null, null, null, null)) then
   error('insert stat #' & c)
fi;

inc c;
delete 3, 4, 5 from a[1, 1]
delete 2 from a[1, 1]
delete 3 from a[2]
if a <> reg(reg(reg(), reg()), reg()) then
   error('delete stat #' & c)
fi;

# check metamethod __writeindex with insert statement

c := 0;

readonly_mt := []
readonly_mt.__writeindex := proc(t, k, v) is rawset(t, k, v) end;

readonly := proc(t :: {table, set, sequence, register}) is
   setmetatable(t, readonly_mt);
   return t
end;

inc c;
moons := readonly(['Phobos', 'Deimos']);
insert 'Mars' into moons;
insert 'Saturn', 'Uranus' into moons;
if moons <> ['Phobos', 'Deimos', 'Mars', 'Saturn', 'Uranus'] then
   error('insert stat/mt #' & c)
fi;

inc c;
moons := readonly({'Phobos', 'Deimos'});
insert 'Mars' into moons;
if moons <> {'Phobos', 'Deimos', 'Mars'} then
   error('insert stat/mt #' & c)
fi;

inc c;
moons := readonly(seq('Phobos', 'Deimos'));
insert 'Mars', 'Venus' into moons;
if moons <> seq('Phobos', 'Deimos', 'Mars', 'Venus') then
   error('insert stat/mt #' & c)
fi;

inc c;
moons := readonly(reg('Phobos', 'Deimos', null, null, null));
insert 'Mars', 'Venus' into moons;
if moons <> reg('Phobos', 'Deimos', 'Mars', 'Venus', null) then
   error('insert stat/mt #' & c)
fi;


# check metamethod __writeindex with delete statement

readonly_mt := []
readonly_mt.__writeindex := proc(t, k, v) is
   if unassigned v then
      for i, j in t do
         if j = k then
            rawset(t, i, null);
            break
         fi
      od
   else
      rawset(t, k, v)
   fi
end;

readonly := proc(t :: {table, set, sequence, register}) is
   setmetatable(t, readonly_mt);
   return t
end;

c := 0;

inc c;
moons := readonly(['Phobos', 'Deimos']);
delete 'Mars' from moons;
delete 'Phobos', 'Deimos' from moons;
if moons <> [] then
   error('delete stat/mt #' & c)
fi;

inc c;
moons := readonly({'Phobos', 'Deimos'});
delete 'Mars' from moons;
delete 'Phobos', 'Deimos' from moons;
if moons <> {} then
   error('delete stat/mt #' & c)
fi;


inc c
a := [100~[]]
for i to 10k do
   insert i into a[100]
   if a[100][1] <> i then error('insert stat #' & c) fi
   delete i from a[100]
od

inc c;
if size(a[100]) <> 0 then
   error('insert stat #' & c)
fi;

inc c
a := ['a'~[]]
for i to 10k do
   insert i into a['a']
   if a['a'][1] <> i then error('insert stat #' & c) fi
   delete i from a['a']
od

inc c;
if size(a['a']) <> 0 then
   error('insert stat #' & c)
fi;

inc c
a := ['a'~[]]
for i to 10k do
   insert i into a.a
   if a.a[1] <> i then error('insert stat #' & c) fi
   delete i from a.a
od

inc c;
if size(a.a) <> 0 then
   error('insert stat #' & c)
fi;

inc c
a := [1, 2, 3]
b := []
for i to 10k do
   insert a[1], a[2], a[3] into b
   delete a[1], a[2], a[3] from b
od;
if b <> [] then error('insert/delete ' & c) fi

inc c
a := ['a'~1, 'b'~2, 'c'~3]
b := []
for i to 10k do
   insert a.a, a.b, a.c into b
   delete a.a, a.b, a.c from b
od;
if b <> [] then error('insert/delete ' & c) fi

printf(", enum")

c := 0;
enum eins, zwei, drei, vier
if eins <> 1 or zwei <> 2 or drei <> 3 or vier <> 4 then error('enum ' & c) fi
clear eins, zwei, drei, vier
if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi

inc c;
enum eins
if eins <> 1 then error('enum ' & c) fi
clear eins
if eins <> null then error('clear ' & c) fi

inc c;
enum eins, zwei, drei, vier from 2
if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
clear eins, zwei, drei, vier
if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi

a := ['a'~2, 2 ~ 2]
inc c;
enum eins, zwei, drei, vier from a.a
if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
clear eins, zwei, drei, vier
if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi

inc c;
enum eins, zwei, drei, vier from a[2]
if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
clear eins, zwei, drei, vier
if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi

inc c
f := proc(c) is
   local enum eins, zwei, drei, vier
   if eins <> 1 or zwei <> 2 or drei <> 3 or vier <> 4 then error('enum ' & c) fi
   clear eins, zwei, drei, vier
   if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi
end;
f(c);

inc c;
f := proc(c) is
   local enum eins
   if eins <> 1 then error('enum ' & c) fi
   clear eins
   if eins <> null then error('clear ' & c) fi
end
f(c);

inc c;
f := proc(c) is
   local enum eins, zwei, drei, vier from 2
   if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
   clear eins, zwei, drei, vier
   if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi
end;
f(c);

inc c;
f := proc(c) is
   local a := ['a'~2, 2 ~ 2]
   enum eins, zwei, drei, vier from a.a
   if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
   clear eins, zwei, drei, vier
   if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi
end;
f(c);

inc c;
f := proc(c) is
   local a := ['a'~2, 2 ~ 2]
   enum eins, zwei, drei, vier from a[2]
   if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
   clear eins, zwei, drei, vier
   if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi
end;
f(c);


inc c;
f := proc(c, a) is
   enum eins, zwei, drei, vier from a.a
   if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
   clear eins, zwei, drei, vier
   if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi
end;
f(c, a);

inc c;
f := proc(c, a) is
   local a := ['a'~2, 2 ~ 2]
   enum eins, zwei, drei, vier from a[2]
   if eins <> 2 or zwei <> 3 or drei <> 4 or vier <> 5 then error('enum ' & c) fi
   clear eins, zwei, drei, vier
   if eins <> null or zwei <> null or drei <> null or vier <> null then error('clear ' & c) fi
end;
f(c, a);

# copy

printf(', copy')

a := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
b := [a, a, a, a, a, a, a, a, a, a];
c := [{unpack(a)}, seq(unpack(a)), {unpack(a)}, seq(unpack(a)), {unpack(a)}, seq(unpack(a)), {unpack(a)}, seq(unpack(a)), {unpack(a)}, seq(unpack(a)), {unpack(a)}, seq(unpack(a)), {unpack(a)}, seq(unpack(a)), a, a, a, a, a, a];

for i to 1k do
   z := copy(c);
   for i from 2 to size(c) do
      r := environ.pointer(z[i-1]) <> environ.pointer(z[i])
   od;
   if r then print('Error in copy, 1') fi;
   local z := copy(c);
   for i from 2 to size(c) do
      r := environ.pointer(z[i-1]) <> environ.pointer(z[i])
   od;
   if r then error('Error in copy, 2') fi;
   if alternate(true, null) <> true then
      print('error in alternate, 1')
   fi;
   if alternate(true, fail) <> fail then
      print('error in alternate, 2')
   fi
od;

s := {};
settype(s, 'alex')
if gettype(copy(s)) <> 'alex' then print('copy error with sets') fi

s := [];
settype(s, 'alex')
if gettype(copy(s)) <> 'alex' then print('copy error with tables') fi

s := seq();
settype(s, 'alex')
if gettype(copy(s)) <> 'alex' then print('copy error with sequences') fi

s := 1:2;
settype(s, 'alex')
if gettype(copy(s)) <> 'alex' then print('copy error with pairs') fi

s := reg(1, 2);
settype(s, 'alex')
if gettype(copy(s)) <> 'alex' then print('copy error with registers') fi


# copy with cycles

a := [];
a['s'] := -1
a[a] := -2
a[2] := a
a[3] := a

to 1k do
   b := copy(a);
   if b['s'] <> -1 then
      print('Error with copying cycles, 1')
   fi;
   if b[b] <> -2 then
      print('Error with copying cycles, 2')
   fi;
   if b[2] <> b then
      print('Error with copying cycles, 3')
   fi;
   if b[3] <> b then
      print('Error with copying cycles, 4')
   fi;
   if environ.pointer(b[2]) <> environ.pointer(b) then
      print('Error with copying cycles, 5')
   fi;
   if environ.pointer(b[3]) <> environ.pointer(b) then
      print('Error with copying cycles, 6')
   fi
od;

a := [];
insert a into a
insert a into a
b := copy(a)
for i in b do
   if environ.pointer(i) <> environ.pointer(b) then
      print('Error with copying cycle, 7')
   fi
od;

a := {};
insert a into a
insert a into a
b := copy(a)
for i in b do
   if environ.pointer(i) <> environ.pointer(b) then
      print('Error with copying cycle, 8')
   fi
od;

a := seq();
insert a into a
insert a into a
b := copy(a)
for i in b do
   if environ.pointer(i) <> environ.pointer(b) then
      print('Error with copying cycle, 9')
   fi
od;

a := 1:2;
a[1] := a
a[2] := a
b := copy(a)
for i to 2 do
   if environ.pointer(b[i]) <> environ.pointer(b) then
      print('Error with copying cycle, 10')
   fi;
   if environ.isselfref(a) <> true then
      print('Error with pair cycle, 11')
   fi;
   if environ.isselfref(b) <> true then
      print('Error with pair cycle, 12')
   fi
od;

a := [1, 2, 3, 4, 5, 'a' ~ 10, 'b' ~ 11];

f := proc(a) is
   local b, c, d;
   for i to 100 do
      b := copy(a);
      c := copy(a, 'array');
      d := copy(a, 'hash')
   od;
   return b, c, d
end;

a1, b1, c1 := f(a);

if a1 <> a then
   print('Error in copy, 3')
fi;
if b1 <> [1, 2, 3, 4, 5] then
   print('Error in copy, 4')
fi;
if c1 <> ['a' ~ 10, 'b' ~ 11] then
   print('Error in copy, 5')
fi;

clear a, b, f, a1, b1, c1;

# pop top/bottom

printf(', pop/bottom')

for i to 1k do
   a := [1, 2, 3, 4, 5];
   for j from 1 to 100 do
     pop top from a
   od;
   if top(a) <> null then print('pop/top error') fi
   if bottom(a) <> null then print('pop/bottom error') fi
od
if filled(a) then print('pop/top error') fi

for i to 1k do
   a := [1, 2, 3, 4, 5];
   for j from 1 to 100 do
     pop bottom from a
   od;
   if top(a) <> null then print('pop/top error') fi
   if bottom(a) <> null then print('pop/bottom error') fi
od
if filled(a) then print('pop/bottom error') fi

printf(', pop/top')

for i to 1k do
   a := [1, 2, 3, 4, 5, 10~10];
   for j from 1 to 100 do
     pop top from a
   od;
   if top(a) <> null then print('pop/top error') fi
   if bottom(a) <> null then print('pop/bottom error') fi
od
if filled(a) then print('pop/top error') fi

for i to 1k do
   a := [1, 2, 3, 4, 5, 10~10];
   for j from 1 to 100 do
     pop bottom from a
   od;
   if top(a) <> null then print('pop/top error') fi
   if bottom(a) <> null then print('pop/bottom error') fi
od
if filled(a) then print('pop/bottom error') fi

# protect

printf(', protect')

iszero := proc(x) is
   if x <> 0 then
      error('argument must be zero')
   else
      return true
   fi
end;

if protect(iszero, 1) <> 'argument must be zero' then
   print('error in protect (iszero, 1)')
fi;

if protect(iszero, 0) <> true then
   print('error in protect (iszero, 1)')
fi;

# new ops version Agena 1.2

printf(', nseq');

s := nseq(1, 256);
if size seq(ops(s, unpack(s))) <> 256 then print('error in ops/seq') fi;

# :: and :- ops, settype core dumps before 1.2.1
s := seq(1, 2);
settype(s, 'duo');
if not(s :: 'duo') then error('error in :: op, 9') fi;
if s :- 'duo' then error('error in :: op, 10') fi;
# crashed before Agena 1.2.1
settype(s, null);
if not(s :: sequence) then error('error in :: op, 11') fi;
if s :- sequence then error('error in :: op, 12') fi;

s := [1, 2];
settype(s, 'duo');
if not(s :: 'duo') then error('error in :: op, 13') fi;
if s :- 'duo' then error('error in :: op, 14') fi;
# crashed before Agena 1.2.1
settype(s, null);
if not(s :: table) then error('error in :: op, 15') fi;
if s :- table then error('error in :: op, 16') fi;

s := {1, 2};
settype(s, 'duo');
if not(s :: 'duo') then error('error in :: op, 17') fi;
if s :- 'duo' then error('error in :: op, 18') fi;
# crashed before Agena 1.2.1
settype(s, null);
if not(s :: set) then error('error in :: op, 19') fi;
if s :- set then error('error in :: op, 20') fi;

s := 1:2;
settype(s, 'duo');
if not(s :: 'duo') then error('error in :: op, 20') fi;
if s :- 'duo' then error('error in :- op, 21') fi;
# crashed before Agena 1.2.1
settype(s, null);
if not(s :: pair) then error('error in :: op, 22') fi;
if s :- pair then error('error in :- op, 23') fi;

s := << x -> x >>;
settype(s, 'duo');
if not(s :: 'duo') then error('error in :: op, 24') fi;
if s :- 'duo' then error('error in :- op, 25') fi;
# crashed before Agena 1.2.1
settype(s, null);
if not(s :: procedure) then error('error in :: op, 26') fi;
if s :- procedure then error('error in :- op, 27') fi;

d := [[1, 2], [3, 4]]
if not(d[1]::table) then print('error in :: op, 28') fi;
if d[1]:-table then print('error in :- op, 29') fi;
if not(d[2]::table) then print('error in :: op, 30') fi;
if d[2]:-table then print('error in :- op, 31') fi;

if not(setbit(0, 2, 1) = 2) then print('error in setbit, 31') fi;
if not(getbit(2, 2)) then print('error in getbit, 32') fi;

if setbits(0, reg(1, 1, 1, 1, 1, 1, 1, 1)) <> 255 then
   print('error in setbits, 1')
fi;

if setbits(0, reg(true, true, true, true, true, true, true, 1)) <> 255 then
   print('error in setbits, 2')
fi;

if setnbits(8, 3, 2, 2, 'or') <> 14 then
   print('error in setnbits, 1')
fi;

if setnbits(0, 3, 2, 2) <> 6 then
   print('error in setnbits, 2')
fi;

if getbits(255) <> reg(
   false, false, false, false, false, false, false, false,
   false, false, false, false, false, false, false, false,
   false, false, false, false, false, false, false, false,
   true, true, true, true, true, true, true, true) then
   print('error in getbits, 1')
fi;

if getbits(255, 1) <> reg(
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) then
   print('error in getbits, 2')
fi;

if getnbits(7, 1, 3) <> 7 then
   print('error in getnbits, 1')
fi;

if (2 :: number::boolean::boolean::boolean::boolean::boolean::boolean) <> true then
   print('error in :: op, 33')
fi

if (1 :: integer) <> true then
   print('error in :: op, 34')
fi;

if (1 :: posint) <> true then
   print('error in :: op, 35')
fi;

if (1 :: nonnegint) <> true then
   print('error in :: op, 36')
fi;

if (1 :: positive) <> true then
   print('error in :: op, 37')
fi;

if (1 :: nonnegative) <> true then
   print('error in :: op, 38')
fi;

if (1.1 :: integer) = true then
   print('error in :: op, 39')
fi;

if (1.1 :: posint) = true then
   print('error in :: op, 40')
fi;

if (1.1 :: nonnegint) = true then
   print('error in :: op, 41')
fi;

if (-1 :: positive) = true then
   print('error in :: op, 42')
fi;

if (-1.1 :: nonnegative) = true then
   print('error in :: op, 43')
fi;

if (1 :- integer) = true then
   print('error in :: op, 44')
fi;

if (1 :- posint) = true then
   print('error in :: op, 45')
fi;

if (1 :- nonnegint) = true then
   print('error in :: op, 46')
fi;

if (1 :- positive) = true then
   print('error in :: op, 47')
fi;

if (1 :- nonnegative) = true then
   print('error in :: op, 48')
fi;

if (1.1 :- number) = true then
   print('error in :: op, 49')
fi;

if (1.1 :- posint) <> true then
   print('error in :: op, 50')
fi;

if (1.1 :- nonnegint) <> true then
   print('error in :: op, 51')
fi;

if (1.1 :- positive) = true then
   print('error in :: op, 52')
fi;

if (1.1 :- nonnegative) = true then
   print('error in :: op, 53')
fi;


printf(', has');

s := seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(1))))))))))))))))))));
if has(s, 1) <> true then print('error in has, 33') fi;
if has(s, 2) <> false then print('error in has, 34') fi;

s := [[[[[[[[[[[[[[[[[[[[1]]]]]]]]]]]]]]]]]]]];
if has(s, 1) <> true then print('error in has, 35') fi;
if has(s, 2) <> false then print('error in has, 36') fi;

s := {{{{{{{{{{{{{{{{{{{{1}}}}}}}}}}}}}}}}}}}};
if has(s, 1) <> true then print('error in has, 37') fi;
if has(s, 2) <> false then print('error in has, 38') fi;

s := {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for i to 512 do
   if has(s, 'a') <> false then print('error in has, 39') fi;
   if has(s, 10) <> true then print('error in has, 40') fi
od;

s := seq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for i to 512 do
   if has(s, 'a') <> false then print('error in has, 41') fi;
   if has(s, 10) <> true then print('error in has, 42') fi
od;

s := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for i to 512 do
   if has(s, 'a') <> false then print('error in has, 43') fi;
   if has(s, 10) <> true then print('error in has, 44') fi
od;

s := 1:2;
for i to 512 do
   if has(s, 1) <> true then print('error in has, 45') fi;
   if has(s, 2) <> true then print('error in has, 46') fi;
   if has(s, 3) <> false then print('error in has, 47') fi
od;

s := [1]:2;
for i to 512 do
   if has(s, 1) <> true then print('error in has, 48') fi;
   if has(s, 2) <> true then print('error in has, 49') fi;
   if has(s, 3) <> false then print('error in has, 50') fi
od;

s := 1:[2];
for i to 512 do
   if has(s, 1) <> true then print('error in has, 51') fi;
   if has(s, 2) <> true then print('error in has, 52') fi;
   if has(s, 3) <> false then print('error in has, 53') fi
od;

s := 1:[2]:3;
for i to 512 do
   if has(s, 1) <> true then print('error in has, 54') fi;
   if has(s, 2) <> true then print('error in has, 55') fi;
   if has(s, 3) <> true then print('error in has, 56') fi;
   if has(s, 4) <> false then print('error in has, 57') fi
od;

s := s:4;
for i to 512 do
   if has(s, 1) <> true then print('error in has, 58') fi;
   if has(s, 2) <> true then print('error in has, 59') fi;
   if has(s, 3) <> true then print('error in has, 60') fi;
   if has(s, 4) <> true then print('error in has, 61') fi;
   if has(s, 'a') <> false then print('error in has, 62') fi
od;

s := s:seq('b':seq(5));
for i to 512 do
   if has(s, 1) <> true then print('error in has, 63') fi;
   if has(s, 2) <> true then print('error in has, 64') fi;
   if has(s, 3) <> true then print('error in has, 65') fi;
   if has(s, 4) <> true then print('error in has, 66') fi;
   if has(s, 4) <> true then print('error in has, 67') fi;
   if has(s, 'a') <> false then print('error in has, 68') fi;
   if has(s, 5) <> true then print('error in has, 69') fi;
   if has(s, []) <> false then print('error in has, 70') fi;
   if has(s, s) <> true then print('error in has, 71') fi
od;

printf(', recurse');

s := seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(seq(1))))))))))))))))))));
if recurse(s, << x -> x = 1 >>) <> true then print('error in recurse, 33') fi;
if recurse(s, << x -> x = 2 >>) <> false then print('error in recurse, 34') fi;

s := reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(reg(1))))))))))))))))))));
if recurse(s, << x -> x = 1 >>) <> true then print('error in recurse, 35') fi;
if recurse(s, << x -> x = 2 >>) <> false then print('error in recurse, 36') fi;

s := [[[[[[[[[[[[[[[[[[[[1]]]]]]]]]]]]]]]]]]]];
if recurse(s, << x -> x = 1 >>) <> true then print('error in recurse, 37') fi;
if recurse(s, << x -> x = 2 >>) <> false then print('error in recurse, 38') fi;

s := {{{{{{{{{{{{{{{{{{{{1}}}}}}}}}}}}}}}}}}}};
if recurse(s, << x -> x = 1 >>) <> true then print('error in recurse, 39') fi;
if recurse(s, << x -> x = 2 >>) <> false then print('error in recurse, 40') fi;

s := {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for i to 512 do
   if recurse(s, << x -> x = 'a' >>) <> false then print('error in recurse, 41') fi;
   if recurse(s, << x -> x = 10 >>) <> true then print('error in recurse, 42') fi
od;

s := seq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for i to 512 do
   if recurse(s, << x -> x = 'a' >>) <> false then print('error in recurse, 43') fi;
   if recurse(s, << x -> x = 10 >>) <> true then print('error in recurse, 44') fi
od;

s := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for i to 512 do
   if recurse(s, << x -> x = 'a' >>) <> false then print('error in recurse, 45') fi;
   if recurse(s, << x -> x = 10 >>) <> true then print('error in recurse, 46') fi
od;

s := reg(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for i to 512 do
   if recurse(s, << x -> x = 'a' >>) <> false then print('error in recurse, 47') fi;
   if recurse(s, << x -> x = 10 >>) <> true then print('error in recurse, 48') fi
od;


printf(', descend');

s := seq(1, 2, 3, [1, 2, 3], seq(1, 2, 2, 4, {2, 4, 5}));

for i to 512 do
   if descend(s, << x -> x = 2 >>) <> seq(2, [2], seq(2, 2), {2}) then
      print('error in descend, 1')
   fi
od;

ge := proc(x, y) is  # x greater or equal y ?
   try
      return x >= y
   catch  # avoid comparisons of numbers with other data types which issue an error
      return false
   yrt
end;

for i to 512 do
   if descend(s, ge, 3) <> seq(3, [3], seq(4), {4, 5}) then
      print('error in descend, 2')
   fi
od;

if not(os.system()[1] in {'MS-DOS'}) then
   temperatures := '<data>
      <location>Bundeshauptstadt Bonn</location>
      <date>20150231</date>
      <measurement>
         <time>10:00:00</time>
         <celsius>0.9</celsius>
      </measurement>
      <measurement>
         <time>10:05:00</time>
         <celsius>1.07</celsius>
      </measurement>
      <measurement>
         <time>12:030:00</time>
         <celsius>5.31</celsius>
      </measurement>
      <measurement>
         <time>23:59:00</time>
         <celsius>-1.07</celsius>
      </measurement>
   </data>'

   celsius := utils.decodexml(temperatures);

   for i to 512 do
      if descend(celsius, << x -> x = 'celsius' >>) <> [[0.9], [1.07], [5.31], [-1.07]] then
         print('error in descend, 3')
      fi
   od;

   for i to 512 do
      if descend(celsius, ge, 1.05) <> [[20150231], [1.07], [5.31]] then
         print('error in descend, 4')
      fi
   od;

   clear temperatures, celsius
fi;


printf(', satisfy');

if satisfy(1, << x -> x > 0 >>) <> true then
   print('Error in satisfy, 1')
fi;

if satisfy([1, 1, 1], << x -> x > 0 >>) <> true then
   print('Error in satisfy, 2')
fi;

if satisfy([1, 1, seq(0)], << x -> x > 0 >>) <> false then
   print('Error in satisfy, 3')
fi

if satisfy({1, 1, 1}, << x -> x > 0 >>) <> true then
   print('Error in satisfy, 4')
fi;

if satisfy({1, {1}, 1}, << x -> x > 0 >>) <> true then
   print('Error in satisfy, 5')
fi;

if satisfy(seq(1, 1, 1), << x -> x > 0 >>) <> true then
   print('Error in satisfy, 6')
fi;

if satisfy(seq(1, [1], seq(1)), << x -> x > 0 >>) <> true then
   print('Error in satisfy, 7')
fi;

if satisfy(seq(1, [0], seq(1)), << x -> x > 0 >>) <> false then
   print('Error in satisfy, 8')
fi;

if satisfy(seq(1, [0], seq(1)), << x -> x > 0 >>) <> false then
   print('Error in satisfy, 9')
fi;

if satisfy([1, [0], seq(1)], << x -> x > 0 >>) <> false then
   print('Error in satisfy, 10')
fi;

if satisfy([1, [0], seq(0)], << x -> x > 0 >>) <> false then
   print('Error in satisfy, 11')
fi;

if satisfy([1, [0], seq(0, {0, [0, reg(0, seq(0, [0]))]})], << x -> x = 0 >>) <> false then
   print('Error in satisfy, 11')
fi;

if satisfy([0, [0], seq(0, {0, [0, reg(0, seq(0, [0]))]})], << x -> x = 0 >>) <> true then
   print('Error in satisfy, 12')
fi;

if satisfy([0, [0], seq(0, {0, [0, reg(0, seq(0, [1]))]})], << x -> x = 0 >>) <> false then
   print('Error in satisfy, 13')
fi;


printf(', checkoption');

if checkoptions('check', ['alex':'walz'], alex=string) <> ['alex' ~ 'walz'] then
   print('error in checkoptions, 1')
fi;

if checkoptions('check', ['alex':'walz', 'value':1], alex=string, value=number) <> ['alex' ~ 'walz', 'value' ~ 1] then
   print('error in checkoptions, 2')
fi;

z := [];
settype(z, 'ppp')
if checkoptions('check', ['alex':'walz', 'value':z], alex=string, value='ppp') <> ['alex' ~ 'walz', 'value' ~ []] then
   print('error in checkoptions, 3')
fi;

printf(', values');

g := proc() is
   local c, t, a, b, z, e;
   c := [11, 12, 13, 14, 15, 16];
   d := toseq(c);
   e := [1, 2, 3, 4, 5, 6];
   for i to 10k do
      a := values(c, unpack([3, 4, 5]))
      b := values(d, unpack([3, 4, 5]))
      z := values(e, unpack([unpack(values(e, unpack([1, 2, 3])))]))
   od;
   if [a == [3 ~ 13, 4 ~ 14, 5 ~ 15], b == seq(13, 14, 15), z == [1, 2, 3]] <> [true, true, true] then
      print('Error in values/basics')
   fi
end;
g();


printf(', if/onsuccess');

f := proc(x) is
   local flag, a;
   flag := false;
   if 1 = x then
      a := 1
   elif 2 = x then
      a := 2
   elif 3 = x then
      a := 3
   onsuccess
      a := 4;
      flag := true
      if false then
         a := 5
      elif true then
         a := 6
      onsuccess
         flag := fail
      fi
   else
      a := -1
   fi;
   return a, flag
end;

for i to 2 do
   to 100 do
      a, b := f(i);
      if a <> 6 or b <> fail then
         print('Error in if/onsuccess statement', i)
      fi
   od
od;

to 100 do
   a, b := f(4);
   if a <> -1 or b <> false then
      print('Error in if/onsuccess statement', 4)
   fi
od;

printf(', for/as & for/until');

for i to 10 do
as i < 5;

if i <> 5 then
   print('Error in for/as', 1)
fi;

printf(', for/until');

for i to 10 do
until i >= 5;

if i <> 5 then
   print('Error in for/until', 1)
fi;

to 1k do
   for i to 10 do
      if a = 5 then break fi
   as i < 5
od;

if i <> 5 then
   print('Error in for/as', 2)
fi;

to 1k do
   for i to 10 do
      if a = 5 then break fi
   until i >= 5
od;

if i <> 5 then
   print('Error in for/until', 2)
fi;

f := proc(x) is
   local flag, a, b;
   flag := false;
   if 1 = x then
      a := 1
   elif 2 = x then
      a := 2
   elif 3 = x then
      a := 3
   onsuccess
      a := 4;
      flag := true
      if false then
         a := 5
      elif true then
         a := 6
      onsuccess
         flag := fail
         for i to 10 do
            if i = 1 then skip fi;
            if i = 4 then break fi;
         as i < 7;
         b := i
      fi;
   else
      a := -1
   fi;
   return a, flag, b
end;

printf(', if/onsuccess/for/as');

a, b, c := f();
if a <> -1 or b <> false then
   print('Error in if/onsuccess/for/as statement, 1', i)
fi;

a, b, c := f(3);
if a <> 6 or b <> fail or c <> 4 then
   print('Error in if/onsuccess/for/as statement, 2', i)
fi;


f := proc(x) is
   local flag, a, b;
   flag := false;
   if 1 = x then
      a := 1
   elif 2 = x then
      a := 2
   elif 3 = x then
      a := 3
   onsuccess
      a := 4;
      flag := true
      if false then
         a := 5
      elif true then
         a := 6
      onsuccess
         flag := fail
         for i to 10 do
            skip when i = 1;
            break when i = 4
         as i < 7;
         b := i
      fi;
   else
      a := -1
   fi;
   return a, flag, b
end;

a, b, c := f();
if a <> -1 or b <> false then
   print('Error in if/onsuccess/for/as statement, 3', i)
fi;

a, b, c := f(3);
if a <> 6 or b <> fail or c <> 4 then
   print('Error in if/onsuccess/for/as statement, 4', i)
fi;

printf(', for/to/redo');

for i to 1k do
   flag := true;
   c := 0;
   for j in [10, 11, 12] do
      inc c;
      if flag and j = 11 then
         flag := false;
         redo
      fi;
   od
od;

if c <> 4 then
   print('Error in for/redo', 1, c)
fi;


for i to 1k do
   flag := true;
   c := 0;
   for j from 10 to 12 do
      inc c;
      if flag and j = 11 then
         flag := false;
         redo
      fi;
   od
od;

if c <> 4 then
   print('Error in for/redo', 2, c)
fi;


for i to 1k do
   flag := true;
   for j to 10 while flag do
      jj := j;
      if j = 5 then
         flag := false;
         redo
      fi
   od
od;

if jj <> 5 then
   print('Error in for/while/redo', 3)
fi;


for i to 1k do
   flag := false;
   for j to 10 until flag do
      jj := j;
      if j = 5 then
         flag := true;
         redo
      fi
   od
od;

if jj <> 5 then
   print('Error in for/until/redo', 4)
fi;

printf(', for/downto');

c := 0;

for i from 1k downto 1 do inc c od;

if i <> 0 or c <> 1k then
   print('Error in for/downto, 1', i)
fi;


c := 0;

flag := true;

for i from 100 downto 1 do
   inc c;
   if flag and i = 95 then
      flag := false;
      redo
   fi;
od;

if i <> 0 or c <> 101 then
   print('Error in for/downto, 2', i)
fi;


c := 0;

flag := true;

for i from 50 downto 1 do
   inc c;
   if flag and i = 45 then
      flag := false;
      relaunch
   fi;
od;

if i <> 0 or c <> 56 then
   print('Error in for/downto, 3', i)
fi;


c := 0;

flag := true;

for i from 50 downto 1 while i <> 10 do
   inc c;
   if flag and i = 45 then
      flag := false;
      relaunch
   fi;
od;

if i <> 10 or c <> 46 then
   print('Error in for/while/downto, 3', i)
fi;


c := 0;

flag := true;

for i from 50 downto 1 until i = 10 do
   inc c;
   if flag and i = 45 then
      flag := false;
      relaunch
   fi;
od;

if i <> 10 or c <> 46 then
   print('Error in for/until/downto, 4', i)
fi;


c := 0;

for i from 5 downto 1 do
   flag := true;
   for j from 3 downto 1 do
      inc c
      if flag and j = 2 then flag := false; redo fi
   od
od;

if i <> 0 or c <> 20 then
   print('Error in for/downto, 4', i)
fi;

printf(', try');

s := seq(10, 11, 12);

f := proc(s) is
   local flag, c, result, intermediate;
   c := 0;
   for j to 4 do
      try
         flag := true;
         for i to 4 do
            inc c
            intermediate := s[i];
            if flag and j = 2 then
               flag := false;
               redo
            fi
         od
      catch err then
         result := 'out of range' in err <> null
      yrt
   od;
   return c, result
end;

a, b := f(s);

if a <> 17 or b <> true then
   print('Error in try/redo, 1, a, b')
fi;

f := proc(s) is
   local flag, c, result, intermediate;
   c := 0;
   for j to 4 do
      try
         flag := true;
         for i to 4 do
            inc c
            intermediate := s[i];
            if flag and j = 2 then
               flag := false;
               redo
            fi
         od
      catch err then
         result := 'out of range' in err <> null;
         if j = 2 then break fi
      yrt
   od;
   return c, result
end;

a, b := f(s);

if a <> 9 or b <> true then
   print('Error in try/redo, 2')
fi;

f := proc() is
   local flag, c, s;
   flag := true;
   s := seq(1, 2, 3, 4, 5, 6, 7);
   c := 0;
   for i in s do
      inc c;
      if i=5 and flag then
         flag := false;
         delete i from s;
         relaunch
      fi
   od;
   return c, s
end;

printf(', relaunch');

a, b := f();

if a <> 11 or b <> seq(1, 2, 3, 4, 6, 7) then
   print('Error in relaunch, 1')
fi;

f := proc() is
   local flag, c, s;
   flag := true;
   s := seq(1, 2, 3, 4, 5, 6, 7);
   c := 0;
   for i to size s do
      inc c;
      if s[i] = 5 and flag then
         flag := false;
         delete s[i] from s;
         relaunch
      fi
   od;
   return c, s, i
end;

a, b, c := f();

if a <> 11 or b <> seq(1, 2, 3, 4, 6, 7) or c <> 7 then
   print('Error in relaunch, 2')
fi;

f := proc(s) is
   local flag, c, result, intermediate;
   c := 0;
   flag := true;
   for j to 4 do
      try
         for i to 4 do
            inc c;
            intermediate := s[i]
         od
      catch err then
         result := 'out of range' in err <> null;
         if flag and j = 2 then flag := false; redo fi
      yrt
   od;
   return c, result
end;

a, b := f(s);

if a <> 20 or b <> true then
   print('Error in try/redo, 3')
fi;

for i to 50 do
   for j to 50 do
      local cothx := proc(x :: {number, complex}) is
         return 1/tanh(x)
      end;
      a := cothx(i!j)
   od
od;

for i to 50 do
   for j to 50 do
      local cothx := proc(x :: complex) is
         return 1/tanh(x)
      end;
      a := cothx(i!j)
   od
od;

for i to 50 do
   for j to 50 do
      local cothx := proc(x) is
         return 1/tanh(x)
      end;
      a := cothx(i!j)
   od
od;

c := 0;
for i to 100 do
   t := time();
   e := environ.used();
   for j to 1k do
      f := << z :: complex -> sin(z) >>;
      a := f(i!(j-1))
   od;
   inc c, e;
od;

for i to 100 do
   if [4, 1, 'a'~2] = [5, 1, 'a'~2] then
      print('Error in simple table equality, 1/1')
   fi
od;


printf(', @');

f := << x -> x**2 >>;

to 1k do
  if f @ seq(1, 2, 3, 4) <> seq(1, 4, 9, 16) then
     print('Error in @ operator, 1')
  fi;
  if f @ [1, 2, 3, 4, 'a'~10, 'b'~100] <> [1, 4, 9, 16, 'a'~100, 'b'~10k] then
     print('Error in @ operator, 2')
  fi;
  if f @ {1, 2, 3, 4} <> {1, 4, 9, 16} then
     print('Error in @ operator, 3')
  fi;
  if f @ 2:3 <> 4:9 then
     print('Error in @ operator, 4')
  fi;
  if f @ f @ seq(1, 2, 3, 4) <> seq(1, 16, 81, 256) then
     print('Error in @ operator, 5')
  fi
od;


printf(', $');

f := << x -> x > 2 >>;

to 1k do
  if f $ {1, 2, 3, 4} <> {3, 4} then
     print('Error in $ operator, 1')
  fi;
  if f $ seq(1, 2, 3, 4) <> seq(3, 4) then
     print('Error in $ operator, 2')
  fi;
  if f $ [1, 2, 3, 4, 'a'~10, 'b'~100] <> [3, 4, 'a'~10, 'b'~100] then
     print('Error in $ operator, 3')
  fi;
  if f $ f $ seq(1, 2, 3, 4) <> seq(3, 4) then
     print('Error in $ operator, 4')
  fi
od;


f := proc(x) is
   return if x <= 0 then 0 else 1 fi
end;

for i from -10 to 10 do
   if i <= 0 and f(i) <> 0 then
      print('Error in if/fi op, 1', i)
   elif i > 0 and f(i) <> 1 then
      print('Error in if/fi op, 2', i)
   fi
od;


lname := 'c:/program files (x86)/agena/lib';

if << x -> ('/lib' atendof lower(x)) <> null >> $ lname split environ.kernel('pathsep') <> seq('c:/program files (x86)/agena/lib') then
   print('Error in atendof/$/split')
fi;

if << x -> ('/lib' atendof lower(x)) <> null >> @ lname split environ.kernel('pathsep') <> seq(true) then
   print('Error in atendof/@/split')
fi;


printf(', type check metamethod');

duo := 1:2;
mt := [ '__oftype' ~ proc(x) is return type(x) = pair and left(x) = 1 and right(x) = 2 end ];
setmetatable(duo, mt)
to 1k do
   if duo :: pair = false then
      print('Error in :: type check metamethod, 1')
   fi
   if duo :- pair = true then
      print('Error in :: type check metamethod, 2')
   fi
od;

settype(duo, 'duo');
to 1k do
   if duo :: 'duo' = false then
      print('Error in :: type check metamethod, 3')
   fi
   if duo :- 'duo' = true then
      print('Error in :: type check metamethod, 4')
   fi
od;

f := proc(x :: duo, y, z :: number) is return x end;
for i to 1k do
   if f(duo, 0, i) <> 1:2 then
      print('Error in argument list type check metamethod, 1')
   fi
od;
f := proc(x :: duo, y, z :: number) :: duo is return x end;
for i to 1k do
   if f(duo, 0, i) <> 1:2 then
      print('Error in argument list type check metamethod, 2')
   fi
od;

duo := 1:2;
setmetatable(duo, mt);
f := proc(x :: pair, y, z :: number) :: pair is return x end;
for i to 1k do
   if f(duo, 0, i) <> 1:2 then
      print('Error in argument list type check metamethod, 3')
   fi
od;

printf(', self-defined binary operator');

plus := proc(x, y) is return x + y end;

f := proc(z :: number) is
   return 1 plus z
end;

for i to 100 do
   f(i)
od;

for i to 100 do
   b := f(i)
od;

if b <> 101 then
   error('Error', b)
fi;

for i to 1k do
   if f(i) <> i + 1 then error() fi
od;

for i to 100 do
   for j from 0 to 3 do
      b := f(2^j) plus f(2) plus f(4) plus f(8)
   od
od;

if b <> 26 then
   error('Error', b)
fi

plus := << x, y -> x + y >>;

f := << x -> x >>;

if f(1) plus f(2) plus f(4) plus f(8) <> 15 then
   error('Error', b)
fi;

f := proc(z :: number) :: {number, complex} is
   return 1 plus z
end;

for i to 100 do
   f(i)
od;


f := proc(z :: number) :: number is
   return 1 plus z
end;

for i to 100 do
   f(i)
od;


f := ['or' ~ << x, y -> x or y >>];

g := [true, false];

to 100 do
   if g[1] f['or'] g[2] <> true then
      print('Error with indexed functions, 1')
   fi;
   if true f['or'] g[2] <> true then
      print('Error with indexed functions, 2')
   fi;
   if g[1] f['or'] false <> true then
      print('Error with indexed functions, 3')
   fi;
   if true f['or'] false <> true then
      print('Error with indexed functions, 4')
   fi
   if g[1] f['or'] g[2] f['or'] g[1] <> true then
      print('Error with indexed functions, 5')
   fi;
   if true f['or'] g[2] f['or'] g[1] <> true then
      print('Error with indexed functions, 6')
   fi;
   if g[1] f['or'] false f['or'] true <> true then
      print('Error with indexed functions, 7')
   fi;
   if true f['or'] false f['or'] false <> true then
      print('Error with indexed functions, 8')
   fi;
   if (g[1] f['or'] g[2] f['or'] g[1]) <> true then
      print('Error with indexed functions, 9')
   fi;
   if (true f['or'] g[2] f['or'] g[1]) <> true then
      print('Error with indexed functions, 10')
   fi;
   if (g[1] f['or'] false f['or'] true) <> true then
      print('Error with indexed functions, 11')
   fi;
   if (true f['or'] false f['or'] false) <> true then
      print('Error with indexed functions, 12')
   fi
   if (g[1] or g[2] f['or'] g[1]) <> true then
      print('Error with indexed functions, 13')
   fi;
   if (true f['or'] g[2] or g[1]) <> true then
      print('Error with indexed functions, 14')
   fi
od;


printf(', remember tables');

# Maple V R4: with(combinat, fibonacci); seq(fibonacci(i), i=0 .. 76);
ffib := [ 0 ~ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,
       6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269,
       2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155,
       165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976,
       7778742049, 12586269025, 20365011074, 32951280099, 53316291173, 86267571272, 139583862445,
       225851433717, 365435296162, 591286729879, 956722026041, 1548008755920, 2504730781961,
       4052739537881, 6557470319842, 10610209857723, 17167680177565, 27777890035288, 44945570212853,
       72723460248141, 117669030460994, 190392490709135, 308061521170129, 498454011879264,
       806515533049393, 1304969544928657, 2111485077978050, 3416454622906707 ];

k := 500;

for x to 100 do
   fib := proc(n) is
      if n = 0 or n = 1 then return n fi;  # exit conditions
      return fib(n - 2) + fib(n - 1)
   end;
   rtable.rinit(fib);  # switch on remember table
   for i to k do
      if fib(50) <> ffib[50] then
         print('Error in remember table, 1a', fib(50), ffib[50])
      fi
   od
od;

for x to 100 do
   fib := proc(n) is
      feature reminisce;  # creates a read-write remember table
      if n = 0 or n = 1 then return n fi;  # exit conditions
      return fib(n - 2) + fib(n - 1)
   end;
   for i to k do
      if fib(50) <> ffib[50] then
         print('Error in remember table, 1b')
      fi
   od
od;

r := proc(x) is
   return math.rint(x)
end;

to 20 do
   for i from 0 to 76 do
      if ffib[i] <> math.fib(i) then print('Error in remember table, 2, ', i, ffib[i], math.fib(i), ffib[i] - math.fib(i)) fi
   od;
od;

if fib(10) <> ffib[10] then
   print('Error in remember table, 3, ', fib(10), 89)
fi;

fib := proc(n) is
   assume(n >= 0);
   return fib(n - 2) + fib(n - 1)
end;

rtable.remember(fib, [0 ~ 0, 1 ~ 1]);

if fib(50) <> ffib[50] then
   print('Error in remember table, 4')
fi;

# procname test

for x to 100 do
   fib := proc(n) is
      if n = 0 or n = 1 then return n fi;  # exit conditions
      return procname(n - 2) + procname(n - 1)
   end;
   rtable.rinit(fib);  # switch on remember table
   for i to k do
      if fib(50) <> ffib[50] then
         print('Error in remember table, 1a', fib(50), ffib[50])
      fi
   od
od;

fib := proc(n) is
   if n = 0 or n = 1 then return n fi; # exit conditions
   return procname(n - 2) + procname(n - 1)
end;

to 100 do
   if fib(3) <> 2 then
      print('Error in procname'); break;
   fi
od;

clear k, fib, ffib, r;


printf(', storage');

to 100 do
   f := proc() is
      feature storage;
      storage[1] := Pi;
      storage.entry := E;
      return storage[1], storage.entry
   end;
   g := proc() is
      feature storage;
      storage[1], storage[2] -> Pi;
      return storage
   end
od;

to 100 do
   a, b := f();
od;

if [a, b] <> [Pi, E] then
   print('Error with storage table, 1');
fi;


if g() <> [Pi, Pi] then
   print('Error with storage table, 2');
fi

clear f, g


printf(', with & related');

zips := ['duedo' ~ 40210:40629, 'bonn' ~ 53111:53229, 'cologne' ~ 50667:51149];

with duedo, bonn in zips scope
   if duedo <> 40210:40629 or bonn <> 53111:53229 or cologne <> null then
      print('Error in with/in statement, 1')
   fi;
   duedo := null  # zips.duedo is not changed
epocs;

if duedo <> null or bonn <> null then
   print('Error in with/in statement, 2')
fi;

if zips.duedo <> 40210:40629 then
   print('Error in with statement, 3')
fi;

x := 0;
to 100 do
   a := with n := exp(1) if x > 0 then n else 2*n fi;
   if a <> 2*exp(1) then
      print('Error in with/if op, 1'); break
   fi
od;

to 100 do
   a := with n := exp(1) -> if x = 0 then n else 2*n fi;
   if a <> exp(1) then
      print('Error in with/if op, 2'); break
   fi
od;

clear a, b;

to 100 do
   with a, b := 10, 11 do
      if a <> 10 or b <> 11 then
         print('Error in with/:= op, 1'); break
      fi
   od;
   if assigned a or assigned b then
      print('Error in with/:= op, 2'); break
   fi;
od;

scope
   local duedo, bonn in zips;
   if duedo <> 40210:40629 or bonn <> 53111:53229 or cologne <> null then
      print('Error in assignment/unpack, 1')
   fi
epocs

if duedo <> null or bonn <> null then
   print('Error in assignment/unpack, 2')
fi;

scope
   local duedo, bonn;
   duedo, bonn in zips;
   if duedo <> 40210:40629 or bonn <> 53111:53229 or cologne <> null then
      print('Error in assignment/unpack, 3')
   fi
epocs

if duedo <> null or bonn <> null then
   print('Error in assignment/unpack, 4')
fi;

zips := [duedo = 4000, bonn = 5300];

with zips do
   if _.bonn <> 5300 then
      print('Error in with, 1')
   fi;
   _.bonn := 53111
od;

if zips <> [bonn = 53111, duedo = 4000] then
   print('Error in with, 2')
fi;


printf(', case');

to 100 do
   a := 0; s := false; r := null;
   case
      of a < 0 -> r := -1
      of a = 0 -> r := 0
      of a > 0 -> r := 1
      onsuccess s := true
      else print('Error in case of, 1')
   esac;
   if r <> 0 or s = false then
      print('Error in case of, 2')
   fi
   s := false;
   case a
      of undefined then r := undefined
      of -1 to 1 then r := 0
      onsuccess s := true
      else print('Error in case val of, 3')
   esac;
   if r <> 0 or s = false then
      print('Error in case of, 4')
   fi;
   a := ''; r := null; s := false;
   case a
     of '' then r := 1
     of 'a' to 'c' then r := 2
     onsuccess s := true
     else r := 0
   esac;
   if r <> 1 or s = false then
      print('Error in case of, 5')
   fi;
   a := 'b'; r := null; s := false;
   case a
     of '' then r := 1
     of 'a' to 'c' then r := 2
     onsuccess s := true
     else r := 0
   esac;
   if r <> 2 then
      print('Error in case of, 6')
   fi;
   a := 0;
   case a
      of -1 then r := -1
      of 'a' to 'c' then r := 0
      of 0 to 10 then r := 10
   esac;
   if r <> 10 then
      print('Error in case of, 7')
   fi
od


printf(', empty')

if empty([]) <> true then
   print('Error in empty, 1')
fi;
if empty(seq()) <> true then
   print('Error in empty, 2')
fi;
if empty({}) <> true then
   print('Error in empty, 3')
fi;
if empty(reg()) <> false then
   print('Error in empty, 4')
fi;
if empty(['aa' ~ 1]) <> false then
   print('Error in empty, 5')
fi;
if empty([1, 'aa' ~ 2, 3, 1000 ~ 4]) <> false then
   print('Error in empty, 6')
fi;


printf(', times')

if times(<< x -> 2 + 1/x >>, 1, 40) ~<> 2.4142135623731 then
  print('Error in times')
fi;


printf(', pre & post')

h := proc(x :: number)
   pre x > 0 is
   return post x <> 1 is x
end;

for i from 2 to 1k do
   a := h(i)
od;


printf(', map & @')

to 100 do
   g := << x -> -x >>
   f := << x -> 2*x >>

   h := map(g, f);   # g(f(x)) = (g @ f)(x)

   if h(2) <> -4 then
      print('Error in map, 1')
   fi;

   g := << x, y -> -x * y >>
   f := << x, y -> y*x, 10 >>

   h := map(g, f);   # g(f(x)) = (g @ f)(x)

   if h(2, 3) <> -60 then
      print('Error in map, 2')
   fi;

   g := << x, y -> -x * y, 0 >>
   f := << x, y -> y*x, 10 >>

   h := map(g, f);   # g(f(x)) = (g @ f)(x)

   if [h(2, 3)] <> [-60, 0] then
      print('Error in map, 3')
   fi;

   g := << x -> -x >>
   f := << x -> 2*x >>

   h := g @ f;   # g(f(x)) = (g @ f)(x)

   if h(2) <> -4 then
      print('Error in @ composite, 1')
   fi;

   g := << x, y -> -x * y >>
   f := << x, y -> y*x, 10 >>

   h := g @ f;   # g(f(x)) = (g @ f)(x)

   if h(2, 3) <> -60 then
      print('Error in @ composite, 2')
   fi;

   g := << x, y -> -x * y, 0 >>
   f := << x, y -> y*x, 10 >>

   h := g @ f;   # g(f(x)) = (g @ f)(x)

   if [h(2, 3)] <> [-60, 0] then
      print('Error in @ composite, 3')
   fi;
od;


printf(', global')

to 50 do
   f := proc() is
      local x
      global y
      x := 1;
      global y
   end;
   g := proc() is
      local y
      global x
      x := 1;
      global x
   end
od;


printf(', parameter check')

f := proc( x :: { complex, set, string, table, nonnegative } ) is return x end;  # keep very last type at the end of the check list

to 50 do
   f(1);
   f(1!1);
   f(1);
   f([])
od;

f := proc( x :: { complex, set, string, table, nonnegative } ) :: { complex, set, string, table, nonnegative } is return 1 end;  # keep very last type at the end of the check list

to 50 do
   f(1);
   f(1!1);
   f(1);
   f('1');
   f([])
od;

# we are now checking OP_TFORPREP and OP_TFORLOOP when looping over tables and functions

printf(', table and function looping')

tbl := [10, 20, 30, 'a'~40, 'b'~50];
inds := tables.indices(tbl);
vals := tables.entries(tbl);

for i in tbl do
   local j;
   if not(i in vals) then
      print('Error in loop over table, 1')
   fi;
   if j then
      print('Error in loop over table, 2')
   fi
od;

for i, j in tbl do
   local k;
   if k then
      print('Error in loop over table, 5')
   fi;
   if not(i in inds) then
      print('Error in loop over table, 3')
   fi;
   if not(j in vals) then
      print('Error in loop over table, 4')
   fi
od;

g := proc(tbl) is
   local inds := tables.indices(tbl);
   local vals := tables.entries(tbl);
   for i in tbl do
      local j;
      if not(i in vals) then
         print('Error in loop over table, 5')
      fi;
      if j then
         print('Error in loop over table, 6')
      fi
   od;
   for i, j in tbl do
      local k;
      if k then
         print('Error in loop over table, 7')
      fi;
      if not(i in inds) then
         print('Error in loop over table, 8')
      fi;
      if not(j in vals) then
         print('Error in loop over table, 9')
      fi
   od
end;
g(tbl);

clear tbl, inds, vals, g;

str := 'hello world from Lua'
tbl := str split ' ';
for w in strings.gmatch(str, '%a+') do
   local k;
   if k then
      print('Error in loop over table, 10')
   fi;
   if not(w in tbl) then
      print('Error in loop over table, 11')
   fi
od;

for v, w in strings.gmatch(str, '%a+') do
   local k;
   if k then
      print('Error in loop over table, 12')
   fi;
   if not(v in tbl) then
      print('Error in loop over table, 13')
   fi;
   if not(w in tbl) then
      print('Error in loop over table, 14')
   fi
od;

f := strings.gmatch(str, '%a+');
g := proc(f) is
   for w in f do
      local k;
      if k then
         print('Error in loop over table, 15')
      fi;
      if not(w in tbl) then
         print('Error in loop over table, 16')
      fi
   od;
   for v, w in strings.gmatch(str, '%a+') do
      local k;
      if k then
         print('Error in loop over table, 17')
      fi;
      if not(v in tbl) then
         print('Error in loop over table, 18')
      fi;
      if not(w in tbl) then
         print('Error in loop over table, 19')
      fi
   od
end;
g(f);

tbl := reg(10, 20, null, 40);

for i in tbl do
   if not(i in tbl) then
      print('Error in loop over register, 1', i)
   fi
od;

g := proc(tbl) is
   for w in tbl do
      local k;
      if k then
         print('Error in loop over register, 2')
      fi;
      if not(w in tbl) then
         print('Error in loop over register, 3')
      fi
   od;
   for v, w in tbl do
      local k;
      if k then
         print('Error in loop over register, 4')
      fi;
      if not(v in [1, 2, 3, 4]) then
         print('Error in loop over register, 5')
      fi
      if not(w in tbl) then
         print('Error in loop over register, 6')
      fi
   od
end;
g(tbl);

clear tbl, str, f, g;


printf(', if is op');

a := 10;

sgn := if is a < 0 then  # determines sign of `a'
          print('I am negative');
          a +:= 2;
          return -1
       elif a = 0 then
          print('I am zero');
          return 0
       else
          return 1
       fi;

if sgn <> 1 or a <> 10 then
   print('Error in if is op, 1')
fi;

clear a, sgn;


printf(', |x|');

if | -Pi | <> abs(-Pi) then
   print('Error in |x| op, 1')
fi;

if | -Pi + 1 | <> abs(-Pi + 1) then
   print('Error in |x| op, 2')
fi;

for x from -5 to 5 do
   if | x + 1 | <> abs(x + 1) then
      print('Error in |x| op, 3')
   fi
od;

for x from -5 to 5 do
   if | 1 + x | <> abs(1 + x) then
      print('Error in |x| op, 4')
   fi
od;

for x from -5 to 5 do
   if | sin(x) - 10 | <> abs(sin(x) - 10) then
      print('Error in |x| op, 5')
   fi
od;

for x from -5 to 5 do
   if | -10 - sin(x) | <> abs(-10 - sin(x)) then
      print('Error in |x| op, 6')
   fi
od;

for x from -5 to 5 do
   if | x | <> abs(x) then
      print('Error in |x| op, 7')
   fi
od;


/*

printf(', relrange')

f := << x -> x >>;
a := 1; b := 2; c := 3;
to 50 do
   if (1 < 2 < 3) <> true then
      print('error in relrange, 1')
   fi;
   if (1 <= 1 < 3) <> true then
      print('error in relrange, 2')
   fi;
   if (1 <= b < 3) <> true then
      print('error in relrange, 3')
   fi;
   if (1 <= b < c) <> true then
      print('error in relrange, 4')
   fi;
   if (a <= b < c) <> true then
      print('error in relrange, 5')
   fi;
   if (identity(a) <= b < c) <> true then
      print('error in relrange, 6')
   fi;
   if (identity(2*a) <= identity(2*b) < 2*c) <> true then
      print('error in relrange, 7')
   fi;
   if (2*a <= identity(2*b) < 2*c) <> true then
      print('error in relrange, 8')
   fi;
   if (2 <= identity(2*b) < 2*c) <> true then
      print('error in relrange, 9')
   fi;
   if (2 <= identity(2*b) < identity(2*c)) <> true then
      print('error in relrange, 10')
   fi;
   if (f(exp(2*a)) <= f(exp(2*b)) < identity(200*c)) <> true then
      print('error in relrange, 11')
   fi;
   if (exp(f(2*a)) <= f(exp(2*b)) < identity(200*c)) <> true then
      print('error in relrange, 12')
   fi;
   if (exp(f(2*a)) <= f(exp(f(2*b))) < identity(200*c)) <> true then
      print('error in relrange, 13')
   fi;
   if (exp(f(2*a)) <= exp(f(2*b)) < identity(200*c)) <> true then
      print('error in relrange, 14')
   fi;
   if 1 < 2 < 3 <> true then
      print('error in relrange, 15')
   fi;
   if 1 <= 1 < 3 <> true then
      print('error in relrange, 16')
   fi;
   if 1 <= b < 3 <> true then
      print('error in relrange, 17')
   fi;
   if 1 <= b < c <> true then
      print('error in relrange, 18')
   fi;
   if a <= b < c <> true then
      print('error in relrange, 19')
   fi;
   if identity(a) <= b < c <> true then
      print('error in relrange, 20')
   fi;
   if identity(2*a) <= identity(2*b) < 2*c <> true then
      print('error in relrange, 21')
   fi;
   if 2*a <= identity(2*b) < 2*c <> true then
      print('error in relrange, 22')
   fi;
   if 2 <= identity(2*b) < 2*c <> true then
      print('error in relrange, 23')
   fi;
   if 2 <= identity(2*b) < identity(2*c) <> true then
      print('error in relrange, 24')
   fi;
   if f(exp(2*a)) <= f(exp(2*b)) < identity(200*c) <> true then
      print('error in relrange, 25')
   fi;
   if exp(f(2*a)) <= f(exp(2*b)) < identity(200*c) <> true then
      print('error in relrange, 26')
   fi;
   if exp(f(2*a)) <= f(exp(f(2*b))) < identity(200*c) <> true then
      print('error in relrange, 27')
   fi;
   if exp(f(2*a)) <= exp(f(2*b)) < identity(200*c) <> true then
      print('error in relrange, 28')
   fi;
od;

to 50 do
   f := << x -> x >>
   if 1 < 2 < 3 <> true then
      print('error in relrange, 29')
   fi;
   if 1 <= 1 < 3 <> true then
      print('error in relrange, 30')
   fi;
   a := 1; b := 2; c := 3;
   if 1 <= b < 3 <> true then
      print('error in relrange, 31')
   fi;
   if 1 <= b < c <> true then
      print('error in relrange, 32')
   fi;
   if a <= b < c <> true then
      print('error in relrange, 33')
   fi;
   if identity(a) <= b < c <> true then
      print('error in relrange, 34')
   fi;
   if identity(2*a) <= identity(2*b) < 2*c <> true then
      print('error in relrange, 35')
   fi;
   if 2*a <= identity(2*b) < 2*c <> true then
      print('error in relrange, 36')
   fi;
   if 2 <= identity(2*b) < 2*c <> true then
      print('error in relrange, 37')
   fi;
   if 2 <= identity(2*b) < identity(2*c) <> true then
      print('error in relrange, 38')
   fi;
   if f(exp(2*a)) <= f(exp(2*b)) < identity(200*c) <> true then
      print('error in relrange, 39')
   fi;
   if exp(f(2*a)) <= f(exp(2*b)) < identity(200*c) <> true then
      print('error in relrange, 40')
   fi;
   if exp(f(2*a)) <= f(exp(f(2*b))) < identity(200*c) <> true then
      print('error in relrange, 41')
   fi;
   if exp(f(2*a)) <= exp(f(2*b)) < identity(200*c) <> true then
      print('error in relrange, 42')
   fi;
od;

a := 1; b := 2; c := 3;
p := proc() is
      if 2*a <= identity(2*b) < 2*c <> true then
         print('error in relrange, 2::8')
      fi;
      if -2 <= identity(2*b) < 2*c <> true then
         print('error in relrange, 2::9')
      fi;
      if -2 <= identity(2*b) < identity(2*c) <> true then
         print('error in relrange, 2::10')
      fi;
end;



f := << x -> x >>;
a := 1; b := 2; c := 3;
p := proc() is
   to 50 do
      if 1 < 2 < 3 <> true then
         print('error in relrange, 2::1')
      fi;
      if 1 <= 1 < 3 <> true then
         print('error in relrange, 2::2')
      fi;
      if 1 <= b < 3 <> true then
         print('error in relrange, 2::3')
      fi;
      if 1 <= b < c <> true then
         print('error in relrange, 2::4')
      fi;
      if a <= b < c <> true then
         print('error in relrange, 2::5')
      fi;
      if identity(a) <= b < c <> true then
         print('error in relrange, 2::6')
      fi;
      if identity(2*a) <= identity(2*b) < 2*c <> true then
         print('error in relrange, 2::7')
      fi;
      if 2*a <= identity(2*b) < 2*c <> true then
         print('error in relrange, 2::8')
      fi;
      if 2 <= identity(2*b) < 2*c <> true then
         print('error in relrange, 2::9')
      fi;
      if 2 <= identity(2*b) < identity(2*c) <> true then
         print('error in relrange, 2::10')
      fi;
      if f(exp(2*a)) <= f(exp(2*b)) < identity(200*c) <> true then
         print('error in relrange, 2::11')
      fi;
      if exp(f(2*a)) <= f(exp(2*b)) < identity(200*c) <> true then
         print('error in relrange, 2::12')
      fi;
      if exp(f(2*a)) <= f(exp(f(2*b))) < identity(200*c) <> true then
         print('error in relrange, 2::13')
      fi;
      if exp(f(2*a)) <= exp(f(2*b)) < identity(200*c) <> true then
         print('error in relrange, 2::14')
      fi;
   od;
end;
p();
to 50 do
   p();
od;

a, b, c := 1, 2, 3;
to 50 do
   if not(a < 2 < 3) then
      print('error in relrange, 2::15')
   fi;
   if not(a < b < 3) then
      print('error in relrange, 2::16')
   fi;
   if not(a < b < c) then
      print('error in relrange, 2::17')
   fi;
   if not(1 < 2 < c) then
      print('error in relrange, 2::18')
   fi;
   if not(1 < b < c) then
      print('error in relrange, 2::19')
   fi;
   if not(1 < b < 3) then
      print('error in relrange, 2::20')
   fi
od;

f := << x -> 2*x >>
to 50 do
   if not(f(1) < 4 < 6) then
      print('error in relrange, 2::21')
   fi;
   if not(f(1) < f(3) < 9) then
      print('error in relrange, 2::22')
   fi;
   if not(f(1) < f(3) < f(10)) then
      print('error in relrange, 2::23')
   fi;
   if not(1 < 2 < f(10)) then
      print('error in relrange, 2::24')
   fi;
   if not(1 < f(3) < f(10)) then
      print('error in relrange, 2::25')
   fi;
   if not(1 < f(3) < 10) then
      print('error in relrange, 2::26')
   fi
od;

a := [1, 3.5, 10]; b := 1; f := << x -> x*Pi >>;
to 50 do
   if not(a[1] < 4 < 6) then
      print('error in relrange, 2::27')
   fi;
   if not(a[1] < a[2] < 6) then
      print('error in relrange, 2::28')
   fi;
   if not(a[1] < a[2] < a[3]) then
      print('error in relrange, 2::29')
   fi;
   if not(1 < 2 < a[3]) then
      print('error in relrange, 2::30')
   fi;
   if not(1 < a[2] < a[3]) then
      print('error in relrange, 2::31')
   fi;
   if not(1 < a[2] < 10) then
      print('error in relrange, 2::32')
   fi;
   if not(b < 2 < a[3]) then
      print('error in relrange, 2::33')
   fi;
   if not(b < a[2] < a[3]) then
      print('error in relrange, 2::34')
   fi;
   if not(b < a[2] < 10) then
      print('error in relrange, 2::35')
   fi;
   if not(f(1) < 4 < a[3]) then
      print('error in relrange, 2::36')
   fi;
   if not(f(1) < a[2] < a[3]) then
      print('error in relrange, 2::37')
   fi;
   if not(f(1) < a[2] < 10) then
      print('error in relrange, 2::38')
   fi;
od;

to 50 do
   if not(2*a[1] < 2*4 < 2*6) then
      print('error in relrange, 2::39')
   fi;
   if not(2*a[1] < 2*a[2] < 2*6) then
      print('error in relrange, 2::40')
   fi;
   if not(2*a[1] < 2*a[2] < 2*a[3]) then
      print('error in relrange, 2::41')
   fi;
   if not(2*1 < 2*2 < 2*a[3]) then
      print('error in relrange, 2::42')
   fi;
   if not(2*1 < 2*a[2] < 2*a[3]) then
      print('error in relrange, 2::43')
   fi;
   if not(2*1 < 2*a[2] < 2*10) then
      print('error in relrange, 2::44')
   fi;
   if not(2*b < 2*2 < 2*a[3]) then
      print('error in relrange, 2::45')
   fi;
   if not(2*b < 2*a[2] < 2*a[3]) then
      print('error in relrange, 2::46')
   fi;
   if not(2*b < 2*a[2] < 2*10) then
      print('error in relrange, 2::47')
   fi;
   if not(2*f(1) < 2*4 < 2*a[3]) then
      print('error in relrange, 2::48')
   fi;
   if not(2*f(1) < 2*a[2] < 2*a[3]) then
      print('error in relrange, 2::49')
   fi;
   if not(2*f(1) < 2*a[2] < 2*10) then
      print('error in relrange, 2::50')
   fi;
od;

test := proc(o, n :: number) is
   local R := [];
   if float(n) then
      error('Error in `linalg.column`: only positive integers accepted, got ' & n & '.')
   fi;
   case typeof(o)
      of table then
         #local rowdim;
         if not(1 <= n <= size o) then
            error('Error in `linalg.column`: column ' & n & ' does not exist.')
         fi;
      of sequence then
         if n < 1 or n > o.dim then
            error('Error in `linalg.column`: column ' & n & ' does not exist.')
         fi;
      else
         argerror(o, 'linalg.column', 'matrix or vector expected')  # 2.10.0 changed
   esac;
   return R
end;

if test([[1, 2], [3, 4]], 1) <> [] then
   print('Error in relrange/test procedure')
fi;

f := proc(x, a, b) is return a < x < b end

if f(2, 0, 10) <> true then
   print('Error in relrange/f procedure')
fi;

*/

print('\n\nbasics: ' & tostring(time() - t) & ' seconds');

# delete all global names
clear a, b, c, d, duo, e, f, fib, flag, g, h, i, iszero, j, jj, lname, moons, mt, p, plus, r,
      readonly, readonly_mt.__writeindex, s, t, test, x, z, zips;

