------------------------->  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 <mbk@caffeine.engr.utk.edu>
-- integrated by gomes@icsi.berkeley.edu

abstract class $VEC{ET < $NFE{ET}, VT < $VEC{ET,VT}} is
   -- 
   -- The specification of the general vector class.
   -- 
   -- c.f. $MAT{*,*,*}
   --
   -- This is mostly straightforward except for a small trickiness:
   -- complex vectors still need to have lengths which return
   -- real numbers, and not CPX.  
   -- (ben) However, the length in a complex vector has to be
   -- the same as the type of the components of the complex, since
   -- this fact is used in some of the functions.
   -- 
   -- the vector type should not need to know about its companion,
   -- matrix type, though the matrix type does know about the vector
   -- type.  Hence, all matrix-vector operations are in the matrix class
   -- and not the vector class.
   -- 
   
   dim:INT;
   -- The number of dimensions.
   
   same_size(arg:VT):BOOL; 
   --
   -- true if arg has the same size as self.  Is false if either 'self'
   -- or 'arg' is void or even both. Intent is to be useful in preconditions. 
   --
   
   is_eq(arg:VT):BOOL;
   --
   -- Return true if 'arg = self'

   --
   
   create(sz:INT):VT;
   --
   -- result := "new vector size 'sz' "
   --
   
   create(arg:VT):VT;
   -- 
   -- result := "new vector same size as arg"
   -- 
   
   str:STR;
   -- 
   -- result := "a string representation of self"
   -- 
	 
   array: ARRAY{ET};
   -- 
   -- result := An array of same dimensionality with projections
   -- of this vector upon each axis. 
   -- 

   copy:VT;
   -- 
   -- result := copy of self.  Creates new return value.
   -- 
   -- Example:  v2 ::= v.copy;
   
   inplace_contents(arg:VT);
   -- 
   -- "array portion of self" := "array portion of arg"
   -- 
   -- Example:  v2.inplace_contents(v);

   inplace_contents_subspace(destbeg,n,srcbeg:INT,arg:VT);
   -- 
   -- Assign the components of 'arg' from [srcbeg,srcbeg+n-1]
   -- to 'self' from [destbeg,destbeg+n-1].  For vectors of elementary
   -- value objects, this means "copy elements".
   -- 

   inplace_contents_from_function(function:ROUT{INT}:ET); 
   --
   -- "array portion of self"(i) = function(i) all i
   -- 
   
   inplace_elements(arg:ET);
   --
   -- make self be 'arg' in all directions.
   -- 

   inplace_unit_vector(i:INT);
   --
   -- make "self" the unit vector in the 'ith' direction. i in [0,dim-1].
   --
   
   times(s:ET):VT;
   -- 
   -- result (created) := self * s;
   -- 
   -- Example:  v2 ::= v * 0.40d0;
   -- Sugar for "vec * scalar", synonym for 'scaled_by'.
   
   scaled_by(s:ET):VT;
   -- 
   -- result (created) := self * s;
   -- 
   -- Example:  m2 ::= m * 0.40d0;
   -- 

   inplace_scaled_by(s:ET);
   -- 
   -- self := self * s;
   -- 
   -- Example:  v.inplace_scaled_by(4.0d0);
   
   aget(i:INT):ET;
   -- 
   -- Get the projection of the vector in the i'th direction.
   -- 
   
   aset(i:INT,s:ET);
   -- 
   -- Set the projection of the vector in the i'th direction.
   -- 
   
   plus(arg:VT):VT;
   -- 
   -- result (created) := self + arg.
   -- 
   -- Example:  a,b,c:VEC;  c := a + b;
   -- Sugar for "a + b", synonym for "plus_arg".
   
   plus_arg(arg:VT):VT;
   -- 
   -- result (created) := self + arg.
   -- 
   -- Example:  a,b,c:VEC;  c := a + b;
   
   minus(arg:VT):VT;
   -- 
   -- result (created) := self + arg.
   -- 
   -- Example:  a,b,c:VEC;  c := a - b;
   -- Sugar for "a - b", synonym for "minus_arg".

   minus_arg(arg:VT):VT;
   -- 
   -- result (created) := self - arg.
   -- 
   -- Example:  a,b,c:VEC;  c := a - b;

   inplace_plus_arg(arg:VT);
   -- 
   -- self := self + arg.  
   -- 
   -- Example:  a,b:VEC; a.inplace_plus_arg(b); 

   inplace_minus_arg(arg:VT);
   -- 
   -- self := self - arg.  
   -- 
   -- Example:  a,b:VEC; a.inplace_minus_arg(b); 
   
   inplace_arg_plus_arg(arg1,arg2:VT);
   -- 
   -- self := arg1 + arg2
   -- 
   -- Example:  a,b,c:VEC; c.inplace_arg_plus_arg(a,b); 

   inplace_arg_minus_arg(arg1,arg2:VT);
   -- 
   -- self := arg1 - arg2
   -- 
   -- Example:  a,b,c:VEC; c.inplace_arg_minus_arg(a,b); 
   
   plus_scaled_arg(s:ET,arg:VT):VT;
   -- 
   -- result := self + s*arg;
   -- 
   -- Example:  a,b,c:VEC;  c := a.plus_scaled_arg(3.0d0,b);

   inplace_plus_scaled_arg(s:ET,arg:VT);
   -- 
   -- self := self + s*arg;
   -- 
   -- Example:  a,b:VEC;  a.inplace_plus_scaled_arg(3.0d0,b);

   inplace_arg_plus_scaled_arg(arg1:VT,s:ET,arg2:VT);
   -- 
   -- self := arg1 + s*arg2;
   -- 
   -- Example:  a,b,c:VEC; c.inplace_arg_plus_scaled_arg(a,3.1415d0,b); 
   
   inplace_swapped(arg:VT);
   -- 
   -- Swap contents of self with same sized "arg".
   -- 
   -- Example:  v2.swap(v1);

