2 # This file is part of Language::Befunge.
3 # Copyright (c) 2001-2008 Jerome Quelin, all rights reserved.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the same terms as Perl itself.
10 package Language
::Befunge
::Vector
;
18 '-' => \
&vector_subtract
,
19 'neg' => \
&vector_invert
,
21 '+=' => \
&vector_add_inplace
,
23 '==' => \
&vector_equality
,
24 '!=' => \
&vector_inequality
,
25 '""' => \
&vector_as_string
;
31 # my $v = LB::Vector->new( $x [, $y, ...] );
33 # Create a new vector. The arguments are the actual vector data; one
34 # integer per dimension.
40 my $usage = "Usage: $pkg->new(\$x, ...)";
41 croak
$usage unless scalar(@_) > 0;
51 # new_zeroes( dimensions )
53 # Creates a new vector, set to the origin (all zeroes). ->new_zeroes(2) is
54 #exactly equivalent to ->new(0, 0).
58 my $dimensions = shift;
59 my $usage = "Usage: $package->new_zeroes(\$dimensions)";
60 croak
$usage unless defined $dimensions;
61 croak
$usage unless $dimensions > 0;
63 push(@initial,0) for(1..$dimensions);
64 return bless([@initial], $package);
73 # my $dims = $vec->get_dims;
75 # Return the number of dimensions, an integer.
79 return scalar(@
$self);
84 # my $val = $vec->get_component($dim);
86 # Get the value for dimension $dim.
89 my ($self, $dim) = @_;
90 croak
"No such dimension $dim!" unless $dim >= 0 && $self->get_dims > $dim;
98 # $vec->set_component($dim, $value);
100 # Set the value for dimension $dim to $value.
103 my ($self, $dim, $val) = @_;
104 croak
"No such dimension $dim!" unless $dim >= 0 && $self->get_dims > $dim;
105 $self->[$dim] = $val;
112 # vector_subtract( v2 )
114 # $v0 = $v1->vector_subtract($v2);
117 # Returns a new Vector object, which is the result of v1 minus v2.
119 sub vector_subtract
{
121 croak
"uneven dimensions in vector subtraction!" unless $v1->get_dims == $v2->get_dims;
122 my $vr = ref($v1)->new_zeroes($v1->get_dims);
123 for(my $i = 0; $i < $v1->get_dims; $i++) {
124 $vr->[$i] = $v1->[$i] - $v2->[$i];
133 # $v1->vector_invert();
136 # Subtracts v1 from the origin. Effectively, gives the inverse of the
137 # original vector. The new vector is the same distance from the origin,
138 #in the opposite direction.
142 my $rv = ref($v1)->new_zeroes($v1->get_dims);
143 for(my $i = 0; $i < $v1->get_dims; $i++) {
144 $rv->[$i] = -$v1->[$i];
153 # $v0 = $v1->vector_add($v2);
156 # Returns a new Vector object, which is the result of v1 plus v2.
160 croak
"uneven dimensions in vector addition!" unless $v1->get_dims == $v2->get_dims;
161 my $rv = ref($v1)->new_zeroes($v1->get_dims);
162 for(my $i = 0; $i < $v1->get_dims; $i++) {
163 $rv->[$i] = $v1->[$i] + $v2->[$i];
170 # vector_add_inplace( v2 )
172 # $v1->vector_add_inplace($v2);
175 # Adds v2 to v1, and stores the result back into v1.
177 sub vector_add_inplace
{
179 croak
"uneven dimensions in vector addition!" unless $v1->get_dims == $v2->get_dims;
180 for(my $i = 0; $i < $v1->get_dims; $i++) {
181 $v1->[$i] += $v2->[$i];
190 # $v0 = $v1->vector_copy();
193 # Returns a new Vector object, which has the same dimensions and coordinates as v1.
197 return bless [@
$v], ref $v;
202 # get_all_components( )
204 # my $v = Language::Befunge::Vector->new(1, 2, 3);
205 # # $v now holds a 3-dimensional vector, <1,2,3>
206 # my @list = $v->get_all_components(); # returns (1, 2, 3)
208 # Gets the value for all dimensions, in order from 0..N.
210 sub get_all_components
{
219 # Sets the vector back to the origin, all 0's. See also the constructor,
220 # new_from_origin, above.
224 @
$self = (0) x
$self->get_dims;
229 # bounds_check( begin, end )
231 # die "out of bounds"
232 # unless $vector->bounds_check($begin, $end);
234 # Checks whether the given vector is within the box defined by begin and end.
235 # Returns 1 if vector is contained within the box, and 0 otherwise.
238 my ($vchk, $begin, $end) = @_;
239 croak
"uneven dimensions in bounds check!" unless $vchk->get_dims == $begin->get_dims;
240 croak
"uneven dimensions in bounds check!" unless $vchk->get_dims == $end->get_dims;
241 for(my $d = 0; $d < $vchk->get_dims; $d++) {
242 return 0 if $vchk->get_component($d) < $begin->get_component($d);
243 return 0 if $vchk->get_component($d) > $end->get_component($d);
250 # vector_as_string( )
252 # Returns the stringified form of the vector. For instance, a Befunge vector might look like "(1,2)".
254 sub vector_as_string
{
256 return "(" . join(",",@
$self) . ")";
261 # vector_equality( v2 )
263 # print("Equal!\n") if $v1->vector_equality($v2);
264 # print("Equal!\n") if $v1 == $v2;
266 # Checks whether the vectors both point at the same spot. Returns 1 if they
267 # do, 0 if they don't.
269 sub vector_equality
{
271 croak
"uneven dimensions in bounds check!" unless $v1->get_dims == $v2->get_dims;
272 for(my $d = 0; $d < $v1->get_dims; $d++) {
273 return 0 unless $v1->get_component($d) == $v2->get_component($d);
280 # vector_inequality( v2 )
282 # print("Equal!\n") unless $v1->vector_inequality($v2);
283 # print("Equal!\n") unless $v1 != $v2;
285 # Checks whether the vectors point to different spots. Returns 1 if they
286 # don't, 0 if they do. Compare vector_equality, above.
288 sub vector_inequality
{
289 return !vector_equality
(@_);
297 Language::Befunge::Vector - an opaque, N-dimensional vector class.
302 my $v1 = Language::Befunge::Vector->new($d, $x, $y, ...);
303 my $v2 = Language::Befunge::Vector->new_zeroes($d);
307 This class abstracts normal vector manipulation. It lets you pass
308 around one argument to your functions, rather than N arguments, one
309 per dimension. This means much of your code doesn't have to care
310 how many dimensions you're working with.
312 You can do vector arithmetic, test for equality, or even stringify
313 the vector to a string like I<"(1,2,3)">.
318 =head2 new( dimensions, x, [y, ...] )
320 Creates a new vector. The first argument is an integer specifying
321 how many dimensions this vector operates in. The remaining arguments
322 constitute the actual vector data; one integer per dimension.
325 =head2 new_zeroes( dimensions )
327 Creates a new vector, set to the origin (all zeroes).
328 ->B<new_zeroes>(2) is exactly equivalent to ->B<new>(2, 0, 0).
331 =head1 PUBLIC METHODS
335 Returns the number of dimensions, an integer.
338 =head2 vector_subtract( v2 )
340 $v0 = $v1->vector_subtract($v2);
343 Returns a new Vector object, which is the result of I<v1> minus I<v2>.
346 =head2 vector_invert( )
348 $v1->vector_invert();
351 Subtracts I<v1> from the origin. Effectively, gives the inverse of
352 the original vector. The new vector is the same distance from the
353 origin, in the opposite direction.
356 =head2 vector_add( v2 )
358 $v0 = $v1->vector_add($v2);
361 Returns a new Vector object, which is the result of I<v1> plus I<v2>.
364 =head2 vector_add_inplace( v2 )
366 $v1->vector_add_inplace($v2);
369 Adds I<v2> to I<v1>, and stores the result back into I<v1>.
372 =head2 vector_copy( )
374 $v0 = $v1->vector_copy();
377 Returns a new Vector object, which has the same dimensions and
378 coordinates as I<v1>.
381 =head2 set_component( dimension, data )
383 $v->set_component(0, 1); # set X to 1
385 Sets the value for dimension I<dimension> to the value I<data>.
388 =head2 get_component( dimension )
390 my $x = $v->get_component(0);
392 Gets the value for dimension I<dimension>.
395 =head2 get_all_components( )
397 my $v = Language::Befunge::Vector->new(3, 1, 2, 3);
398 # $v now holds a 3-dimensional vector, <1,2,3>
399 my @list = $v->get_all_components(); # returns (1, 2, 3)
401 Gets the value for all dimensions, in order from 0..N.
406 Sets the vector back to the origin, all 0's. See also the
407 constructor, B<new_from_origin>, above.
410 =head2 bounds_check( begin, end )
413 unless $vector->bounds_check($begin, $end);
415 Checks whether the given I<vector> is within the box defined by
416 I<begin> and I<end>. Returns I<1> if I<vector> is contained within
417 the box, and I<0> otherwise.
420 =head2 vector_as_string( )
422 Returns the stringified form of the vector. For instance, a Befunge
423 vector might look like I<"(1,2)">.
426 =head2 vector_equality( v2 )
428 print("Equal!\n") if $v1->vector_equality($v2);
429 print("Equal!\n") if $v1 == $v2;
431 Checks whether the vectors both point at the same spot. Returns
432 I<1> if they do, I<0> if they don't.
435 =head2 vector_inequality( v2 )
437 print("Equal!\n") unless $v1->vector_inequality($v2);
438 print("Equal!\n") unless $v1 != $v2;
440 Checks whether the vectors point to different spots. Returns
441 I<1> if they don't, I<0> if they do. Compare B<vector_equality>,
453 Jerome Quelin, E<lt>jquelin@cpan.orgE<gt>
455 Development is discussed on E<lt>language-befunge@mongueurs.netE<gt>
458 =head1 COPYRIGHT & LICENSE
460 Copyright (c) 2001-2008 Jerome Quelin, all rights reserved.
462 This program is free software; you can redistribute it and/or modify
463 it under the same terms as Perl itself.