home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
sa104os2.zip
/
SATHR104.ZIP
/
SATHER
/
LIBRARY
/
VEC.SA
< prev
Wrap
Text File
|
1995-02-16
|
14KB
|
379 lines
-- Copyright (C) International Computer Science Institute, 1994. COPYRIGHT --
-- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
-- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in --
-- the file "Doc/License" of the Sather distribution. The license is also --
-- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA. --
--------> Please email comments to "sather-bugs@icsi.berkeley.edu". <----------
-- vec.sa: Vectors.
-------------------------------------------------------------------
class VEC is
-- A vector of FLT's.
include ARRAY{FLT};
dim:INT is
-- The dimension of the space containing self.
return(asize) end;
create(sz:INT):SAME is
-- A new vector of dimension sz initialized to zero.
return(new(sz)) end;
create(arr: ARRAY{FLT}): SAME is
res ::= new(arr.size);
loop res.set!(arr.elt!) end;
return(res); end;
str: STR is
-- Return a string representing the vector
-- Eg. |0,1|
res ::= #STR+"|";
loop res := res + elt!(0,dim-1) + ","; end;
res := res + [dim-1] + "|";
return(res); end;
to_array: ARRAY{FLT} is
-- Return the vector as a 1d array of floats
res ::= #ARRAY{FLT}(dim);
-- loop res.set!(elt!) end; end; -- NLP !
loop res.set!(elt!) end; return res; end; -- NLP !
to_uniform_random is
-- Make self's entires uniform in [0,1) and return it
loop set!((RND::uniform).flt) end; end;
plus(v1:SAME):SAME is
-- A new vector equal to self plus v1.
res::=#SAME(dim); res.to_sum_of(self,v1); return(res) end;
minus(v1:SAME):SAME is
-- A new vector which is self minus v1.
res::=#SAME(dim); res.to_difference_of(self,v1); return(res) end;
dot(v1:SAME):FLT
-- The dot product of self and v1.
pre v1.dim = dim is
res ::= 0.0; loop res:=res+(elt!*v1.elt!); end; return(res); end;
scale_by(s:FLT) is
-- Scale self by s.
loop set!(s*elt!) end; end;
to(v1:SAME)
-- Set self equal to v1.
pre v1.dim = dim is loop set!(v1.elt!) end; end;
add(v1:SAME)
-- Add v1 into self.
pre v1.dim = dim is loop set!(elt!+v1.elt!) end; end;
add_scaled(s: FLT, v1:SAME)
-- Add `s' times v1 to self.
pre v1.dim = dim is loop set!(elt!+s*v1.elt!) end; end;
scale_and_add_scaled(self_scale,v1_scale: FLT, v1: SAME)
-- Set self to self_scale*self + v1_scale*v1
pre v1.dim=dim is loop set!(self_scale*elt!+v1_scale*v1.elt!) end end;
to_sum_of(v1,v2:SAME)
-- Set self to the sum of `v1' and `v2'.
pre dim.is_eq(v1.dim,v2.dim) is
loop set!(v1.elt!+v2.elt!) end; end;
to_difference_of(v1,v2:SAME)
-- Set self to the difference of `v1' and `v2'.
pre dim.is_eq(v1.dim,v2.dim) is
loop set!(v1.elt!-v2.elt!) end; end;
to_difference_with(v1:SAME)
-- Subtract v1 from self.
pre v1.dim=dim is loop set!(elt!-v1.elt!) end; end;
eltwise_product(v1: SAME): SAME
-- Return a new vector containing the element-wise product of
-- self with v1
pre v1.dim = dim is
v ::= #SAME(dim); v.to_eltwise_product_of(self,v1); return(v) end;
to_eltwise_product_with(v1: SAME)
-- Set self to the elementwise product of self with v1
pre dim = v1.dim is
loop set!(elt!*v1.elt!) end end;
to_eltwise_product_of(v1,v2: SAME)
-- Set self to the elementwise product of v1 and v2
pre dim=v1.dim and dim=v2.dim is
loop set!(v1.elt!*v2.elt!) end; end;
add_eltwise_product_of(v1,v2: SAME)
-- Add the elementwise product of v1 and v2 to self
pre dim=v1.dim and dim=v2.dim is
loop set!(elt! + (v1.elt!*v2.elt!)) end; end;
scale_and_add_scaled_eltwise_product_of(self_sc,prod_sc: FLT,v1,v2:SAME)
-- Set self to the sum of self scaled by a "self_sc"
-- and the element wise product of v1 and v2 scaled by "prod_sc"
-- self <- self_scale*self + product_scale*(v1*v2)
pre dim=v1.dim and dim=v2.dim is
loop set!(self_sc*elt! + prod_sc*(v1.elt!*v2.elt!)) end; end;
to(s:FLT) is
-- Set each component of self to s.
loop set!(s) end; end;
to_zero is
-- Set self to the zero vector.
loop set!(0.0) end; end;
to_ones is
-- Set each component of self to 1.0.
loop [asize.times!]:=1.0 end; end;
-- loop aset!(1.0) end; return(self); end;
square_length:FLT is
-- The square of the Euclidean length of self.
res ::= 0.0; loop res:=res+elt!.square end; return(res); end;
length:FLT is
-- The Euclidean length of self.
return(square_length.sqrt) end;
normalize is
-- Scale self to be unit length. Don't change it if it vanishes.
l::=length; if l/=0.0 then scale_by(1.0/l) end; end;
is_normalized(epsilon: FLT):BOOL is
-- True if self is approximately normalized.
#ERR+"Unimplemented Function is_normalized"; return(false) end;
square_dist_to(v1:SAME):FLT
-- The square of the Euclidean distance from self to v1.
pre v1.dim=dim is
res::=0.0; loop res:=res+(elt!-v1.elt!).square end; return(res) end;
dist_to(v1:SAME):FLT
-- The Euclidean distance from self to v1.
pre v1.dim=dim is return(square_dist_to(v1).sqrt) end;
bounded_square_dist_to(v1:SAME, sbnd:FLT):FLT
-- The square of the Euclidean distance from self to arg if it is
-- less than or equal to `sbnd', `-1.0' if it is greater than it.
-- Can avoid some operations if used in a bounding test.
pre v1.dim = dim is
res ::=0.0;
loop res:=res+(elt!-v1.elt!).square;
if res>=sbnd then res:=-1.0; break! end; end;
return(res); end;
to_midpoint_with(v1:SAME)
-- Set self to the midpoint of self and v1.
pre v1.dim=dim is
loop set!((elt!+v1.elt!)/2.0) end; end;
move_away_from(v1:SAME, d:FLT)
-- Move self a distance `d' in the direction away from v1.
-- Don't change it if it is equal to v1.
pre v1.dim = dim is
s::=dist_to(v1);
if s/=0.0 then
s:=d/s; ops::=s+1.0; loop set!(ops*elt!-s*v1.elt!) end;
end;
end;
move_toward(v1:SAME, d:FLT)
-- Move self a distance `d' in the direction toward v1.
-- Don't change it if it is equal to v1.
pre v1.dim=dim is
s::=dist_to(v1); if s/=0.0 then
s:=d/s; oms::=1.0-s; loop set!(oms*elt!+s*v1.elt!) end;
end;
end;
to_interpolate_between(v0,v1:SAME, t:FLT)
-- When `t=0.0' set `self=v0', when `t=1.0' set `self=v1' and
-- interpolate for intermediate values.
pre v0.dim=dim and v1.dim=dim is
ot::=1.0-t; loop set!(ot*v0.elt!+t*v1.elt!) end; end;
max_index:INT is
-- The index of the maximum component of self. Lowest index
-- in case of equality.
mval::=[0]; res::=0;
loop i::=ind!; e::=elt!; if e>mval then mval:=e; res:=i; end; end;
return(res); end;
max_value:FLT is return([max_index]) end;
-- The largest component of self.
min_index:INT is
-- The index of the minimum component of self. Lowest index in case
-- of equality.
mval::=[0]; res ::= 0;
loop i::=ind!; e::=elt!; if e<mval then mval:=e; res:=i; end; end;
return(res); end;
min_value:FLT is return([min_index]) end;
-- The smallest component of self.
make_orthogonal_to_unit(v1:SAME)
-- Subtract off the projection of self onto the unit vector v1.
pre v1.dim=dim and v1.is_normalized(0.0001) is
add_scaled(-dot(v1),v1); end;
is_approx(v1:SAME):BOOL
pre v1.dim=dim is #ERR+"Not Implemented"; return(false) end;
-- True if the components of self are approximately equal to those of v1.
--!! loop if not elt!.is_approx(v1.elt!) then return end end; res:=true end;
reflect_through_zero is
-- Reflect self through the origin.
loop set!(-elt!) end end;
outer_product(v2: SAME): MAT is
-- Return a matrix which is the outer product of self*v1
res ::= #MAT(dim,v2.dim);
res.to_outer_product_of(self,v2);
return(res); end;
times(m: MAT): SAME is
-- Return a vector that is the result of self*matrix
res ::= #SAME(m.nc);
m.transpose_times_in(self,res);
return(res);
end;
times_in(m: MAT, v: SAME) is
-- Set v to the result of self*matrix
m.transpose_times_in(self,v);
-- #OUT+str+"*"+m.str+"="+v.str+"\n";
end;
times_add_into(m: MAT, v: SAME) is
-- Set v to self*m + v
m.transpose_times_add_into(self,v);
end;
end; -- class VEC
-------------------------------------------------------------------
class TEST_VEC is
include TEST;
main is
-- Test of `VEC'.
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|");
-- Having tested str, make use of it in the following
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.scale_by(5.0);
test("scale_by", r.str, #VEC(|5.0,0.0,0.0|).str);
r := v0.copy;
r.to(v1);
test("to", r.str, #VEC(|0.0,1.0,0.0|).str);
r := v0.copy;
r.add(v1);
test("add", r.str,#VEC(|1.0,1.0,0.0|).str);
r := v0.copy;
r.add_scaled(5.0,v1);
test("add_scaled", r.str , #VEC(|1.0,5.0,0.0|).str);
r := v0.copy;
r.to_sum_of(v1,v2);
test("to_sum_of", r.str ,#VEC(|0.0,1.0,1.0|).str);
r := v0.copy; r.to_difference_of(v1,v2);
test("to_difference_of", r.str, #VEC(|0.0,1.0,-1.0|).str);
r := v0.copy; r.to_difference_with(v1);
test("to_difference_with", r.str,#VEC(|1.0,-1.0,0.0|).str);
r := v0.copy; r.to(3.0);
test("to", r.str, #VEC(|3.0,3.0,3.0|).str);
r := v0.copy; r.to_ones;
test("to_ones", r.str, #VEC(|1.0,1.0,1.0|).str);
r := v0.copy; r.to_zero;
test("to_zero", r.str, #VEC(|0.0,0.0,0.0|).str);
r := v0.copy; r.scale_by(2.0);
test("scale_by", r.length.str, 2.str);
r := v0.copy; r.scale_by(2.0);
test("square_length", r.square_length.str, 4.str);
r := v0.copy; r.scale_by(5.0); r.normalize;
test("normalize", r.str , #VEC(|1.0,0.0,0.0|).str);
-- test("is_normalized 1", v0.copy.scale_by(5.0).is_normalized.str, false.str);
-- test("is_normalized 2", v0.is_normalized.str, true.str);
r := v0.copy; r.scale_by(3.0);
r1 ::= v1.copy; r1.scale_by(4.0);
test("square_dist_to", r.square_dist_to(r1).str, 25.str);
r := v0.copy; r.scale_by(3.0);
r1 := v1.copy; r1.scale_by(4.0);
test("dist_to", r.dist_to(r1).str, 5.str);
-- test("bounded_square_dist_to 1",
-- v0.copy.scale_by(3.0)
-- .bounded_square_dist_to(v1.copy.scale_by(4.0),30.0).str
-- , "25");
-- test("bounded_square_dist_to 2",
-- v0.copy.scale_by(3.0)
-- .bounded_square_dist_to(v1.copy.scale_by(4.0),3.0).str
-- , "-1");
r1 := v1.copy; r1.to_midpoint_with(v2);
test("to_midpoint_with", r1.str,#VEC(|0.0,0.5,0.5|).str);
r1 := v1.copy; r1.to_zero; r1.move_away_from(v2,1.0);
test("move_away_from", r1.str,#VEC(|0.0,0.0,-1.0|).str);
r1 := v1.copy; r1.to_zero; r1.move_toward(v2,0.5);
test("move_toward", r1.str,#VEC(|0.0,0.0,0.5|).str);
r2 ::= v2.copy; r2.to_interpolate_between(v0,v1,0.5);
test("to_interpolate_between", r2.str, #VEC(|0.5,0.5,0.0|).str);
test("max_index", v0.max_index.str, 0.str);
test("max_value", v0.max_value.str, 1.str);
test("min_index", (v0+v1).min_index.str, 2.str);
test("min_value", (v0+v1).min_value.str, 0.str);
test("eltwise_product",v0.eltwise_product(v1).str,#VEC(|0.0,0.0,0.0|).str);
test("eltwise_product2",
#VEC(|1.0,2.0,3.0|).eltwise_product(#VEC(|2.0,5.0,7.0|)).str,
#VEC(|2.0,10.0,21.0|).str);
-- test("make_orthogonal_to_unit",
-- v0.plus(v1).make_orthogonal_to_unit(v1).str, "|1.0,0.0,0.0|");
-- unchecked_test("to_uniform_random", v1.copy.to_uniform_random.str, "");
-- unchecked_test("to_cube_random", v1.copy.to_cube_random.str, "");
-- unchecked_test("to_normal_random",
-- v1.copy.to_normal_random(1.0).str, "");
-- unchecked_test("to_standard_normal_random",
-- v1.copy.to_standard_normal_random.str, "");
-- unchecked_test("to_cantor_random",
-- v1.copy.to_cantor_random(.333).str, "");
-- unchecked_test("to_curve_random", v1.copy.to_curve_random.str, "");
-- unchecked_test("to_unit_random", v1.copy.to_unit_random.str, "");
-- unchecked_test("to_ball_random", v1.copy.to_ball_random.str, "");
-- test("is_epsilon_equal 1", v1.is_epsilon_equal(v1).str, "T");
-- test("is_epsilon_equal 2", v1.is_epsilon_equal(v2).str, "F");
finish;
end; -- vector_test
end;