#!/usr/local/bin/webwork-perl
# This file     is PGcomplexmacros.pl
# This includes the subroutines for the ANS macros, that
# is, macros allowing a more flexible answer checking
####################################################################
# Copyright @ 1995-2001 The WeBWorK Team
# All Rights Reserved
####################################################################
#$Id$


=head1 NAME

	Macros for complex numbers for the PG language

=head1 SYNPOSIS



=head1 DESCRIPTION

=cut


BEGIN{
	be_strict();
	
}
sub _PGcomplexmacros_init {
}
# export functions from Complex1.

foreach my $f (@Complex1::EXPORT) {
		#PG_restricted_eval("\*$f = \*Complex1::$f"); # this is too clever -- 
		                                              # the original subroutines are destroyed
        next if $f eq 'sqrt';  #exporting the square root caused conflicts with the standard version
                               # You can still use Complex1::sqrt to take square root of complex numbers
        next if $f eq 'log';  #exporting loq caused conflicts with the standard version
                               # You can still use Complex1::log to take square root of complex numbers

		my $string = qq{
		   sub main::$f {
		   	   &Complex1::$f;
		   }
		};
		PG_restricted_eval($string);
}

# You need to add 
# sub i();  # to your problem or else to dangerousMacros.pl
# in order to use expressions such as 1 +3*i;
# Without this prototype you would have to write 1+3*i();
# The prototype has to be defined at compile time, but dangerousMacros.pl is complied first.
#Complex1::display_format('cartesian');


=head4 polar
	Usage	polar($complex_number,r_format=>"%0.3f",theta_format=>"%0.3f")
	
	Output is text displaying the complex number in "e to the i theta" form.  The
	formats for the argument theta is determined by the option C<theta_format> and the
	format for the modulus is determined by the C<r_format> option.
	
	 

sub polar{
 	my $z = shift;
 	my %options = @_;
	set_default_options(\%options,  r_format 	=> ':%0.3f',
					theta_format 	=> ':%0.3f',
	);
	my $r = rho($z);
	my $theta = $z->theta;
	$r_format=":" . $options{r_format};
	$theta_format = ":" . $options{theta_format});
	"{$r$r_format} e^{i {$theta$theta_format}}";

}

sub cplx_cmp {
	my $correctAns = shift;
	my %options = @_;
	$correctAns = cplx($correctAns,0) unless ref($correctAns) =~/Complex/;
	assign_option_aliases( \%options,
    						'reltol'    =>      'relTol',
    );
    set_default_options(\%options,
    			'tolType'		=>  (defined($options{tol}) ) ? 'absolute' : 'relative',
    			# default mode should be relative, to obtain this tol must not be defined
			'tol'			=>	$main::numAbsTolDefault, 
	               	'relTol'		=>	$main::numRelPercentTolDefault,
			'zeroLevel'		=>	$main::numZeroLevelDefault,
			'zeroLevelTol'		=>	$main::numZeroLevelTolDefault,
			'format'		=>	$main::numFormatDefault,
			'debug'			=>  0,

    );

    
	my $ans_eval = sub {
	             my $in = shift;
			my $rh_ans = new AnswerHash;
				 $rh_ans->{correct_ans} = $correctAns;
				 unless (defined($in) and $in =~/\S/ ) { #bail on empty answer
				    $rh_ans->{student_ans} = "error: empty";
				 	return $rh_ans; 
				 }
				 my($PG_errors,$PG_errors_long);
				 
                 $rh_ans->input($in);
                 
                 $rh_ans->{student_ans}=math_constants($rh_ans->{student_ans});
                 $rh_ans->{student_ans} =~ s/e\^/exp /g;  #try to handle exponents
                 $rh_ans=check_syntax($rh_ans);
                 $rh_ans->{student_ans} =~ s/\bi\b/(i)/g;  #try to keep -i being recognized as a file reference
                                                           # and recognized as a function whose output is an imaginary number
                                                                     
                 
                 
				 warn $rh_ans->pretty_print() if defined($options{debug}) and $options{debug}==1;
				 ($in,$PG_errors,$PG_errors_long) = PG_restricted_eval($rh_ans->{student_ans});
                 $in = $in +0*i;   # force the input to be complex
				 if ($PG_errors_long) {
				 	$rh_ans->{error}=1;
				 	$rh_ans->{ans_message} = $PG_errors;
				 } else {
					 $in->display_format('cartesian') if ref($in) =~/Complex/;
					 $rh_ans->{student_ans}="$in";
					 my $permitted_error;
					if (defined($options{tolType}) && $options{tolType} eq 'absolute')	{
						$permitted_error = $options{tol};
					} elsif ( abs($correctAns) <= $options{zeroLevel}) {
							$permitted_error = $options{zeroLevelTol};  ## want $tol	to be non zero
					} else {
							$permitted_error = abs(.01*$options{relTol}*$correctAns); # relative tolerance is given in per cent
					}
	                $rh_ans->{score} =  (abs($in - $correctAns)<$permitted_error )? 1:0;
	                 
	             }
	             
                 $rh_ans;
                 };
    $ans_eval;
}

1;
