------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 1995 by International Computer Science Institute            --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  is distributed  in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------

-- Author: Matthew B. Kennel <kennel@msr.epm.ornl.gov>

class MATVEC_TEST is
   -- tests stolen from everywhere.
   include TEST;
   
   main is
      testmat;
      testmatd;      
      testvec;
      testvecd;
   end;
   
   testvec is
      class_name("VEC");
      v0 ::=#VEC(|1.0,0.0,0.0|);
      v1 ::=#VEC(|0.0,1.0,0.0|);
      v2 ::=#VEC(|0.0,0.0,1.0|);
      test("dim",v1.dim.str,"3");
      test("str",v0.str,"|1,0,0|");
      test("str",v1.str,"|0,1,0|");
      test("str",v2.str,"|0,0,1|");

      test("plus", (v0+v1).str,#VEC(|1.0,1.0,0.0|).str);

      test("minus", (v0-v1).str, #VEC(|1.0,-1.0,0.0|).str);

      test("dot", v0.dot(v1).str, 0.str);

      r ::= v0.copy;
      r.inplace_scaled_by(5.0);
      test("inplace_scaled_by", r.str, #VEC(|5.0,0.0,0.0|).str);

      r := v0.copy;
      r.inplace_contents(v1);
      test("inplace_contents", r.str, #VEC(|0.0,1.0,0.0|).str);

      r := v0.copy;
      r.inplace_plus_arg(v1);
      test("inplace_plus_arg", r.str,#VEC(|1.0,1.0,0.0|).str);
      
      r := v0.copy;
      r.inplace_plus_scaled_arg(5.0,v1);
      test("inplace_plus_scaled_arg", r.str , #VEC(|1.0,5.0,0.0|).str);

      r := v0.copy;
      r.inplace_arg_plus_arg(v1,v2);
      test("inplace_arg_plus_arg", r.str ,#VEC(|0.0,1.0,1.0|).str);

      r := v0.copy;  r.inplace_arg_minus_arg(v1,v2);
      test("inplace_arg_minus_arg", r.str, #VEC(|0.0,1.0,-1.0|).str);

      r := v0.copy;  r.inplace_elements(3.0);      
      test("inplace_elements", r.str, #VEC(|3.0,3.0,3.0|).str);

      r := v0.copy;  r.inplace_scaled_by(2.0);      
      test("inplace_scaled_by/length", r.length.str, 2.str);

      r := v0.copy;  r.inplace_scaled_by(2.0);      
      test("length_squared", r.length_squared.str, 4.str);
      
      r := v0.copy;  r.inplace_scaled_by(5.0); r.inplace_normalized;
      test("inplace_normalized", r.str , #VEC(|1.0,0.0,0.0|).str);
      
      r := v0.copy;  r.inplace_scaled_by(3.0);
      r1 ::= v1.copy; r1.inplace_scaled_by(4.0);
      test("distance_to_squared", r.distance_to_squared(r1).str, 25.str);

      r := v0.copy;  r.inplace_scaled_by(3.0);
      r1 := v1.copy; r1.inplace_scaled_by(4.0);
      test("distance_to", r.distance_to(r1).str, 5.str);
      
      finish;
   end;
   
   testvecd is
      class_name("VECD");
      v0 ::=#VECD(|1.0d,0.0d,0.0d|);
      v1 ::=#VECD(|0.0d,1.0d,0.0d|);
      v2 ::=#VECD(|0.0d,0.0d,1.0d|);
      test("dim",v1.dim.str,"3");
      test("str",v0.str,"|1,0,0|");
      test("str",v1.str,"|0,1,0|");
      test("str",v2.str,"|0,0,1|");

      test("plus", (v0+v1).str,#VECD(|1.0d,1.0d,0.0d|).str);

      test("minus", (v0-v1).str, #VECD(|1.0d,-1.0d,0.0d|).str);

      test("dot", v0.dot(v1).str, 0.str);

      r ::= v0.copy;
      r.inplace_scaled_by(5.0d);
      test("inplace_scaled_by", r.str, #VECD(|5.0d,0.0d,0.0d|).str);

      r := v0.copy;
      r.inplace_contents(v1);
      test("inplace_contents", r.str, #VECD(|0.0d,1.0d,0.0d|).str);

      r := v0.copy;
      r.inplace_plus_arg(v1);
      test("inplace_plus_arg", r.str,#VECD(|1.0d,1.0d,0.0d|).str);
      
      r := v0.copy;
      r.inplace_plus_scaled_arg(5.0d,v1);
      test("inplace_plus_scaled_arg", r.str , #VECD(|1.0d,5.0d,0.0d|).str);

      r := v0.copy;
      r.inplace_arg_plus_arg(v1,v2);
      test("inplace_arg_plus_arg", r.str ,#VECD(|0.0d,1.0d,1.0d|).str);

      r := v0.copy;  r.inplace_arg_minus_arg(v1,v2);
      test("inplace_arg_minus_arg", r.str, #VECD(|0.0d,1.0d,-1.0d|).str);

      r := v0.copy;  r.inplace_elements(3.0d);      
      test("inplace_elements", r.str, #VECD(|3.0d,3.0d,3.0d|).str);

      r := v0.copy;  r.inplace_scaled_by(2.0d);      
      test("inplace_scaled_by/length", r.length.str, 2.str);

      r := v0.copy;  r.inplace_scaled_by(2.0d);      
      test("length_squared", r.length_squared.str, 4.str);
      
      r := v0.copy;  r.inplace_scaled_by(5.0d); r.inplace_normalized;
      test("inplace_normalized", r.str , #VECD(|1.0d,0.0d,0.0d|).str);
      
      r := v0.copy;  r.inplace_scaled_by(3.0d);
      r1 ::= v1.copy; r1.inplace_scaled_by(4.0d);
      test("distance_to_squared", r.distance_to_squared(r1).str, 25.str);

      r := v0.copy;  r.inplace_scaled_by(3.0d);
      r1 := v1.copy; r1.inplace_scaled_by(4.0d);
      test("distance_to", r.distance_to(r1).str, 5.str);
      
      finish;
   end;
   
   testmat is
      class_name("MAT");
      a ::= #MAT(3,4);
      test("create1 and nr",a.nr.str,"3");
      test("create1 and nc",a.nc.str,"4");
      test("create1 and size1",a.size1.str,"3");
      test("create1 and size2",a.size2.str,"4");
      ainit: ARRAY{ARRAY{FLT}} := ||0.0,1.0,2.0,3.0|
	    ,|10.0,11.0,12.0,13.0|,|20.0,21.0,22.0,23.0||;
      a2 ::= #MAT(ainit);

      test("create2 and nr",a2.nr.str,"3");
      test("create2 and nc",a2.nc.str,"4");
      test("create2 and size1",a2.size1.str,"3");
      test("create2 and size2",a2.size2.str,"4");
      test("aget",a2[0,2].str,"2");
      test("aget",a2[0,2].str,"2");
      test("aget",a2[1,3].str,"13");
      test("aget[2,3]",a2[2,3].str,"23");
      a2[0,2] := 3.0; test("aset",a2[0,2].str,"3");
      a2[0,2] := 2.0; test("aset",a2[0,2].str,"2");
      a2[1,1] := 99.0; test("aset",a2[1,1].str,"99");
      a2[1,1] := 11.0; test("aset",a2[1,1].str,"11");
      
      res::="";   loop res := res+" "+a.ind1! end;
      test("index 1",res," 0 1 2");
      res:="";  loop res := res+" "+a.ind2! end;
      test("index 2",res," 0 1 2 3");
      res:=""; 

      res:="";   loop res := res+" "+a.row_ind! end;
      test("row",res," 0 1 2");
      res:="";  loop res := res+" "+a.col_ind! end;
      test("col",res," 0 1 2 3");
      res:=""; 
      loop 
	 res := res+" "+a.inds!.t1+","+a.inds!.t2 end;
      test("inds",res," 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3");

      -- The 1th column of a2
      res:="";  loop res := res+" "+a2.col_elt!(1) end;
      test("col 1",res," 1 11 21");

      res:="";  loop res := res+" "+a2.elt2!(1) end;
      test("elt2 1",res," 1 11 21");
      
      -- The 2 column of a2
      res:="";  loop res := res+" "+a2.col_elt!(2) end;
      test("col_elt 2",res," 2 12 22");

      res:="";  loop res := res+" "+a2.elt2!(2) end;
      test("elt2 2",res," 2 12 22");
      
      -- The 1th row of a2
      res:="";  loop res := res+" "+a2.row_elt!(1) end;
      test("row 1",res," 10 11 12 13");

      res:="";  loop res := res+" "+a2.elt1!(1) end;
      test("elt1 1",res," 10 11 12 13");

      -- The 2 row of a2
      res:="";  loop res := res+" "+a2.row_elt!(2) end;
      test("row_elt 2",res," 20 21 22 23");

      res:="";  loop res := res+" "+a2.elt1!(2) end;
      test("elt1 2",res," 20 21 22 23");

      -- Set column 2 of b to col 1 of a2
      b::=a.copy;		
      loop b.inplace_col!(2,a2.col_elt!(1)) end;
      res:="";  loop res := res+" "+b.col_elt!(2) end;
      test("set col 2 1 ",res," 1 11 21");

      b:=a.copy;		
      loop b.set2!(2,a2.elt2!(1)) end;
      res:="";  loop res := res+" "+b.elt2!(2) end;
      test("set2 2 1 ",res," 1 11 21");
      
      -- Set column 3 of b to col 2 of a2
      b:=a.copy;		
      loop b.inplace_col!(3,a2.col_elt!(2)) end;
      res:="";  loop res := res+" "+b.col_elt!(3) end;
      test("set_col 3 2 ",res," 2 12 22");

      b:=a.copy;		
      loop b.set2!(3,a2.elt2!(2)) end;
      res:="";  loop res := res+" "+b.elt2!(3) end;
      test("set2 3 2 ",res," 2 12 22");

      -- Set row 0 of c  to row 1 of a2
      c::=a.copy;  loop c.inplace_row!(0,a2.row_elt!(1)) end;
      res:="";  loop res := res+" "+c.row_elt!(0) end;
      test("set_row 0 1",res," 10 11 12 13");

      c:=a.copy;  loop c.set1!(0,a2.elt1!(1)) end;
      res:="";  loop res := res+" "+c.elt1!(0) end;
      test("set1 0 1",res," 10 11 12 13");
      
      -- Set row 1 of c  to row 0 of a2
      c:=a.copy;  loop c.inplace_row!(1,a2.row_elt!(0)) end;
      res:="";  loop res := res+" "+c.row_elt!(1) end;
      test("set_row 1 0",res," 0 1 2 3");

      c:=a.copy;  loop c.set1!(1,a2.elt1!(0)) end;
      res:="";  loop res := res+" "+c.elt1!(1) end;
      test("set1 1 0",res," 0 1 2 3");
      
      -- more matrix tests from MBK
      
      m ::= #MAT(||1.1,4.2|,|3.7,5.6|,|5.9,6.3||);
      test("nr", m.nr.str, "3");
      test("nc", m.nc.str, "2");
      mstring ::= "||1.1,4.2|,|3.7,5.6|,|5.9,6.3||";
      mtransstring ::= "||1.1,3.7,5.9|,|4.2,5.6,6.3||";
      test("to_string", m.str,mstring);
      
      -- OK string machinery is OK. Next, check transposition.
      test("trans",m.trans.str,mtransstring);
      
      b := m.copy;
      test("copy",b.str,mstring);
      
      b.inplace_trans;
      test("inplace_trans",b.str,mtransstring);
      
      b.inplace_arg_trans(m);
      test("inplace_arg_trans",b.str,mtransstring);

-- transposition OK, a prereq to checking the rest.
      test("MAT::element_one",(MAT::element_one).str,(1.0).str);
      test("MAT::element_zero",(MAT::element_zero).str,(0.0).str);
      
      id ::= m.ident;
      test("ident",id.str,"||1,0|,|0,1|,|0,0||");
      id2 ::= m.ident;
      test("inplace_ident",id2.str,id.str);
      
      m_test::= #MAT(||2.0,0.0|,|0.0,2.0|,|0.0,0.0||);
      test("scaled_by",id.scaled_by(2.0).str,m_test.str);
      
      id2.inplace_scaled_by(2.0);
      test("inplace_scaled_by",id2.str,m_test.str);

      m.inplace_elements(7.0);
      m_test:= #MAT(||7.0,7.0|,|7.0,7.0|,|7.0,7.0||);
      test("inplace_elements",m.str,m_test.str);
      
      a := #MAT(||1.0,2.0|,|3.0,4.0|,|5.0,6.0||);
      adbl ::= a.scaled_by(2.0); -- already tested
      
      asum ::= a + a;
      test("plus",asum.str,adbl.str);

      adiff ::= a - a; 
      azero ::= a.scaled_by(0.0);
      test("minus",adiff.str,azero.str);
      
      test("plus_arg_trans",a.plus_arg_trans(a.trans).str,adbl.str);

      test("minus_arg_trans",a.minus_arg_trans(a.trans).str,azero.str);

      b := a.copy; b.inplace_plus_arg_trans(a.trans);
      test("inplace_plus_arg_trans",b.str,adbl.str);
      
      b := a.copy; b.inplace_minus_arg_trans(a.trans);
      test("inplace_minus_arg_trans",b.str,azero.str);
      
      b.inplace_arg_plus_arg(a,a);
      test("inplace_arg_plus_arg",b.str,adbl.str);
      
      b.inplace_arg_minus_arg(a,a);
      test("inplace_arg_minus_arg",b.str,azero.str);

      atrans ::= a.trans;

      b.inplace_arg_plus_arg_trans(a,atrans);
      test("inplace_arg_plus_arg_trans",b.str,adbl.str);
      
      b.inplace_arg_minus_arg_trans(a,atrans);
      test("inplace_arg_plus_arg_trans",b.str,azero.str);
      
      b.inplace_arg_trans_plus_arg_trans(atrans,atrans);
      test("inplace_arg_trans_plus_arg_trans",b.str,adbl.str);
      
      b.inplace_arg_trans_minus_arg_trans(atrans,atrans);
      test("inplace_arg_trans_minus_arg_trans",b.str,azero.str);
      
      afour ::= a + a + a + a;
      
      b := a.plus_scaled_arg(3.0,a);
      test("plus_scaled_arg",b.str,afour.str);
      
      b := a.copy; b.inplace_plus_scaled_arg(3.0,a);
      test("inplace_plus_scaled_arg",b.str,afour.str);
      
      b := a.plus_scaled_arg_trans(3.0,atrans);
      test("plus_scaled_arg_trans",b.str,afour.str);
      
      b := a.copy; b.inplace_plus_scaled_arg_trans(3.0,atrans);
      test("inplace_plus_scaled_arg_trans",b.str,afour.str);
      

      b.inplace_arg_plus_scaled_arg(a,3.0,a);
      test("inplace_arg_plus_scaled_arg",b.str,afour.str);

      b.inplace_arg_plus_scaled_arg_trans(a,3.0,atrans);
      test("inplace_arg_plus_scaled_arg_trans",b.str,afour.str);

-- multiplication
      
      aatstr ::= #MAT(||5.0,11.0,17.0|,|11.0,25.0,39.0|,
			 |17.0,39.0,61.0||).str;
      
      b := #MAT(3,3);

      b.inplace_arg_times_arg(a,atrans);
      test("inplace_arg_times_arg",b.str,aatstr);
      
      b.inplace_arg_trans_times_arg(atrans,atrans);
      test("inplace_arg_trans_times_arg",b.str,aatstr);
      
      b.inplace_arg_times_arg_trans(a,a);
      test("inplace_arg_times_arg_trans",b.str,aatstr);
      
      b.inplace_arg_trans_times_arg_trans(atrans,a);
      test("inplace_arg_trans_times_arg_trans",b.str,aatstr);
      
      b := a.times(a.trans);
      test("times", b.str, aatstr);

      b := atrans.trans_times_arg(a.trans);
      test("trans_times_arg",b.str, aatstr);
      
      b := a.times_arg_trans(a);
      test("times_arg_trans",b.str,aatstr);
      
      b := atrans.trans_times_arg_trans(a);
      test("trans_times_arg_trans",b.str,aatstr);
      
-- matrix/vector operations.

      v ::= #VEC(|1.0,2.0,3.0|);
      v2 ::= #VEC(|22.0,28.0|);

      r ::= atrans.times_vec(v);
      test("times",r.str, v2.str);
      
      atrans.times_vec_into_vec(v,r);
      test("times_vec_into_vec",r.str,v2.str);
      
      r := a.trans_times_vec(v);
      test("trans_times_vec",r.str,v2.str);

      a.trans_times_vec_into_vec(v,r);
      test("trans_times_vec_into_vec",r.str,v2.str);
      
      atrans.times_scaled_vec_into_vec(2.0,v,r);
      v3 ::= v2.scaled_by(2.0);
      test("times_scaled_vec_into_vec",r.str,v3.str);
      
      a.trans_times_scaled_vec_into_vec(2.0,v,r);
      test("trans_times_scaled_vec_into_vec",r.str,v3.str);
      
      c := #MAT(3,2);
      c.inplace_plus_scaled_vec_times_vec(2.0, #VEC(|1.0,1.0,2.0|),
				       #VEC(|3.0,4.0|));
      c2 ::= #MAT(||6.0,8.0|,|6.0,8.0|,|12.0,16.0||);
      test("inplace_plus_scaled_vec_times_vec",c.str,c2.str);

      
      
      
      
      finish;
      
   end;
   
   testmatd is
      class_name("MATD");
      a ::= #MATD(3,4);
      test("create1 and nr",a.nr.str,"3");
      test("create1 and nc",a.nc.str,"4");
      test("create1 and size1",a.size1.str,"3");
      test("create1 and size2",a.size2.str,"4");
      ainit: ARRAY{ARRAY{FLTD}} := ||0.0d,1.0d,2.0d,3.0d|
	    ,|10.0d,11.0d,12.0d,13.0d|,|20.0d,21.0d,22.0d,23.0d||;
      a2 ::= #MATD(ainit);

      test("create2 and nr",a2.nr.str,"3");
      test("create2 and nc",a2.nc.str,"4");
      test("create2 and size1",a2.size1.str,"3");
      test("create2 and size2",a2.size2.str,"4");
      test("aget",a2[0,2].str,"2");
      test("aget",a2[0,2].str,"2");
      test("aget",a2[1,3].str,"13");
      test("aget[2,3]",a2[2,3].str,"23");
      a2[0,2] := 3.0d; test("aset",a2[0,2].str,"3");
      a2[0,2] := 2.0d; test("aset",a2[0,2].str,"2");
      a2[1,1] := 99.0d; test("aset",a2[1,1].str,"99");
      a2[1,1] := 11.0d; test("aset",a2[1,1].str,"11");
      
      res::="";   loop res := res+" "+a.ind1! end;
      test("index 1",res," 0 1 2");
      res:="";  loop res := res+" "+a.ind2! end;
      test("index 2",res," 0 1 2 3");
      res:=""; 

      res:="";   loop res := res+" "+a.row_ind! end;
      test("row",res," 0 1 2");
      res:="";  loop res := res+" "+a.col_ind! end;
      test("col",res," 0 1 2 3");
      res:=""; 
      loop 
	 res := res+" "+a.inds!.t1+","+a.inds!.t2 end;
      test("inds",res," 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3");

      -- The 1th column of a2
      res:="";  loop res := res+" "+a2.col_elt!(1) end;
      test("col 1",res," 1 11 21");

      res:="";  loop res := res+" "+a2.elt2!(1) end;
      test("elt2 1",res," 1 11 21");
      
      -- The 2 column of a2
      res:="";  loop res := res+" "+a2.col_elt!(2) end;
      test("col_elt 2",res," 2 12 22");

      res:="";  loop res := res+" "+a2.elt2!(2) end;
      test("elt2 2",res," 2 12 22");
      
      -- The 1th row of a2
      res:="";  loop res := res+" "+a2.row_elt!(1) end;
      test("row 1",res," 10 11 12 13");

      res:="";  loop res := res+" "+a2.elt1!(1) end;
      test("elt1 1",res," 10 11 12 13");

      -- The 2 row of a2
      res:="";  loop res := res+" "+a2.row_elt!(2) end;
      test("row_elt 2",res," 20 21 22 23");

      res:="";  loop res := res+" "+a2.elt1!(2) end;
      test("elt1 2",res," 20 21 22 23");

      -- Set column 2 of b to col 1 of a2
      b::=a.copy;		
      loop b.inplace_col!(2,a2.col_elt!(1)) end;
      res:="";  loop res := res+" "+b.col_elt!(2) end;
      test("set col 2 1 ",res," 1 11 21");

      b:=a.copy;		
      loop b.set2!(2,a2.elt2!(1)) end;
      res:="";  loop res := res+" "+b.elt2!(2) end;
      test("set2 2 1 ",res," 1 11 21");
      
      -- Set column 3 of b to col 2 of a2
      b:=a.copy;		
      loop b.inplace_col!(3,a2.col_elt!(2)) end;
      res:="";  loop res := res+" "+b.col_elt!(3) end;
      test("set_col 3 2 ",res," 2 12 22");

      b:=a.copy;		
      loop b.set2!(3,a2.elt2!(2)) end;
      res:="";  loop res := res+" "+b.elt2!(3) end;
      test("set2 3 2 ",res," 2 12 22");

      -- Set row 0 of c  to row 1 of a2
      c::=a.copy;  loop c.inplace_row!(0,a2.row_elt!(1)) end;
      res:="";  loop res := res+" "+c.row_elt!(0) end;
      test("set_row 0 1",res," 10 11 12 13");

      c:=a.copy;  loop c.set1!(0,a2.elt1!(1)) end;
      res:="";  loop res := res+" "+c.elt1!(0) end;
      test("set1 0 1",res," 10 11 12 13");
      
      -- Set row 1 of c  to row 0 of a2
      c:=a.copy;  loop c.inplace_row!(1,a2.row_elt!(0)) end;
      res:="";  loop res := res+" "+c.row_elt!(1) end;
      test("set_row 1 0",res," 0 1 2 3");

      c:=a.copy;  loop c.set1!(1,a2.elt1!(0)) end;
      res:="";  loop res := res+" "+c.elt1!(1) end;
      test("set1 1 0",res," 0 1 2 3");
      
      -- more matrix tests from MBK
      
      m ::= #MATD(||1.1d,4.2d|,|3.7d,5.6d|,|5.9d,6.3d||);
      test("nr", m.nr.str, "3");
      test("nc", m.nc.str, "2");
      mstring ::= "||1.1,4.2|,|3.7,5.6|,|5.9,6.3||";
      mtransstring ::= "||1.1,3.7,5.9|,|4.2,5.6,6.3||";
      test("to_string", m.str,mstring);
      
      -- OK string machinery is OK. Next, check transposition.
      test("trans",m.trans.str,mtransstring);
      
      b := m.copy;
      test("copy",b.str,mstring);
      
      b.inplace_trans;
      test("inplace_trans",b.str,mtransstring);
      
      b.inplace_arg_trans(m);
      test("inplace_arg_trans",b.str,mtransstring);

-- transposition OK, a prereq to checking the rest.
      test("MATD::element_one",(MATD::element_one).str,(1.0).str);
      test("MATD::element_zero",(MATD::element_zero).str,(0.0).str);
      
      id ::= m.ident;
      test("ident",id.str,"||1,0|,|0,1|,|0,0||");
      id2 ::= m.ident;
      test("inplace_ident",id2.str,id.str);
      
      m_test::= #MATD(||2.0d,0.0d|,|0.0d,2.0d|,|0.0d,0.0d||);
      test("scaled_by",id.scaled_by(2.0d).str,m_test.str);
      
      id2.inplace_scaled_by(2.0d);
      test("inplace_scaled_by",id2.str,m_test.str);

      m.inplace_elements(7.0d);
      m_test:= #MATD(||7.0d,7.0d|,|7.0d,7.0d|,|7.0d,7.0d||);
      test("inplace_elements",m.str,m_test.str);
      
      a := #MATD(||1.0d,2.0d|,|3.0d,4.0d|,|5.0d,6.0d||);
      adbl ::= a.scaled_by(2.0d); -- already tested
      
      asum ::= a + a;
      test("plus",asum.str,adbl.str);

      adiff ::= a - a; 
      azero ::= a.scaled_by(0.0d);
      test("minus",adiff.str,azero.str);
      
      test("plus_arg_trans",a.plus_arg_trans(a.trans).str,adbl.str);

      test("minus_arg_trans",a.minus_arg_trans(a.trans).str,azero.str);

      b := a.copy; b.inplace_plus_arg_trans(a.trans);
      test("inplace_plus_arg_trans",b.str,adbl.str);
      
      b := a.copy; b.inplace_minus_arg_trans(a.trans);
      test("inplace_minus_arg_trans",b.str,azero.str);
      
      b.inplace_arg_plus_arg(a,a);
      test("inplace_arg_plus_arg",b.str,adbl.str);
      
      b.inplace_arg_minus_arg(a,a);
      test("inplace_arg_minus_arg",b.str,azero.str);

      atrans ::= a.trans;

      b.inplace_arg_plus_arg_trans(a,atrans);
      test("inplace_arg_plus_arg_trans",b.str,adbl.str);
      
      b.inplace_arg_minus_arg_trans(a,atrans);
      test("inplace_arg_plus_arg_trans",b.str,azero.str);
      
      b.inplace_arg_trans_plus_arg_trans(atrans,atrans);
      test("inplace_arg_trans_plus_arg_trans",b.str,adbl.str);
      
      b.inplace_arg_trans_minus_arg_trans(atrans,atrans);
      test("inplace_arg_trans_minus_arg_trans",b.str,azero.str);
      
      afour ::= a + a + a + a;
      
      b := a.plus_scaled_arg(3.0d,a);
      test("plus_scaled_arg",b.str,afour.str);
      
      b := a.copy; b.inplace_plus_scaled_arg(3.0d,a);
      test("inplace_plus_scaled_arg",b.str,afour.str);
      
      b := a.plus_scaled_arg_trans(3.0d,atrans);
      test("plus_scaled_arg_trans",b.str,afour.str);
      
      b := a.copy; b.inplace_plus_scaled_arg_trans(3.0d,atrans);
      test("inplace_plus_scaled_arg_trans",b.str,afour.str);
      

      b.inplace_arg_plus_scaled_arg(a,3.0d,a);
      test("inplace_arg_plus_scaled_arg",b.str,afour.str);

      b.inplace_arg_plus_scaled_arg_trans(a,3.0d,atrans);
      test("inplace_arg_plus_scaled_arg_trans",b.str,afour.str);

-- multiplication
      
      aatstr ::= #MATD(||5.0d,11.0d,17.0d|,|11.0d,25.0d,39.0d|,
			 |17.0d,39.0d,61.0d||).str;
      
      b := #MATD(3,3);

      b.inplace_arg_times_arg(a,atrans);
      test("inplace_arg_times_arg",b.str,aatstr);
      
      b.inplace_arg_trans_times_arg(atrans,atrans);
      test("inplace_arg_trans_times_arg",b.str,aatstr);
      
      b.inplace_arg_times_arg_trans(a,a);
      test("inplace_arg_times_arg_trans",b.str,aatstr);
      
      b.inplace_arg_trans_times_arg_trans(atrans,a);
      test("inplace_arg_trans_times_arg_trans",b.str,aatstr);
      
      b := a.times(a.trans);
      test("times", b.str, aatstr);

      b := atrans.trans_times_arg(a.trans);
      test("trans_times_arg",b.str, aatstr);
      
      b := a.times_arg_trans(a);
      test("times_arg_trans",b.str,aatstr);
      
      b := atrans.trans_times_arg_trans(a);
      test("trans_times_arg_trans",b.str,aatstr);
      
-- matrix/vector operations.
      
      v ::= #VECD(|1.0d,2.0d,3.0d|);
      v2 ::= #VECD(|22.0d,28.0d|);

      r ::= atrans.times_vec(v);
      test("times",r.str, v2.str);
      
      atrans.times_vec_into_vec(v,r);
      test("times_vec_into_vec",r.str,v2.str);
      
      r := a.trans_times_vec(v);
      test("trans_times_vec",r.str,v2.str);

      a.trans_times_vec_into_vec(v,r);
      test("trans_times_vec_into_vec",r.str,v2.str);
      
      atrans.times_scaled_vec_into_vec(2.0d,v,r);
      v3 ::= v2.scaled_by(2.0d);
      test("times_scaled_vec_into_vec",r.str,v3.str);
      
      a.trans_times_scaled_vec_into_vec(2.0d,v,r);
      test("trans_times_scaled_vec_into_vec",r.str,v3.str);
      
      c := #MATD(3,2);
      c.inplace_plus_scaled_vec_times_vec(2.0d, #VECD(|1.0d,1.0d,2.0d|),
				       #VECD(|3.0d,4.0d|));
      c2 ::= #MATD(||6.0d,8.0d|,|6.0d,8.0d|,|12.0d,16.0d||);
      test("inplace_plus_scaled_vec_times_vec",c.str,c2.str);

      
      finish;
      
   end;
   
end;
   

