write('Testing registers ...\n\n');
t := time();

c := 0;
for i to 10 do
   a := reg();
   b := reg();
   for i from 0 to 15 do
      a[i+1] := i;
      b[i+1] := i
   od;
   inc c;
   if a <> b then
      print(tostring(c) & '>1|', '<>')
   fi;
   if not(a = b) then
      print(tostring(c) & '>2|', '=')
   fi;
   if not(a == b) then
      print(tostring(c) & '>3|', '==')
   fi;
   a[16] := 'a';
   if a = b then
      print(tostring(c) & '>4|', '<>')
   fi;
   if a = b then
      print(tostring(c) & '>5|', '=')
   fi;
   if a == b then
      print(tostring(c) & '>6|', '==')
   fi;
   delete 'a' from a;
   d := copy(a);
   if a <> d then
      print(tostring(c) & '>7|', 'copy <>')
   fi;
   if not(a = d) then
      print(tostring(c) & '>8|', 'not/=')
   fi;
   if not(a == d) then
      print(tostring(c) & '>9|', 'not/==')
   fi;
   if size(a) <> size(d) then
      print(tostring(c), 'size')
   fi;
   if not(filled(a)) then
      print(tostring(c), 'filled')
   fi;
   if 'a' in a then
      print(tostring(c), 'in')
   fi;
   if not(0 in a) then
      print(tostring(c), 'in')
   fi;
   if [1, 2] in reg([1, 2]) <> true then
      print(tostring(c), 'in')
   fi;
   if [1, 2] in reg() <> false then
      print(tostring(c), 'in')
   fi;
   if 1:2 in reg(1:2) <> true then
      print(tostring(c), 'in')
   fi;
   if 1:2 in reg() <> false then
      print(tostring(c), 'in')
   fi;
   if seq(1, 2) in reg(seq(1, 2)) <> true then
      print(tostring(c), 'in')
   fi;
   if seq(1, 2) in reg() <> false then
      print(tostring(c), 'in')
   fi;
   if reg(1, 2) in reg(reg(1, 2)) <> true then
      print(tostring(c), 'in')
   fi;
   if reg(1, 2) in reg() <> false then
      print(tostring(c), 'in')
   fi;
   if a intersect b = a then
      print(tostring(c), 'intersect')
   fi;
   if a minus b <> reg(null) then
      print(tostring(c), 'minus')
   fi;
   registers.settop(a, 15);
   if not(a subset b) then
      print(tostring(c), 'subset')
   fi;
   if not(a xsubset b) then
      print(tostring(c), 'xsubset')
   fi;
   if getentry(a, 1) <> 0 then
      print(tostring(c), 'getentry')
   fi;
   registers.settop(a, 16);
   a[16] := null;
   insert 1 into a;
   d := copy(a);
   #insert 0 into d;
   if duplicates(d) <> reg(1) then
      print(tostring(c), 'duplicates')
   fi;
   clear d;
   d := copy(a);
   registers.settop(a, 15);
   if a <> unique(d) then
      print(tostring(c), 'unique')
   fi;
   create register a1(100), register b1(100), register c1(200);
   for i from 1 to 100 do
      insert i into a1;
      insert i+100 into b1;
   od;
   for i from 1 to 200 do
      insert i into c1
   od;
   if a1 union b1 <> c1 then
      print(tostring(c), 'union')
   fi;
   create register a(2001), register d(2001);
   for i from -1k to 1k do insert i^2 into d od;
   for i from -1k to 1k do insert i into a od;
   if d <> map(<< x -> x^2 >>, a) then
      print(tostring(c), 'map')
   fi;
   clear a, d;
   b2 := reg(3, 6);
   if map(<< (x) ->  x^2 >>, b2) <> reg(9, 36) then
      print(tostring(c), 'map')
   fi;
   if reduce(<< item, accumulator -> item + accumulator >>, reg(1, 2, 3, 4), 0) <> 10 then
      print(tostring(c), 'reduce')
   fi;
   a2 := reg(1, 2);
   b2 := reg(1, 2);
   if zip(<< (x, y) ->  x + y >>, a2, b2) <> reg(2, 4) then
      print(tostring(c), 'zip')
   fi;
   create register a3(1k), register b3(500);
   for i to 1000 do
      insert i into a3;
      if i > 500 then
         insert i into b3
      fi
   od;
   if select(<< x -> x > 500 >>, a3) <> b3 then
      print(tostring(c), 'select, 1')
   fi;
   c3 := nreg(2, 1000, 2);  # register of even numbers
   if select( << x -> even(x) >>, a3, newarray=true) <> c3 then
      print(tostring(c), 'select, 2')
   fi;
   c4 := nreg(1, 1000, 2);
   if remove( << x -> even(x) >>, a3) <> c4 then
      print(tostring(c), 'remove, 1')
   fi;
   if remove(<< x -> even(x) >>, a3, newarray=true) <> c4 then
      print(tostring(c), 'remove, 2')
   fi;
   if remove(<< x, y -> even(x-y) >>, a3, 1, newarray=true) <> c3 then
      print(tostring(c), 'remove, 3')
   fi;
   p, q := selectremove(<< x -> even(x) >>, a3);
   if p <> c3 then
      print(tostring(c), 'selectremove, 1')
   fi;
   if q <> c4 then
      print(tostring(c), 'selectremove, 2')
   fi;
   p, q := selectremove(<< x -> even(x) >>, a3, newarray=true);
   if p <> c3 then
      print(tostring(c), 'selectremove, 3')
   fi;
   if q <> c4 then
      print(tostring(c), 'selectremove, 4')
   fi;
   if countitems(<< x -> x > 500 >>, a3) <> 500 then
      print(tostring(c), 'countitems')
   fi;
   a4 := reg('a', 'a', 1000, 'a');
   if whereis(a4, 'a') <> reg(1, 2, 4) then
      print(tostring(c), 'whereis')
   fi;
   a5 := reg();
   insert a5 into a5
   if environ.isselfref(a5) <> true then
      print(tostring(c), 'environ.isselfref')
   fi;
