The problem is you are subclassing the wrong thing. It turns out that the complex functions are computed in the Value::Complex
package, not the Parser::Function
package (and the same is true of real functions, vector functions, and so on in their respective Value classes). That is, cos($z)
is actually computed by $z->cos()
(which is why you used $self->value
because it is the object calling that function that is actually the argument of the function).
So you need to put your cis
function into a subclass of Value::Complex
, not Parser::Function
, and the class that it has is Parser::Function::complex
. So how do you hook in your complex subclass, you ask? You set Context->{value}{Complex}
to point to your complex class. That will make the parser create your class when a complex value is needed rather than Value::Complex
. So here is an example:
package my::Complex;
our @ISA = ('Value::Complex');
sub cis {
my $z = shift;
return cos($z) + main::i * sin($z);
}
package main;
Context("Complex");
Context()->{value}{Complex} = 'my::Complex';
Context()->constants->set(i => {value => my::Complex->new(0,1)});
Context()->functions->add(cis => {
class => 'Parser::Function::complex', TeX => '\operatorname{cis}',
complex => 1, isCommand => 1
});
sub cis {Parser::Function->call("cis", my::Complex->new(@_))}
You also need to tell the parser that the return value for cis
is a complex number (complex => 1
) and that you need to use the internal command for calling the function rather than a native perl function when an executable version of a formula containing cis
is generated (for evaluating student answers, for example) with isCommand => 1
. You can remove that last if you add the sub cis
that is the last line of code. That line also allows you to use cis()
in your perl code directly (e.g., my $z = cis(3+i)
), but is otherwise optional.
The last thing to worry about is the fact that the constant i
in the Complex context is an instance of Value::Complex
, so I added a line to modify the constant so that it is a my::Complex
object. (I have to say, that one took me a while to realize -- I kept getting Value::Complex
values when I thought they should be my::Complex
.)
So that should do it for you.