[system] / trunk / pg / macros / contextLimitedPowers.pl Repository:
ViewVC logotype

Annotation of /trunk/pg/macros/contextLimitedPowers.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6058 - (view) (download) (as text)

1 : sh002i 5556 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
4 : gage 6058 # $CVSHeader$
5 : sh002i 5556 #
6 :     # This program is free software; you can redistribute it and/or modify it under
7 :     # the terms of either: (a) the GNU General Public License as published by the
8 :     # Free Software Foundation; either version 2, or (at your option) any later
9 :     # version, or (b) the "Artistic License" which comes with this package.
10 :     #
11 :     # This program is distributed in the hope that it will be useful, but WITHOUT
12 :     # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 :     # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14 :     # Artistic License for more details.
15 :     ################################################################################
16 :    
17 : sh002i 5551 =head1 NAME
18 : dpvc 4664
19 : sh002i 5551 contextLimitedPowers.pl - Restrict the base or power allowed in exponentials.
20 : dpvc 4664
21 : sh002i 5551 =head1 DESCRIPTION
22 : dpvc 5373
23 : sh002i 5551 Implements subclasses of the "^" operator that restrict
24 :     the base or power that is allowed. There are four
25 :     available restrictions:
26 : dpvc 5373
27 : sh002i 5555 No raising e to a power
28 :     Only allowing integer powers (positive or negative)
29 :     Only allowing positive interger powers
30 :     Only allowing positive interger powers (and 0)
31 : dpvc 5373
32 : sh002i 5551 You install these via one of the commands:
33 : dpvc 5373
34 : sh002i 5555 LimitedPowers::NoBaseE();
35 :     LimitedPowers::OnlyIntegers();
36 :     LimitedPowers::OnlyPositiveIntegers();
37 :     LimitedPowers::OnlyNonNegativeIntegers();
38 : gage 4997
39 : sh002i 5551 Only one of the three can be in effect at a time; setting
40 :     a second one overrides the first.
41 : dpvc 4664
42 : sh002i 5551 These function affect the current context, or you can pass
43 :     a context reference, as in
44 :    
45 : sh002i 5555 $context = Context("Numeric")->copy;
46 :     LimitedPowers::OnlyIntegers($context);
47 : sh002i 5551
48 :     For the Interger power functions, you can pass additional
49 :     parameters that control the range of values that are allowed
50 :     for the powers. The oprtions include:
51 :    
52 :     =over
53 :    
54 :     =item S<C<< minPower => m >>>
55 :    
56 :     only integer powers bigger than or equal
57 :     to m are allowed. (If m is undef, then
58 :     there is no minimum power.)
59 :    
60 :     =item S<C<< maxPower => M >>>
61 :    
62 :     only integer powers less than or equal
63 :     to M are allowed. (If M is undef, then
64 :     there is no maximum power.)
65 :    
66 :     =item S<C<< message => "text" >>>
67 :    
68 :     a description of the type of power
69 :     allowed (e.g., "positive integer constants");
70 :    
71 :     =item S<C<< checker => code >>>
72 :    
73 :     a reference to a subroutine that will be
74 :     used to check if the powers are acceptable.
75 :     It should accept a reference to the BOP::power
76 :     structure and return 1 or 0 depending on
77 :     whether the power is OK or not.
78 :    
79 :     =back
80 :    
81 :     For example:
82 :    
83 :     LimitedPowers::OnlyIntegers(
84 :     minPower => -5, maxPower => 5,
85 :     message => "integer constants between -5 and 5",
86 :     );
87 :    
88 :     would accept only powers between -5 and 5, while
89 :    
90 :     LimitedPowers::OnlyIntegers(
91 :     checker => sub {
92 :     return 0 unless LimitedPowers::isInteger(@_);
93 :     my $self = shift; my $p = shift; # the power as a constant
94 :     return $p != 0 && $p != 1;
95 :     },
96 :     message => "integer constants other than 0 or 1",
97 :     );
98 :    
99 :     would accept any integer power other than 0 and 1.
100 :    
101 : gage 4997 =cut
102 : dpvc 4664
103 : sh002i 5551 loadMacros("MathObjects.pl");
104 :    
105 :     sub _contextLimitedPowers_init {}; # don't load it again
106 :    
107 : dpvc 4664 package LimitedPowers;
108 :    
109 : dpvc 5350 sub NoBaseE {
110 :     my $context = (Value::isContext($_[0]) ? shift : Value->context);
111 :     $context->operators->set(
112 : dpvc 5351 '^' => {class => 'LimitedPowers::NoBaseE', isCommand=>1, perl=>'LimitedPowers::NoBaseE->_eval', @_},
113 :     '**' => {class => 'LimitedPowers::NoBaseE', isCommand=>1, perl=>'LimitedPowers::NoBaseE->_eval', @_},
114 : dpvc 5350 );
115 :     }
116 :    
117 :     sub OnlyIntegers {
118 :     my $context = (Value::isContext($_[0]) ? shift : Value->context);
119 :     $context->operators->set(
120 : dpvc 5351 '^' => {class => 'LimitedPowers::OnlyIntegers', message => "integer constants", @_},
121 :     '**' => {class => 'LimitedPowers::OnlyIntegers', message => "integer constants",@_},
122 : dpvc 5350 );
123 :     }
124 :    
125 :     sub OnlyNonNegativeIntegers {
126 :     my $context = (Value::isContext($_[0]) ? shift : Value->context);
127 :     OnlyIntegers($context, minPower=>0, message=>"non-negative integer constants", @_);
128 :     }
129 :    
130 :     sub OnlyPositiveIntegers {
131 :     my $context = (Value::isContext($_[0]) ? shift : Value->context);
132 :     OnlyIntegers($context, minPower => 1, message => "positive integer constants", @_);
133 :     }
134 :    
135 :     sub OnlyNonTrivialPositiveIntegers {
136 :     my $context = (Value::isContext($_[0]) ? shift : Value->context);
137 :     OnlyIntegers($context, minPower=>2, message=>"integer constants bigger than 1", @_);
138 :     }
139 :    
140 :     #
141 : dpvc 5351 # Test for whether the power is an integer in the specified range
142 :     #
143 :     sub isInteger {
144 :     my $self = shift; my $n = shift;
145 :     my $def = $self->{def};
146 :     return 0 if defined($def->{minPower}) && $n < $def->{minPower};
147 :     return 0 if defined($def->{maxPower}) && $n > $def->{maxPower};
148 :     return Value::Real->make($n - int($n)) == 0;
149 :     }
150 :    
151 :     #
152 : dpvc 5350 # Legacy code to accommodate older approach to setting the operators
153 :     #
154 : dpvc 4664 our @NoBaseE = (
155 : dpvc 5351 '^' => {class => 'LimitedPowers::NoBaseE', isCommand=>1, perl=>'LimitedPowers::NoBaseE->_eval'},
156 :     '**' => {class => 'LimitedPowers::NoBaseE', isCommand=>1, perl=>'LimitedPowers::NoBaseE->_eval'},
157 : dpvc 4664 );
158 :     our @OnlyIntegers = (
159 : dpvc 5351 '^' => {class => 'LimitedPowers::OnlyIntegers', message => "integer constants"},
160 :     '**' => {class => 'LimitedPowers::OnlyIntegers', message => "integer constants"},
161 : dpvc 4664 );
162 : dpvc 5350 our @OnlyNonNegativeIntegers = (
163 : dpvc 5351 '^' => {class => 'LimitedPowers::OnlyIntegers', minPower => 0, message => "non-negative integer constants"},
164 :     '**' => {class => 'LimitedPowers::OnlyIntegers', minPower => 0, message => "non-negative integer constants"},
165 : dpvc 5350 );
166 : dpvc 4664 our @OnlyPositiveIntegers = (
167 : dpvc 5351 '^' => {class => 'LimitedPowers::OnlyIntegers', minPower => 1, message => "positive integer constants"},
168 :     '**' => {class => 'LimitedPowers::OnlyIntegers', minPower => 1, message => "positive integer constants"},
169 : dpvc 4664 );
170 : dpvc 5350 our @OnlyNonTrivialPositiveIntegers = (
171 : dpvc 5351 '^' => {class => 'LimitedPowers::OnlyIntegers', minPower => 2, message => "integer constants bigger than 1"},
172 :     '**' => {class => 'LimitedPowers::OnlyIntegers', minPower => 2, message => "integer constants bigger than 1"},
173 : dpvc 5332 );
174 :    
175 : dpvc 5350
176 : dpvc 4664 ##################################################
177 :    
178 :     package LimitedPowers::NoBaseE;
179 :     @ISA = qw(Parser::BOP::power);
180 :    
181 :     my $e = CORE::exp(1);
182 :    
183 :     sub _check {
184 :     my $self = shift;
185 :     $self->SUPER::_check(@_);
186 :     $self->Error("Can't raise e to a power") if $self->{lop}->string eq 'e';
187 :     }
188 :    
189 :     sub _eval {
190 :     my $self = shift;
191 :     Value::cmp_Message("Can't raise e to a power") if $_[0] - $e == 0;
192 :     $self->SUPER::_eval(@_);
193 :     }
194 :    
195 :     ##################################################
196 :    
197 :     package LimitedPowers::OnlyIntegers;
198 :     @ISA = qw(Parser::BOP::power);
199 :    
200 :     sub _check {
201 : dpvc 5350 my $self = shift; my $p = $self->{rop}; my $def = $self->{def};
202 : dpvc 5351 my $checker = (defined($def->{checker}) ? $def->{checker} : \&LimitedPowers::isInteger);
203 : dpvc 4664 $self->SUPER::_check(@_);
204 : dpvc 5350 $self->Error("Powers must be $def->{message}")
205 : dpvc 5351 if $p->type ne 'Number' || !$p->{isConstant} || !&{$checker}($self,$p->eval);
206 : dpvc 4664 }
207 :    
208 :     ##################################################
209 :    
210 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9