# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)

BEGIN { $| = 1; print "1..last_test_to_print\n"; }
END {print "not ok 1\n" unless $loaded;}

use Vector;

$loaded = 1;
print "ok 1\n";

######################### End of black magic.
# Insert your test code below (better if it prints "ok 13"
# (correspondingly "not ok 13") depending on the success of chunk 13
# of the test code):
###########################################

# --------------------------------------------------

# The format of the tests below should be
#
#    eval { <put code here that may fail> };
#    check( error=>$!, assert=> <a boolean expressoinwhich should be true> );
#
# 'error', if present,  is the value of a possible runtime exception.
#          If it is 'true', then the check fails.  
# 'assert, if present', gives a boolean condition which must
#          be true for the check to succeed.
#
#  Both 'assert' and 'error' are optional; neither will cause 
#  the check to fail if omitted.
#

my $test = 1;   # counter for which test we're doing.
my %hash;       # of arguments passed to check().

# only true if $hash{$key} exists and is true.
sub is {
    my ($key) = @_;
    return 0 unless exists $hash{$key};
    return $hash{$key};
}

# only true if $hash{$key} exists and is false.
sub isnot {
    my ($key) = @_;
    return 0 unless exists $hash{$key};
    return not $hash{$key};
}

sub check {
    %hash = @_;  # declared above as "my %hash".
    $test++;     # declared above as "my $test" =  test number
    if ( is('error') or isnot('assert') ) { 
        print "not ok $test\n"; return; }
    else {
        print "ok $test\n"; return; }
}

# -------------------------------------------------------

# empty vector creation
eval { $a = new Vector size=>20; };
check( error=>$! );

# sequence vector creation
eval { $b = new Vector size=>20, value=>0.0; };
check( error=>$! );

# constant vector creation
eval {  $c = new Vector size=>20, first=>0, by=>0.1; };
check( error=>$! );

# check creation via explicit perl array ref (slow)
eval { $cc = new Vector values=>[21..25]; };
check( error=>$! );

# set a value
eval { $a->[2] = 2.3; };
check( error=>$! );

# return same value
eval { $z = $a->[2]; };
check( error=>$!, assert=>($z==2.3) );

# size of array via either a method call or perl idiom.
eval{ $z1 = $b->size;  $z2 = 1+$#$b; };
check( error=>$!, assert=>( $z1==20 and $z2==20 ) );

# subscripts bigger than array size or smaller than zero should wrap.
eval{ $b->[ $b->size + 5 ] = -33.1;  $z1 = $b->[ 5 ]; 
      $b->[  -3 ]          =  22.1;  $z2 = $b->[ $b->size - 3 ] };
check( error=>$!, assert=>( $z1==-33.1 and $z2==22.1) );

# conversion to string.
eval{ $z = "".$c; };
check( error=>$!, assert=>($z eq '[0,0.1,0.2,...,1.7,1.8,1.9]' ) );
#print " test $test : '$z'\n";

# addition
eval{ $d = $b+$c; };
check( error=>$!, assert=>( ''.$d eq '[0,0.1,0.2,...,23.8,1.8,1.9]' ) );
#print " test $test: '$d'\n";

# multiplication
eval{ $e = $d*$c; };
#print "'$e'\n";
check( error=>$!, assert=>( ''.$e eq '[0,0.01,0.04,...,40.46,3.24,3.61]' ) );

# multiplying different size vectors
$a = new Vector size=>5, first=>1, by=>2;
$b = new Vector size=>10, first=>100, by=>100;
eval { $c = $a + $b;  $d = $b + $a; };
#print " c size = " . $c->size  . " , d size = " . $d->size  . " \n";
#print " c = '$c' \n";
#print " d = '$d' \n";
check( error=>$!, assert=>( ''.$d eq ''.$c  and 
                            ''.$d eq '[101,203,305,...,805,907,1009]' ) );

$a = new Vector size=>10, first=>10, by=>2;
$b = new Vector size=>10, value=>2;

# subtracting vectors
eval{ $f = $a-$b; };
#print " subtract : '$f' \n";
check (error=>$!, assert=>( $f->[0] == (10 - 2) and $f->[9] == (28-2) ) );

# dividing vectors
eval{ $f = $a / $b; };
#print " divide :  '$f' \n";
check (error=>$!, assert=>( $f->[0] == (10 / 2) and $f->[9] == (28/2) ) );

# powers of vectors
$a = new Vector size=>4; $a->[0]=4; $a->[1]=25; $a->[2]=10; $a->[3]=100;
$b = new Vector size=>1, value=>0.5;
eval{ $f = $a ** $b; };
check (error=>$!, assert=>( $f->[0]==2 and $f->[3]==10)  );
#print " a = '$a' \n";
#print " b = '$b' \n";
#print " f = '$f' \n";
# print " a + b = " . ($a+$b) . "\n";

# sin
$pi = 2*atan2(1,0);  # these two give same results.
#$pi = 3.141592653589793 2384626433832795028842  ;  # these digits are right
#  print printf(" %30.28f \n",  2*atan2(1,0))
#      3.141592653589793 1159979634685   (darwin, powerbook g4)
#
$a->[0]=0; $a->[1] = $pi/4; $a->[2] = $pi/2; $a->[3] = $pi;
@r = ( 0.0, sqrt(2.0)/2.0, 1.0, 0.0 );
$err = 1e-15;
eval{ $f = sin($a); };
check( error=>$!, assert => ( abs($f->[1]-$r[1]) < $err) );
#print " a = '$a' \n";
#print " sin = '$f' \n";
# foreach $i (0..3) { print " error = " . ($f->[$i] - $r[$i]) . "\n"; }

# sqrt
$a = new Vector size=>4; $a->[0]=4; $a->[1]=25; $a->[2]=10; $a->[3]=100;
eval{ $f = sqrt($a) };
check (error=>$!, assert=>( $f->[0] == 2.0 and $f->[3] == 10.0 ) );
#print " a = $a \n";
#print " sqrt(a) = '$f' \n";

# binary operation with non-vectors.
$a = new Vector values=>[1, 10, 100];
eval{ $c = $a+1; $d = $a + [2,3,4]; };
check(error=>$!, assert=>( ''.$c eq '[2,11,101]' and ''.$d eq '[3,13,104]' ));

                           



big ~...perl/Math-Vector> 