-- Note what isn't quite in here:
--   length, square_length, dot: 
-- because they require an auxiliary type in addition.
end;
----------------------------------------------------------------------
abstract class $VEC{ET < $NFE{ET}, VT<$VEC{ET,VT},LTP<$REAL_NUMBER{LTP}} <$VEC{ET,VT} is 
   -- The full fledged version of the vector abstraction which is parametrized
   -- over the type of the vector length in order to deal correctly with
   -- the length, magnitudes etc. 
   
   dot(arg:VT):ET; 
   --
   -- Return the dot product of self and arg
   --

   angle_with(arg:VT):LTP;
   --
   -- Return the angle between self and arg in radians.
   -- 
   
   cosine_angle_with(arg:VT):LTP;
   --
   -- Return the cosine of angle between self and arg in radians.
   -- Faster than 'angle_with', usually.
   -- 
   -- This is one reason why LTP needs to be a field element,
   -- one must divide:  cos(theta) = self.dot(arg) / self.length * arg.length;
   
   
   length_squared:LTP;
   --  
   -- Return the squared length of self.  Conventionally the Euclidean
   -- metric. Often faster than 'length'. 
   -- 
   
   length:LTP;
   --  
   -- Return the length of self.  Conventionally the Euclidean
   -- metric.
   -- 
   
   distance_to_squared(arg:VT):LTP;
   --
   -- return the distance between self and arg squared. 
   -- 
   
   distance_to(arg:VT):LTP;
   --
   -- return the distance between self and arg.
   -- 
   
   bounded_distance_to_squared(arg:VT,sbnd:LTP):LTP;
   -- 
   -- Return the distance between arg and self as long as it's less
   -- than or equal to 'sbnd'.  May be faster than 'distance_to_squared'.
   -- Return "-1.0" if the distance is greater than sbnd. 
   
   inplace_normalized;
   --
   -- Make self have unit length.
   -- 
   
end; -- abstract class $VEC{ET,VT,LTP}

-------------------------------------------------------------------








