# Calculator.pm # # Copyright (c) 2002 Cunningham & Cunningham, Inc. # Released under the terms of the GNU General Public License version 2 or later. # # Perl translation by Dave W. Smith package Calculator; use base qw(ColumnFixture); sub new { my \$pkg = shift; return \$pkg->SUPER::new(hp => new HP35(), key => undef, @_); } sub key { return \$_[0]->{'key'} } sub hp { return \$_[0]->{'hp'} } sub points { return 0 } sub flash { return 0 } sub watts { return 0.5 } sub reset { my \$self = shift; \$self->{'key'} = undef; } sub execute { my \$self = shift; if ( defined(\$self->key()) ) { \$self->hp()->key(\$self->key()); } } sub x { my \$self = shift; return \$self->hp()->{'rh'}->[0]; } sub y { my \$self = shift; return \$self->hp()->{'rh'}->[1]; } sub z { my \$self = shift; return \$self->hp()->{'rh'}->[2]; } sub t { my \$self = shift; return \$self->hp()->{'rh'}->[3]; } package HP35; my \$D2R = (4.0 * CORE::atan2(1, 1)) / 180.0; sub new { my \$pkg = shift; bless { rh => [0.0, 0.0, 0.0, 0.0], s => 0.0 }, \$pkg; } sub key { my \$self = shift; my(\$key) = @_; if ( \$key =~ m/^-?\d+(?:\.\d+)?\$/ ) { \$self->_push(\$key); } elsif ( \$key eq "enter" ) { \$self->_push(); } elsif ( \$key eq "+" ) { \$self->_push(\$self->_pop() + \$self->_pop()); } elsif ( \$key eq "-" ) { my \$t = \$self->_pop(); \$self->_push(\$self->_pop() - \$t); } elsif ( \$key eq "*" ) { \$self->_push(\$self->_pop() * \$self->_pop()); } elsif ( \$key eq "/" ) { # HACK divide-by-zero catch my \$t = \$self->_pop(); eval { \$self->_push(\$self->_pop() / \$t); }; \$self->_push("Infinity") if \$@; } elsif ( \$key eq "x^y" ) { \$self->_push(exp(log(\$self->_pop()) * \$self->_pop())); } elsif ( \$key eq "clx" ) { \$self->{'rh'}->[0] = 0.0; } elsif ( \$key eq "clr" ) { \$self->{'rh'} = [0.0, 0.0, 0.0, 0.0]; } elsif ( \$key eq "chs" ) { \$self->{'rh'}->[0] *= -1.0; } elsif ( \$key eq "x<>y" ) { my \$t = \$self->{'rh'}->[0]; \$self->{'rh'}->[0] = \$self->{'rh'}->[1]; \$self->{'rh'}->[1] = \$t; } elsif ( \$key eq "r!" ) { \$self->{'rh'}->[3] = \$self->_pop(); } elsif ( \$key eq "sto" ) { \$self->{'s'} = \$self->{'rh'}->[0]; } elsif ( \$key eq "rcl" ) { \$self->_push(\$self->{'s'}); } elsif ( \$key eq "sqrt" ) { \$self->_push(sqrt(\$self->_pop())); } elsif ( \$key eq "ln" ) { \$self->_push(log(\$self->_pop())); } elsif ( \$key eq "sin" ) { \$self->_push(sin(\$self->_pop() * \$D2R)); } elsif ( \$key eq "cos" ) { \$self->_push(cos(\$self->_pop() * \$D2R)); } elsif ( \$key eq "tan" ) { my \$t = \$self->_pop(); \$self->_push(sin(\$t * \$D2R)/cos(\$t * \$D2R)); } else { die "can't do key: \$key\n"; } } sub _push { my \$self = shift; my(\$value) = @_; for ( my \$i = 3; \$i > 0 ; --\$i ) { \$self->{'rh'}->[\$i] = \$self->{'rh'}->[\$i - 1]; } \$self->{'rh'}->[0] = \$value if defined(\$value); } sub _pop { my \$self = shift; my \$result = \$self->{'rh'}->[0]; for ( my \$i = 0 ; \$i < 3 ; ++\$i ) { \$self->{'rh'}->[\$i] = \$self->{'rh'}->[\$i + 1]; } return \$result; } 1;