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   
Text File  |  1995-02-16  |  14KB  |  379 lines

  1. -- Copyright (C) International Computer Science Institute, 1994.  COPYRIGHT  --
  2. -- NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject --
  3. -- to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in    --
  4. -- the file "Doc/License" of the Sather distribution.  The license is also   --
  5. -- available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA.  --
  6. --------> Please email comments to "sather-bugs@icsi.berkeley.edu". <----------
  7.  
  8. -- vec.sa: Vectors.
  9. -------------------------------------------------------------------
  10. class VEC is
  11.    -- A vector of FLT's.
  12.    include ARRAY{FLT};
  13.    
  14.    dim:INT is 
  15.       -- The dimension of the space containing self.
  16.       return(asize) end;
  17.    
  18.    create(sz:INT):SAME is 
  19.       -- A new vector of dimension sz initialized to zero.
  20.       return(new(sz)) end;
  21.    
  22.    create(arr: ARRAY{FLT}): SAME is
  23.       res ::= new(arr.size);  
  24.       loop res.set!(arr.elt!) end; 
  25.       return(res); end;
  26.       
  27.    str: STR is
  28.       -- Return a string representing the vector
  29.       -- Eg. |0,1|
  30.       res ::= #STR+"|";
  31.       loop res := res + elt!(0,dim-1) + ","; end;
  32.       res := res + [dim-1] + "|"; 
  33.       return(res);  end;
  34.       
  35.    to_array: ARRAY{FLT} is
  36.       -- Return the vector as a 1d array of floats
  37.       res ::= #ARRAY{FLT}(dim);
  38. --    loop res.set!(elt!) end; end;                                             -- NLP !
  39.       loop res.set!(elt!) end; return res; end;                                 -- NLP !
  40.    
  41.    to_uniform_random is
  42.       -- Make self's entires uniform in [0,1) and return it
  43.       loop set!((RND::uniform).flt) end; end;
  44.       
  45.    plus(v1:SAME):SAME is 
  46.       -- A new vector equal to self plus v1.
  47.       res::=#SAME(dim); res.to_sum_of(self,v1); return(res) end;
  48.    
  49.    minus(v1:SAME):SAME is 
  50.       -- A new vector which is self minus v1.
  51.       res::=#SAME(dim); res.to_difference_of(self,v1); return(res) end;
  52.       
  53.    dot(v1:SAME):FLT 
  54.       -- The dot product of self and v1.
  55.       pre v1.dim = dim is   
  56.       res ::= 0.0; loop res:=res+(elt!*v1.elt!); end; return(res);  end;
  57.    
  58.  
  59.    scale_by(s:FLT) is
  60.       -- Scale self by s.
  61.       loop set!(s*elt!) end;  end;
  62.    
  63.    to(v1:SAME) 
  64.       -- Set self equal to v1.
  65.       pre v1.dim = dim is loop set!(v1.elt!) end; end;
  66.    
  67.    add(v1:SAME)
  68.       -- Add v1 into self.
  69.       pre v1.dim = dim is loop set!(elt!+v1.elt!) end;  end;
  70.    
  71.    add_scaled(s: FLT, v1:SAME)
  72.       -- Add `s' times v1 to self.
  73.       pre v1.dim = dim is loop set!(elt!+s*v1.elt!) end; end;
  74.  
  75.    scale_and_add_scaled(self_scale,v1_scale: FLT, v1: SAME)
  76.       -- Set self to  self_scale*self + v1_scale*v1
  77.       pre v1.dim=dim is loop set!(self_scale*elt!+v1_scale*v1.elt!) end end;
  78.    
  79.    to_sum_of(v1,v2:SAME)
  80.       -- Set self to the sum of `v1' and `v2'.
  81.       pre dim.is_eq(v1.dim,v2.dim) is
  82.       loop set!(v1.elt!+v2.elt!) end;  end;
  83.  
  84.    to_difference_of(v1,v2:SAME)
  85.       -- Set self to the difference of `v1' and `v2'.
  86.       pre dim.is_eq(v1.dim,v2.dim) is
  87.       loop set!(v1.elt!-v2.elt!) end; end;      
  88.  
  89.    to_difference_with(v1:SAME)
  90.       -- Subtract v1 from self.
  91.       pre v1.dim=dim is loop set!(elt!-v1.elt!) end; end;      
  92.  
  93.    eltwise_product(v1: SAME): SAME 
  94.       -- Return a new vector containing the element-wise product of 
  95.       -- self with v1
  96.       pre v1.dim = dim is  
  97.       v ::= #SAME(dim); v.to_eltwise_product_of(self,v1); return(v) end;
  98.    
  99.    to_eltwise_product_with(v1: SAME) 
  100.       -- Set self to the elementwise product of self with v1
  101.       pre dim = v1.dim is 
  102.       loop set!(elt!*v1.elt!) end end;
  103.       
  104.    to_eltwise_product_of(v1,v2: SAME) 
  105.       -- Set self to the elementwise product of v1 and v2
  106.       pre dim=v1.dim and dim=v2.dim is
  107.       loop set!(v1.elt!*v2.elt!) end; end;
  108.       
  109.    add_eltwise_product_of(v1,v2: SAME) 
  110.       -- Add the elementwise product of v1 and v2 to self
  111.       pre dim=v1.dim and dim=v2.dim is
  112.       loop set!(elt! + (v1.elt!*v2.elt!)) end; end;
  113.    
  114.    scale_and_add_scaled_eltwise_product_of(self_sc,prod_sc: FLT,v1,v2:SAME) 
  115.       -- Set self to the sum of self scaled by a "self_sc" 
  116.       -- and the element wise product of v1 and v2 scaled by "prod_sc"
  117.       -- self <- self_scale*self + product_scale*(v1*v2)
  118.       pre dim=v1.dim and dim=v2.dim is
  119.       loop set!(self_sc*elt! + prod_sc*(v1.elt!*v2.elt!)) end; end;
  120.    
  121.    to(s:FLT) is 
  122.       -- Set each component of self to s.
  123.       loop set!(s) end; end;
  124.    
  125.    to_zero is 
  126.       -- Set self to the zero vector.
  127.       loop set!(0.0) end; end;      
  128.    
  129.    to_ones is 
  130.       -- Set each component of self to 1.0.
  131.       loop [asize.times!]:=1.0 end; end;
  132. --      loop aset!(1.0) end; return(self); end;            
  133.  
  134.    square_length:FLT is
  135.       -- The square of the Euclidean length of self.
  136.       res ::= 0.0;  loop res:=res+elt!.square end; return(res); end;
  137.    
  138.    length:FLT is
  139.       -- The Euclidean length of self.
  140.       return(square_length.sqrt) end;
  141.  
  142.    normalize is
  143.       -- Scale self to be unit length. Don't change it if it vanishes.
  144.       l::=length; if l/=0.0 then scale_by(1.0/l) end; end;
  145.  
  146.     is_normalized(epsilon: FLT):BOOL is 
  147.       -- True if self is approximately normalized.
  148.       #ERR+"Unimplemented Function is_normalized"; return(false) end;
  149.    
  150.    square_dist_to(v1:SAME):FLT 
  151.       -- The square of the Euclidean distance from self to v1.
  152.       pre v1.dim=dim is 
  153.       res::=0.0; loop res:=res+(elt!-v1.elt!).square end; return(res) end;
  154.    
  155.    dist_to(v1:SAME):FLT 
  156.       -- The Euclidean distance from self to v1.
  157.       pre v1.dim=dim is return(square_dist_to(v1).sqrt) end;
  158.    
  159.    bounded_square_dist_to(v1:SAME, sbnd:FLT):FLT 
  160.       -- The square of the Euclidean distance from self to arg if it is
  161.       -- less than or equal to `sbnd', `-1.0' if it is greater than it.
  162.       -- Can avoid some operations if used in a bounding test.
  163.       pre v1.dim = dim is
  164.       res ::=0.0;
  165.       loop res:=res+(elt!-v1.elt!).square;
  166.      if res>=sbnd then res:=-1.0; break! end; end;
  167.       return(res);   end;
  168.       
  169.    to_midpoint_with(v1:SAME)
  170.       -- Set self to the midpoint of self and v1.
  171.       pre v1.dim=dim is
  172.       loop set!((elt!+v1.elt!)/2.0) end; end;
  173.  
  174.    move_away_from(v1:SAME, d:FLT)
  175.       -- Move self a distance `d' in the direction away from v1.
  176.       -- Don't change it if it is equal to v1.
  177.       pre v1.dim = dim is 
  178.       s::=dist_to(v1); 
  179.       if s/=0.0 then 
  180.      s:=d/s; ops::=s+1.0; loop set!(ops*elt!-s*v1.elt!) end;
  181.      end;
  182.       end;
  183.  
  184.    move_toward(v1:SAME, d:FLT)
  185.       -- Move self a distance `d' in the direction toward v1.
  186.       -- Don't change it if it is equal to v1.
  187.       pre v1.dim=dim is
  188.       s::=dist_to(v1); if s/=0.0 then 
  189.      s:=d/s; oms::=1.0-s; loop set!(oms*elt!+s*v1.elt!) end;
  190.      end;
  191.       end;
  192.  
  193.    to_interpolate_between(v0,v1:SAME, t:FLT)
  194.       -- When `t=0.0' set `self=v0', when `t=1.0' set `self=v1' and
  195.       -- interpolate for intermediate values.
  196.       pre v0.dim=dim and v1.dim=dim is
  197.       ot::=1.0-t; loop set!(ot*v0.elt!+t*v1.elt!) end; end;
  198.  
  199.    max_index:INT is
  200.       -- The index of the maximum component of self. Lowest index
  201.       -- in case of equality.
  202.       mval::=[0]; res::=0;
  203.       loop i::=ind!; e::=elt!; if e>mval then mval:=e; res:=i; end; end;
  204.       return(res); end; 
  205.  
  206.    max_value:FLT is return([max_index]) end;
  207.       -- The largest component of self.
  208.    
  209.    min_index:INT is
  210.       -- The index of the minimum component of self. Lowest index in case
  211.       -- of equality.
  212.       mval::=[0]; res ::= 0;
  213.       loop i::=ind!; e::=elt!; if e<mval then mval:=e; res:=i; end; end; 
  214.       return(res);  end;
  215.  
  216.    min_value:FLT is return([min_index]) end;
  217.       -- The smallest component of self.
  218.  
  219.    make_orthogonal_to_unit(v1:SAME)
  220.       -- Subtract off the projection of self onto the unit vector v1.
  221.       pre v1.dim=dim and v1.is_normalized(0.0001) is
  222.       add_scaled(-dot(v1),v1); end;
  223.  
  224.    is_approx(v1:SAME):BOOL 
  225.       pre v1.dim=dim is #ERR+"Not Implemented"; return(false) end;
  226.       -- True if the components of self are approximately equal to those of v1.
  227. --!!  loop if not elt!.is_approx(v1.elt!) then return end end; res:=true end;
  228.    
  229.    reflect_through_zero is 
  230.       -- Reflect self through the origin.
  231.       loop set!(-elt!) end end;
  232.    
  233.    outer_product(v2: SAME): MAT is
  234.       -- Return a matrix which is the outer product of self*v1
  235.       res ::= #MAT(dim,v2.dim);
  236.       res.to_outer_product_of(self,v2);
  237.       return(res);  end;
  238.    
  239.    times(m: MAT): SAME is
  240.       -- Return a vector that is the result of self*matrix
  241.       res ::= #SAME(m.nc);
  242.       m.transpose_times_in(self,res);
  243.       return(res);
  244.       end;
  245.    
  246.    times_in(m: MAT, v: SAME) is
  247.       -- Set v to the result of self*matrix
  248.       m.transpose_times_in(self,v);   
  249. --      #OUT+str+"*"+m.str+"="+v.str+"\n";
  250.       end;
  251.    
  252.    times_add_into(m: MAT, v: SAME) is
  253.       -- Set v to self*m + v
  254.       m.transpose_times_add_into(self,v);
  255.       end;
  256.    
  257. end; -- class VEC
  258. -------------------------------------------------------------------
  259. class TEST_VEC is
  260.    
  261.    include TEST;
  262.    
  263.    main is
  264.       -- Test of `VEC'.
  265.       class_name("VEC");
  266.       v0 ::=#VEC(|1.0,0.0,0.0|);
  267.       v1 ::=#VEC(|0.0,1.0,0.0|);
  268.       v2 ::=#VEC(|0.0,0.0,1.0|);
  269.       test("dim",v1.dim.str,"3");
  270.       test("str",v0.str,"|1,0,0|");
  271.       test("str",v1.str,"|0,1,0|");
  272.       test("str",v2.str,"|0,0,1|");
  273.      -- Having tested str, make use of it in the following
  274.       
  275.       test("plus", (v0+v1).str,#VEC(|1.0,1.0,0.0|).str);
  276.       test("minus", (v0-v1).str, #VEC(|1.0,-1.0,0.0|).str);
  277.       test("dot", v0.dot(v1).str, 0.str);
  278.       r ::= v0.copy;
  279.       r.scale_by(5.0);
  280.       test("scale_by", r.str, #VEC(|5.0,0.0,0.0|).str);
  281.       r := v0.copy;
  282.       r.to(v1);
  283.       test("to", r.str, #VEC(|0.0,1.0,0.0|).str);
  284.       r := v0.copy;
  285.       r.add(v1);
  286.       test("add", r.str,#VEC(|1.0,1.0,0.0|).str);
  287.       r := v0.copy;
  288.       r.add_scaled(5.0,v1);
  289.       test("add_scaled", r.str , #VEC(|1.0,5.0,0.0|).str);
  290.       r := v0.copy;
  291.       r.to_sum_of(v1,v2);
  292.       test("to_sum_of", r.str ,#VEC(|0.0,1.0,1.0|).str);
  293.       
  294.       r := v0.copy;  r.to_difference_of(v1,v2);
  295.       test("to_difference_of", r.str, #VEC(|0.0,1.0,-1.0|).str);
  296.  
  297.       r := v0.copy;  r.to_difference_with(v1);
  298.       test("to_difference_with", r.str,#VEC(|1.0,-1.0,0.0|).str);
  299.  
  300.       r := v0.copy;  r.to(3.0);      
  301.       test("to", r.str, #VEC(|3.0,3.0,3.0|).str);
  302.       
  303.       r := v0.copy;  r.to_ones;      
  304.       test("to_ones", r.str, #VEC(|1.0,1.0,1.0|).str);
  305.       
  306.       r := v0.copy;  r.to_zero;      
  307.       test("to_zero", r.str, #VEC(|0.0,0.0,0.0|).str);
  308.  
  309.       r := v0.copy;  r.scale_by(2.0);      
  310.       test("scale_by", r.length.str, 2.str);
  311.  
  312.       r := v0.copy;  r.scale_by(2.0);      
  313.       test("square_length", r.square_length.str, 4.str);
  314.       
  315.       r := v0.copy;  r.scale_by(5.0); r.normalize;
  316.       test("normalize", r.str , #VEC(|1.0,0.0,0.0|).str);
  317. --      test("is_normalized 1", v0.copy.scale_by(5.0).is_normalized.str, false.str);
  318. --      test("is_normalized 2", v0.is_normalized.str, true.str);
  319.       
  320.       r := v0.copy;  r.scale_by(3.0);
  321.       r1 ::= v1.copy; r1.scale_by(4.0);
  322.       test("square_dist_to", r.square_dist_to(r1).str, 25.str);
  323.  
  324.       r := v0.copy;  r.scale_by(3.0);
  325.       r1 := v1.copy; r1.scale_by(4.0);
  326.       test("dist_to", r.dist_to(r1).str, 5.str);
  327.       
  328.  
  329. --      test("bounded_square_dist_to 1",
  330. --     v0.copy.scale_by(3.0)
  331. --           .bounded_square_dist_to(v1.copy.scale_by(4.0),30.0).str
  332. --           , "25");
  333. --      test("bounded_square_dist_to 2",
  334. --     v0.copy.scale_by(3.0)
  335. --           .bounded_square_dist_to(v1.copy.scale_by(4.0),3.0).str
  336. --           , "-1");
  337.       r1 := v1.copy;  r1.to_midpoint_with(v2);
  338.       test("to_midpoint_with", r1.str,#VEC(|0.0,0.5,0.5|).str);
  339.       
  340.       r1 := v1.copy;  r1.to_zero; r1.move_away_from(v2,1.0);
  341.       test("move_away_from", r1.str,#VEC(|0.0,0.0,-1.0|).str);
  342.       
  343.       r1 := v1.copy;  r1.to_zero; r1.move_toward(v2,0.5);
  344.       test("move_toward", r1.str,#VEC(|0.0,0.0,0.5|).str);
  345.       
  346.       r2 ::= v2.copy; r2.to_interpolate_between(v0,v1,0.5);
  347.       test("to_interpolate_between", r2.str, #VEC(|0.5,0.5,0.0|).str);
  348.       test("max_index", v0.max_index.str, 0.str);
  349.       test("max_value", v0.max_value.str, 1.str);
  350.       test("min_index", (v0+v1).min_index.str, 2.str);
  351.       test("min_value", (v0+v1).min_value.str, 0.str);
  352.       test("eltwise_product",v0.eltwise_product(v1).str,#VEC(|0.0,0.0,0.0|).str);
  353.       test("eltwise_product2",
  354.              #VEC(|1.0,2.0,3.0|).eltwise_product(#VEC(|2.0,5.0,7.0|)).str,
  355.              #VEC(|2.0,10.0,21.0|).str);
  356.       
  357. --      test("make_orthogonal_to_unit",
  358. --     v0.plus(v1).make_orthogonal_to_unit(v1).str, "|1.0,0.0,0.0|");
  359.       
  360. --      unchecked_test("to_uniform_random", v1.copy.to_uniform_random.str, "");
  361. --      unchecked_test("to_cube_random", v1.copy.to_cube_random.str, "");
  362. --      unchecked_test("to_normal_random",
  363. --     v1.copy.to_normal_random(1.0).str, "");
  364. --      unchecked_test("to_standard_normal_random",
  365. --     v1.copy.to_standard_normal_random.str, "");
  366. --      unchecked_test("to_cantor_random",
  367. --     v1.copy.to_cantor_random(.333).str, "");
  368. --      unchecked_test("to_curve_random", v1.copy.to_curve_random.str, "");
  369. --      unchecked_test("to_unit_random", v1.copy.to_unit_random.str, "");
  370. --      unchecked_test("to_ball_random", v1.copy.to_ball_random.str, "");
  371. --      test("is_epsilon_equal 1", v1.is_epsilon_equal(v1).str, "T");
  372. --      test("is_epsilon_equal 2", v1.is_epsilon_equal(v2).str, "F");
  373.       finish;
  374.    end; -- vector_test
  375.    
  376.    
  377. end;
  378.  
  379.