od;

# seq bug with inserts and subsequent deletions (earlier than Agena 1.0.6)
create register a(512);

for i to 128 do
   insert i into a;
   delete i from a
od;

if not filled(a) then print('Error in regs/delete') fi;

for i to 256 do  # twice as above
   insert i into a;
   if top(a) <> null then print('error in top') fi;
   if bottom(a) <> i then print('error in bottom') fi;
   pop top from a;
   pop bottom from a
od;

if filled(a) then print('Error in regs/pop') fi;

a := reg(10, 20, 30, 40, 50);
for i to 128 do
   c := a[2 to 3]
od;

if c <> reg(20, 30) then print('error in new sublists/regs, 1') fi;

for i to 128 do
   local c1 := a[2 to 3]
   c := c1
od;

if c <> reg(20, 30) then print('error in new sublists/regs, 2') fi;

f := proc(x, a, b) is
   return x[a to b]
end;

for i to 128 do
   local c1 := f(a, 2, 3)
   c := c1
od;

if c <> reg(20, 30) then print('error in new sublists/regs, 3') fi;

a := reg('a', 'b', 'c');
for i to 1k do
   c := values(a, 1, 2, 3)
od;
if a <> c then error('error in values/register') fi;

x := nreg(1, 100);

for i to 128 do
   rotate bottom x
od;

for i to 128 do
   rotate top x
od;

if x <> nreg(1, 100) then
   print('Error in rotate statement, 1')
fi;

for i from 100 to 1 by -1 do
   if pop(x) <> i then
      print('Error in pop statement, 1')
   fi
od;

if x = reg() then
   print('Error in pop statement, 2')
fi;

create register s(3);

to 10 do
   for i to 3 do s[i] := i od;
   exchange s
od;

if s <> reg(1, 3, 2) then
   print('Error in duplicate/exchange statement')
fi;

if size nreg(1, 2, 0.1) <> 11 then
   print('Error reg creation')
fi;

writeline('\nDone in ' & time()-t & ' seconds');

# delete all global variables
clear a, a1, a2, a3, a4, a5, b, b1, b2, b3, c, c1, c2, f, i, k, p, q, str, s, t, v, x;

